@fro.bot/systematic 3.10.2 → 3.12.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.
@@ -10,7 +10,7 @@ You are a systems architect evaluating whether this plan can actually be built a
10
10
 
11
11
  ## What you check
12
12
 
13
- **"What already exists?"** -- Does the plan acknowledge existing code, services, and infrastructure? If it proposes building something new, does an equivalent already exist in the codebase? Does it assume greenfield when reality is brownfield? This check requires reading the codebase alongside the plan.
13
+ **"What already exists?"** -- Does the plan acknowledge existing code, services, and infrastructure? If it proposes building something new, does an equivalent already exist in the codebase? Does it assume greenfield when reality is brownfield? When the plan carries a Prior-Art Survey, verify that every named candidate resolves to real code, spot-check that its stated ownership matches what the code actually does, and confirm that a `build-new-within-scope` verdict's insufficiency reasons hold. Treat an absence claim as limited to the survey's stated scope and budget, not as repository-wide evidence. If the survey reports an equivalent, does the plan name the corresponding requirement or implementation-unit change? Citing an equivalent under related work without changing the design is a finding. This check requires reading the codebase alongside the plan.
14
14
 
15
15
  **Architecture reality** -- Do proposed approaches conflict with the framework or stack? Does the plan assume capabilities the infrastructure doesn't have? If it introduces a new pattern, does it address coexistence with existing patterns?
16
16
 
@@ -23,6 +23,7 @@ Valid scopes and the phases they control:
23
23
  | `conventions` | Documentation and Guidelines Review: contribution guidelines, coding standards, review processes | Documentation Insights |
24
24
  | `issues` | GitHub Issue Pattern Analysis: formatting patterns, label conventions, issue structures | Issue Conventions |
25
25
  | `templates` | Template Discovery: issue templates, PR templates, RFC templates | Templates Found |
26
+ | `prior-art` | Concern-Anchored Prior-Art Survey: search for what currently handles the concern | Prior-Art Survey |
26
27
 
27
28
  **Scoping rules:**
28
29
 
@@ -150,6 +151,53 @@ This context informs all subsequent research phases -- use it to focus documenta
150
151
 
151
152
  ---
152
153
 
154
+ **Prior-Art Survey (run for `prior-art` scope)**
155
+
156
+ Run this survey for every software-work concern, including shallow plans. Skip it only when the work is explicitly non-software or mechanical with no behavior change. Scale the survey's depth with plan depth, but do not make existence of the survey conditional on plan depth.
157
+
158
+ 1. Treat the input as a concern, not a proposed solution or design. Restate it in terms of its **trigger**, **effect**, **state**, and **integration boundary** before searching. Do not let a named implementation, component, or desired mechanism substitute for that concern.
159
+ 2. Bound the search to a workspace or subtree using the existing Phase 0.1 and 0.1b detection logic above. For a monorepo, use the named workspace or service when the concern identifies one; otherwise report the workspace map and choose the smallest defensible subtree. State a finite search budget before searching, covering the search passes and candidate inspection depth you will use.
160
+ 3. Search the bounded scope for source, registrations, tests, schemas, and configuration that currently handle the trigger, effect, state, or integration boundary. Use the concern's synonyms and nearby domain terms, including terms discovered from filenames, symbols, registrations, and schemas.
161
+ 4. Collect every plausible candidate before assigning any disposition. For each candidate, describe what it owns in the vocabulary the code itself uses: use its symbols, module names, events, records, states, or boundaries rather than translating it into the request's vocabulary.
162
+ 5. Only after the candidate inventory is complete, disposition candidates and identify the strongest evidence. Preserve the stated scope and budget in the result, including whether the budget was exhausted.
163
+
164
+ The prior-art output must report the concern framing, surveyed workspace or subtree, freshness record, search budget, candidate inventory, and dispositions. Emit exactly one machine-checkable result using `skills/ce-plan/references/prior-art-survey-schema.json` as the contract. Use `schema_version: 1`. The `freshness` object must include at least one of `vcs_reference` (the current VCS reference for the surveyed scope, when available) or `scope_baseline` (a portable digest or compact baseline for the surveyed scope when VCS is unavailable); include both when both are available. Do not replace this record with prose.
165
+
166
+ ```json
167
+ {
168
+ "schema_version": 1,
169
+ "verdict": "reuse | extend | build-new-within-scope | unscoped | unresolved",
170
+ "scope": "<workspace or subtree searched>",
171
+ "freshness": {
172
+ "vcs_reference": "<current VCS reference for the surveyed scope, when available>",
173
+ "scope_baseline": "<portable digest or baseline for the surveyed scope when VCS is unavailable>"
174
+ },
175
+ "budget": {
176
+ "max_search_passes": 3,
177
+ "max_candidate_inspections": 10,
178
+ "exhausted": false
179
+ },
180
+ "candidates": [
181
+ {
182
+ "path_or_symbol": "<repository-relative path or source symbol>",
183
+ "description": "<what it owns in the code's vocabulary>",
184
+ "disposition": "reuse | extend | insufficient | undispositioned",
185
+ "insufficiency_reason": "<required for build-new-within-scope candidates>"
186
+ }
187
+ ],
188
+ "scopes_considered": ["<required for an unscoped verdict>"],
189
+ "acceptance": {
190
+ "accepted_by_user": true,
191
+ "accepted_verdict": "unscoped | unresolved",
192
+ "reason": "<what the user accepted>"
193
+ }
194
+ }
195
+ ```
196
+
197
+ Use exactly one verdict. `build-new-within-scope` requires at least one candidate, every candidate must have disposition `insufficient`, and every candidate must include `insufficiency_reason`. `unscoped` requires a non-empty `scopes_considered` list. `unresolved` requires at least one `undispositioned` candidate and must retain every disposition already reached. Include `acceptance` only when a user accepts an `unscoped` or `unresolved` verdict. An empty candidate list is the only representation of absence: keep it alongside the searched `scope` and `budget`, and never claim that no equivalent exists anywhere.
198
+
199
+ ---
200
+
153
201
  **Core Responsibilities:**
