opencode-codeops 1.7.0 → 1.8.0

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,6 +2,39 @@
2
2
 
3
3
  All notable changes to CodeOps are recorded here.
4
4
 
5
+ ## 1.8.0 — 2026-10-04
6
+
7
+ ### Documentation
8
+
9
+ - readme: document project specialists
10
+ - skills: wire specialist agents into planning and execution
11
+ - specialist-agents: add canonical protocol and content spec tests
12
+ - plan: add specialist-agents plan set and roadmap
13
+
14
+ ### Fixes
15
+
16
+ - installer: refuse a symlinked codeops parent in migration
17
+ - installer: harden removal and migration per phase-3 review
18
+ - installer: harden specialist generation per phase-2 review
19
+ - test: strengthen specialist content oracle per phase-1 review
20
+
21
+ ### Features
22
+
23
+ - installer: add migration guard and lifecycle coverage
24
+ - installer: add specialist check, removal, and AGENTS.md sync
25
+ - installer: generate specialist agents from project briefs
26
+
27
+ ### Tests
28
+
29
+ - installer: lock the routing sandbox enum per re-review observation
30
+ - installer: cover sanitizer fixed point and parser edge cases
31
+
32
+ ## 1.7.1 — 2026-09-24
33
+
34
+ ### Fixes
35
+
36
+ - release: create annotated tags so --follow-tags pushes them
37
+
5
38
  ## 1.7.0 — 2026-09-24
6
39
 
7
40
  ### Fixes
package/README.md CHANGED
@@ -151,6 +151,36 @@ To pin specific models per role, use the `setup-routing` skill or add overrides
151
151
  }
152
152
  ```
153
153
 
154
+ ## Project specialists
155
+
156
+ CodeOps can recommend project-specific specialist subagents when repository evidence shows a
157
+ capability gap the twelve catalog roles and dynamic packets cannot close. Specialists are created
158
+ only with your explicit approval — the `--auto-design` mode cannot approve them.
159
+
160
+ - **Detect** — `make-requirements`, `make-plan`, and `analyze-project` run an evidence-based check
161
+ and record the outcome (including a negative one). At most two candidates are proposed per
162
+ requirements set or plan.
163
+ - **Create** — after you approve the candidate packet, `setup-routing` writes a brief at
164
+ `codeops/specialists/<role>.md`, writes routing policy first, generates a visible agent with
165
+ `install_agents.py --custom <role>`, and updates a managed index block in `AGENTS.md` with
166
+ `--sync-agents-md`.
167
+ - **Route** — a plan's `## Specialist Agents` table maps roles to phases. During `exec-plan`,
168
+ listed specialists are dispatched as **additional** reviewers or executors: they never replace a
169
+ required reviewer or gate, reviewer findings use the `SR-NNN` prefix, and the generated agent
170
+ defaults to `reasoningEffort: max` (override it with `routing.roles.<role>.reasoning`).
171
+ - **Fallback** — OpenCode loads agents at startup, so a specialist created during a session becomes
172
+ available in the next one; while unavailable, dispatch falls back to a generic subagent carrying
173
+ the brief excerpt and reports the fallback. No review depends on a specialist existing.
174
+
175
+ Lifecycle checks: `--check` reports `INVALID`, `MISSING`, `STALE`, `ORPHAN`, `HAND-AUTHORED`, and
176
+ `AGENTS.md` states; `--remove-custom <role> --yes` deletes the generated agent and its brief and
177
+ updates the index.
178
+
179
+ > **Upgrading:** specialist agents embed the generic template contract. When a newer plugin changes
180
+ > those templates, `--check` reports the agent as `STALE`; re-run
181
+ > `python3 scripts/install_agents.py --project . --custom <role>` (then `--sync-agents-md`) to
182
+ > regenerate it.
183
+
154
184
  ## Requirements
155
185
 
156
186
  - OpenCode (current)
@@ -49,6 +49,7 @@ fi
49
49
  | Feature roadmap | `plans/00-roadmap.md` | `codeops/features/<f>/00-roadmap.md` |
50
50
  | Portfolio roadmap | *(n/a)* | `codeops/00-roadmap.md` |
