@davidorex/pi-jit-agents 0.14.6 → 0.28.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 +49 -0
- package/README.md +2 -2
- package/dist/agent-spec.d.ts.map +1 -1
- package/dist/agent-spec.js +69 -5
- package/dist/agent-spec.js.map +1 -1
- package/dist/budget-enforcer.d.ts +43 -0
- package/dist/budget-enforcer.d.ts.map +1 -0
- package/dist/budget-enforcer.js +172 -0
- package/dist/budget-enforcer.js.map +1 -0
- package/dist/compile.d.ts +39 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +363 -24
- package/dist/compile.js.map +1 -1
- package/dist/dispatch-inline.d.ts +25 -0
- package/dist/dispatch-inline.d.ts.map +1 -0
- package/dist/dispatch-inline.js +41 -0
- package/dist/dispatch-inline.js.map +1 -0
- package/dist/field-path.d.ts +32 -0
- package/dist/field-path.d.ts.map +1 -0
- package/dist/field-path.js +48 -0
- package/dist/field-path.js.map +1 -0
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/dist/jit-runtime.d.ts +14 -3
- package/dist/jit-runtime.d.ts.map +1 -1
- package/dist/jit-runtime.js +41 -5
- package/dist/jit-runtime.js.map +1 -1
- package/dist/markers.d.ts +28 -0
- package/dist/markers.d.ts.map +1 -0
- package/dist/markers.js +36 -0
- package/dist/markers.js.map +1 -0
- package/dist/renderer-registry.d.ts +60 -0
- package/dist/renderer-registry.d.ts.map +1 -0
- package/dist/renderer-registry.js +141 -0
- package/dist/renderer-registry.js.map +1 -0
- package/dist/template.d.ts +15 -0
- package/dist/template.d.ts.map +1 -1
- package/dist/template.js +29 -3
- package/dist/template.js.map +1 -1
- package/dist/trace-redactor.d.ts +1 -1
- package/dist/trace-redactor.js +1 -1
- package/dist/trace-writer.js +2 -2
- package/dist/types.d.ts +86 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -4
- package/schemas/agent-trace.schema.json +30 -2
- package/templates/analyzers/base-analyzer.md +9 -0
- package/templates/analyzers/patterns-task.md +11 -0
- package/templates/analyzers/patterns.md +15 -0
- package/templates/analyzers/quality-task.md +11 -0
- package/templates/analyzers/quality.md +15 -0
- package/templates/analyzers/structure-task.md +17 -0
- package/templates/analyzers/structure.md +15 -0
- package/templates/architecture-designer/task.md +117 -0
- package/templates/architecture-inferrer/task.md +61 -0
- package/templates/audit-finding-verifier/task.md +59 -0
- package/templates/audit-fixer/task.md +67 -0
- package/templates/audit-results-router/task.md +37 -0
- package/templates/decomposer/task.md +56 -0
- package/templates/explorer/system.md +3 -0
- package/templates/explorer/task.md +9 -0
- package/templates/gap-identifier/task.md +103 -0
- package/templates/gap-resolution-assessor/task.md +48 -0
- package/templates/handoff-writer/task.md +101 -0
- package/templates/investigator/task.md +30 -0
- package/templates/items/architecture.md +33 -0
- package/templates/items/conformance.md +26 -0
- package/templates/items/conventions.md +19 -0
- package/templates/items/decisions.md +47 -0
- package/templates/items/domain.md +21 -0
- package/templates/items/features.md +63 -0
- package/templates/items/framework-gaps.md +43 -0
- package/templates/items/issues.md +21 -0
- package/templates/items/layer-plans.md +50 -0
- package/templates/items/project.md +48 -0
- package/templates/items/requirements.md +20 -0
- package/templates/items/research.md +57 -0
- package/templates/items/spec-reviews.md +51 -0
- package/templates/items/tasks.md +29 -0
- package/templates/phase-author/task.md +82 -0
- package/templates/plan-creator/task.md +143 -0
- package/templates/plan-decomposer/task.md +46 -0
- package/templates/project-definer/task.md +67 -0
- package/templates/project-inferrer/task.md +56 -0
- package/templates/requirements-gatherer/task.md +90 -0
- package/templates/researcher/task.md +26 -0
- package/templates/shared/macros.md +169 -0
- package/templates/shared/render-helpers.md +106 -0
- package/templates/spec-implementer/task.md +53 -0
- package/templates/synthesizer/system.md +3 -0
- package/templates/synthesizer/task.md +38 -0
- package/templates/task-verifier/task.md +44 -0
- package/templates/task-worker/task.md +52 -0
- package/templates/verifier/task.md +57 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
## Vision Statement
|
|
2
|
+
|
|
3
|
+
{{ vision }}
|
|
4
|
+
|
|
5
|
+
{% if context %}
|
|
6
|
+
## Additional Context
|
|
7
|
+
|
|
8
|
+
{{ context }}
|
|
9
|
+
{% endif %}
|
|
10
|
+
|
|
11
|
+
## Instructions
|
|
12
|
+
|
|
13
|
+
Produce a structured project identity from the vision statement above. Extract, infer, or derive each field — do not leave gaps where the vision provides signal.
|
|
14
|
+
|
|
15
|
+
### Fields to produce
|
|
16
|
+
|
|
17
|
+
1. **name** — short, lowercase-hyphenated project identifier
|
|
18
|
+
2. **description** — 1-3 sentences capturing what the project does and why it matters
|
|
19
|
+
3. **core_value** — one sentence a stakeholder outside the project could understand
|
|
20
|
+
4. **target_users** — array of user roles or personas who benefit
|
|
21
|
+
5. **constraints** — array of `{ type, description }` objects reflecting real limitations from the vision
|
|
22
|
+
- type examples: "technical", "organizational", "timeline", "budget", "regulatory", "compatibility"
|
|
23
|
+
6. **scope_boundaries** — `{ in: [...], out: [...] }` capturing what is and is not in scope
|
|
24
|
+
- `out` is especially important: document what a reader might assume is in scope but is not
|
|
25
|
+
7. **goals** — array of `{ id, description, success_criteria: [...] }` objects
|
|
26
|
+
- IDs: G-001, G-002, etc.
|
|
27
|
+
- success_criteria: measurable or verifiable statements (not aspirational)
|
|
28
|
+
8. **status** — set to `"inception"`
|
|
29
|
+
|
|
30
|
+
{% if stack %}
|
|
31
|
+
### Stack
|
|
32
|
+
|
|
33
|
+
The following technology stack has been specified:
|
|
34
|
+
|
|
35
|
+
{% for item in stack %}
|
|
36
|
+
- {{ item }}
|
|
37
|
+
{% endfor %}
|
|
38
|
+
|
|
39
|
+
Include these in the output `stack` array.
|
|
40
|
+
{% endif %}
|
|
41
|
+
|
|
42
|
+
{% if repository %}
|
|
43
|
+
### Repository
|
|
44
|
+
|
|
45
|
+
Repository: {{ repository }}
|
|
46
|
+
|
|
47
|
+
Include this in the output `repository` field.
|
|
48
|
+
{% endif %}
|
|
49
|
+
|
|
50
|
+
### Output format
|
|
51
|
+
|
|
52
|
+
Produce a single JSON object. Every required field must be present. The object should conform to the project block schema:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"name": "string (required)",
|
|
57
|
+
"description": "string (required)",
|
|
58
|
+
"core_value": "string (required)",
|
|
59
|
+
"target_users": ["string"],
|
|
60
|
+
"constraints": [{ "type": "string", "description": "string" }],
|
|
61
|
+
"scope_boundaries": { "in": ["string"], "out": ["string"] },
|
|
62
|
+
"goals": [{ "id": "G-001", "description": "string", "success_criteria": ["string"] }],
|
|
63
|
+
"status": "inception",
|
|
64
|
+
"repository": "string (if provided)",
|
|
65
|
+
"stack": ["string (if provided)"]
|
|
66
|
+
}
|
|
67
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Infer the project identity for the project at `{{ path }}`.
|
|
2
|
+
|
|
3
|
+
## Codebase Analysis
|
|
4
|
+
|
|
5
|
+
{% if exploration.files is defined %}
|
|
6
|
+
### Files ({{ exploration.files | length }} total)
|
|
7
|
+
{% for file in exploration.files | batch(20) | first %}
|
|
8
|
+
- `{{ file.path }}` ({{ file.language | default("unknown") }})
|
|
9
|
+
{% endfor %}
|
|
10
|
+
{% if exploration.files | length > 20 %}
|
|
11
|
+
... and {{ exploration.files | length - 20 }} more files
|
|
12
|
+
{% endif %}
|
|
13
|
+
{% endif %}
|
|
14
|
+
|
|
15
|
+
{% if exploration.entryPoints is defined %}
|
|
16
|
+
### Entry Points
|
|
17
|
+
{% for ep in exploration.entryPoints %}
|
|
18
|
+
- `{{ ep }}`
|
|
19
|
+
{% endfor %}
|
|
20
|
+
{% endif %}
|
|
21
|
+
|
|
22
|
+
## Instructions
|
|
23
|
+
|
|
24
|
+
Read project metadata and documentation to determine the project's identity. Start with:
|
|
25
|
+
- README.md (or equivalent)
|
|
26
|
+
- Package manifest (package.json, Cargo.toml, pyproject.toml, go.mod, etc.)
|
|
27
|
+
- CLAUDE.md or similar project instructions if present
|
|
28
|
+
- CI/CD configuration if present
|
|
29
|
+
|
|
30
|
+
Produce a project identity block:
|
|
31
|
+
|
|
32
|
+
1. **name** — the project's canonical name (from package manifest, not directory name)
|
|
33
|
+
2. **description** — concise summary of what the project does (2-3 sentences max)
|
|
34
|
+
3. **core_value** — single sentence: why does this project exist? What value does it provide?
|
|
35
|
+
4. **target_users** — who uses this? (e.g., "TypeScript developers", "DevOps engineers", "data scientists")
|
|
36
|
+
5. **constraints** — each with `type` and `description`:
|
|
37
|
+
- Runtime constraints (Node.js version, browser support, etc.)
|
|
38
|
+
- Language constraints (TypeScript strict mode, ESM-only, etc.)
|
|
39
|
+
- Compatibility constraints (API stability, backward compat, etc.)
|
|
40
|
+
6. **scope_boundaries**:
|
|
41
|
+
- `in`: what the project explicitly does
|
|
42
|
+
- `out`: what the project explicitly does not do (deferred or excluded)
|
|
43
|
+
7. **goals** — each with `id`, `description`, and optional `success_criteria` array
|
|
44
|
+
- Only include goals evidenced by the codebase (README roadmap, issues, TODO markers)
|
|
45
|
+
8. **status** — one of: inception, planning, development, maintenance, complete
|
|
46
|
+
- Infer from: version maturity, commit recency, test coverage, presence of CI
|
|
47
|
+
9. **repository** — repository URL if discoverable from package manifest or git remote
|
|
48
|
+
10. **stack** — primary technology choices only (language, framework, key libraries — not every dependency)
|
|
49
|
+
|
|
50
|
+
## Required Output Schema
|
|
51
|
+
|
|
52
|
+
You MUST produce JSON conforming exactly to this schema. Every required field must be present.
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{{ output_schema }}
|
|
56
|
+
```
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
## Project Identity
|
|
2
|
+
|
|
3
|
+
**Name:** {{ project.name }}
|
|
4
|
+
**Description:** {{ project.description }}
|
|
5
|
+
**Core Value:** {{ project.core_value }}
|
|
6
|
+
|
|
7
|
+
### Target Users
|
|
8
|
+
{% for user in project.target_users %}
|
|
9
|
+
- {{ user }}
|
|
10
|
+
{% endfor %}
|
|
11
|
+
|
|
12
|
+
### Constraints
|
|
13
|
+
{% for constraint in project.constraints %}
|
|
14
|
+
- [{{ constraint.type }}] {{ constraint.description }}
|
|
15
|
+
{% endfor %}
|
|
16
|
+
|
|
17
|
+
### Scope Boundaries
|
|
18
|
+
|
|
19
|
+
**In scope:**
|
|
20
|
+
{% for item in project.scope_boundaries.in %}
|
|
21
|
+
- {{ item }}
|
|
22
|
+
{% endfor %}
|
|
23
|
+
|
|
24
|
+
**Out of scope:**
|
|
25
|
+
{% for item in project.scope_boundaries.out %}
|
|
26
|
+
- {{ item }}
|
|
27
|
+
{% endfor %}
|
|
28
|
+
|
|
29
|
+
### Goals
|
|
30
|
+
{% for goal in project.goals %}
|
|
31
|
+
- **{{ goal.id }}**: {{ goal.description }}
|
|
32
|
+
{% for criterion in goal.success_criteria %}- {{ criterion }}
|
|
33
|
+
{% endfor %}
|
|
34
|
+
{% endfor %}
|
|
35
|
+
|
|
36
|
+
{% if vision %}
|
|
37
|
+
## Original Vision
|
|
38
|
+
|
|
39
|
+
{{ vision }}
|
|
40
|
+
{% endif %}
|
|
41
|
+
|
|
42
|
+
## Instructions
|
|
43
|
+
|
|
44
|
+
Derive requirements from the project identity above. Produce a comprehensive but proportionate set of requirements covering what the system must do (functional), quality attributes it must exhibit (non-functional), hard limits it must respect (constraint), and external connections it must support (integration).
|
|
45
|
+
|
|
46
|
+
### For each requirement, provide:
|
|
47
|
+
|
|
48
|
+
1. **id** — unique, formatted as REQ-NNN (zero-padded three-digit suffix)
|
|
49
|
+
2. **description** — clear statement of what is required
|
|
50
|
+
3. **type** — one of: `functional`, `non-functional`, `constraint`, `integration`
|
|
51
|
+
4. **status** — set to `"proposed"` for all
|
|
52
|
+
5. **priority** — MoSCoW: `must`, `should`, `could`, `wont`
|
|
53
|
+
6. **acceptance_criteria** — array of specific, verifiable statements
|
|
54
|
+
7. **source** — set to `"agent"` for all
|
|
55
|
+
8. **depends_on** — array of other requirement IDs this depends on (empty array if none)
|
|
56
|
+
|
|
57
|
+
### Priority guidance
|
|
58
|
+
|
|
59
|
+
- **must**: the project fails without this — directly tied to core_value and essential goals
|
|
60
|
+
- **should**: important for target users but the project could ship a minimal version without it
|
|
61
|
+
- **could**: enhances the experience but is clearly secondary
|
|
62
|
+
- **wont**: explicitly excluded — derive these from scope_boundaries.out
|
|
63
|
+
|
|
64
|
+
### Coverage expectations
|
|
65
|
+
|
|
66
|
+
- Every goal should map to at least one "must" requirement
|
|
67
|
+
- Every constraint should appear as a "constraint" type requirement
|
|
68
|
+
- Include at least one non-functional requirement for each quality attribute the project implies (performance, security, usability, reliability, etc. — only those that are relevant)
|
|
69
|
+
- Include "wont" requirements for major items in scope_boundaries.out
|
|
70
|
+
|
|
71
|
+
### Output format
|
|
72
|
+
|
|
73
|
+
Produce a single JSON object with a `requirements` array:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"requirements": [
|
|
78
|
+
{
|
|
79
|
+
"id": "REQ-NNN",
|
|
80
|
+
"description": "string",
|
|
81
|
+
"type": "functional",
|
|
82
|
+
"status": "proposed",
|
|
83
|
+
"priority": "must",
|
|
84
|
+
"acceptance_criteria": ["string"],
|
|
85
|
+
"source": "agent",
|
|
86
|
+
"depends_on": []
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## Research Request
|
|
2
|
+
|
|
3
|
+
**Gap:** {{ gap.id }} — {{ gap.description }}
|
|
4
|
+
|
|
5
|
+
## Questions
|
|
6
|
+
|
|
7
|
+
{% for q in research_questions %}
|
|
8
|
+
{{ loop.index }}. {{ q }}
|
|
9
|
+
{% endfor %}
|
|
10
|
+
|
|
11
|
+
## Instructions
|
|
12
|
+
|
|
13
|
+
For each question:
|
|
14
|
+
1. Answer based on known software engineering patterns, best practices, and established solutions
|
|
15
|
+
2. Rate your confidence: `high` (well-known, widely used), `medium` (established but context-dependent), `low` (best guess)
|
|
16
|
+
3. List sources where possible — documentation, known projects, pattern names
|
|
17
|
+
|
|
18
|
+
Also identify applicable patterns and concrete recommendations.
|
|
19
|
+
|
|
20
|
+
## Required Output Schema
|
|
21
|
+
|
|
22
|
+
You MUST produce JSON conforming exactly to this schema. Every required field must be present.
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{{ output_schema }}
|
|
26
|
+
```
|
|
@@ -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
|
+
```
|