154
202
 
155
203
  1. **Architecture and Structure Analysis**
@@ -190,7 +238,7 @@ This context informs all subsequent research phases -- use it to focus documenta
190
238
  2. Start with high-level documentation to understand project context
191
239
  3. Progressively drill down into specific areas based on findings
192
240
  4. Cross-reference discoveries across different sources
193
- 5. Prioritize official documentation over inferred patterns
241
+ 5. Apply authority by claim type: source, tests, registrations, and schemas establish what exists; documentation and history explain why it exists and what constrains it; orientation prose is a lead requiring verification and never establishes absence.
194
242
  6. Note any inconsistencies or areas lacking documentation
195
243
 
196
244
  **Output Format:**
@@ -232,6 +280,18 @@ Structure your findings as:
232
280
  - Naming conventions
233
281
  - Project-specific practices
234
282
 
283
+ ### Prior-Art Survey
284
+ - Concern framing: trigger, effect, state, and integration boundary
285
+ - A structured result conforming to `skills/ce-plan/references/prior-art-survey-schema.json`
286
+ - `schema_version: 1` and a `freshness` record with at least one of `vcs_reference` or `scope_baseline`
287
+ - Exactly one verdict: `reuse`, `extend`, `build-new-within-scope`, `unscoped`, or `unresolved`
288
+ - The searched workspace or subtree in `scope`, plus bounded `budget` fields and whether the budget was exhausted
289
+ - A complete `candidates` inventory with each path or symbol, code-vocabulary ownership description, and disposition
290
+ - For `build-new-within-scope`, a non-empty candidate list whose candidates all explain their insufficiency
291
+ - For `unscoped`, a non-empty `scopes_considered` list; for `unresolved`, at least one `undispositioned` candidate while preserving reached dispositions
292
+ - An optional `acceptance` record only when a user accepted an `unscoped` or `unresolved` verdict
293
+ - Absence represented only by the searched scope, budget, and an empty candidate list; never assert an unbounded absence
294
+
235
295
  ### Recommendations
236
296
  - How to best align with project conventions
237
297
  - Areas needing clarification
package/dist/index.js CHANGED
@@ -13201,7 +13201,7 @@ var initializePlugin = async ({
13201
13201
  };
13202
13202
  })()
13203
13203
  });