51
51
  | Staged AGENTS.md notes | *(n/a)* | `codeops/features/<f>/AGENTS.notes.md` |
52
+ | Specialist briefs | `codeops/specialists/<role>.md` (project-level) | `codeops/specialists/<role>.md` (project-level) |
52
53
  | Ambiguity register | `requirements/00-ambiguity-register.md` or `plans/<plan>/00-ambiguity-register.md` | the same file, under the feature |
53
54
  | Scope-expansion register | See the target-qualified rules below | the same target-qualified filename, under the feature |
54
55
  | Task mini-plan | `plans/<task-slug>/99-execution-plan.md` | `codeops/features/<f>/plans/<task-slug>/99-execution-plan.md` |
@@ -58,6 +59,10 @@ In nested layout, a feature's inner directories are created **lazily** — only
58
59
  feature's first RD, plan, or task is written. The marker and the (possibly empty) portfolio
59
60
  roadmap are the only things `setup-codeops` creates up front.
60
61
 
62
+ Specialist briefs are **project-level in both layouts**: a specialist describes a project-wide
63
+ domain or capability, so it is never scoped to one feature. The flat-to-nested migration leaves
64
+ `codeops/specialists/` in place.
65
+
61
66
  ### Scope-expansion register paths
62
67
 
63
68
  Scope-expansion register paths are collision-free because their authority is scoped to one audit or
@@ -67,9 +67,9 @@ Findings reuse the preflight severity scale **by reference** — 🔴 CRITICAL /
67
67
 
68
68
  ### Finding prefixes
69
69
 
70
- RV (phase-reviewer) · SA (security-auditor) · PA (preflight-auditor) · PE (perf-auditor), each
71
- numbered `XX-NNN`. Every finding-producing agent reports "no findings" explicitly rather than
72
- returning empty output.
70
+ RV (phase-reviewer) · SA (security-auditor) · PA (preflight-auditor) · PE (perf-auditor) ·
71
+ SR (domain-specialist-reviewer), each numbered `XX-NNN`. Every finding-producing agent reports
72
+ "no findings" explicitly rather than returning empty output.
73
73
 
74
74
  ## Activation & supersession
75
75
 
@@ -102,9 +102,20 @@ or response content.
102
102
  | plan-task-executor, plan-task-executor-opus | Phase task + Deliverable + Verify lines, governing spec/ST/AR excerpts, original goal + smallest viable design, relevant approved complexity PF/RV excerpts, target paths, scope mode (`strict` or `explore`), confirmed scope baseline, verify command |
103
103
  | spec-test-author | Spec excerpts + test cases, planned interface signatures from the plan documents, test framework/conventions, the FORBIDDEN implementation-file list, verify command (expected RED) |
104
104
  | preflight-auditor | The artifact under audit + ONE assigned dimension cluster + original goal + smallest viable design + relevant approved complexity AR/PF/RV excerpts + scope mode (`strict` or `explore`) + confirmed scope baseline |
105
+ | domain-specialist-reviewer | Line-1 dispatch header; phase diff; original goal + smallest viable design; phase task + Deliverable lines; active lenses plus the brief's domain checklist; scope mode + confirmed baseline; verify command + last result; the specialist brief excerpt |
106
+ | domain-specialist-executor | Phase task + Deliverable + Verify lines; governing spec/ST/AR excerpts; original goal + smallest viable design; target paths; scope mode + confirmed baseline; verify command; the specialist brief excerpt |
105
107
  | design-challenger | Problem + candidate options, **without** the parent's preferred choice (per `_shared/recommendation-hardening.md`) |
106
108
  | codebase-scout | The factual questions, search hints, and the facts-only contract |
107
109
 
110
+ ## Project specialists
111
+
112
+ A project may define specialist roles on top of the catalog (see `_shared/specialist-agents.md`).
113
+ Specialists resolve like any project agent; routing policy may pin model, effort, sandbox, and
114
+ reasoning, and a generated agent embeds `reasoningEffort` (default `max`). Dispatch only roles
115
+ listed in the plan's `## Specialist Agents` table, as **additional** reviewers or executors — a
116
+ specialist never replaces a required reviewer or gate, and an unavailable or invalid-brief
117
+ specialist falls back to a complete dynamic packet with the fallback reported.
118
+
108
119
  ## Budget caps
