@davidorex/pi-jit-agents 0.26.0 → 0.28.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +2 -2
  3. package/dist/compile.d.ts.map +1 -1
  4. package/dist/compile.js +9 -3
  5. package/dist/compile.js.map +1 -1
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -2
  9. package/dist/index.js.map +1 -1
  10. package/dist/jit-runtime.d.ts +11 -0
  11. package/dist/jit-runtime.d.ts.map +1 -1
  12. package/dist/jit-runtime.js +36 -0
  13. package/dist/jit-runtime.js.map +1 -1
  14. package/dist/renderer-registry.d.ts +23 -7
  15. package/dist/renderer-registry.d.ts.map +1 -1
  16. package/dist/renderer-registry.js +34 -21
  17. package/dist/renderer-registry.js.map +1 -1
  18. package/dist/template.d.ts +15 -0
  19. package/dist/template.d.ts.map +1 -1
  20. package/dist/template.js +19 -0
  21. package/dist/template.js.map +1 -1
  22. package/dist/types.d.ts +4 -0
  23. package/dist/types.d.ts.map +1 -1
  24. package/package.json +7 -3
  25. package/schemas/agent-trace.schema.json +30 -2
  26. package/templates/analyzers/base-analyzer.md +9 -0
  27. package/templates/analyzers/patterns-task.md +11 -0
  28. package/templates/analyzers/patterns.md +15 -0
  29. package/templates/analyzers/quality-task.md +11 -0
  30. package/templates/analyzers/quality.md +15 -0
  31. package/templates/analyzers/structure-task.md +17 -0
  32. package/templates/analyzers/structure.md +15 -0
  33. package/templates/architecture-designer/task.md +117 -0
  34. package/templates/architecture-inferrer/task.md +61 -0
  35. package/templates/audit-finding-verifier/task.md +59 -0
  36. package/templates/audit-fixer/task.md +67 -0
  37. package/templates/audit-results-router/task.md +37 -0
  38. package/templates/decomposer/task.md +56 -0
  39. package/templates/explorer/system.md +3 -0
  40. package/templates/explorer/task.md +9 -0
  41. package/templates/gap-identifier/task.md +103 -0
  42. package/templates/gap-resolution-assessor/task.md +48 -0
  43. package/templates/handoff-writer/task.md +101 -0
  44. package/templates/investigator/task.md +30 -0
  45. package/templates/items/architecture.md +33 -0
  46. package/templates/items/conformance.md +26 -0
  47. package/templates/items/conventions.md +19 -0
  48. package/templates/items/decisions.md +47 -0
  49. package/templates/items/domain.md +21 -0
  50. package/templates/items/features.md +63 -0
  51. package/templates/items/framework-gaps.md +43 -0
  52. package/templates/items/issues.md +21 -0
  53. package/templates/items/layer-plans.md +50 -0
  54. package/templates/items/project.md +48 -0
  55. package/templates/items/requirements.md +20 -0
  56. package/templates/items/research.md +57 -0
  57. package/templates/items/spec-reviews.md +51 -0
  58. package/templates/items/tasks.md +29 -0
  59. package/templates/phase-author/task.md +82 -0
  60. package/templates/plan-creator/task.md +143 -0
  61. package/templates/plan-decomposer/task.md +46 -0
  62. package/templates/project-definer/task.md +67 -0
  63. package/templates/project-inferrer/task.md +56 -0
  64. package/templates/requirements-gatherer/task.md +90 -0
  65. package/templates/researcher/task.md +26 -0
  66. package/templates/shared/macros.md +169 -0
  67. package/templates/shared/render-helpers.md +106 -0
  68. package/templates/spec-implementer/task.md +53 -0
  69. package/templates/synthesizer/system.md +3 -0
  70. package/templates/synthesizer/task.md +38 -0
  71. package/templates/task-verifier/task.md +44 -0
  72. package/templates/task-worker/task.md +52 -0
  73. package/templates/verifier/task.md +57 -0
