opencode-codeops 2.0.4 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,8 +2,77 @@
2
2
 
3
3
  All notable changes to CodeOps are recorded here.
4
4
 
5
+ ## 2.1.1 — 2026-10-09
6
+
7
+ ### Fixes
8
+
9
+ - plugin: stop deleting the shared scratch directory on unload
10
+
11
+ ### Tests
12
+
13
+ - plugin: pin the scratch-directory lifecycle contract (red phase)
14
+
15
+ ### Documentation
16
+
17
+ - changelog: add the 2.1.0 usage notes and complete the feature
18
+
19
+ ## 2.1.0 — 2026-10-09
20
+
21
+ ### Usage
22
+
23
+ - Run the `analyze-agents` skill on demand for a project-level specialist check; it records
24
+ `codeops/specialist-check.json`, and `analyze-project` reports the coverage line.
25
+ - `exec-plan` records each ruling batch in `plans/<plan>/05-findings.md`, which feeds finding-area
26
+ recurrence in the check.
27
+
28
+ ### Documentation
29
+
30
+ - readme: list the analyze-agents skill and the on-demand detection flow
31
+ - exec-plan: record ruling batches in the per-plan findings ledger
32
+ - skills: complete T-07 with the coverage-line smoke and render clarifications
33
+ - skills: surface specialist checks and split proposals from the creation gate
34
+ - plans: resolve the analyze-agents preflight findings and pass the plan
35
+ - plans: add the analyze-agents feature plan set (gate passed)
36
+ - changelog: add the 2.0.4 upgrade notes and record the release
37
+
38
+ ### Chores
39
+
40
+ - plan: record the 3.1.1 live smoke
41
+ - plan: record 2.1.3 full verification
42
+ - plan: record 1.1.3 full verification
43
+ - plan: use plain-bullet deliverables so progress counts only tasks
44
+ - plan: record T-07.3 full verification
45
+ - plan: complete T-06 - v2.0.4 verified and issue #2 closed
46
+
47
+ ### Fixes
48
+
49
+ - skills: harden the ledger assertions per the phase-2 review
50
+ - skills: anchor the phase-1 review assertions and clarify the fallback wording
51
+ - tests: drop the borrowed ST id from the T-07 content suite
52
+ - skills: resolve the T-07 review findings
53
+
54
+ ### Tests
55
+
56
+ - skills: extend the analyze-agents content tests with the ledger wiring (red phase)
57
+ - skills: add analyze-agents content spec tests (red phase)
58
+ - skills: add specialist awareness content tests (red phase)
59
+
60
+ ### Features
61
+
62
+ - skills: add the analyze-agents check skill and protocol wiring
63
+
5
64
  ## 2.0.4 — 2026-10-09
6
65
 
66
+ ### Upgrade Notes
67
+
68
+ - Existing installs upgrade in place: run `npx opencode-codeops update` (package-scope installs) or
69
+ re-run `install_agents.py --roles` / `--custom` (project-generated agents); `--check` reports
70
+ `STALE` until the files are regenerated.
71
+ - Generated agent files now open with `---`, so OpenCode parses `mode`, `hidden`, `permissions`,
72
+ descriptions, and model pins. Catalog roles are hidden subagents instead of selectable primary
73
+ agents. `temperature`/`reasoningEffort` values remain preserved but are not yet sent by the
74
+ OpenCode V2 runner.
75
+
7
76
  ### Chores
8
77
 
9
78
  - plan: sync the T-06 progress header (6/8 tasks)
package/README.md CHANGED
@@ -16,6 +16,7 @@ Turn an idea or existing system into ambiguity-free requirements, grounded speci
16
16
  | `exec-plan` | Execute a plan — implement → verify → commit loop with quality reviews |
17
17
  | `roadmap` | Live feature-set roadmap — make, update, review, archive |
18
18
  | `analyze-project` | Analyze repo and create/refresh CodeOps-aware `AGENTS.md` guidance |
19
+ | `analyze-agents` | Run the project-level specialist check on demand — proposals or a recorded None, with check state |
19
20
  | `setup-codeops` | Set up or migrate CodeOps in a git repo |
20
21
  | `setup-routing` | Configure per-role subagent model and policy routing |