109
120
 
110
121
  - **Preflight fan-out:** ~5 clustered auditor dispatches — an exact partition of the preflight
@@ -117,6 +128,8 @@ or response content.
117
128
  diff — never a third pass.
118
129
  - **Scout:** ≤3 codebase-scout dispatches per skill run, enforced by the dispatching parent.
119
130
  - **Challenger:** caps live in `_shared/recommendation-hardening.md` and apply unchanged.
131
+ - **Specialist dispatch:** limited to the roles listed in the plan's `## Specialist Agents` table;
132
+ no additional fan-out.
120
133
 
121
134
  ## Model, effort, and agent resolution
122
135
 
@@ -129,6 +142,6 @@ Resolution order is:
129
142
  3. project `[agents]` defaults in `opencode.json`;
130
143
  4. the parent session's model and effort.
131
144
 
132
- Use `python3 "${CODEOPS_PLUGIN_ROOT}/scripts/install_agents.py" --project . --roles ...` to create optional project agents. Generated agent files carry a CodeOps marker. The installer owns only marked files and preserves every hand-authored file. Use `--check` to detect missing or stale generated agents and `--dry-run` to preview changes.
145
+ Use `python3 "${CODEOPS_PLUGIN_ROOT}/scripts/install_agents.py" --project . --roles ...` to create optional project agents. Generated agent files carry a CodeOps marker. The installer owns only marked files and preserves every hand-authored file. Use `--check` to detect missing or stale generated agents and `--dry-run` to preview changes. Project specialists are generated with `--custom <role>` from `codeops/specialists/<role>.md` and indexed into `AGENTS.md` with `--sync-agents-md`; their routing policy may also set `reasoning`.
133
146
 
134
147
  Dynamic packets are the correctness baseline. If a named agent is missing or a model pin is unavailable, spawn a generic subagent with the complete packet or run inline. Report the fallback and preserve required reviewer independence, sandbox intent, and every ambiguity/readiness/verification gate.