@@ -0,0 +1,169 @@
1
+ {#- Block rendering macros — whole-block forms as derived views over per-item macros.
2
+
3
+ Plan 8 (Wave 4) refactor: each whole-block macro that has a per-item sibling
4
+ in templates/items/<kind>.md delegates to that per-item macro by mapping
5
+ over the items array. Per-item macros own field rendering; whole-block macros
6
+ own the surrounding heading and the null/empty guard.
7
+
8
+ v0.24.2 follow-up (Item 3 of 2026-05-02 residual-debt patch): the
9
+ repeated `{% if data and data.<key> [and data.<key> | length > 0] %}` +
10
+ `## <Heading>` + `{% for x in data.<key> %}{{ render_<kind>_item(x) }}
11
+ {% endfor %}` shape that previously lived inline in render_requirements,
12
+ render_domain, render_tasks, and render_issues now routes through the
13
+ `render_whole_block_truthy` / `render_whole_block_nonempty` scaffolds in
14
+ shared/render-helpers.md. The guard / heading / loop chassis lives once
15
+ in render-helpers; each whole-block macro here is the per-kind binding
16
+ (heading text, items slice, per-item macro inside the `{% call %}` body).
17
+ Output stays byte-identical to the prior inline shape — the two
18
+ truthy-vs-nonempty helpers preserve the empty-array surface each
19
+ delegator originally shipped (tasks/issues/domain emit `## <Heading>`
20
+ with empty array; requirements emits nothing — both regimes are kept
21
+ explicitly so existing consumers see no diff).
22
+
23
+ Imports for downstream consumers (unchanged signatures):
24
+ {% from "shared/macros.md" import render_project, render_architecture,
25
+ render_requirements, render_conformance,
26
+ render_domain, render_tasks, render_issues,
27
+ render_conventions,
28
+ render_exploration, render_exploration_full %}
29
+
30
+ Each macro:
31
+ - null/empty guard via the helper or local conditional,
32
+ - markdown heading (via the helper for list kinds; inline for the
33
+ singletons and the heading-bearing block-level shapes),
34
+ - delegation loop calling the per-item macro per item.
35
+
36
+ Retired in Plan 8:
37
+ - render_decisions(data) — legacy whole-block decisions macro deleted.
38
+ The new lifecycle decisions block has its own per-item macro
39
+ (templates/items/decisions.md ships render_decision + alias
40
+ render_decisions). The legacy macro rendered fields (decision,
41
+ rationale) that no longer match the current decisions.schema.json.
42
+ - render_gap(gap) — legacy single-item validation-concept macro deleted.
43
+ The framework-gaps.json block uses Plan 7's render_framework_gap in
44
+ templates/items/framework-gaps.md.
45
+
46
+ Retained as-is:
47
+ - render_exploration(exploration) and render_exploration_full(exploration)
48
+ are workflow-step output formatters (rendering exploration payloads
49
+ emitted by exploration agents), not project-block renderers. They do
50
+ not fit the per-item refactor pattern and stay unchanged. -#}
51
+
52
+ {% from "shared/render-helpers.md" import render_whole_block_truthy, render_whole_block_nonempty %}
53
+
54
+ {% from "items/project.md" import render_project_item %}
55
+ {% macro render_project(data) %}
56
+ {% if data %}{{ render_project_item(data) }}{% endif %}
57
+ {% endmacro %}
58
+
59
+ {% from "items/architecture.md" import render_architecture_item %}
60
+ {% macro render_architecture(data) %}
61
+ {% if data %}{{ render_architecture_item(data) }}{% endif %}
62
+ {% endmacro %}
63
+
64
+ {% from "items/requirements.md" import render_requirement %}
65
+ {% macro render_requirements(data) %}{% call(req) render_whole_block_nonempty("Requirements", data.requirements if data else None) %}{{ render_requirement(req) }}{% endcall %}{% endmacro %}
66
+
67
+ {% from "items/conformance.md" import render_conformance_principle %}
68
+ {% macro render_conformance(data) %}
69
+ {% if data and data.principles %}
70
+ ## Conformance Reference
71
+ {% if data.name %}**{{ data.name }}**{% endif %}
72
+ {% for p in data.principles %}{{ render_conformance_principle(p) }}{% endfor %}
73
+ {% endif %}
74
+ {% endmacro %}
75
+
76
+ {% from "items/domain.md" import render_domain_entry %}
77
+ {% macro render_domain(data) %}{% call(e) render_whole_block_truthy("Domain Knowledge", data.entries if data else None) %}{{ render_domain_entry(e) }}{% endcall %}{% endmacro %}
78
+
79
+ {% from "items/tasks.md" import render_task %}
80
+ {% macro render_tasks(data) %}{% call(t) render_whole_block_truthy("Tasks", data.tasks if data else None) %}{{ render_task(t) }}{% endcall %}{% endmacro %}
81
+
82
+ {% from "items/issues.md" import render_issue %}
83
+ {% macro render_issues(data) %}{% call(i) render_whole_block_truthy("Issues", data.issues if data else None) %}{{ render_issue(i) }}{% endcall %}{% endmacro %}
84
+
85
+ {#- 6 whole-block delegators landed via the template-relocation arc. Each
86
+ delegates to the per-item macro from items/<kind>.md through
87
+ render_whole_block_truthy. Names follow the plural convention
88
+ (render_<plural-kind>). The display_name string and array_key are
89
+ sourced from packages/pi-context/samples/conception.json verbatim;
90
+ array_key diverges from block_kind for 3 of these 6 (framework-gaps→
91
+ gaps, layer-plans→plans, spec-reviews→reviews). The canonical macro
92
+ name + the array_key are also encoded in CANONICAL_MACRO_NAMES at
93
+ packages/pi-jit-agents/src/renderer-registry.ts for programmatic
94
+ resolution. Alphabetical by block_kind. -#}
95
+
96
+ {% from "items/decisions.md" import render_decision %}
97
+ {% macro render_decisions(data) %}{% call(d) render_whole_block_truthy("Decisions", data.decisions if data else None) %}{{ render_decision(d) }}{% endcall %}{% endmacro %}
98
+
99
+ {% from "items/features.md" import render_feature %}
100
+ {% macro render_features(data) %}{% call(f) render_whole_block_truthy("Features", data.features if data else None) %}{{ render_feature(f) }}{% endcall %}{% endmacro %}
101
+
102
+ {% from "items/framework-gaps.md" import render_framework_gap %}
103
+ {% macro render_framework_gaps(data) %}{% call(g) render_whole_block_truthy("Framework Gaps", data.gaps if data else None) %}{{ render_framework_gap(g) }}{% endcall %}{% endmacro %}
104
+
105
+ {% from "items/layer-plans.md" import render_layer_plan %}
106
+ {% macro render_layer_plans(data) %}{% call(p) render_whole_block_truthy("Layer Restructure Plans", data.plans if data else None) %}{{ render_layer_plan(p) }}{% endcall %}{% endmacro %}
107
+
108
+ {#- research per-item macro is itself named render_research (the canonical
109
+ per-item name in CANONICAL_MACRO_NAMES); alias on import to avoid the
110
+ name collision with the whole-block delegator declared just below. -#}
111
+ {% from "items/research.md" import render_research as render_research_item %}
112
+ {% macro render_research(data) %}{% call(r) render_whole_block_truthy("Research", data.research if data else None) %}{{ render_research_item(r) }}{% endcall %}{% endmacro %}
113
+
114
+ {% from "items/spec-reviews.md" import render_spec_review %}
115
+ {% macro render_spec_reviews(data) %}{% call(rev) render_whole_block_truthy("Spec Reviews", data.reviews if data else None) %}{{ render_spec_review(rev) }}{% endcall %}{% endmacro %}
116
+
117
+ {#- Authored fresh in Plan 8: render_conventions did not previously exist in
118
+ macros.md despite README references implying it did. The block-level
119
+ header surfaces test_conventions, lint_command, and lint_scope (all
120
+ optional) before iterating rules through render_convention.
121
+
122
+ Block schema: .project/schemas/conventions.schema.json. Required: rules.
123
+ Optional: test_conventions { runner_command, file_pattern }, lint_command,
124
+ lint_scope. -#}
125
+ {% from "items/conventions.md" import render_convention %}
126
+ {% macro render_conventions(data) %}
127
+ {% if data and data.rules %}
128
+ ## Conventions
129
+ {% if data.test_conventions %}
130
+ **Tests:** `{{ data.test_conventions.runner_command }}` (pattern: `{{ data.test_conventions.file_pattern }}`)
131
+ {% endif %}{% if data.lint_command %}**Lint:** `{{ data.lint_command }}`{% if data.lint_scope %} (scope: {{ data.lint_scope }}){% endif %}
132
+ {% endif %}
133
+ {% for rule in data.rules %}{{ render_convention(rule) }}{% endfor %}
134
+ {% endif %}
135
+ {% endmacro %}
136
+
137
+ {% macro render_exploration(exploration) %}
138
+ {% if exploration %}
139
+ {% if exploration.files is defined %}
140
+ ## Prior Exploration
141
+ {% for file in exploration.files %}- `{{ file.path }}` ({{ file.lines | default("?") }} lines){% if file.exports %}: {{ file.exports | length }} exports{% endif %}
142
+ {% endfor %}{% endif %}
143
+ {% if exploration.types is defined %}
144
+ ### Known Types
145
+ {% for t in exploration.types %}- `{{ t.name }}` ({{ t.kind }}) in `{{ t.file }}`
146
+ {% endfor %}{% endif %}
147
+ {% endif %}
148
+ {% endmacro %}
149
+
150
+ {% macro render_exploration_full(exploration) %}
151
+ {% if exploration %}
152
+ {% if exploration.files is defined %}
153
+ ### Files{% if exploration.files | length > 20 %} ({{ exploration.files | length }} total){% endif %}
154
+ {% for file in exploration.files %}- `{{ file.path }}` ({{ file.language | default("unknown") }}, {{ file.lines | default("?") }} lines){% if file.exports %} — {{ file.exports | length }} exports{% endif %}
155
+ {% endfor %}{% endif %}
156
+ {% if exploration.types is defined %}
157
+ ### Types
158
+ {% for t in exploration.types %}- `{{ t.name }}` ({{ t.kind }}) in `{{ t.file }}`
159
+ {% endfor %}{% endif %}
160
+ {% if exploration.dependencies is defined %}
161
+ ### Dependencies
162
+ {% for d in exploration.dependencies %}- `{{ d.from }}` → `{{ d.to }}` ({{ d.type | default("import") }})
163
+ {% endfor %}{% endif %}
164
+ {% if exploration.entryPoints is defined %}
165
+ ### Entry Points
166
+ {% for ep in exploration.entryPoints %}- `{{ ep }}`
167
+ {% endfor %}{% endif %}
168
+ {% endif %}
169
+ {% endmacro %}
@@ -0,0 +1,106 @@
1
+ {#-
2
+ Shared rendering helpers for per-item macros.
3
+
4
+ Captures repeated micro-patterns that previously lived inline in every
5
+ per-item macro file under `items/*.md`. The aim is one definition per
6
+ pattern, consumed by every per-item macro that uses it.
7
+
8
+ Helpers exported:
9
+ render_id_list_block(label, ids, depth)
10
+ render_id_single_block(label, id, depth)
11
+ render_id_list_inline(label, ids, depth)
12
+ render_id_single_inline(label, id, depth)
13
+ render_optional_scalar(label, value)
14
+
15
+ Output convention:
16
+ Block-style helpers emit `<Label>:\n` followed by ` - <id>\n` per entry
17
+ (or ` (none)\n` for present-but-empty arrays). Absent (undefined)
18
+ arrays emit nothing.
19
+
20
+ Inline-style helpers emit ` <Label>: <id>[, <id>...]\n` (or `(none)\n`
21
+ for empty). The two-space indent prefix is part of the inline shape used
22
+ by domain.related_requirements, requirements.traces_to/depends_on, and
23
+ tasks.depends_on/verification — it is the indent under a parent list
24
+ bullet, not arbitrary padding.
25
+
26
+ Depth contract:
27
+ Each helper that takes `depth` honours the same recursion budget as the
28
+ per-item macros: depth <= 0 emits bare ID text; depth > 0 calls resolve
29
+ + render_recursive (ambient Nunjucks globals registered by compileAgent
30
+ in @davidorex/pi-jit-agents) and falls back to bare-ID on resolve miss.
31
+ Cycles → `[cycle: <id>]` and missing per-item macros → `[unrendered:
32
+ <kind>/<id>]` are produced inside render_recursive itself, not here.
33
+
34
+ resolve(id) and render_recursive(loc, depth) are env-level globals
35
+ available to imported macros without re-import.
36
+
37
+ Empty-array convention:
38
+ `is defined` discriminates absent vs present. Present-but-empty arrays
39
+ render the label with `(none)`; absent fields render nothing. This
40
+ preserves the per-item macro contract documented in items/decisions.md
41
+ and mirrored across every per-item macro.
42
+
43
+ Output equivalence:
44
+ The helper bodies are byte-identical to the patterns they replace. The
45
+ existing render-*.test.ts assertions are the regression net. If a
46
+ helper drifts from the inline pattern's output, those tests break.
47
+ -#}
48
+
49
+ {% macro render_id_list_block(label, ids, depth) %}{% if ids is defined %}{{ label }}:
50
+ {% if ids | length > 0 %}{% for id in ids %}{% if depth > 0 %}{% set loc = resolve(id) %}{% if loc %}{{ render_recursive(loc, depth - 1) }}
51
+ {% else %} - {{ id }}
52
+ {% endif %}{% else %} - {{ id }}
53
+ {% endif %}{% endfor %}{% else %} (none)
54
+ {% endif %}{% endif %}{% endmacro %}
55
+
56
+ {% macro render_id_single_block(label, id, depth) %}{% if id is defined and id %}{{ label }}:
57
+ {% if depth > 0 %}{% set loc = resolve(id) %}{% if loc %}{{ render_recursive(loc, depth - 1) }}
58
+ {% else %} - {{ id }}
59
+ {% endif %}{% else %} - {{ id }}
60
+ {% endif %}{% endif %}{% endmacro %}
61
+
62
+ {% macro render_id_list_inline(label, ids, depth) %}{% if ids is defined %} {{ label }}: {% if ids | length > 0 %}{% for id in ids %}{% if depth > 0 %}{% set loc = resolve(id) %}{% if loc %}{{ render_recursive(loc, depth - 1) }}{% else %}{{ id }}{% endif %}{% else %}{{ id }}{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% else %}(none){% endif %}
63
+ {% endif %}{% endmacro %}
64
+
65
+ {% macro render_id_single_inline(label, id, depth) %}{% if id %} {{ label }}: {% if depth > 0 %}{% set loc = resolve(id) %}{% if loc %}{{ render_recursive(loc, depth - 1) }}{% else %}{{ id }}{% endif %}{% else %}{{ id }}{% endif %}
66
+ {% endif %}{% endmacro %}
67
+
68
+ {% macro render_optional_scalar(label, value) %}{% if value %}{{ label }}: {{ value }}
69
+ {% endif %}{% endmacro %}
70
+
71
+ {#-
72
+ Whole-block list scaffold (Plan 8 follow-up).
73
+
74
+ Centralises the truthy-guard + heading + per-item iteration shape that
75
+ previously repeated across the whole-block delegators in shared/macros.md
76
+ for `render_domain`, `render_tasks`, and `render_issues`. Each delegator
77
+ now reduces to one `{% call %}` block that supplies the per-item macro as
78
+ its body — the heading-and-loop chassis lives here once.
79
+
80
+ Two variants encode the two empty-handling regimes the legacy delegators
81
+ shipped, kept distinct so output stays byte-identical to the originals:
82
+
83
+ `render_whole_block_truthy(heading, items)`
84
+ Heading-and-loop fire whenever `items` is truthy (matches the
85
+ legacy `{% if data and data.<key> %}` guard used by tasks, issues,
86
+ domain). Empty arrays still emit the heading because `[]` is truthy
87
+ in Nunjucks — that surface is preserved deliberately.
88
+
89
+ `render_whole_block_nonempty(heading, items)`
90
+ Heading-and-loop fire only when `items | length > 0` (matches the
91
+ legacy `{% if data and data.requirements and data.requirements |
92
+ length > 0 %}` guard used by requirements). Empty arrays produce
93
+ nothing.
94
+
95
+ In both, the caller body (`{{ caller(item) }}`) is invoked once per item
96
+ with the item bound to the call-block parameter.
97
+ -#}
98
+ {% macro render_whole_block_truthy(heading, items) %}{% if items %}
99
+ ## {{ heading }}
100
+ {% for item in items %}{{ caller(item) }}{% endfor %}
101
+ {% endif %}{% endmacro %}
102
+
103
+ {% macro render_whole_block_nonempty(heading, items) %}{% if items and items | length > 0 %}
104
+ ## {{ heading }}
105
+ {% for item in items %}{{ caller(item) }}{% endfor %}
106
+ {% endif %}{% endmacro %}
@@ -0,0 +1,53 @@
1
+ ## Plan: {{ spec.name }}
2
+
3
+ ### Intent
4
+ {{ spec.intent | default(spec.description, true) }}
5
+
6
+ {% if spec.tasks %}
7
+ ### Tasks
8
+ {% for task in spec.tasks %}
9
+ {{ loop.index }}. {{ task }}
10
+ {% endfor %}
11
+ {% endif %}
12
+
13
+ ### Files to Change
14
+ {% for f in spec.files_to_change | default(spec.files, true) %}
15
+ - `{{ f }}`
16
+ {% endfor %}
17
+
18
+ ### Acceptance Criteria
19
+ {% for criterion in spec.acceptance_criteria %}
20
+ - {{ criterion }}
21
+ {% endfor %}
22
+
23
+ {% if spec.context_needed %}
24
+ ### Context to Read First
25
+ {% for ctx in spec.context_needed %}
26
+ - `{{ ctx }}`
27
+ {% endfor %}
28
+ {% endif %}
29
+
30
+ ### Architecture Reference
31
+ {% for module in architecture.modules %}
32
+ - **{{ module.name }}** ({{ module.file }}): {{ module.responsibility }}
33
+ {% endfor %}
34
+
35
+ ### Conventions
36
+ {% for rule in conventions.rules %}
37
+ - {{ rule.id }}: {{ rule.description }} ({{ rule.enforcement }})
38
+ {% endfor %}
39
+
40
+ ## Instructions
41
+
42
+ Implement this plan. Follow these steps:
43
+
44
+ 1. **Read context first**: Read the files listed under "Context to Read First" and any related source files to understand existing patterns
45
+ 2. **Implement each task**: Work through the task list in order, writing code that follows the project conventions
46
+ 3. **Run tests**: After implementation, run the relevant test suite to verify your changes work
47
+ 4. **Validate acceptance criteria**: Confirm each acceptance criterion is met
48
+
49
+ Produce a JSON result conforming to this schema:
50
+
51
+ ```json
52
+ {{ output_schema }}
53
+ ```
@@ -0,0 +1,3 @@
1
+ You are a report synthesizer. You receive typed analysis data from three independent reviewers (structure, quality, patterns) and produce a unified synthesis as structured JSON.
2
+
3
+ Every finding must trace to specific data from the input analyses. Do not invent findings that aren't grounded in the input data.
@@ -0,0 +1,38 @@
1
+ Synthesize the following analyses into a unified report.
2
+
3
+ ## Structure Analysis
4
+ Architecture: {{ structure.architecture.organization }}
5
+ Patterns: {% for p in structure.architecture.patterns %}{{ p }}{% if not loop.last %}, {% endif %}{% endfor %}
6
+
7
+ ### Modules
8
+ {% for m in structure.modules %}
9
+ - **{{ m.name }}**: {{ m.responsibility }} ({{ m.files | length }} files)
10
+ {% endfor %}
11
+
12
+ ### Dependencies
13
+ {% for d in structure.dependencies %}
14
+ - `{{ d.from }}` → `{{ d.to }}` ({{ d.type }})
15
+ {% endfor %}
16
+
17
+ ## Quality Analysis
18
+ {% for c in quality.concerns %}
19
+ - [{{ c.severity }}] {{ c.description }}{% if c.file %} in `{{ c.file }}`{% endif %}
20
+ {% endfor %}
21
+
22
+ ### Test Coverage
23
+ - Tested: {% for t in quality.testCoverage.tested %}`{{ t }}`{% if not loop.last %}, {% endif %}{% endfor %}
24
+ - Untested: {% for t in quality.testCoverage.untested %}`{{ t }}`{% if not loop.last %}, {% endif %}{% endfor %}
25
+
26
+ ### Maintainability: {{ quality.maintainability.score }}
27
+
28
+ ## Pattern Analysis
29
+ {% for p in patterns.patterns %}
30
+ - **{{ p.name }}**: {{ p.usage }}{% if not p.correct %} ⚠️{% endif %}
31
+ {% endfor %}
32
+
33
+ ### Recommendations
34
+ {% for r in patterns.recommendations %}
35
+ - [{{ r.priority }}] **{{ r.pattern }}**: {{ r.suggestion }}
36
+ {% endfor %}
37
+
38
+ Write your synthesis as JSON conforming to the output schema.
@@ -0,0 +1,44 @@
1
+ Verify whether the following task implementation satisfies its acceptance criteria.
2
+
3
+ ## Task: {{ task_id }}
4
+
5
+ ## Acceptance Criteria
6
+
7
+ {% for criterion in acceptance_criteria %}
8
+ {{ loop.index }}. {{ criterion }}
9
+ {% endfor %}
10
+
11
+ ## Implementation Changes
12
+
13
+ {% if changes is mapping %}
14
+ {% if changes.tasks is defined %}
15
+ ### Worker Results
16
+ - Status: {{ changes.status | default("unknown") }}
17
+ {% for t in changes.tasks %}
18
+ - **{{ t.name }}**: {{ t.status }}{% if t.files_modified %} (files: {{ t.files_modified | join(", ") }}){% endif %}
19
+ {% if t.notes %} — {{ t.notes }}{% endif %}
20
+ {% endfor %}
21
+ {% else %}
22
+ ```json
23
+ {{ changes | dump(2) }}
24
+ ```
25
+ {% endif %}
26
+ {% else %}
27
+ {{ changes }}
28
+ {% endif %}
29
+
30
+ ## Instructions
31
+
32
+ For EACH acceptance criterion above:
33
+
34
+ 1. Read the relevant source files to understand the current code state
35
+ 2. If the criterion is verifiable by command (test, build, lint), run the command
36
+ 3. If the criterion requires code inspection, read the files and assess
37
+ 4. Record your verdict: `passed`, `failed`, or `skipped`
38
+ 5. Provide specific evidence (file:line references, command output, code snippets)
39
+
40
+ Then produce a JSON verification entry:
41
+
42
+ ```json
43
+ {{ output_schema }}
44
+ ```
@@ -0,0 +1,52 @@
1
+ ## Task: {{ task.id }}
2
+
3
+ ### Description
4
+ {{ task.description }}
5
+
6
+ {% if task.phase %}
7
+ ### Phase
8
+ {{ task.phase }}
9
+ {% endif %}
10
+
11
+ ### Files
12
+ {% for f in task.files %}
13
+ - `{{ f }}`
14
+ {% endfor %}
15
+
16
+ ### Acceptance Criteria
17
+ {% for criterion in task.acceptance_criteria %}
18
+ - [ ] {{ criterion }}
19
+ {% endfor %}
20
+
21
+ {% if task.depends_on %}
22
+ ### Dependencies (completed)
23
+ {% for dep in task.depends_on %}
24
+ - {{ dep }}
25
+ {% endfor %}
26
+ {% endif %}
27
+
28
+ {% if task.notes %}
29
+ ### Notes
30
+ {{ task.notes }}
31
+ {% endif %}
32
+
33
+ {% if context %}
34
+ ### Context
35
+ {{ context }}
36
+ {% endif %}
37
+
38
+ ## Instructions
39
+
40
+ Implement this task. Follow these steps:
41
+
42
+ 1. **Read the target files** listed above to understand the current state
43
+ 2. **Implement changes** that satisfy each acceptance criterion
44
+ 3. **Stay within scope** — only modify the files listed, unless a new file is strictly necessary
45
+ 4. **Run tests** after implementation to verify nothing is broken
46
+ 5. **Validate each criterion** — confirm every acceptance criterion is addressed
47
+
48
+ Produce a JSON result conforming to this schema:
49
+
50
+ ```json
51
+ {{ output_schema }}
52
+ ```
@@ -0,0 +1,57 @@
1
+ You are verifying the output of a prior step against declared success criteria.
2
+
3
+ ## Success Criteria
4
+
5
+ {% for criterion in criteria %}
6
+ - {{ criterion }}
7
+ {% endfor %}
8
+
9
+ ## Step Output to Verify
10
+
11
+ ```json
12
+ {{ step_output | dump(2) }}
13
+ ```
14
+
15
+ {% if files_to_check %}
16
+ ## Files to Check
17
+
18
+ {% for f in files_to_check %}
19
+ - `{{ f }}`
20
+ {% endfor %}
21
+ {% endif %}
22
+
23
+ ## Instructions
24
+
25
+ For each criterion, choose the appropriate verification method and execute it:
26
+
27
+ 1. **command** — Run a shell command (test suite, build, lint) and report exit code + output as evidence
28
+ 2. **grep** — Search for specific patterns in files and report matches as evidence
29
+ 3. **inspect** — Read files and assess their content (use your judgment)
30
+ 4. **human** — Flag items that require human eyes and explain why automation cannot verify them
31
+
32
+ ### Process
33
+
34
+ 1. Evaluate each success criterion using the most appropriate verify method
35
+ 2. For `command` criteria: actually run the command and capture the output
36
+ 3. For `grep` criteria: search the relevant files and report what you find
37
+ 4. For `inspect` criteria: read the files and assess whether they meet the criterion
38
+ 5. For `human` criteria: describe what needs to be checked and why it needs a person
39
+ 6. Build truth claims from your observations, marking each as `verified`, `failed`, or `uncertain`
40
+ 7. Check that all referenced artifacts exist and are substantive (not stubs)
41
+ 8. Compute an overall score as "N/M" where N = passed criteria, M = total criteria
42
+ 9. Set status: `passed` if all criteria pass, `gaps_found` if any fail, `human_needed` if any require human review
43
+
44
+ ### Output Format
45
+
46
+ Produce JSON conforming to the verifier-output schema with these fields:
47
+
48
+ - `status`: "passed" | "gaps_found" | "human_needed"
49
+ - `score`: "N/M" format
50
+ - `truths[]`: observable claims with status and evidence
51
+ - `criteria_results[]`: one entry per criterion with verify_method, status, expected/actual outcome, evidence
52
+ - `artifacts[]`: (optional) file paths checked with existence/substance status
53
+ - `requirements_coverage[]`: (optional) requirement satisfaction mapping
54
+ - `human_verification[]`: (optional) items needing human review
55
+ - `gaps[]`: (optional) failed or uncertain truths with reasons
56
+
57
+ Be thorough. Run actual commands. Read actual files. Report what you observe, not what you assume.