21
22
  | `upgrade-plan` | Upgrade legacy CodeOps artifacts to current schema |
@@ -144,11 +145,11 @@ The plugin also warns (non-blocking) if any tool attempts to edit `codeops/.code
144
145
 
145
146
  Every session also gets a workspace-hygiene guard: the plugin exports `CODEOPS_TMPDIR`, a scratch
146
147
  directory under the OS temp directory that belongs to the running OpenCode plugin instance. Skills
147
- and agents put temporary files there and delete them when the run completes; the plugin removes the
148
- directory when it unloads and sweeps directories abandoned by interrupted runs at startup, so
149
- CodeOps does not accumulate scratch data. Because OpenCode 2 does not expose a session id to shell
150
- hooks, concurrent sessions served by one instance share this directory. The full protocol is in
151
- `_shared/workspace-hygiene.md`.
148
+ and agents put temporary files there and delete them when the run completes; the plugin sweeps
149
+ directories abandoned by interrupted runs at startup (older than seven days), so CodeOps does not
150
+ accumulate scratch data. Because OpenCode 2 does not expose a session id to shell hooks, concurrent
151
+ sessions served by one instance share this directory, and no session's scratch is deleted while
152
+ others may still use it. The full protocol is in `_shared/workspace-hygiene.md`.
152
153
 
153
154
  ## Agent model configuration
154
155
 
@@ -191,8 +192,10 @@ capability gap the twelve catalog roles and dynamic packets cannot close. Specia
191
192
  only with your explicit approval — the `--auto-design` mode cannot approve them.
192
193
 
193
194
  - **Detect** — `make-requirements`, `make-plan`, and `analyze-project` run an evidence-based check
194
- and record the outcome (including a negative one). At most two candidates are proposed per
195
- requirements set or plan.
195
+ and record the outcome (including a negative one); the `analyze-agents` skill runs the same
196
+ check on demand and maintains `codeops/specialist-check.json` for the coverage line. At most two
197
+ candidates per scope surface as lightweight, evidence-backed proposals; the creation gate
198
+ applies when you choose to proceed.
196
199
  - **Create** — after you approve the candidate packet, `setup-routing` writes a brief at
197
200
  `codeops/specialists/<role>.md`, writes routing policy first, generates a visible agent with
198
201
  `install_agents.py --custom <role>`, and updates a managed index block in `AGENTS.md` with
@@ -64,6 +64,52 @@ escalation)` entry.
64
64
  - Rejection and deferral are valid outcomes. A rejected candidate may not reappear in the same
65
65
  scope without new evidence.
66
66
 
67
+ ## Proposals and the creation gate
68
+
69
+ A **lightweight proposal** is a short, evidence-backed suggestion — role slug, kind, one-line
70
+ capability, evidence (`file:line`), the smallest alternative and why it is insufficient — surfaced
71
+ in the normal findings/plan flow. Proposals need no gate: they are suggestions, not machinery.
72
+
73
+ The Complexity Escalation Gate, the independent challenger verdict, and the reserved-authority
74
+ decision apply only when the user chooses to proceed to creation. Approved roles are then created
75
+ through `setup-routing` as described below; the lightweight proposal format is what `analyze-agents`
76
+ and every detection step emit for at most two candidates per scope.
77
+
78
+ ## Check state
79
+
80
+ Running the check records one small project file:
81
+
82
+ ```json
83
+ {
84
+ "checkedAt": "<ISO-8601 timestamp>",
85
+ "plans": ["<plan folder>", "<plan folder>"]
86
+ }
87
+ ```
88
+
89
+ - Path: `codeops/specialist-check.json` (project-level in both layouts).
90
+ - Written at the end of every check run — including `None` outcomes — by the execution surface
91
+ (`analyze-agents`); the `plans` list is layout-aware.
92
+ - Absent, unreadable, or malformed state means **never checked** for consumers; the
93
+ `analyze-project` coverage line then recommends a run. Fail loud, never silent.
94
+
95
+ ## Findings ledger
96
+
97
+ `exec-plan` records each ruling batch in the plan's findings ledger — one compact row per batch,
98
+ identifiers and area tokens only:
99
+
100
+ - Location: `plans/<plan>/05-findings.md` (flat) or
101
+ `codeops/features/<f>/plans/<plan>/05-findings.md` (nested), per
102
+ [`layout-convention.md`](layout-convention.md).
103
+ - Format:
104
+
105
+ | Finding | Phase | Severity | Area | Ruling |
106
+ | ------- | ----- | -------- | ---- | ------ |
107
+ | RV-001 | 2 | MAJOR | scripts/install_agents.py | fixed |
108
+
109
+ - Writer: `exec-plan`'s ruling step appends the batch's rows after each ruling batch; runtime
110
+ complexity decisions stay in the ambiguity register.
111
+ - The `analyze-agents` check reads these rows for finding-area recurrence.
112
+
67
113
  ## Routing layers