@@ -0,0 +1,145 @@
1
+ # Specialist Agents (shared convention)
2
+
3
+ > **CodeOps Artifact Schema**: 1
4
+
5
+ This is the **single canonical definition** of project-specific specialist subagents: how a
6
+ capability gap is detected, how a candidate is proposed and approved, and how the specialist is
7
+ created, used, and retired. It lives at the plugin root in `_shared/`; the participating skills
8
+ (`make-requirements`, `make-plan`, `analyze-project`, `setup-routing`, `exec-plan`) link here
9
+ instead of carrying copies.
10
+
11
+ A specialist is a project-local agent that carries durable domain knowledge a generic catalog role
12
+ does not have. Routing is an optimization and a context mechanism, **never a correctness source**.
13
+ Dynamic packets remain the dispatch baseline: a missing or unavailable specialist falls back
14
+ without weakening any gate, reviewer count, or verification step.
15
+
16
+ ## Detection criteria
17
+
18
+ Run the check after domain-lens selection, when the work's domain and risk profile are known.
19
+ A specialist is warranted only with repository evidence and no disqualifier.
20
+
21
+ | Strong signal (at least one, evidenced) | Disqualifier (any one blocks) |
22
+ | --------------------------------------- | ----------------------------- |
23
+ | A specialized framework, DSL, codegen, or protocol with non-obvious conventions a generic executor repeatedly rediscovers | A catalog role plus a dynamic packet already covers the need |
24
+ | An active domain lens plus project-specific invariants (regulatory, numerical, protocol, compatibility) checked every phase | One-off use with no recurring value |
25
+ | Repeated review findings or rework in the same area (from existing review evidence) | The specialist would only restate `AGENTS.md`, a lens, or base review lenses |
26
+ | An isolated, large-context capability (migration, compatibility audit) a packet cannot carry well | No unique evidence source, checklist, or capability beyond the base lenses |
27
+ | A project convention that must be enforced across phases and would otherwise be re-examined each time | An executor specialist with no demonstrated write-access need (prefer reviewer) |
28
+
29
+ Every candidate must name the **smallest alternative** (usually "keep sending the context in each
30
+ packet") and why it is insufficient. Sophistication, future flexibility, and effort already spent
31
+ are not evidence.
32
+
33
+ ## Candidate packet
34
+
35
+ The candidate is presented to the user as a bounded packet and persisted with the approval
36
+ evidence in the owning requirements or plan ambiguity register as a `Technical (complexity
37
+ escalation)` entry.
38
+
39
+ | Field | Content |
40
+ | ----- | ------- |
41
+ | Role | Proposed slug (validated: `^[a-z][a-z0-9-]{1,40}$`, not a catalog or built-in name) |
42
+ | Kind | `reviewer` or `executor` |
43
+ | Capability | One line: what it knows or does that no catalog role does |
44
+ | Evidence | Repository facts with `file:line` |
45
+ | Why existing options fail | Catalog-role analysis + why a dynamic packet is insufficient |
46
+ | Smallest alternative | The direct alternative and why it is not enough |
47
+ | Use map | Intended features/phases/tags |
48
+ | Permissions | Read-only (reviewer) or the explicit write need (executor) |
49
+ | Effort / reasoning | Optional overrides; default effort `high`, reasoning `max` |
50
+ | Maintenance cost | Files, upkeep, and review attention |
51
+ | Independent verdict | `Unnecessary` / `Simplify` / `Justified` from a blind `design-challenger` |
52
+ | Direct user decision | `approved` / `rejected` / `deferred` — explicit, never silence |
53
+
54
+ ## Authority and budget
55
+
56
+ - Creation is **reserved authority**. `--auto-design` may never approve it; only the user's direct
57
+ choice on the visible Complexity Escalation Gate packet authorizes creation
58
+ (`_shared/zero-ambiguity-gate.md`).
59
+ - The gate's complete approval evidence (original goal, machinery, evidence, smallest solution,
60
+ cost, verdict, decision) is persisted in the owning register entry.
61
+ - At most **two** candidates per requirements set or plan, proposed in one batch; candidates are
62
+ deduplicated against installed project agents and `codeops.json` routing roles.
63
+ - Rejection and deferral are valid outcomes. A rejected candidate may not reappear in the same
64
+ scope without new evidence.
65
+
66
+ ## Routing layers
67
+
68
+ | Layer | Owner | Content | Consumer |
69
+ | ----- | ----- | ------- | -------- |
70
+ | `.opencode/agents/<role>.md` description | installer, from the brief | Mandatory when-to-use text | OpenCode model (task list) |
71
+ | `codeops/codeops.json` → `routing.roles.<role>` | `setup-routing` | model / effort / sandbox / reasoning policy | installer + CodeOps skills |
72
+ | `codeops/specialists/<role>.md` | `setup-routing`, user-approved | Capability, scope, evidence, checklist, description | installer + skills |
73
+ | Plan `00-index.md` "Specialist Agents" | `make-plan` | phase → role selection map | `exec-plan` |
74
+ | `AGENTS.md` managed block | `setup-routing` (rendered by `install_agents.py --sync-agents-md`) | Compact index with when-to-use / required-for rules | every project agent |
75
+
76
+ ## Detection integration
77
+
78
+ ### make-requirements
79
+
80
+ 1. After domain-lens selection and scope confirmation, run the detection criteria.
81
+ 2. For each candidate, open an ambiguity-register entry (`Technical (complexity escalation)`) with
82
+ the candidate packet, run the challenger, and obtain the user's decision.
83
+ 3. Approved candidates are created through `setup-routing` or noted for creation before the first
84
+ implementing plan; rejected candidates are recorded and dropped.
85
+ 4. Record the check in the final summary. No new requirements-template section is created; the
86
+ brief and the register are the durable records.
87
+
88
+ ### make-plan
89
+
90
+ 1. After re-running lens selection and decomposing phases, run the detection criteria against the
91
+ phase plan.
92
+ 2. Record the outcome in `00-index.md` under `## Specialist Agents`, **always** — including the
93
+ **negative outcome**:
94
+
95
+ ```markdown
96
+ ## Specialist Agents
97
+
98
+ | Role | Kind | Use | AR Ref |
99
+ | ---- | ---- | --- | ------ |
100
+ | pg-migration-reviewer | reviewer | Phase 2 (backfill), Phase 3 (cutover) | AR #7 |
101
+
102
+ _Detection evidence: db/migrations/0042_backfill.sql requires mixed-version compatibility; no
103
+ catalog role carries the project's migration ordering rule._
104
+ ```
105
+
106
+ ```markdown
107
+ ## Specialist Agents
108
+
109
+ **None** — the capability-gap check ran against this repository's evidence and found no gap a
110
+ standing specialist would close.
111
+ ```
112
+
113
+ 3. Candidate approval, challenger, and persistence follow the shared gate exactly. Approved roles
114
+ are created through `setup-routing` before execution begins; the plan remains valid without them
115
+ via dynamic-packet fallback.
116
+
117
+ ### analyze-project
118
+
119
+ 1. While inspecting manifests and conventions, note specialization signals (specialized
120
+ framework/DSL, domain invariants, conventions a generic agent would miss).
121
+ 2. When a signal is strong and no specialist exists, report the candidate with evidence and
122
+ recommend running `setup-routing`; never write agent files or candidate artifacts, and keep
123
+ `AGENTS.md` compact.
124
+ 3. Preserve the `<!-- CODEOPS-SPECIALISTS:START -->` / `<!-- CODEOPS-SPECIALISTS:END -->` block
125
+ byte-for-byte when refreshing managed guidance.
126
+
127
+ ## Lifecycle
128
+
129
+ | Stage | Action |
130
+ | ----- | ------ |
131
+ | Detect | Skills run the gap check and record outcomes |
132
+ | Propose | Candidate packet + independent verdict + user decision |
133
+ | Create | `setup-routing` drafts the brief, the user reviews it, routing policy is written first, the installer generates the agent, `--sync-agents-md` updates AGENTS.md, and `--check` verifies last |
134
+ | Use | `exec-plan` selects per the plan table; reviewers are additional and independent; fallback on unavailability |
135
+ | Review | Optional guidance: after first use, the user may evaluate benefit against the evidence and keep, revise, or remove the specialist. Not a gate |
136
+ | Retire | `install_agents.py --remove-custom <role> --yes` removes agent + brief after confirmation; `setup-routing` drops the routing policy and the AGENTS.md entry |
137
+
138
+ ## Dispatch and fallback
139
+
140
+ The authoritative dispatch rules live in `_shared/quality-profile.md` (resolution order, finding
141
+ prefix `SR`, additional-reviewer independence, and dynamic-packet fallback). A specialist
142
+ dispatches only when the plan's `00-index.md` "Specialist Agents" table assigns it to the phase.
143
+ When the agent is unavailable — for example it was created after the session started — dispatch a
144
+ generic subagent with the complete packet, including the brief excerpt, and report the fallback.
145
+ The phase is never marked complete unreviewed because a specialist was missing.
@@ -0,0 +1,20 @@
1
+ You are a project domain specialist executor. The project brief below is embedded into this
2
+ agent at generation time and is your durable source of domain knowledge. You implement exactly
3
+ one dispatched unit — normally a whole phase, occasionally a single task — with that knowledge.
4
+
5
+ - Implement only what the dispatch packet assigns. Do not expand scope. In strict mode do not
6
+ report optional additions; in explore mode return optional ideas as separate `SE-*` proposals
7
+ to the parent, never as implemented changes.
8
+ - Follow the project's `AGENTS.md` for build, test, and verify commands and for code conventions.
9
+ - Never update execution plans, roadmaps, or progress marks; the parent owns those. Never edit a
10
+ specification test to make it pass — a failing specification test means the implementation is
11
+ wrong.
12
+ - Run the packet's verify command per task and report pass or fail with the evidence the packet
13
+ asks for. Keep full verify output out of your report; surface one line on pass and the failure
14
+ excerpt on fail.
15
+ - Stop and return a blocker report when the packet is missing context, a specification test
16
+ fails for a reason the packet does not explain, or the work hits an ambiguity. Never guess and
17
+ never widen your own authority.
18
+ - Never copy plan, requirement, ambiguity-register, or test-case identifiers, or `codeops/`,
19
+ `plans/`, or `requirements/` paths, into code or doc comments. Those files are ephemeral; keep
20
+ the behavior and drop the citation.
@@ -0,0 +1,17 @@
1
+ You are a project domain specialist reviewer. The project brief below is embedded into this
2
+ agent at generation time and is your durable source of domain knowledge. You bring that knowledge
3
+ to a dispatched phase diff as an additional, independent reviewer.
4
+
5
+ - Stay read-only. Never edit files, fix findings, commit, or run commands that change the
6
+ worktree; shell access is for inspection only.
7
+ - Review the phase diff against the brief's capability, scope, and domain checklist. Hunt for the
8
+ domain-specific problems a generic reviewer would miss.
9
+ - Report every finding as a numbered `SR-NNN` entry using the standard severity scale (critical,
10
+ major, minor). Each finding needs the exact file and line, the concrete risk, and a concrete
11
+ remedy. State "no findings" explicitly when the diff is clean.
12
+ - Respect the dispatch's scope mode. In strict mode report only necessary corrections; never
13
+ propose optional additions. In explore mode you may return optional ideas as separate proposals.
14
+ - You are additional: never replace a required reviewer or gate, and never review a phase you
15
+ implemented.
16
+ - Keep the output terse and structured so the parent can merge it directly: findings first, then
17
+ explicit open questions, then "no findings" if applicable. Do not restate the diff.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-codeops",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Specification-first engineering for complex systems — CodeOps plugin for OpenCode",
5
5
  "type": "module",
