Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions .opencode/skills/backlog-to-openspec/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ license: MIT
compatibility: Requires openspec CLI.
metadata:
author: tryweb
version: "1.1"
version: "1.2"
generatedBy: "manual"
---

Expand Down Expand Up @@ -46,6 +46,46 @@ And enforce these sections in artifacts:

---

## Phase 0 — Git Safety Gate (CRITICAL)

**Goal**: block unsafe branch operations before creating a new OpenSpec change.

Run this gate before `openspec new change`:

```bash
# 1) working tree must be clean
git status --porcelain

# 2) identify current branch
git rev-parse --abbrev-ref HEAD

# 3) sync remote refs for branch safety checks
git fetch origin --prune
```

Pass conditions:
- `git status --porcelain` output is empty
- Current branch is `main` (preferred) or `feat/<existing-change-id>` when resuming existing work
- If resuming from `feat/<existing-change-id>`, branch has upstream (if not: `git push -u origin <branch>`)

Failure handling (hard rules):
- **Dirty tree**: commit changes or intentionally discard with `git reset --hard`
- **Never use `git stash` as workflow transport**
- **Wrong starting branch**: switch to `main` and sync first

```bash
git checkout main
git pull origin main
```

### Failure Mode → Remediation

| Failure mode | Detect with | Safe remediation |
|---|---|---|
| Dirty tree | `git status --porcelain` not empty | `git add -A && git commit -m "wip: ..."` OR intentional `git reset --hard` |
| Missing upstream | `git rev-parse --abbrev-ref --symbolic-full-name @{upstream}` fails | `git push -u origin <current-branch>` |
| Wrong base branch | `git rev-parse --abbrev-ref HEAD` is not `main`/`feat/*` | `git checkout main && git pull origin main` |

## Phase 1 — Backlog Normalization

1. Locate source backlog context.
Expand Down Expand Up @@ -106,7 +146,8 @@ git push origin "feat/${CHANGE_ID}" -u
- Chores: `chore/<change-id>`

**If working tree is dirty**:
- Stash or commit current changes first
- Commit current changes first (or intentionally discard with `git reset --hard`)
- Never use `git stash` as branch transport
- Never mix unrelated work in the same branch

---
Expand Down
51 changes: 49 additions & 2 deletions .opencode/skills/release-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ license: MIT
compatibility: Requires git, gh, docker compose, and npm CLI.
metadata:
author: tryweb
version: "2.0"
version: "2.1"
generatedBy: "manual"
---

Expand All @@ -20,17 +20,62 @@ This version adds mandatory anti-drift gates so we do not repeat:

---

## Phase 0 — Git Safety Gate (CRITICAL)

**Goal**: ensure release starts from a safe and reproducible git state.

Run before any release actions:

```bash
# 1) sync refs
git fetch origin --prune

# 2) confirm current branch
git rev-parse --abbrev-ref HEAD

# 3) working tree must be clean
git status --porcelain

# 4) detect unmerged remote branches relative to main
git branch -r --no-merged origin/main

# 5) confirm npm identity on host
npm whoami
```

Pass conditions:
- Current branch is `main`
- Working tree is clean
- Intended feature branches are already merged to `origin/main`
- npm account is available (`npm whoami` succeeds)

Hard rules:
- Never start release from `feat/*` or `fix/*`
- Never use `git stash` as release transport
- If any intended feature branch is not merged to `main`, stop release and merge first

### Failure Mode → Remediation

| Failure mode | Detect with | Safe remediation |
|---|---|---|
| Dirty tree | `git status --porcelain` not empty | Commit changes, or intentional `git reset --hard` if discard is intended |
| Missing upstream push | `git rev-parse --abbrev-ref --symbolic-full-name @{upstream}` fails | `git push -u origin <current-branch>` |
| Wrong base branch | `git rev-parse --abbrev-ref HEAD` is not `main` | `git checkout main && git pull origin main` |
| Unmerged feature before release | `git branch -r --no-merged origin/main` includes intended `origin/feat/*` | Merge feature branch to main before release |

## Pre-Conditions (Check Before Starting)

- All intended feature changes are merged to `main`
- Working tree is clean (`git status --short` is empty)
- `npm whoami` returns the publishing account (run on host)
- `NPM_TOKEN` secret is set in GitHub Actions repository settings
- No open `fix/` branches with uncommitted work
- No intended `feat/` branches remain unmerged into `main`

```bash
git status --short
npm whoami
git branch -r --no-merged origin/main
```