68
114
 
69
115
  | Layer | Owner | Content | Consumer |
@@ -76,15 +122,21 @@ escalation)` entry.
76
122
 
77
123
  ## Detection integration
78
124
 
125
+ The `analyze-agents` skill is the execution surface for the criteria in every flow below; each
126
+ step keeps an instruction referencing these criteria so the flow still works when the skill is
127
+ unavailable.
128
+
79
129
  ### make-requirements
80
130
 
81
131
  1. After domain-lens selection and scope confirmation, run the detection criteria.
82
- 2. For each candidate, open an ambiguity-register entry (`Technical (complexity escalation)`) with
83
- the candidate packet, run the challenger, and obtain the user's decision.
132
+ 2. Surface at most two candidates in one batch as lightweight proposals (§Proposals and the
133
+ creation gate). When the user chooses to proceed to creation, open an ambiguity-register entry
134
+ (`Technical (complexity escalation)`) with the candidate packet, run the challenger, and obtain
135
+ the user's decision.
84
136
  3. Approved candidates are created through `setup-routing` or noted for creation before the first
85
137
  implementing plan; rejected candidates are recorded and dropped.
86
- 4. Record the check in the final summary. No new requirements-template section is created; the
87
- brief and the register are the durable records.
138
+ 4. Record the check in the final summary as a `Specialist check:` line. No new requirements-template
139
+ section is created; the brief and the register are the durable records.
88
140
 
89
141
  ### make-plan
90
142
 
@@ -111,16 +163,18 @@ escalation)` entry.
111
163
  standing specialist would close.