6
6
  "engines": {
@@ -39,7 +39,8 @@
39
39
  "properties": {
40
40
  "model": {"type": "string", "minLength": 1},
41
41
  "effort": {"type": "string", "minLength": 1},
42
- "sandbox": {"enum": ["read-only", "workspace-write", "danger-full-access"]}
42
+ "sandbox": {"enum": ["read-only", "workspace-write", "danger-full-access"]},
43
+ "reasoning": {"enum": ["none", "minimal", "low", "medium", "high", "xhigh", "max"]}
43
44
  }
44
45
  }
45
46
  }
@@ -14,6 +14,10 @@
14
14
  # means "already migrated"), and applies via `git mv` (history preserved), writing the marker and
15
15
  # the seeded portfolio roadmap LAST so an interrupted run never leaves a false "migrated" marker.
16
16
  #
17
+ # Existing config: an existing codeops/codeops.json is never overwritten — a valid file is
18
+ # preserved byte-for-byte (the preview prints PRESERVE) and a malformed one refuses the run
19
+ # before any move.
20
+ #
17
21
  # Security: never executes repo data; the feature slug is sanitized so it can never escape
18
22
  # codeops/features/. All mutation requires an explicit --yes; absent that, it only previews.
19
23
  #
@@ -105,6 +109,50 @@ if [[ -e codeops && ! -d codeops ]]; then
105
109
  exit 1
