@fro.bot/systematic 3.11.0 → 3.12.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.
@@ -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. For that verdict, inspect every `excluded_scopes` entry: if the concern plausibly belongs in an excluded scope, the survey's boundary is inadequate and return a finding. 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,59 @@ 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. If the verdict is `build-new-within-scope`, also record every adjacent scope you considered but deliberately did not search, with the reason for each exclusion. Emit `excluded_scopes: []` when the surveyed scope has no adjacent scopes; do not omit the field or use an empty list to mean that exclusions were not considered.
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: 2`. 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": 2,
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
+ "excluded_scopes": [
189
+ {
190
+ "scope": "<adjacent scope considered but not searched>",
191
+ "reason": "<why this adjacent scope was deliberately not searched>"
192
+ }
193
+ ],
194
+ "scopes_considered": ["<required for an unscoped verdict>"],
195
+ "acceptance": {
196
+ "accepted_by_user": true,
197
+ "accepted_verdict": "unscoped | unresolved",
198
+ "reason": "<what the user accepted>"
199
+ }
200
+ }
201
+ ```
202
+
203
+ Use exactly one verdict. `build-new-within-scope` requires at least one candidate, every candidate must have disposition `insufficient`, every candidate must include `insufficiency_reason`, and `excluded_scopes` must be present. Each excluded scope entry must include a non-blank `scope` and a reason; use `excluded_scopes: []` only when no adjacent scopes exist. `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.
204
+
205
+ ---
206
+
153
207
  **Core Responsibilities:**
154
208
 
155
209
  1. **Architecture and Structure Analysis**
@@ -190,7 +244,7 @@ This context informs all subsequent research phases -- use it to focus documenta
190
244
  2. Start with high-level documentation to understand project context
191
245
  3. Progressively drill down into specific areas based on findings
192
246
  4. Cross-reference discoveries across different sources
193
- 5. Prioritize official documentation over inferred patterns
247
+ 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
248
  6. Note any inconsistencies or areas lacking documentation
195
249
 
196
250
  **Output Format:**
@@ -232,6 +286,18 @@ Structure your findings as:
232
286
  - Naming conventions
233
287
  - Project-specific practices
234
288
 
289
+ ### Prior-Art Survey
290
+ - Concern framing: trigger, effect, state, and integration boundary
291
+ - A structured result conforming to `skills/ce-plan/references/prior-art-survey-schema.json`
292
+ - `schema_version: 2` and a `freshness` record with at least one of `vcs_reference` or `scope_baseline`
293
+ - Exactly one verdict: `reuse`, `extend`, `build-new-within-scope`, `unscoped`, or `unresolved`
294
+ - The searched workspace or subtree in `scope`, plus bounded `budget` fields and whether the budget was exhausted
295
+ - A complete `candidates` inventory with each path or symbol, code-vocabulary ownership description, and disposition
296
+ - For `build-new-within-scope`, a non-empty candidate list whose candidates all explain their insufficiency, plus `excluded_scopes` entries naming adjacent scopes deliberately not searched and why (or an explicit empty list when none are adjacent)
297
+ - For `unscoped`, a non-empty `scopes_considered` list; for `unresolved`, at least one `undispositioned` candidate while preserving reached dispositions
298
+ - An optional `acceptance` record only when a user accepted an `unscoped` or `unresolved` verdict
299
+ - Absence represented only by the searched scope, budget, and an empty candidate list; never assert an unbounded absence
300
+
235
301
  ### Recommendations
236
302
  - How to best align with project conventions
237
303
  - 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.11.0",
3
+ "version": "3.12.1",
4
4
  "description": "Compound-engineering loops for OpenCode, Pi, and Claude Code",
5
5
  "type": "module",
6
6
  "homepage": "https://fro.bot/systematic",
@@ -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": 2,
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,335 @@
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": 2,
141
+ "description": "Version discriminator for this survey contract. Bumped to 2 when excluded_scopes became conditionally required for a build-new-within-scope verdict."
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
+ "excluded_scopes": {
180
+ "type": "array",
181
+ "minItems": 0,
182
+ "maxItems": 8,
183
+ "items": {
184
+ "type": "object",
185
+ "required": ["scope", "reason"],
186
+ "properties": {
187
+ "scope": {
188
+ "type": "string",
189
+ "minLength": 1,
190
+ "maxLength": 256,
191
+ "pattern": "\\S",
192
+ "description": "Adjacent scope considered but deliberately not searched."
193
+ },
194
+ "reason": {
195
+ "type": "string",
196
+ "minLength": 1,
197
+ "maxLength": 500,
198
+ "pattern": "\\S",
199
+ "description": "Why the adjacent scope was deliberately not searched."
200
+ }
201
+ },
202
+ "additionalProperties": false
203
+ },
204
+ "description": "Adjacent scopes considered but not searched, with a reason for each exclusion. An empty list explicitly means no adjacent scopes exist."
205
+ },
206
+ "acceptance": {
207
+ "$ref": "#/definitions/acceptance"
208
+ }
209
+ },
210
+ "additionalProperties": false,
211
+ "allOf": [
212
+ {
213
+ "if": {
214
+ "properties": {
215
+ "verdict": {
216
+ "const": "build-new-within-scope"
217
+ }
218
+ }
219
+ },
220
+ "then": {
221
+ "required": ["excluded_scopes"],
222
+ "properties": {
223
+ "candidates": {
224
+ "minItems": 1,
225
+ "items": {
226
+ "allOf": [
227
+ {
228
+ "required": ["insufficiency_reason"]
229
+ },
230
+ {
231
+ "properties": {
232
+ "disposition": {
233
+ "const": "insufficient"
234
+ }
235
+ }
236
+ }
237
+ ]
238
+ }
239
+ }
240
+ }
241
+ }
242
+ },
243
+ {
244
+ "if": {
245
+ "properties": {
246
+ "verdict": {
247
+ "const": "unscoped"
248
+ }
249
+ }
250
+ },
251
+ "then": {
252
+ "required": ["scopes_considered"]
253
+ }
254
+ },
255
+ {
256
+ "if": {
257
+ "properties": {
258
+ "verdict": {
259
+ "const": "unresolved"
260
+ }
261
+ }
262
+ },
263
+ "then": {
264
+ "properties": {
265
+ "candidates": {
266
+ "contains": {
267
+ "properties": {
268
+ "disposition": {
269
+ "const": "undispositioned"
270
+ }
271
+ },
272
+ "required": ["disposition"]
273
+ }
274
+ }
275
+ }
276
+ }
277
+ },
278
+ {
279
+ "if": {
280
+ "required": ["acceptance"]
281
+ },
282
+ "then": {
283
+ "properties": {
284
+ "verdict": {
285
+ "enum": ["unscoped", "unresolved"]
286
+ }
287
+ }
288
+ }
289
+ },
290
+ {
291
+ "if": {
292
+ "required": ["verdict", "acceptance"],
293
+ "properties": {
294
+ "verdict": {
295
+ "const": "unscoped"
296
+ }
297
+ }
298
+ },
299
+ "then": {
300
+ "properties": {
301
+ "acceptance": {
302
+ "properties": {
303
+ "accepted_verdict": {
304
+ "const": "unscoped"
305
+ }
306
+ }
307
+ }
308
+ }
309
+ }
310
+ },
311
+ {
312
+ "if": {
313
+ "required": ["verdict", "acceptance"],
314
+ "properties": {
315
+ "verdict": {
316
+ "const": "unresolved"
317
+ }
318
+ }
319
+ },
320
+ "then": {
321
+ "properties": {
322
+ "acceptance": {
323
+ "properties": {
324
+ "accepted_verdict": {
325
+ "const": "unresolved"
326
+ }
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ ]
333
+ }
334
+ }
335
+ }
@@ -53,6 +53,17 @@ 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
+ - Validate the plan's `Prior-Art Survey` state before environment setup using this exhaustive partition:
57
+ - **No survey section + recorded date before 2026-08-18:** the plan predates this contract; proceed without rejecting it. Read the plan's YAML frontmatter `date:` first. If that is absent, use only another explicit, trustworthy creation date defined by the host workflow or document format; a filename, location, or VCS record counts only when the host explicitly defines it as authoritative, and version control is never required.
58
+ - **No survey section + recorded date on or after 2026-08-18:** this is a contract failure; stop and name the missing section. Resolve it by rerunning planning and recording exactly one schema-conforming structured survey block.
59
+ - **No survey section + no determinable date:** do not guess whether the plan is old or recent. Stop and report that the grandfather condition cannot be established. Resolve it by recording a trustworthy plan date; if the date cannot be established, rerun planning and add the required survey rather than proceeding on an assumption.
60
+ - **Survey section present and valid:** it contains exactly one fenced `json` block, and that block validates against `skills/ce-plan/references/prior-art-survey-schema.json`; continue to the remaining workflow checks below. A present section is never grandfathered by its date.
61
+ - **Survey section present and invalid:** stop before setup when any of these conditions applies:
62
+ 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.
63
+ 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.
64
+ 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.
65
+ 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.
66
+ - When refusing execution for a survey condition, name the condition that fired and the concrete resolution required; do not fail opaquely.
56
67
  - 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
68
  - If anything is unclear or ambiguous, ask clarifying questions now
58
69
  - Get user approval to proceed