112
164
  ```
113
165
 
114
- 3. Candidate approval, challenger, and persistence follow the shared gate exactly. Approved roles
115
- are created through `setup-routing` before execution begins; the plan remains valid without them
116
- via dynamic-packet fallback.
166
+ 3. Candidates surface as lightweight proposals (§Proposals and the creation gate); when the user
167
+ chooses to proceed to creation, the Complexity Escalation Gate, the challenger, and persistence
168
+ apply exactly as defined there. Approved roles are created through `setup-routing` before
169
+ execution begins; the plan remains valid without them via dynamic-packet fallback.
117
170
 
118
171
  ### analyze-project
119
172
 
120
173
  1. While inspecting manifests and conventions, note specialization signals (specialized
121
174
  framework/DSL, domain invariants, conventions a generic agent would miss).
122
- 2. When a signal is strong and no specialist exists, report the candidate with evidence and
123
- recommend running `setup-routing`; never write agent files or candidate artifacts, and keep
175
+ 2. When a signal is strong and no specialist exists, surface the candidate as a lightweight
176
+ proposal (§Proposals and the creation gate) with evidence, and recommend running `setup-routing`
177
+ when the user chooses to proceed; never write agent files or candidate artifacts, and keep
124
178
  `AGENTS.md` compact.
125
179
  3. Preserve the `<!-- CODEOPS-SPECIALISTS:START -->` / `<!-- CODEOPS-SPECIALISTS:END -->` block
126
180
  byte-for-byte when refreshing managed guidance.
@@ -51,7 +51,9 @@ keep scratch file names specific to the run to avoid collisions.
51
51
 
52
52
  ## Automatic safety net
53
53
 
54
- The CodeOps plugin exports `$CODEOPS_TMPDIR` for each runtime and removes that runtime's
55
- directory when the plugin unloads. At startup it also removes CodeOps temp directories older
56
- than seven days, so an interrupted run cannot leak storage forever. The safety net is a
57
- fallback, not a substitute: the run itself still performs the cleanup pass above.
54
+ The CodeOps plugin exports `$CODEOPS_TMPDIR` for each runtime. At startup it removes CodeOps
55
+ temp directories older than seven days, so an interrupted run cannot leak storage forever.
56
+ The plugin never deletes a runtime's directory while sessions may still be running — several
57
+ sessions can share one directory, so reclamation happens only through the age-based sweep.
58
+ The safety net is a fallback, not a substitute: the run itself still performs the cleanup
59
+ pass above.
@@ -33,6 +33,3 @@ export interface CleanStaleTmpDirsOptions {
33
33
 
34
34
  /** Remove session directories abandoned by interrupted or crashed runs. */
35
35
  export declare function cleanStaleTmpDirs(options?: CleanStaleTmpDirsOptions): string[]
36
-
37
- /** Remove exactly one session's temp directory. */
38
- export declare function removeSessionTmpDir(sessionID?: string, base?: string): boolean
@@ -9,8 +9,7 @@
9
9
  * - it computes the per-session directory the plugin exports as
10
10
  * `$CODEOPS_TMPDIR`, under a CodeOps-owned root inside the OS temp directory;
11
11
  * - it sweeps directories abandoned by interrupted runs once they are older
12
- * than a safety cap; and
13
- * - it removes exactly one session's directory when that session is deleted.
12
+ * than a safety cap.
14
13
  *
15
14
  * Safety is the whole point: every path derives from a sanitized session
16
15
  * identifier, the sweep walks only the CodeOps-owned root, symlinked entries
@@ -22,7 +21,7 @@
22
21
 
23
22
  import { lstatSync, mkdirSync, readdirSync, rmSync } from "node:fs"
24
23
  import { tmpdir } from "node:os"
25
- import { join, resolve, sep } from "node:path"
24
+ import { join, resolve } from "node:path"
26
25
 
27
26
  /**
28
27
  * Age after which a session directory is treated as abandoned.
@@ -147,34 +146,3 @@ export function cleanStaleTmpDirs({
147
146
 
148
147
  return removed
149
148
  }
150
-
151
- /**
152
- * Remove exactly one session's temp directory.
153
- *
154
- * Used when a session is deleted: its scratch can no longer be needed. The
155
- * removal refuses anything that is not a regular directory strictly inside
156
- * the CodeOps temp root, so a symlink or an unexpected path is left alone.
157
- *
158
- * @param sessionID - Session identifier whose directory should be removed
159
- * @param base - Base temp directory (injectable for tests)
160
- * @returns True when the directory was removed
161
- */
162
- export function removeSessionTmpDir(sessionID, base = tmpdir()) {
163
- const root = resolve(codeopsTmpRoot(base))
164
- const dir = sessionTmpDir(sessionID, base)
165
-
166
- if (!resolve(dir).startsWith(root + sep)) return false
167
-
168
- try {
169
- if (!lstatSync(dir).isDirectory()) return false
170
- } catch {
171
- return false
172
- }
173
-
174
- try {
175
- rmSync(dir, { recursive: true, force: true })
176
- return true
177
- } catch {
178
- return false
179
- }
180
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-codeops",
3
- "version": "2.0.4",
3
+ "version": "2.1.1",
4
4
  "description": "Specification-first engineering for complex systems — CodeOps plugin for OpenCode",
5
5
  "type": "module",
6
6
  "engines": {
package/plugin/index.ts CHANGED
@@ -8,7 +8,6 @@ import { fileURLToPath } from "node:url"
8
8
  import {
9
9
  cleanStaleTmpDirs,
10
10
  ensureSessionTmpDir,
11
- removeSessionTmpDir,
12
11
  } from "../bin/lib/tmp-hygiene.mjs"
13
12
  import {
14
13
  appendEffortTrace,
@@ -70,9 +69,9 @@ const standardsText = `${codingStandards}\n\n${outputStyle}`
70
69
  // OpenCode 2 does not expose a session identifier to shell hooks, so the plugin
71
70
  // owns one scratch directory per plugin runtime instead of one per session.
72
71
  // Skills and subagents still receive it as CODEOPS_TMPDIR and delete their own
73
- // scratch; the plugin removes the runtime directory on unload and sweeps
74
- // directories abandoned by earlier runs. Two sessions served by the same
75
- // runtime share this directory; see _shared/workspace-hygiene.md.
72
+ // scratch; the startup sweep reclaims directories abandoned by earlier runs.
73
+ // Several sessions can share one runtime directory, so the plugin must never
74
+ // delete it on unload; see _shared/workspace-hygiene.md.
76
75
  // ---------------------------------------------------------------------------
77
76
  const runtimeID = `runtime-${randomUUID()}`
78
77
 
@@ -386,16 +385,12 @@ export default Plugin.define({
386
385
  })
387
386
 
388
387
  // ---------------------------------------------------------------------
389
- // Plugin cleanup: stop listening for events and remove the runtime's
390
- // scratch directory. Both are best effort.
388
+ // Plugin cleanup: stop listening for events. The runtime's scratch
389
+ // directory is deliberately left in place — other sessions may still be
390
+ // using it — and the startup sweep reclaims abandoned directories.
391
391
  // ---------------------------------------------------------------------
392
392
  return () => {
393
393
  controller.abort()
394
- try {
395
- removeSessionTmpDir(runtimeID)
396
- } catch {
397
- // Best effort only.
398
- }
399
394
  }
400
395
  },
401
396
  })
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Specification tests for the scratch-directory lifecycle.
3
+ *
4
+ * The plugin exports one scratch directory (`$CODEOPS_TMPDIR`) per plugin
5
+ * runtime, and every session served by that runtime shares it. Deleting the
6
+ * directory when a plugin instance unloads destroys in-flight scratch files of
7
+ * sessions that are still running, so the contract is: the plugin never
8
+ * deletes the shared directory; the age-based sweep reclaims abandoned
9
+ * directories instead.
10
+ *
11
+ * This is the regression oracle for that contract: a failure here means the
12
+ * repository reintroduced early deletion, never that the test is wrong.
13
+ *
14
+ * @module temp-lifecycle.spec.test
15
+ */
16
+
17
+ import assert from "node:assert/strict"
18
+ import { readFileSync } from "node:fs"
19
+ import { dirname, join, resolve } from "node:path"
20
+ import { describe, it } from "node:test"
21
+ import { fileURLToPath } from "node:url"
22
+
23
+ const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..")
24
+
25
+ /**
26
+ * Read a repository file as UTF-8 text.
27
+ * @param {string} relativePath - Path relative to the repository root.
28
+ * @returns {string} The file contents.
29
+ */
30
+ function read(relativePath) {
31
+ return readFileSync(join(ROOT, relativePath), "utf8")
32
+ }
33
+
34
+ describe("scratch-directory lifecycle", () => {
35
+ it("keeps the plugin free of scratch-directory deletion", () => {
36
+ const plugin = read("plugin/index.ts")
37
+ assert.doesNotMatch(plugin, /removeSessionTmpDir/)
38
+ assert.match(plugin, /cleanStaleTmpDirs\(\)/)
39
+ assert.match(plugin, /controller\.abort\(\)/)
40
+ })
41
+
42
+ it("keeps the temp hygiene module free of exact-directory deletion", () => {
43
+ assert.doesNotMatch(read("bin/lib/tmp-hygiene.mjs"), /removeSessionTmpDir/)
44
+ assert.doesNotMatch(read("bin/lib/tmp-hygiene.d.mts"), /removeSessionTmpDir/)
45
+ })
46
+
47
+ it("documents the age-based sweep as the automatic cleanup", () => {
48
+ const hygiene = read("_shared/workspace-hygiene.md")
49
+ assert.doesNotMatch(hygiene, /removes that runtime's\s+directory when the plugin unloads/i)
50
+ assert.match(hygiene, /seven days/i)
51
+ const readme = read("README.md")
52
+ assert.doesNotMatch(readme, /removes the\s+directory when it unloads/i)
53
+ assert.match(readme, /sweeps\s+directories abandoned/i)
54
+ })
55
+ })
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: analyze-agents
3
+ description: Run the project-level specialist check on demand. Reads the repository's requirements, plans, findings ledgers, and manifests directly (no script), applies the specialist-agent detection criteria, presents at most two evidence-backed lightweight proposals or a None with evidence, and records the check state consumed by the analyze-project coverage line.
4
+ ---
5
+
6
+ # analyze-agents
7
+
8
+ Run this check to re-evaluate whether a project would benefit from a project-specific specialist
9
+ subagent — on request, or because `analyze-project` reported the coverage as due. This skill is the
10
+ execution surface for the detection criteria in
11
+ [`../../_shared/specialist-agents.md`](../../_shared/specialist-agents.md); it reads the
12
+ repository's own artifacts and never invokes a script.
13
+
14
+ ## Evidence
15
+
16
+ Read these sources for the current project. All paths are layout-aware per
17
+ [`../../_shared/layout-convention.md`](../../_shared/layout-convention.md): flat `plans/` or nested
18
+ `codeops/features/<f>/plans/`.
19
+
20
+ - requirements and plan documents — domain/lens tags and scope history;
21
+ - per-plan findings ledgers (`05-findings.md`) — finding-area recurrence;
22
+ - manifests (`package.json`, `pyproject.toml`, `go.mod`, and similar) — specialized framework,
23
+ DSL, codegen, or protocol signals;
24
+ - existing `codeops/specialists/` briefs and `codeops/codeops.json` routing roles —
25
+ deduplicate against installed specialists;
26
+ - `codeops/specialist-check.json` — the prior check state.
27
+
28
+ ## Detection flow
29
+
30
+ 1. Collect the evidence sources above.
31
+ 2. Apply the detection criteria and disqualifiers from the protocol document: a candidate needs
32
+ evidenced strong signal(s) and no disqualifier.
33
+ 3. Recurrence anchor: one area appearing in at least two plans or three findings ranks as a strong
34
+ signal; thresholds anchor judgment, not hard gates.
35
+ 4. Present at most two candidates in one batch as **lightweight proposals** — role slug, kind, a
36
+ one-line capability, evidence with `file:line`, and the smallest alternative with why it is
37
+ insufficient — or record `None` with evidence.
38
+ 5. Write the check state (below) on every run, including a `None` outcome.
39
+ 6. Hand-off: on user interest, hand off to the `setup-routing` flow for creation. Never create or
40
+ modify agent files, briefs, routing policy, or `AGENTS.md`.
41
+
42
+ ## Check state
43
+
44
+ Write `codeops/specialist-check.json` (project-level in both layouts; create the `codeops/`
45
+ directory lazily when it does not exist):
46
+
47
+ ```json
48
+ {
49
+ "checkedAt": "<ISO-8601 timestamp>",
50
+ "plans": ["<plan folder>", "<plan folder>"]
51
+ }
52
+ ```
53
+
54
+ The `plans` list contains the plan folders present at check time (layout-aware). Consumers treat
55
+ absent, unreadable, or malformed state as **never checked** and recommend a run — fail loud, never
56
+ silent.
57
+
58
+ ## Output
59
+
60
+ A short human summary: the candidate proposals in the lightweight format above, or `None` with
61
+ evidence, plus the state write result. The state file is the machine-readable artifact; there is no
62
+ separate JSON output mode.
63
+
64
+ ## Degradation
65
+
66
+ - Missing findings ledger: the output states that the ledger was missing and the check ran on
67
+ reduced evidence (documents and manifests only).
68
+ - Malformed ledger rows: skip the row with a note; never guess its fields.
69
+ - Empty repository (no plans or requirements): record `None` with evidence and still write the
70
+ check state.
71
+
72
+ ---
73
+
74
+ > **Workspace hygiene (non-negotiable):** put every temporary artifact this run creates in
75
+ > `$CODEOPS_TMPDIR` (fallback: the OS temp directory), never in the repository, and delete them
76
+ > all before reporting completion. Never delete user files, versioned artifacts, worktrees, or
77
+ > another session's temporary files. Full rules:
78
+ > [_shared/workspace-hygiene.md](../../_shared/workspace-hygiene.md).
@@ -24,7 +24,7 @@ description: Analyze the current repository and create or refresh concise CodeOp
24
24
  7. On a non-integration branch, preview changes to repository-wide guidance and ask before writing unless repository policy explicitly permits branch-local updates.
25
25
  8. In compact mode, remove duplication and stale generated detail from the managed section only. Flag suspected hand-authored bloat; never silently rewrite it.
26
26
  9. Validate every recorded command or mark it explicitly unverified.
27
- 10. When a specialization signal is strong and no specialist covers it, report the candidate with evidence and recommend the `setup-routing` creation flow ([../../_shared/specialist-agents.md](../../_shared/specialist-agents.md)); never write agent files here. Preserve the `<!-- CODEOPS-SPECIALISTS:START -->` / `<!-- CODEOPS-SPECIALISTS:END -->` block byte-for-byte when refreshing the managed section.
27
+ 10. Specialist coverage: read `codeops/specialist-check.json` when present and include a `Specialist coverage:` line in the managed section — `up to date (<YYYY-MM-DD>)` (from `checkedAt`) when the recorded plan set matches the current one; `check due — run analyze-agents` otherwise; when the state is absent or corrupt, render `check due — run analyze-agents (never checked)`. The `analyze-agents` skill runs the check (criteria: [../../_shared/specialist-agents.md](../../_shared/specialist-agents.md)); when a specialization signal is strong and no specialist covers it, report the candidate with evidence and recommend the `setup-routing` creation flow; never write agent files here. Preserve the `<!-- CODEOPS-SPECIALISTS:START -->` / `<!-- CODEOPS-SPECIALISTS:END -->` block byte-for-byte when refreshing the managed section.
28
28
 
29
29
  Keep `AGENTS.md` small. Operational routing belongs in `codeops/codeops.json` or `opencode.json`, not prose.
30
30
 
@@ -229,9 +229,9 @@ links to them, never restates them.
229
229
  The flow: the protocol records a phase-start ref when the phase begins; after the phase's last
230
230
  task verifies, the correctness reviewer and any active auditors are dispatched **in parallel** on
231
231
  the phase diff, their findings are merged and presented in severity-grouped batches, and each
232
- ruling is recorded in the durable finding artifact. Specialist roles listed in the plan's
233
- `## Specialist Agents` table dispatch per `_shared/quality-profile.md`; an unavailable specialist
234
- falls back to a generic packet and the fallback is reported.
232
+ ruling is recorded in the plan's findings ledger (`05-findings.md`). Specialist roles listed in
233
+ the plan's `## Specialist Agents` table dispatch per `_shared/quality-profile.md`; an unavailable
234
+ specialist falls back to a generic packet and the fallback is reported.
235
235
 