106
110
  fi
107
111
 
112
+ # A symlinked `codeops` would redirect every write and every `git mv` outside the repository.
113
+ # Refuse it before anything moves; `-L` also catches a dangling symlink, which `-e` misses.
114
+ if [[ -L codeops ]]; then
115
+ printf 'ERROR: `codeops` is a symlink — refusing to migrate through it.\n' >&2
116
+ printf ' Replace it with a real directory (or remove it), then re-run. Nothing was modified.\n' >&2
117
+ exit 1
118
+ fi
119
+
120
+ # Committed symlinks or special files at the written targets would make `cat >`
121
+ # write through the link (or block forever); refuse up front, before any move.
122
+ for target in codeops/codeops.json codeops/.codeops.yml codeops/00-roadmap.md; do
123
+ if [[ -L "$target" || ( -e "$target" && ! -f "$target" ) ]]; then
124
+ printf 'ERROR: %s is a symlink or not a regular file — refusing to migrate.\n' "$target" >&2
125
+ printf ' Replace it with a regular file (or remove it), then re-run. Nothing was modified.\n' >&2
126
+ exit 1
127
+ fi
128
+ done
129
+
130
+ # -----------------------------------------------------------------------------
131
+ # Existing structured config: never overwrite it.
132
+ #
133
+ # `codeops/specialists/` is project-level and survives migration; a specialist
134
+ # brief's routing policy may already live in codeops/codeops.json. A valid file
135
+ # is preserved byte-for-byte (the preview says PRESERVE instead of CREATE) and
136
+ # a malformed one refuses the run before anything moves, so a broken config can
137
+ # never be silently replaced by the seeded defaults.
138
+ # -----------------------------------------------------------------------------
139
+ PRESERVE_CONFIG=0
140
+ if [[ -f codeops/codeops.json ]]; then
141
+ if [[ "$HAVE_PY3" -eq 1 ]]; then
142
+ if python3 -c 'import json, sys; json.load(open(sys.argv[1], encoding="utf-8"))' codeops/codeops.json 2>/dev/null; then
143
+ PRESERVE_CONFIG=1
144
+ else
145
+ printf 'ERROR: codeops/codeops.json exists but is not valid JSON — refusing to migrate.\n' >&2
146
+ printf ' Fix or remove it, then re-run. It was not modified.\n' >&2
147
+ exit 1
148
+ fi
149
+ else
150
+ # Without python3 the file cannot be validated; preserving it is the only
151
+ # safe choice (the migration never overwrites an existing config).
152
+ PRESERVE_CONFIG=1
153
+ fi
154
+ fi
155
+
108
156
  # -----------------------------------------------------------------------------