13204
- return {
13204
+ const hooks = {
13205
13205
  config: configHandler,
13206
13206
  tool: {
13207
13207
  systematic_skill: createSkillTool({
@@ -13271,6 +13271,7 @@ var initializePlugin = async ({
13271
13271
  } catch {}
13272
13272
  }
13273
13273
  };
13274
+ return hooks;
13274
13275
  };
13275
13276
  var SystematicPlugin = async (input) => {
13276
13277
  return initializePlugin(input);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fro.bot/systematic",
3
- "version": "3.10.2",
3
+ "version": "3.12.0",
4
4
  "description": "Compound-engineering loops for OpenCode, Pi, and Claude Code",
5
5
  "type": "module",
6
6
  "homepage": "https://fro.bot/systematic",
@@ -108,7 +108,7 @@
108
108
  "rimraf": "6.1.3",
109
109
  "semantic-release": "25.0.9",
110
110
  "semantic-release-export-data": "1.2.0",
111
- "typebox": "1.3.13",
111
+ "typebox": "1.3.14",
112
112
  "typescript": "7.0.2"
113
113
  },
114
114
  "dependencies": {
@@ -226,15 +226,18 @@ Prepare a concise planning context summary (a paragraph or two) to pass as input
226
226
 
227
227
  Run these agents in parallel:
228
228
 
229
- - Dispatch `systematic:research:repo-research-analyst` — scope: technology, architecture, patterns; pass the planning context summary.
229
+ - Dispatch `systematic:research:repo-research-analyst` — scope: technology, architecture, patterns, prior-art; pass the planning context summary to the technology, architecture, and patterns scopes. For the prior-art scope, pass only the independently stated concern — its trigger, effect, state, and integration boundary — plus the classified plan depth, rather than the planning context summary or proposed solution. Skip the prior-art scope for explicitly non-software planning and mechanical work that changes no behavior; make that exemption decision here at dispatch.
230
230
  - Dispatch `systematic:research:learnings-researcher` — pass the planning context summary.
231
231
  Collect:
232
232
  - Technology stack and versions (used in section 1.2 to make sharper external research decisions)
233
233
  - Architectural patterns and conventions to follow
234
234
  - Implementation patterns, relevant files, modules, and tests
235
+ - Prior-art survey result: schema version, verdict, surveyed scope and freshness record, bounded budget, candidate ownership and dispositions, and any recorded acceptance
235
236
  - AGENTS.md guidance that materially affects the plan, with AGENTS.md used only as compatibility fallback when present
236
237
  - Institutional learnings from `docs/solutions/`
237
238
 
239
+ When the prior-art scope runs, apply its verdict before continuing planning: an `unscoped` or `unresolved` result stops planning until the scope narrows, the budget rises, or the user explicitly accepts the uncertainty. Record that acceptance in the Prior-Art Survey section. In a run with no user present, either verdict fails the run rather than proceeding.
240
+
238
241
  **Slack context** (opt-in) — never auto-dispatch. Route by condition:
239
242
 
240
243
  - **Tools available + user asked**: Dispatch `systematic:research:slack-researcher` with the planning context summary in parallel with other Phase 1.1 agents. If the origin document has a Slack context section, pass it verbatim so the researcher focuses on gaps. Include findings in consolidation.
@@ -552,6 +555,43 @@ deepened: YYYY-MM-DD # optional, set when the confidence check substantively st
552
555
 
553
556
  - [Relevant external docs or best-practice source, if used]
554
557
 
558
+ ## Prior-Art Survey
559
+
560
+ Include this section for every qualifying software-work or behavior-changing plan. Omit it only when Phase 1.1 explicitly applies the non-software or mechanical-no-behavior-change exemption. The section must contain exactly one fenced `json` block, and that block must validate against `references/prior-art-survey-schema.json`. Preserve the survey's schema-conforming structured result, including the schema version, verdict, surveyed scope, freshness record, bounded budget, candidate ownership and dispositions, and the acceptance record when present. A plan containing prose, placeholders, a missing block, multiple blocks, or a malformed/schema-invalid block is not compliant.
561
+
562
+ Omit `scopes_considered` unless the verdict is `unscoped`, and omit `acceptance` unless the user has accepted an `unscoped` or `unresolved` verdict.
563
+
564
+ ```json
565
+ {
566
+ "schema_version": 1,
567
+ "verdict": "reuse | extend | build-new-within-scope | unscoped | unresolved",
568
+ "scope": "<workspace or subtree searched>",
569
+ "freshness": {
570
+ "vcs_reference": "<VCS reference for the surveyed scope, when available>",
571
+ "scope_baseline": "<portable digest or baseline for the surveyed scope when VCS is unavailable>"
572
+ },
573
+ "budget": {
574
+ "max_search_passes": 1,
575
+ "max_candidate_inspections": 1,
576
+ "exhausted": false
577
+ },
578
+ "candidates": [
579
+ {
580
+ "path_or_symbol": "<repository-relative path or source symbol>",
581
+ "description": "<what it owns in the code's vocabulary>",
582
+ "disposition": "reuse | extend | insufficient | undispositioned",
583
+ "insufficiency_reason": "<required when verdict is build-new-within-scope>"
584
+ }
585
+ ],
586
+ "scopes_considered": ["<required for an unscoped verdict>"],
587
+ "acceptance": {
588
+ "accepted_by_user": true,
589
+ "accepted_verdict": "unscoped | unresolved",
590
+ "reason": "<what the user accepted and why planning may proceed>"
591
+ }
592
+ }
593
+ ```
594
+
555
595
  ## Key Technical Decisions
556
596
 
557
597
  - [Decision]: [Rationale]
@@ -697,7 +737,7 @@ For larger `Deep` plans, extend the core template only when useful with sections
697
737
 
698
738
  Compose the plan using two paired references:
699
739
 
700
- - `references/plan-sections.md` — the section contract. Describes what the plan contains: the outcome the plan must enable for downstream consumers, the hard floor (Summary, Problem Frame, Requirements, KTDs, Implementation Units), the include-when-material catalog (HTD, Scope Boundaries, Open Questions, System-Wide Impact, Risks & Dependencies, Acceptance Examples, Documentation/Operational Notes, Sources & Research), the agency-driven escape hatch (introduce new sections when content warrants), and the ID/content rules.
740
+ - `references/plan-sections.md` — the section contract. Describes what the plan contains: the outcome the plan must enable for downstream consumers, the hard floor (Summary, Problem Frame, Requirements, Prior-Art Survey, KTDs, Implementation Units), the include-when-material catalog (HTD, Scope Boundaries, Open Questions, System-Wide Impact, Risks & Dependencies, Acceptance Examples, Documentation/Operational Notes, Sources & Research), the agency-driven escape hatch (introduce new sections when content warrants), and the ID/content rules.
701
741
  - `references/markdown-rendering.md` — how to present the sections in markdown (table-vs-prose by content shape, ID prefix format, diagram rendering, etc.).
702
742
 
703
743
  The section catalog is the same regardless of plan depth. Format-specific principles live in the rendering reference. The Core Plan Template above (Section 4.2) is the canonical content authority — `plan-sections.md` is a rendering/ordering layer that describes how sections present, not which sections exist.
@@ -19,6 +19,14 @@ A great plan enables three audiences to act:
19
19
 
20
20
  Sections earn their place by serving one of these audiences. Omit padding.
21
21
 
22
+ ## Section ordering
23
+
24
+ Render the `Prior-Art Survey` as a top-level section after `Context & Research` and before `Key Technical Decisions`. Keep it addressable and separate from general research so downstream review and execution checks can locate the result without interpreting surrounding prose. For qualifying software-work or behavior-changing plans, the section is part of the hard floor; omit it only when planning explicitly records the non-software or mechanical-no-behavior-change exemption.
25
+
26
+ ## Prior-Art Survey rendering
27
+
28
+ The section must contain exactly one fenced `json` block and no alternate survey result in prose or another code block. Parse that block as JSON and validate it against `skills/ce-plan/references/prior-art-survey-schema.json`; a missing, malformed, schema-invalid, or placeholder block is not a survey result. Preserve the contract's field names, including `schema_version`, `verdict`, `scope`, `freshness`, `budget`, and `candidates`. Each candidate must name what it owns in the code's vocabulary and its disposition. Include `scopes_considered` for an `unscoped` verdict and `acceptance` only when the user accepts an `unscoped` or `unresolved` verdict. An `unscoped` or `unresolved` result without that acceptance record remains a planning blocker, not explanatory prose.
29
+
22
30
  ## Decide whether a plan doc is warranted at all
23
31
 
24
32
  Not every invocation of `ce:plan` should produce a plan document. For
@@ -0,0 +1,307 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Prior-Art Survey",
4
+ "description": "Machine-checkable output contract for a bounded prior-art survey.",
5
+ "$ref": "#/definitions/survey",
6
+ "definitions": {
7
+ "verdict": {
8
+ "type": "string",
9
+ "enum": [
10
+ "reuse",
11
+ "extend",
12
+ "build-new-within-scope",
13
+ "unscoped",
14
+ "unresolved"
15
+ ]
16
+ },
17
+ "budget": {
18
+ "type": "object",
19
+ "required": [
20
+ "max_search_passes",
21
+ "max_candidate_inspections",
22
+ "exhausted"
23
+ ],
24
+ "properties": {
25
+ "max_search_passes": {
26
+ "type": "integer",
27
+ "minimum": 1,
28
+ "maximum": 32,
29
+ "description": "Maximum number of bounded search passes permitted."
30
+ },
31
+ "max_candidate_inspections": {
32
+ "type": "integer",
33
+ "minimum": 1,
34
+ "maximum": 100,
35
+ "description": "Maximum number of candidate inspections permitted."
36
+ },
37
+ "exhausted": {
38
+ "type": "boolean",
39
+ "description": "Whether the stated search budget was exhausted."
40
+ }
41
+ },
42
+ "additionalProperties": false
43
+ },
44
+ "freshness": {
45
+ "type": "object",
46
+ "properties": {
47
+ "vcs_reference": {
48
+ "type": "string",
49
+ "minLength": 1,
50
+ "maxLength": 256,
51
+ "pattern": "\\S",
52
+ "description": "VCS revision or equivalent reference for the surveyed scope, when available."
53
+ },
54
+ "scope_baseline": {
55
+ "type": "string",
56
+ "minLength": 1,
57
+ "maxLength": 2048,
58
+ "pattern": "\\S",
59
+ "description": "Portable digest or compact baseline for the surveyed scope when VCS history is unavailable."
60
+ }
61
+ },
62
+ "additionalProperties": false,
63
+ "anyOf": [
64
+ {
65
+ "required": ["vcs_reference"]
66
+ },
67
+ {
68
+ "required": ["scope_baseline"]
69
+ }
70
+ ]
71
+ },
72
+ "candidate": {
73
+ "type": "object",
74
+ "required": ["path_or_symbol", "description", "disposition"],
75
+ "properties": {
76
+ "path_or_symbol": {
77
+ "type": "string",
78
+ "minLength": 1,
79
+ "maxLength": 256,
80
+ "pattern": "\\S",
81
+ "description": "Repository-relative path or source symbol identifying the candidate."
82
+ },
83
+ "description": {
84
+ "type": "string",
85
+ "minLength": 1,
86
+ "maxLength": 500,
87
+ "pattern": "\\S",
88
+ "description": "What the candidate owns, described in the code's own vocabulary."
89
+ },
90
+ "disposition": {
91
+ "type": "string",
92
+ "enum": ["reuse", "extend", "insufficient", "undispositioned"],
93
+ "description": "The survey's disposition of this candidate."
94
+ },
95
+ "insufficiency_reason": {
96
+ "type": "string",
97
+ "minLength": 1,
98
+ "maxLength": 500,
99
+ "pattern": "\\S",
100
+ "description": "Why this candidate cannot satisfy the concern within the surveyed scope."
101
+ }
102
+ },
103
+ "additionalProperties": false
104
+ },
105
+ "acceptance": {
106
+ "type": "object",
107
+ "required": ["accepted_by_user", "accepted_verdict", "reason"],
108
+ "properties": {
109
+ "accepted_by_user": {
110
+ "const": true,
111
+ "description": "Explicit marker that a user accepted the unresolved survey state."
112
+ },
113
+ "accepted_verdict": {
114
+ "type": "string",
115
+ "enum": ["unscoped", "unresolved"],
116
+ "description": "The unscoped or unresolved verdict the user accepted."
117
+ },
118
+ "reason": {
119
+ "type": "string",
120
+ "minLength": 1,
121
+ "maxLength": 500,
122
+ "pattern": "\\S",
123
+ "description": "What the user accepted and why planning may proceed."
124
+ }
125
+ },
126
+ "additionalProperties": false
127
+ },
128
+ "survey": {
129
+ "type": "object",
130
+ "required": [
131
+ "schema_version",
132
+ "verdict",
133
+ "scope",
134
+ "freshness",
135
+ "budget",
136
+ "candidates"
137
+ ],
138
+ "properties": {
139
+ "schema_version": {
140
+ "const": 1,
141
+ "description": "Version discriminator for this survey contract."
142
+ },
143
+ "verdict": {
144
+ "$ref": "#/definitions/verdict"
145
+ },
146
+ "scope": {
147
+ "type": "string",
148
+ "minLength": 1,
149
+ "maxLength": 256,
150
+ "pattern": "\\S",
151
+ "description": "Workspace or subtree searched by this survey."
152
+ },
153
+ "freshness": {
154
+ "$ref": "#/definitions/freshness"
155
+ },
156
+ "budget": {
157
+ "$ref": "#/definitions/budget"
158
+ },
159
+ "candidates": {
160
+ "type": "array",
161
+ "maxItems": 32,
162
+ "items": {
163
+ "$ref": "#/definitions/candidate"
164
+ },
165
+ "description": "Complete candidate inventory collected before dispositioning. Empty is the only absence representation."
166
+ },
167
+ "scopes_considered": {
168
+ "type": "array",
169
+ "minItems": 1,
170
+ "maxItems": 8,
171
+ "items": {
172
+ "type": "string",
173
+ "minLength": 1,
174
+ "maxLength": 256,
175
+ "pattern": "\\S"
176
+ },
177
+ "description": "Alternative scopes considered when no defensible survey scope could be selected."
178
+ },
179
+ "acceptance": {
180
+ "$ref": "#/definitions/acceptance"
181
+ }
182
+ },
183
+ "additionalProperties": false,
184
+ "allOf": [
185
+ {
186
+ "if": {
187
+ "properties": {
188
+ "verdict": {
189
+ "const": "build-new-within-scope"
190
+ }
191
+ }
192
+ },
193
+ "then": {
194
+ "properties": {
195
+ "candidates": {
196
+ "minItems": 1,
197
+ "items": {
198
+ "allOf": [
199
+ {
200
+ "required": ["insufficiency_reason"]
201
+ },
202
+ {
203
+ "properties": {
204
+ "disposition": {
205
+ "const": "insufficient"
206
+ }
207
+ }
208
+ }
209
+ ]
210
+ }
211
+ }
212
+ }
213
+ }
214
+ },
215
+ {
216
+ "if": {
217
+ "properties": {
218
+ "verdict": {
219
+ "const": "unscoped"
220
+ }
221
+ }
222
+ },
223
+ "then": {
224
+ "required": ["scopes_considered"]
225
+ }
226
+ },
227
+ {
228
+ "if": {
229
+ "properties": {
230
+ "verdict": {
231
+ "const": "unresolved"
232
+ }
233
+ }
234
+ },
235
+ "then": {
236
+ "properties": {
237
+ "candidates": {
238
+ "contains": {
239
+ "properties": {
240
+ "disposition": {
241
+ "const": "undispositioned"
242
+ }
243
+ },
244
+ "required": ["disposition"]
245
+ }
246
+ }
247
+ }
248
+ }
249
+ },
250
+ {
251
+ "if": {
252
+ "required": ["acceptance"]
253
+ },
254
+ "then": {
255
+ "properties": {
256
+ "verdict": {
257
+ "enum": ["unscoped", "unresolved"]
258
+ }
259
+ }
260
+ }
261
+ },
262
+ {
263
+ "if": {
264
+ "required": ["verdict", "acceptance"],
265
+ "properties": {
266
+ "verdict": {
267
+ "const": "unscoped"
268
+ }
269
+ }
270
+ },
271
+ "then": {
272
+ "properties": {
273
+ "acceptance": {
274
+ "properties": {
275
+ "accepted_verdict": {
276
+ "const": "unscoped"
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }
282
+ },
283
+ {
284
+ "if": {
285
+ "required": ["verdict", "acceptance"],
286
+ "properties": {
287
+ "verdict": {
288
+ "const": "unresolved"
289
+ }
290
+ }
291
+ },
292
+ "then": {
293
+ "properties": {
294
+ "acceptance": {
295
+ "properties": {
296
+ "accepted_verdict": {
297
+ "const": "unresolved"
298
+ }
299
+ }
300
+ }
301
+ }
302
+ }
303
+ }
304
+ ]
305
+ }
306
+ }
307
+ }
@@ -53,6 +53,12 @@ Determine how to proceed based on what was provided in `<input_document>`.
53
53
  - Check for a `Deferred to Implementation` or `Implementation-Time Unknowns` section — these are questions the planner intentionally left for you to resolve during execution. Note them before starting so they inform your approach rather than surprising you mid-task
54
54
  - Check for a `Scope Boundaries` section — these are explicit non-goals. Refer back to them if implementation starts pulling you toward adjacent work
55
55
  - Review any references or links provided in the plan
56
+ - If the plan has no `Prior-Art Survey` section at all, it predates this contract — proceed without rejecting it. Otherwise validate the section before environment setup: it must contain exactly one fenced `json` block, and that block must validate against `skills/ce-plan/references/prior-art-survey-schema.json`. Stop before setup when any of these conditions applies:
57
+ 1. **Empty or non-unique survey block:** the section is present but empty, or contains zero or multiple fenced `json` blocks. Resolve it by rerunning planning and recording exactly one schema-conforming structured survey block.
58
+ 2. **Malformed or schema-invalid survey block:** the sole block is not valid JSON or fails schema validation. Resolve it by replacing the block with one valid survey payload; prose or placeholder values do not satisfy the contract.
59
+ 3. **Unaccepted failure verdict:** the validated verdict is `unscoped` or `unresolved` and the block has no recorded user acceptance for that same verdict. Resolve it by narrowing the scope, increasing the bounded budget, or getting the user to accept the uncertainty and recording matching acceptance.
60
+ 4. **Stale surveyed scope:** the recorded scope has changed since the survey ran. Check only the workspace or subtree in `scope`, not the whole repository. When `freshness.vcs_reference` is present and usable VCS data is available, compare the current VCS reference or scoped diff; otherwise compare the current portable digest/baseline with `freshness.scope_baseline`. If neither comparison can be performed, stop and request a fresh survey or explicit re-baselining rather than assuming the result is fresh. Resolve a stale result by rerunning the survey against the current scope and updating the plan.
61
+ - When refusing execution for a survey condition, name the condition that fired and the concrete resolution required; do not fail opaquely.
56
62
  - If the user explicitly asks for TDD, test-first, or characterization-first execution in this session, honor that request even if the plan has no `Execution note`
57
63
  - If anything is unclear or ambiguous, ask clarifying questions now
58
64
  - Get user approval to proceed
@@ -22,16 +22,26 @@ task({
22
22
 
23
23
  // Background dispatch (run independent work concurrently; reconcile on completion):
24
24
  task({
25
- subagent_type: "explorer",
25
+ subagent_type: "repo-research-analyst",
26
26
  description: "Map fixture patterns",
27
27
  prompt: "…",
28
28
  background: true,
29
29
  })
30
30
 
31
31
  // Resume a prior specialist session:
32
- task({ subagent_type: "fixer", task_id: "<prior-session-id>", description: "Resume fixer task", prompt: "…" })
32
+ task({ subagent_type: "systematic-implementer", task_id: "<prior-session-id>", description: "Resume the implementation task", prompt: "…" })
33
33
  ```
34
34
 
35
+ `subagent_type` takes a bare agent stem — OpenCode registers bundled agents under
36
+ their filename stem, not a namespaced identifier. Prose that *refers* to an agent
37
+ uses the canonical `systematic:<category>:<name>` form instead, which the
38
+ content-integrity gate validates against real agent files.
39
+
40
+ Both forms are enforced. Examples in bundled content must name agents this
41
+ package actually ships, so they work for every reader. A host may provide
42
+ additional agents through the user's own configuration; those are available at
43
+ runtime but must not appear in bundled examples.
44
+
35
45
  ### Blocking user interaction
36
46
 
37
47
  ```typescript