236
236
  > **🚨 Finding gate (load-bearing).** In normal mode, 🔴 CRITICAL and 🟠 MAJOR findings PAUSE
237
237
  > execution for the user's ruling in ALL commit modes. With active auto-design, select and record
@@ -199,9 +199,17 @@ whole-task diff. Activation rules, packets, supersession, and caps are defined i
199
199
  `[!]`, preserve the diff without marking it verified, and switch to the full standalone-plan
200
200
  path. The new `00-ambiguity-register.md` owns the packet and decision. Resume only after that
201
201
  plan's gates pass.
202
- 4. **Record decisions durably** in the finding artifact after each ruling batch. When the user
203
- approves larger machinery, also append a `Technical (complexity escalation)` runtime AR with
204
- every approval-evidence field required by the shared gate; the RV finding references that AR.
202
+ 4. **Record decisions durably** in the plan's findings ledger after each ruling batch. The ledger
203
+ is `plans/<plan>/05-findings.md` (flat) or
204
+ `codeops/features/<f>/plans/<plan>/05-findings.md` (nested), created lazily on first use, with a
205
+ one-line title and one compact row per batch:
206
+ `| Finding | Phase | Severity | Area | Ruling |` — finding ids use the review prefixes
207
+ `RV-`/`SA-`/`PE-`/`SR-` (for example `RV-001`), followed by the phase number,
208
+ `CRITICAL`/`MAJOR`/`MINOR`, a path or domain token, and
209
+ `fixed`/`accepted`/`deferred`/`dismissed`; identifiers and area tokens only, never prose. Task
210
+ mini-plans keep their ledger in their own plan folder. When the user approves larger machinery,
211
+ also append a `Technical (complexity escalation)` runtime AR with every approval-evidence field
212
+ required by the shared gate; the RV finding references that AR.
205
213
  5. **Accepted fixes:** implement → verify → follow-up commit per the commit mode. If any 🔴/🟠