109
157
  # Derive the feature slug (roadmap header → else repo dir name), then sanitize.
110
158
  # -----------------------------------------------------------------------------
@@ -155,6 +203,9 @@ fi
155
203
  # Hazard scan → warnings (never block; the user resolves these by hand after the move).
156
204
  # -----------------------------------------------------------------------------
157
205
  warnings=()
206
+ if [[ "$PRESERVE_CONFIG" -eq 1 ]]; then
207
+ warnings+=("config-preserved: codeops/codeops.json already exists and is kept byte-for-byte — review it against the seeded defaults")
208
+ fi
158
209
  # (a) plan folders on disk but not referenced in the roadmap.
159
210
  if [[ -f plans/00-roadmap.md ]]; then
160
211
  for d in plans/*/; do
@@ -230,7 +281,11 @@ for m in "${moves[@]}"; do
230
281
  printf 'MOVE %s -> %s\n' "${m%%|*}" "${m##*|}"
231
282
  done
232
283
  printf 'CREATE codeops/.codeops.yml\n'
233
- printf 'CREATE codeops/codeops.json\n'
284
+ if [[ "$PRESERVE_CONFIG" -eq 1 ]]; then
285
+ printf 'PRESERVE codeops/codeops.json (existing file kept byte-for-byte)\n'
286
+ else
287
+ printf 'CREATE codeops/codeops.json\n'
288
+ fi
234
289
  printf 'CREATE codeops/00-roadmap.md\n'
235
290
  for w in "${warnings[@]:-}"; do
236
291
  [[ -n "$w" ]] && printf 'WARN %s\n' "$w"
@@ -294,7 +349,8 @@ find plans requirements -type d -empty -delete 2>/dev/null || true
294
349
  integration_branch="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's#^origin/##')"
295
350
  [[ -n "$integration_branch" ]] || integration_branch="$(git symbolic-ref --quiet --short HEAD 2>/dev/null)"
296
351
  [[ -n "$integration_branch" ]] || integration_branch="main"
297
- cat > codeops/codeops.json <<'JSON' || fail_apply "write codeops/codeops.json"
352
+ if [[ "$PRESERVE_CONFIG" -ne 1 ]]; then
353
+ cat > codeops/codeops.json <<'JSON' || fail_apply "write codeops/codeops.json"
298
354
  {
299
355
  "schema": 1,
300
356
  "mode": "strict",
@@ -307,6 +363,7 @@ cat > codeops/codeops.json <<'JSON' || fail_apply "write codeops/codeops.json"
307
363
  "metrics": {"enabled": false}
308
364
  }
309
365
  JSON
366
+ fi
310
367
  # Seeded portfolio roadmap — one row for the migrated feature. The roadmap skill refines the
311
368
  # stage/progress on the next /update_roadmap; this is a valid starting point.
312
369
  today="$(date '+%Y-%m-%d')"
@@ -0,0 +1,59 @@
1
+ # Generated by CodeOps install_agents.py
2
+ # Role: executor | Template: plan-task-executor
3
+ # Do not edit this file manually — regenerate with: install_agents.py
4
+ ---
5
+ description: CodeOps plan-task-executor agent
6
+ mode: subagent
7
+ temperature: 0.1
8
+ hidden: true
9
+ permission:
10
+ read: allow
11
+ grep: allow
12
+ glob: allow
13
+ edit: allow
14
+ bash: allow
15
+ ---
16
+
17
+ <!-- Agent template: plan-task-executor
18
+ See agents/ for the OpenCode agent definition files generated from this template.
19
+ Do not add YAML frontmatter here — use install_agents.py to generate agent files. -->
20
+
21
+ You execute exactly ONE dispatched unit — normally a whole phase, occasionally a single task —
22
+ from a CodeOps execution plan, via a phase packet (the phase's task lines, Deliverables and
23
+ Verify lines, spec excerpts, ST-cases, AR decisions, relevant approved complexity PF/RV decisions,
24
+ original goal, smallest viable design, scope mode, confirmed product scope baseline, target files,
25
+ verify command). Missing or invalid scope context fails closed to strict mode. Missing or invalid
26
+ original-goal or smallest-design context blocks execution; report it to the parent.
27
+ - Follow the project's AGENTS.md for build/test/verify commands and conventions.
28
+ - Work the packet's tasks in order; implement only what it assigns and what the confirmed product
29
+ scope baseline authorizes — do not expand scope. In strict mode, do not report optional additions.
30
+ In explore mode, return optional ideas as `SE-*` proposals to the parent; never implement or
31
+ authorize them.
32
+ - **Documentation ban (non-negotiable).** The packet quotes AR decisions, ST-cases, and spec
33
+ excerpts for YOUR understanding only — never copy a plan/requirement/AR/RD/ST/PA/task identifier
34
+ or a `codeops/`/`plans/`/`requirements/` path into a code comment or doc comment. Those files are
35
+ ephemeral; the shipped code must stand on its own. Keep the behavior a plan note describes, drop
36
+ the citation, and restate any rationale in plain language.
37
+ - **Documentation gate (non-negotiable).** Before reporting a task done, read the changed code as a
38
+ junior developer. Document every public/exported class, interface, method, function, property,
39
+ type, and constant, plus every non-trivial internal entity, in the language's doc-comment format.
40
+ Cover applicable purpose, parameters, return value, thrown errors, side effects, and invariants.
41
+ Explain complex logic and non-obvious decisions in calm comments, and add `@example` to public API
42
+ wherever practical. Do not pad trivial private code with comments that merely restate it.
43
+ **Missing documentation blocks completion.** Use the project's documentation linter when
44
+ configured, but also perform this semantic read. Finally, grep your
45
+ changed files for `\b(RD|AR|PA|PF|HR|GATE|AC|ST|ADR|DEF)-[0-9]` and `(codeops|plans|requirements)/`
46
+ and fix any hit that landed in a comment.
47
+ - Write/update tests as the plan specifies, then run the verify command with output captured
48
+ to a temp log — report a PASS one-liner per task, or the last 50 log lines on failure.
49
+ - Never modify a spec test's expectations (`*.spec.test.*`) — if a spec test fails, the
50
+ implementation is wrong; report it as a blocker instead of changing the test.
51
+ - **Complexity checkpoint.** Before editing each task, compare the intended approach with the
52
+ original goal, existing patterns, approved complexity decisions, and the smallest viable
53
+ solution. If it would add a material layer, dependency, harness, framework, infrastructure
54
+ surface, cross-cutting refactor, or future-proofing without specific approval, STOP and return a
55
+ Complexity Escalation Gate blocker to the parent. Do not build it or approve it yourself.
56
+ - If the packet is insufficient, or you hit a decision it doesn't cover, STOP and report
57
+ exactly what is missing or ambiguous as a blocker — never guess, and never edit the
58
+ execution plan or roadmap (the parent session owns those and the user conversation).
59
+ - Report per task, 3-4 lines each: what changed, test status, any blocker.