If working tree is dirty: stop and clean up before release.
Expand Down Expand Up @@ -121,8 +166,10 @@ chore: bump version to X.Y.Z and update changelog
## Phase 5 — Release Branch

```bash
git checkout main
git pull origin main
git checkout -b release/vX.Y.Z
git push origin release/vX.Y.Z
git push origin release/vX.Y.Z -u
```

---
Expand Down
105 changes: 85 additions & 20 deletions docs/DEVELOPMENT_WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,44 @@ gh auth status # Should show "Logged in to github.com"

---

## Shared Git Safety Gate (CRITICAL)

Run this gate **before** any feature or release operation.

```bash
# 1) Sync refs
git fetch origin --prune

# 2) Confirm current branch
git rev-parse --abbrev-ref HEAD

# 3) Working tree must be clean
git status --porcelain
```

### Pass Conditions

- For feature work: current branch is `main` (new work) or `feat/<change-id>` (resume work)
- For release work: current branch is `main`
- `git status --porcelain` output is empty

### Hard Rules

- **Never use `git stash` as workflow transport**
- If tree is dirty: commit changes, or intentionally discard with `git reset --hard`
- If upstream is missing: `git push -u origin <current-branch>`

### Failure Mode → Remediation

| Failure mode | Detect with | Safe remediation |
|---|---|---|
| Dirty tree | `git status --porcelain` not empty | `git add -A && git commit -m "wip: ..."` or intentional `git reset --hard` |
| Missing upstream | `git rev-parse --abbrev-ref --symbolic-full-name @{upstream}` fails | `git push -u origin <current-branch>` |
| Wrong base branch | branch is not expected for current phase | `git checkout main && git pull origin main` |
| Unmerged feature before release | `git branch -r --no-merged origin/main` includes intended `origin/feat/*` | Merge feature branch to main first |

---

## Development Workflow

### Phase 1: From Backlog to Implementation
Expand Down Expand Up @@ -104,15 +142,16 @@ When prompted, provide:
**What happens:**

1. **Backlog Normalization** — Parses and validates the backlog item
2. **Create OpenSpec Change** — Runs `openspec new change "<id>"`
3. **Create Feature Branch** — Creates `feat/<change-id>` branch and pushes to origin ⭐
4. **Write Proposal** — Documents problem, goal, scope
5. **Write Design** — Architecture decisions, runtime surface, entrypoint
6. **Write Specs** — Testable requirements with scenarios
7. **Build Tasks** — Atomic implementation tasks with verification matrix
2. **Git Safety Gate** — Enforces clean tree + branch safety before change creation
3. **Create OpenSpec Change** — Runs `openspec new change "<id>"`
4. **Create Feature Branch** — Creates `feat/<change-id>` branch and pushes to origin ⭐
5. **Write Proposal** — Documents problem, goal, scope
6. **Write Design** — Architecture decisions, runtime surface, entrypoint
7. **Write Specs** — Testable requirements with scenarios
8. **Build Tasks** — Atomic implementation tasks with verification matrix

**Output:**
- OpenSpec artifacts in `.opencode/changes/<change-id>/`
- OpenSpec artifacts in `openspec/changes/<change-id>/`
- Feature branch: `feat/<change-id>`

---
Expand All @@ -132,6 +171,18 @@ If not, switch manually:
git checkout feat/<change-id>
```

If working tree is dirty at this point:

```bash
# Option A: keep changes
git add -A && git commit -m "wip: save local changes"

# Option B: intentionally discard
git reset --hard
```

Do **not** use `git stash` in this workflow.

---

### Step 3: Implement with `/opsx-apply`
Expand Down Expand Up @@ -162,8 +213,8 @@ git commit -m "feat: implement <change-id>

- Proposal: docs/...
- Design: docs/...
- Specs: .opencode/changes/<change-id>/specs/
- Tasks: .opencode/changes/<change-id>/tasks.md
- Specs: openspec/changes/<change-id>/specs/
- Tasks: openspec/changes/<change-id>/tasks.md
- Code: src/...
- Tests: test/..."
```
Expand Down Expand Up @@ -234,15 +285,26 @@ When you're ready to publish a new version:

The skill will guide you through:

1. **Local Preparation** — Run `npm run release:check` in Docker
2. **Claim-to-Evidence Gate** — Verify every changelog claim has evidence
3. **Operability Gate** — Verify user-facing features have runtime entrypoints
4. **Version & Changelog** — Update `package.json` and `CHANGELOG.md`
5. **Release Branch** — Create `release/vX.Y.Z` branch
6. **PR to Main** — Create PR with pre-merge checks
7. **Branch Cleanup Verification** — Ensure remote `release/vX.Y.Z` branch is deleted/pruned
8. **Tag and Trigger CI** — Push tag to trigger npm publish
9. **Post-Release Verification** — Confirm npm + GitHub Release
1. **Git Safety Gate** — Require clean tree + start from `main`
2. **Local Preparation** — Run `npm run release:check` in Docker
3. **Claim-to-Evidence Gate** — Verify every changelog claim has evidence
4. **Operability Gate** — Verify user-facing features have runtime entrypoints
5. **Version & Changelog** — Update `package.json` and `CHANGELOG.md`
6. **Release Branch** — Create `release/vX.Y.Z` branch
7. **PR to Main** — Create PR with pre-merge checks
8. **Branch Cleanup Verification** — Ensure remote `release/vX.Y.Z` branch is deleted/pruned
9. **Tag and Trigger CI** — Push tag to trigger npm publish
10. **Post-Release Verification** — Confirm npm + GitHub Release

Before release branch creation, verify no intended feature branch is left unmerged:

```bash
git fetch origin --prune
git checkout main && git pull origin main
git branch -r --no-merged origin/main
```

If output still includes intended `origin/feat/*`, merge those features first.

### Important: Squash merge topology is expected

Expand Down Expand Up @@ -298,6 +360,9 @@ git branch

# Check status
git status --short

# Check unmerged branches before release
git branch -r --no-merged origin/main
```

### Branch Naming Convention
Expand Down Expand Up @@ -354,7 +419,7 @@ If you're unsure, ask: "Does this need a specification document?" If no → use
| Purpose | Location |
|---------|----------|
| Backlog | `docs/backlog.md` |
| OpenSpec changes | `.opencode/changes/<change-id>/` |
| OpenSpec changes | `openspec/changes/<change-id>/` |
| Release notes | `CHANGELOG.md` |
| Package config | `package.json` |

Expand All @@ -368,7 +433,7 @@ Either:
1. Commit changes: `git add . && git commit`
2. Or discard local changes intentionally: `git reset --hard`

For release flow specifically, do **not** use `git stash` as a transport mechanism before rebase.
For all workflows, do **not** use `git stash` as a transport mechanism.

### "Branch protection prevents push"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-03-29
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## Context

This design addresses BL-013: `/why-this-memory` 解釋能力 - enabling users to understand why a memory was recalled and what factors contributed to its ranking.

The memory system already has rich metadata (citation, recency, importance, scope) but this information is not exposed to users. This feature will surface those factors in an understandable way.

## Goals / Non-Goals

**Goals:**
- Expose recall factors: relevance score, recency, citation status, importance, scope match
- Provide on-demand explanation via `memory_why` tool
- Support explanation of last recall operation
- Integrate explanation into auto-injected context

**Non-Goals:**
- Real-time recalculation of scores (explanation is derived from stored metadata)
- Natural language generation beyond template-based explanations
- Cross-session recall history (per-session explanation only)

## Decisions

| Decision | Choice | Why | Trade-off |
|---|---|---|---|
| Runtime surface | opencode-tool | User-facing feature requiring explicit invocation | Must ensure tool is discoverable |
| Entrypoint | src/index.ts -> tools: `memory_why`, `memory_explain_recall` | Direct user tools for explanation requests | Additional tool registration overhead |
| Data model | Derive from existing metadata (no new schema) | Leverages existing BL-023 citation, BL-025 recency | Limited to existing metadata fields |
| Explanation format | Template-based with score breakdown | Deterministic, no LLM dependency | Less natural than LLM-generated |
| Explanation scope | Per-memory and per-recall-session | Covers both explicit query and auto-inject | Need to track recall session |

## Operability

### Trigger Path

1. **User-triggered**: User invokes `memory_why id="<memory-id>"`
2. **Auto-inject**: System adds explanation snippet to injected memories

### Expected Visible Output

```
Memory: "Use React useState hook for counter"
Explanation:
- Relevance: 92% (high semantic match to query)
- Recency: 3 days ago (within 72h half-life)
- Citation: verified (from explicit-remember)
- Importance: 0.8 (user-tagged high value)
- Scope: matches current project
```

### Misconfiguration/Failure Behavior

- Memory ID not found: Return "Memory not found" error
- No recall session available: Return "No recent recall to explain"
- Missing metadata fields: Show "N/A" for missing factors

## Observability

- Log explanation requests for feature usage tracking
- Track explanation satisfaction via optional feedback
- Monitor explanation generation latency
Loading