206
214
  fix was applied, dispatch ONE re-review scoped to the fix diff — never a third pass. A fix
207
215
  the re-review still rejects is reported. Normal mode returns the ruling to the user; active
@@ -71,7 +71,7 @@ with active scope exploration.
71
71
 
72
72
  Re-run [../../references/domains/selection.md](../../references/domains/selection.md) before component decomposition. Requirements-stage lens selection is evidence, not a permanent assumption. Apply every selected lens to specifications, acceptance criteria, failure narratives, and test strategy.
73
73
 
74
- After lens selection and phase decomposition, run the specialist-gap check in [../../_shared/specialist-agents.md](../../_shared/specialist-agents.md). Record the outcome in `00-index.md` under `## Specialist Agents` — always, including `None` with its reason and evidence. Candidate creation is reserved authority: `--auto-design` may not approve it, and approved roles are created through `setup-routing`.
74
+ After lens selection and phase decomposition, run the specialist-gap check in [../../_shared/specialist-agents.md](../../_shared/specialist-agents.md). The `analyze-agents` skill executes the same detection flow on demand; the manual criteria in the linked protocol document remain the fallback when the skill is unavailable. Record the outcome in `00-index.md` under `## Specialist Agents` — always, including `None` with its reason and evidence. In the final plan summary, include a `Specialist check:` line — `None — <evidence>` or the candidate names. Candidate creation is reserved authority: `--auto-design` may not approve it, and approved roles are created through `setup-routing`.
75
75
 
