diff --git a/.gitignore b/.gitignore index 418d5d8..9086910 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,10 @@ npm-debug.log* .env *.tgz -.opencode/ +.opencode/* !.opencode/config.json +!.opencode/skills/ +!.opencode/skills/** # Agent guidelines (local development instructions for AI agents) AGENT.md diff --git a/.opencode/config.json b/.opencode/config.json new file mode 100644 index 0000000..dd3bf91 --- /dev/null +++ b/.opencode/config.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [ + "file:///workspace/dist/index.js" + ] +} diff --git a/.opencode/skills/backlog-to-openspec/SKILL.md b/.opencode/skills/backlog-to-openspec/SKILL.md new file mode 100644 index 0000000..43f6cac --- /dev/null +++ b/.opencode/skills/backlog-to-openspec/SKILL.md @@ -0,0 +1,238 @@ +--- +name: backlog-to-openspec +description: Convert backlog items into implementation-ready OpenSpec changes with explicit runtime surface, acceptance criteria, and E2E verification requirements. +license: MIT +compatibility: Requires openspec CLI. +metadata: + author: tryweb + version: "1.0" + generatedBy: "manual" +--- + +# Backlog to OpenSpec — Implementable Spec Pipeline + +Use this skill when backlog items are still high-level and you need a spec that engineers can implement and verify without ambiguity. + +This skill prevents "spec says done, runtime not operable" drift. + +--- + +## Input + +Expected input contains one or more backlog items, for example: +- `BL-014 Task episode capture` +- a markdown table row from `docs/backlog.md` +- a short intent statement (feature/problem/outcome) + +If backlog IDs are missing, derive a temporary change name and explicitly note assumptions. + +--- + +## Output Contract + +Produce an OpenSpec change with artifacts: +- `proposal.md` (problem/goal/scope) +- `design.md` (architecture and integration decisions) +- `specs/*/spec.md` (testable requirements + scenarios) +- `tasks.md` (atomic implementation and verification tasks) + +And enforce these sections in artifacts: + +1. **Runtime Surface**: `internal-api | opencode-tool | hook-driven` +2. **Entrypoint**: exact code path (`hooks.tool.`, `event:`, etc.) +3. **Operability**: how user/system can actually trigger/observe behavior +4. **Verification Matrix**: unit / integration / e2e mapping per requirement +5. **Changelog Wording Class**: `internal-only` or `user-facing` + +--- + +## Phase 1 — Backlog Normalization + +1. Locate source backlog context. + +```bash +rg "BL-0|BL-1|BL-2|BL-3" docs/backlog.md +``` + +2. Convert each backlog item into a normalized card: + +```text +- ID: +- Title: +- User/Operator outcome: +- Scope boundaries (in/out): +- Risk level: +``` + +3. Group items into one coherent change only if they share one goal. + If they are independent, split into separate changes. + +--- + +## Phase 2 — Create OpenSpec Change Scaffold + +```bash +openspec new change "" +openspec status --change "" --json +``` + +If a related archived change already exists, reuse patterns but do not copy stale assumptions. + +--- + +## Phase 3 — Write Proposal (What/Why) + +In `proposal.md`, include: + +- Problem statement linked to backlog IDs +- Why now (risk/cost of not doing) +- Scope and non-goals +- Impacted modules +- Release impact type (`internal-only` vs `user-facing`) + +**Hard rule**: if proposal claims user-facing capability, it must later map to an explicit runtime entrypoint and e2e scenario. + +--- + +## Phase 4 — Write Design (How) + +In `design.md`, include mandatory decision table: + +| Decision | Choice | Why | Trade-off | +|---|---|---|---| +| Runtime surface | internal-api / opencode-tool / hook-driven | ... | ... | +| Entrypoint | exact file + symbol/hook | ... | ... | +| Data model | table/record changes | ... | ... | +| Failure handling | retry/stop/escalate | ... | ... | +| Observability | logs/events/metrics | ... | ... | + +Also add **Operability section**: +- Trigger path (how behavior is activated) +- Expected visible output +- Misconfiguration/failure behavior + +--- + +## Phase 5 — Write Specs (Verifiable Requirements) + +For each requirement in `specs/*/spec.md`, enforce: + +1. Requirement sentence (`The system SHALL ...`) +2. Runtime Surface + Entrypoint note +3. Positive scenario(s) +4. Negative/error scenario(s) +5. Observability scenario (what can be inspected) + +Example requirement extension pattern: + +```text +### Requirement: Similar task recall is operable via runtime surface +The system SHALL recall similar tasks before execution. + +Runtime Surface: hook-driven +Entrypoint: src/index.ts -> event hook "session.idle" + +#### Scenario: Recall injected on threshold match +- WHEN ... +- THEN ... + +#### Scenario: No recall when below threshold +- WHEN ... +- THEN ... +``` + +--- + +## Phase 6 — Build Tasks with Verification Matrix + +In `tasks.md`, tasks must be atomic and include verification hooks: + +```text +- [ ] Implement runtime wiring in src/index.ts (hook/tool registration) +- [ ] Implement core logic in src/store.ts +- [ ] Add unit tests for edge conditions +- [ ] Add integration test for runtime entrypoint +- [ ] Add e2e test for user-facing flow (if user-facing) +- [ ] Update changelog wording class (internal-only/user-facing) +``` + +Mandatory matrix (add to tasks.md or design.md): + +| Requirement | Unit | Integration | E2E | Required to release | +|---|---|---|---|---| +| R1 | ✅ | ✅ | n/a | yes | +| R2 (user-facing) | ✅ | ✅ | ✅ | yes | + +--- + +## Phase 7 — Pre-Implementation Gate + +Before implementation starts, verify the change is apply-ready: + +```bash +openspec status --change "" +``` + +Checklist: +- No ambiguous requirement wording +- Every user-facing claim has runtime entrypoint + e2e requirement +- Every internal-only claim is explicitly marked internal +- tasks include both implementation and verification + +If any item is missing, revise artifacts before coding. + +--- + +## Changelog Policy (Built-in) + +When drafting release notes from this change: + +- `internal-only`: wording must explicitly say internal/foundation/not exposed as tool +- `user-facing`: wording allowed only after integration/e2e evidence passes + +Never publish changelog bullets that cannot be executed by users/operators. + +--- + +## Guardrails + +- Do not mark a backlog item done based only on store/API implementation. +- Do not allow "SHALL support" without surface/entrypoint/verification details. +- Do not collapse independent backlog goals into one oversized change. +- Do not skip negative scenarios for failure behavior. +- Do not produce user-facing claims without e2e tests. + +--- + +## Quick Reference Commands + +```bash +# 1) inspect backlog +rg "BL-" docs/backlog.md + +# 2) create change +openspec new change "" + +# 3) inspect artifact state +openspec status --change "" --json + +# 4) inspect artifact instructions +openspec instructions proposal --change "" --json +openspec instructions design --change "" --json +openspec instructions tasks --change "" --json + +# 5) final readiness check +openspec status --change "" +``` + +--- + +## Done Criteria + +This skill is complete for a backlog item only when: + +1. OpenSpec artifacts exist and are coherent +2. Runtime surface and entrypoint are explicit +3. Verification matrix includes required unit/integration/e2e +4. Changelog wording class is defined (`internal-only` / `user-facing`) +5. Change is ready for `/opsx-apply` implementation diff --git a/.opencode/skills/release-workflow/SKILL.md b/.opencode/skills/release-workflow/SKILL.md index ad28178..1c7c37c 100644 --- a/.opencode/skills/release-workflow/SKILL.md +++ b/.opencode/skills/release-workflow/SKILL.md @@ -1,10 +1,11 @@ --- name: release-workflow -description: Standard release procedure for lancedb-opencode-pro. Use when publishing a new npm version. Covers version bump, local verification, branch/PR flow, tagging, CI gate, and npm publish confirmation. +description: Hardened release workflow for lancedb-opencode-pro. Use when publishing a new npm version and when you must prevent claim/code/spec drift. license: MIT +compatibility: Requires git, gh, docker compose, and npm CLI. metadata: author: tryweb - version: "1.0" + version: "2.0" generatedBy: "manual" --- @@ -12,15 +13,28 @@ metadata: Use this skill when the user wants to publish a new version to npm. +This version adds mandatory anti-drift gates so we do not repeat: +- changelog claim without shipped code +- implemented store APIs without runtime operability +- spec requirement without test evidence + --- ## Pre-Conditions (Check Before Starting) - All intended feature changes are merged to `main` -- `npm whoami` returns the publishing account (run on host, not in Docker) +- 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 +```bash +git status --short +npm whoami +``` + +If working tree is dirty: stop and clean up before release. + --- ## Phase 1 — Local Preparation (Host) @@ -28,27 +42,73 @@ Use this skill when the user wants to publish a new version to npm. **Goal**: Confirm the current codebase builds and passes all tests before touching version numbers. ```bash -# Run the full release gate inside Docker docker compose build --no-cache && docker compose up -d -docker compose exec app npm run verify:full +docker compose exec opencode-dev npm run release:check ``` Gate passes when: - typecheck exits 0 - build exits 0 -- foundation 10/10, regression 18/18, retrieval 2/2 +- effectiveness/retrieval/benchmark all pass - benchmark latency within thresholds - `npm pack` produces a `.tgz` with no errors +- `npm publish --dry-run` succeeds If the gate fails, **stop and fix root causes** before proceeding. Never bump the version on a failing codebase. --- -## Phase 2 — Version & Changelog +## Phase 2 — Claim-to-Evidence Gate (CRITICAL) + +**Goal**: every changelog claim must map to shipped evidence. + +For each planned changelog bullet, prepare evidence triplet: +1. Spec reference (requirement/scenario path) +2. Code reference (commit + file path) +3. Verification reference (unit/integration/e2e) + +Use this checklist format while drafting release note bullets: + +```text +[ ] Claim text + - Spec: openspec/changes/.../specs/.../spec.md#Requirement: ... + - Code: + - Tests: + - Surface: internal-api | opencode-tool | hook-driven +``` + +**Hard rule**: if a claim is user-facing (tool/hook behavior), it MUST include integration/e2e evidence. + +--- + +## Phase 3 — Operability Gate (CRITICAL) + +**Goal**: prevent "implemented but not usable" releases. + +If a claim says user can use a feature: +- verify runtime entrypoint exists (`hooks.tool` or explicit event hook path) +- verify this entrypoint is exercised by tests + +Suggested checks: + +```bash +# list exposed tools (example pattern) +rg "^[[:space:]]*[a-z0-9_]+:\s*tool\(" src/index.ts + +# ensure claimed symbol is reachable from runtime wiring +rg "" src/index.ts src/**/*.ts test/**/*.ts +``` + +If feature is internal-only, changelog wording must explicitly say "internal API/foundation; not exposed as tool". + +--- + +## Phase 4 — Version & Changelog ```bash -# On main, bump version in package.json -# Edit CHANGELOG.md — add a new ## [X.Y.Z] section at the top +# After gates pass, update version and changelog +# package.json version +# CHANGELOG.md: only claims with evidence ``` Commit message format: @@ -58,7 +118,7 @@ chore: bump version to X.Y.Z and update changelog --- -## Phase 3 — Release Branch +## Phase 5 — Release Branch ```bash git checkout -b release/vX.Y.Z @@ -67,7 +127,7 @@ git push origin release/vX.Y.Z --- -## Phase 4 — PR to Main +## Phase 6 — PR to Main ### PRE-MERGE CHECK (CRITICAL) @@ -83,6 +143,17 @@ git diff main..release/vX.Y.Z --stat - Your code changes are NOT committed - Stop and commit your changes before proceeding +### CLAIM DRIFT CHECK (CRITICAL) + +Before merge, re-check release note bullets against branch content: + +```bash +# check that each referenced file/area actually changed +git diff main..release/vX.Y.Z -- CHANGELOG.md src/ test/ openspec/ +``` + +If changelog mentions a capability without matching code/tests in the PR, fix changelog or add missing implementation before merge. + ### Merge Steps ```bash @@ -113,15 +184,20 @@ git checkout main && git pull origin main --- -## Phase 5 — Tag and Trigger CI Release +## Phase 7 — Tag and Trigger CI Release + +**Tag timing rule (CRITICAL):** +- Never tag from a commit that only bumps version/changelog while feature commit is still ahead/behind. +- Tag must point to the already-merged commit that includes real implementation + tests. ### VERIFY CODE IS COMMITTED (CRITICAL) Before tagging, confirm all changes are committed: ```bash -# Check that tag will include all intended changes +# Check that tag delta contains expected implementation and tests git log vX.Y.Z-1..HEAD --oneline +git diff --name-only vX.Y.Z-1..HEAD # If this shows unexpected commits or is empty, STOP # Your release is missing code! @@ -151,7 +227,7 @@ gh run list --workflow=ci.yml --limit=5 --- -## Phase 6 — Post-Release Verification +## Phase 8 — Post-Release Verification ```bash # Confirm npm version is live @@ -165,7 +241,7 @@ Both must succeed before declaring the release complete. --- -## Phase 6.5 — Release Correctness Verification (CRITICAL) +## Phase 8.5 — Release Correctness Verification (CRITICAL) After tagging, verify the release contains all intended changes: @@ -174,7 +250,7 @@ After tagging, verify the release contains all intended changes: git log vX.Y.Z-1..vX.Y.Z --oneline # Check file changes are included -git diff vX.Y.Z-1..vX.Y.Z --stat | head -20 +git diff vX.Y.Z-1..vX.Y.Z --stat ``` **Expected output**: Should show your src/, test/, openspec/ changes @@ -246,7 +322,7 @@ Some build artifacts were created by root inside Docker: ```bash docker compose up -d -docker compose exec -T -u root app sh -lc \ +docker compose exec -T -u root opencode-dev sh -lc \ 'chown -R 1000:1000 /workspace/dist /workspace/dist-test 2>/dev/null || true' npm publish ``` @@ -284,28 +360,44 @@ EOF ```bash # Phase 1 — local gate docker compose build --no-cache && docker compose up -d -docker compose exec app npm run verify:full +docker compose exec opencode-dev npm run release:check -# Phase 2 — version bump +# Phase 2-3 — evidence and operability checks +rg "^[[:space:]]*[a-z0-9_]+:\s*tool\(" src/index.ts +git diff --name-only main..HEAD + +# Phase 4 — version bump # Edit package.json + CHANGELOG.md, then: git add package.json CHANGELOG.md git commit -m "chore: bump version to X.Y.Z and update changelog" -# Phase 3 — release branch +# Phase 5 — release branch git checkout -b release/vX.Y.Z git push origin release/vX.Y.Z -# Phase 4 — PR + merge +# Phase 6 — PR + merge gh pr create --title "chore: release vX.Y.Z" --base main --head release/vX.Y.Z gh pr merge --squash --delete-branch git checkout main && git pull origin main -# Phase 5 — tag +# Phase 7 — tag git tag vX.Y.Z HEAD git push origin vX.Y.Z gh run list --workflow=ci.yml --limit=3 -# Phase 6 — verify +# Phase 8 — verify npm view lancedb-opencode-pro version gh release view vX.Y.Z --repo tryweb/lancedb-opencode-pro ``` + +--- + +## Release Definition of Done (DoD) + +Release can be declared complete only if all are true: + +1. `docker compose exec opencode-dev npm run release:check` passed +2. Every changelog bullet has spec/code/test evidence +3. Any user-facing bullet has runtime entrypoint proof (`hooks.tool`/hook path) +4. Tag points to merged implementation commit, not version-only commit +5. Post-release verification confirms npm + GitHub Release