76
76
  A folder `plans/<feature-name>/` containing:
77
77
 
@@ -274,6 +274,8 @@ Report what was created:
274
274
 
275
275
  **Summary:** Total Phases: X · Total Sessions: X · Estimated Time: X–X hours
276
276
 
277
+ **Specialist check:** [None — evidence / candidate names]
278
+
277
279
  **To begin implementation:** use the exec-plan skill on `[feature-name]`.
278
280
  ```
279
281
 
@@ -7,6 +7,7 @@ Run this before finalizing the plan documents. The **Specification-First Testing
7
7
  - [ ] All affected components identified
8
8
  - [ ] All scope decisions documented
9
9
  - [ ] All dependencies mapped
10
+ - [ ] The `## Specialist Agents` outcome is recorded in `00-index.md` (candidate or `None` with evidence)
10
11
  - [ ] Every planned item traces to the confirmed scope baseline or a user-kept `SE-*` entry
11
12
  - [ ] Strict scope contains no optional suggestions; exploration proposals remain non-executable
12
13
  until the user chooses `Keep`
@@ -55,7 +55,7 @@ than stored as a second mutable status.
55
55
 
56
56
  Before discovery, read [../../references/domains/selection.md](../../references/domains/selection.md), select every applicable system lens, and read those lens files completely. Record selected lenses and evidence in the requirements index. Re-evaluate selection when discovery reveals another domain; a financial web service, for example, requires financial, web, distributed/concurrent, and data/migration lenses.
57
57
 
58
- After lens selection and scope confirmation, run the specialist-gap check in [../../_shared/specialist-agents.md](../../_shared/specialist-agents.md). Propose at most two candidates in one batch, each through the Complexity Escalation Gate; creation is reserved authority (`--auto-design` may never approve it). Record the check outcome — including "none" — in the final summary.
58
+ After lens selection and scope confirmation, run the specialist-gap check in [../../_shared/specialist-agents.md](../../_shared/specialist-agents.md). The `analyze-agents` skill executes the same detection flow on demand; the manual criteria in the linked protocol document remain the fallback when the skill is unavailable. Surface at most two candidates in one batch as lightweight proposals (that document's §Proposals and the creation gate); the Complexity Escalation Gate and the reserved-authority approval apply only when the user chooses to proceed to creation (`--auto-design` may never approve it). Record the outcome in the final summary as a `Specialist check:` line — including `Specialist check: None — <evidence>`.
59
59
 
60
60
  You are NOT a passive interviewer. You are a **domain-aware consultant** that:
61
61