@davidorex/pi-workflows 0.1.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 +28 -0
- package/README.md +169 -0
- package/agents/audit-fixer.agent.yaml +18 -0
- package/agents/code-explorer.agent.yaml +11 -0
- package/agents/decomposer.agent.yaml +51 -0
- package/agents/investigator.agent.yaml +49 -0
- package/agents/pattern-analyzer.agent.yaml +21 -0
- package/agents/phase-author.agent.yaml +16 -0
- package/agents/plan-decomposer.agent.yaml +12 -0
- package/agents/quality-analyzer.agent.yaml +21 -0
- package/agents/researcher.agent.yaml +38 -0
- package/agents/spec-implementer.agent.yaml +12 -0
- package/agents/structure-analyzer.agent.yaml +21 -0
- package/agents/synthesizer.agent.yaml +23 -0
- package/agents/verifier.agent.yaml +12 -0
- package/package.json +40 -0
- package/schemas/decomposition-specs.schema.json +50 -0
- package/schemas/execution-results.schema.json +50 -0
- package/schemas/investigation-findings.schema.json +45 -0
- package/schemas/pattern-analysis.schema.json +43 -0
- package/schemas/plan-breakdown.schema.json +22 -0
- package/schemas/quality-analysis.schema.json +35 -0
- package/schemas/research-findings.schema.json +44 -0
- package/schemas/structure-analysis.schema.json +42 -0
- package/schemas/synthesis.schema.json +33 -0
- package/schemas/verifier-output.schema.json +96 -0
- package/src/agent-spec.test.ts +289 -0
- package/src/agent-spec.ts +122 -0
- package/src/block-validation.test.ts +350 -0
- package/src/checkpoint.test.ts +237 -0
- package/src/checkpoint.ts +139 -0
- package/src/completion.test.ts +143 -0
- package/src/completion.ts +68 -0
- package/src/dag.test.ts +350 -0
- package/src/dag.ts +219 -0
- package/src/dispatch.test.ts +473 -0
- package/src/dispatch.ts +353 -0
- package/src/expression.test.ts +353 -0
- package/src/expression.ts +332 -0
- package/src/format.test.ts +80 -0
- package/src/format.ts +41 -0
- package/src/graduated-failure.test.ts +556 -0
- package/src/index.test.ts +114 -0
- package/src/index.ts +488 -0
- package/src/loop.test.ts +549 -0
- package/src/output.test.ts +213 -0
- package/src/output.ts +70 -0
- package/src/parallel-integration.test.ts +175 -0
- package/src/resume.test.ts +192 -0
- package/src/state.test.ts +192 -0
- package/src/state.ts +253 -0
- package/src/step-agent.test.ts +327 -0
- package/src/step-agent.ts +178 -0
- package/src/step-command.test.ts +330 -0
- package/src/step-command.ts +132 -0
- package/src/step-foreach.test.ts +647 -0
- package/src/step-foreach.ts +148 -0
- package/src/step-gate.test.ts +185 -0
- package/src/step-gate.ts +116 -0
- package/src/step-loop.test.ts +626 -0
- package/src/step-loop.ts +323 -0
- package/src/step-parallel.test.ts +475 -0
- package/src/step-parallel.ts +168 -0
- package/src/step-pause.test.ts +30 -0
- package/src/step-pause.ts +27 -0
- package/src/step-shared.test.ts +355 -0
- package/src/step-shared.ts +157 -0
- package/src/step-transform.test.ts +155 -0
- package/src/step-transform.ts +47 -0
- package/src/template-integration.test.ts +72 -0
- package/src/template.test.ts +162 -0
- package/src/template.ts +92 -0
- package/src/test-helpers.ts +51 -0
- package/src/tui.test.ts +355 -0
- package/src/tui.ts +182 -0
- package/src/types.ts +195 -0
- package/src/verifier-schema.test.ts +226 -0
- package/src/workflow-discovery.test.ts +105 -0
- package/src/workflow-discovery.ts +113 -0
- package/src/workflow-executor.test.ts +1530 -0
- package/src/workflow-executor.ts +810 -0
- package/src/workflow-sdk.test.ts +238 -0
- package/src/workflow-sdk.ts +262 -0
- package/src/workflow-spec.test.ts +576 -0
- package/src/workflow-spec.ts +471 -0
- package/templates/analyzers/base-analyzer.md +9 -0
- package/templates/analyzers/macros.md +1 -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/audit-fixer/task.md +67 -0
- package/templates/decomposer/task.md +56 -0
- package/templates/explorer/system.md +3 -0
- package/templates/explorer/task.md +9 -0
- package/templates/investigator/task.md +30 -0
- package/templates/phase-author/task.md +74 -0
- package/templates/plan-decomposer/task.md +46 -0
- package/templates/researcher/task.md +26 -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/verifier/task.md +57 -0
- package/workflows/create-phase.workflow.yaml +67 -0
- package/workflows/do-gap.workflow.yaml +153 -0
- package/workflows/fix-audit.workflow.yaml +217 -0
- package/workflows/gap-to-phase.workflow.yaml +98 -0
- package/workflows/parallel-analysis.workflow.yaml +62 -0
- package/workflows/parallel-explicit.workflow.yaml +42 -0
- package/workflows/pausable-analysis.workflow.yaml +44 -0
- package/workflows/resumable-analysis.workflow.yaml +42 -0
- package/workflows/self-implement.workflow.yaml +63 -0
- package/workflows/typed-analysis.workflow.yaml +63 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
## Decomposition Request
|
|
2
|
+
|
|
3
|
+
**Gap:** {{ gap.id }} — {{ gap.description }}
|
|
4
|
+
|
|
5
|
+
## Investigation Findings
|
|
6
|
+
|
|
7
|
+
**Complexity:** {{ investigation.complexity }}
|
|
8
|
+
**Summary:** {{ investigation.summary }}
|
|
9
|
+
|
|
10
|
+
### Affected Files
|
|
11
|
+
{% for f in investigation.affected_files %}
|
|
12
|
+
- `{{ f.path }}` — {{ f.role }}: {{ f.current_behavior }}
|
|
13
|
+
{% endfor %}
|
|
14
|
+
|
|
15
|
+
### Constraints
|
|
16
|
+
{% for c in investigation.constraints %}
|
|
17
|
+
- {{ c }}
|
|
18
|
+
{% endfor %}
|
|
19
|
+
|
|
20
|
+
### Risks
|
|
21
|
+
{% for r in investigation.risks %}
|
|
22
|
+
- {{ r }}
|
|
23
|
+
{% endfor %}
|
|
24
|
+
|
|
25
|
+
{% if research %}
|
|
26
|
+
## Research Findings
|
|
27
|
+
|
|
28
|
+
### Patterns
|
|
29
|
+
{% for p in research.patterns %}
|
|
30
|
+
- **{{ p.name }}**: {{ p.description }} — {{ p.applicability }}
|
|
31
|
+
{% endfor %}
|
|
32
|
+
|
|
33
|
+
### Recommendations
|
|
34
|
+
{% for r in research.recommendations %}
|
|
35
|
+
- {{ r }}
|
|
36
|
+
{% endfor %}
|
|
37
|
+
{% endif %}
|
|
38
|
+
|
|
39
|
+
## Instructions
|
|
40
|
+
|
|
41
|
+
Decompose this gap into implementation specs. Each spec is a unit of work for a single implementing agent.
|
|
42
|
+
|
|
43
|
+
1. Break the work into the smallest meaningful units
|
|
44
|
+
2. Declare file targets for each spec
|
|
45
|
+
3. Set `depends_on` for specs that must be sequential (shared files, interface dependencies)
|
|
46
|
+
4. Mark `parallel_safe` for specs that can run concurrently
|
|
47
|
+
5. Write acceptance criteria that are verifiable (grep patterns, test commands, not "it works")
|
|
48
|
+
6. Estimate complexity per spec
|
|
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,9 @@
|
|
|
1
|
+
Explore the code at `{{ path }}`.
|
|
2
|
+
|
|
3
|
+
Produce a JSON object with:
|
|
4
|
+
- `files`: array of { path, type, language, lines, exports, imports }
|
|
5
|
+
- `types`: array of { name, file, line, kind, definition }
|
|
6
|
+
- `dependencies`: array of { from, to, type }
|
|
7
|
+
- `entryPoints`: array of file paths that serve as entry points
|
|
8
|
+
|
|
9
|
+
Write your findings as valid JSON.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Gap to Investigate
|
|
2
|
+
|
|
3
|
+
**ID:** {{ gap.id }}
|
|
4
|
+
**Description:** {{ gap.description }}
|
|
5
|
+
**Category:** {{ gap.category }}
|
|
6
|
+
**Priority:** {{ gap.priority }}
|
|
7
|
+
{% if gap.details %}
|
|
8
|
+
**Details:** {{ gap.details }}
|
|
9
|
+
{% endif %}
|
|
10
|
+
|
|
11
|
+
## Instructions
|
|
12
|
+
|
|
13
|
+
Produce structured findings for this gap. Scope your investigation to the minimum needed:
|
|
14
|
+
|
|
15
|
+
1. If the gap names specific files, read those. If not, use `find` or `ls` to identify candidates — don't read file contents unless you need to confirm behavior.
|
|
16
|
+
2. For each affected file: what it does, what needs to change.
|
|
17
|
+
3. List hard constraints (existing tests, interfaces, conventions that must not break).
|
|
18
|
+
4. Note risks only if non-obvious.
|
|
19
|
+
5. Set `needs_research` to true only if the solution requires knowledge you don't have. Most gaps don't.
|
|
20
|
+
6. Complexity: `low` = single concern, mechanical. `medium` = multiple files, design choices. `high` = architectural.
|
|
21
|
+
|
|
22
|
+
Match your depth to the gap's category and priority. A `cleanup/low` gap needs a few lines of findings, not a codebase survey.
|
|
23
|
+
|
|
24
|
+
## Required Output Schema
|
|
25
|
+
|
|
26
|
+
You MUST produce JSON conforming exactly to this schema. Every required field must be present.
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{{ output_schema }}
|
|
30
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
## Intent
|
|
2
|
+
|
|
3
|
+
{{ intent }}
|
|
4
|
+
|
|
5
|
+
## Existing Phases
|
|
6
|
+
|
|
7
|
+
{% for phase in phases %}
|
|
8
|
+
- Phase {{ phase.number }}: {{ phase.name }} ({{ phase.status }})
|
|
9
|
+
{% endfor %}
|
|
10
|
+
|
|
11
|
+
## Current Architecture
|
|
12
|
+
|
|
13
|
+
{% for module in architecture.modules %}
|
|
14
|
+
- **{{ module.name }}** ({{ module.file }}, {{ module.lines }} lines): {{ module.responsibility }}
|
|
15
|
+
{% endfor %}
|
|
16
|
+
|
|
17
|
+
{% if architecture.compilation_pipeline %}
|
|
18
|
+
### Compilation Pipeline
|
|
19
|
+
{% for stage in architecture.compilation_pipeline %}
|
|
20
|
+
{{ loop.index }}. **{{ stage.stage }}**: {{ stage.description }}
|
|
21
|
+
{% endfor %}
|
|
22
|
+
{% endif %}
|
|
23
|
+
|
|
24
|
+
## Conventions
|
|
25
|
+
|
|
26
|
+
{% for rule in conventions.rules %}
|
|
27
|
+
- {{ rule.id }}: {{ rule.description }} ({{ rule.enforcement }})
|
|
28
|
+
{% endfor %}
|
|
29
|
+
|
|
30
|
+
## Current Gaps
|
|
31
|
+
|
|
32
|
+
{% for gap in gaps %}
|
|
33
|
+
{% if gap.status == "open" %}
|
|
34
|
+
- [{{ gap.priority }}] {{ gap.id }}: {{ gap.description }}
|
|
35
|
+
{% endif %}
|
|
36
|
+
{% endfor %}
|
|
37
|
+
|
|
38
|
+
## Current Inventory
|
|
39
|
+
|
|
40
|
+
- Step types: {{ inventory.step_types | length }}
|
|
41
|
+
- Agent specs: {{ inventory.agent_specs | length }}
|
|
42
|
+
- Schemas: {{ inventory.schemas | length }}
|
|
43
|
+
- Tests: {{ inventory.test_count }}
|
|
44
|
+
|
|
45
|
+
## Instructions
|
|
46
|
+
|
|
47
|
+
Convert the intent above into a structured phase spec. Read the codebase to understand what exists and what the intent requires.
|
|
48
|
+
|
|
49
|
+
1. **Determine the phase number** — next after the highest existing phase number
|
|
50
|
+
2. **Write a clear intent statement** — what this phase accomplishes and why
|
|
51
|
+
3. **Define success criteria** — each with a verify_method:
|
|
52
|
+
- `command`: can be verified by running a shell command (test suite, grep, validate)
|
|
53
|
+
- `inspect`: requires reading files and assessing content
|
|
54
|
+
- `human`: requires human judgment
|
|
55
|
+
4. **Decompose into specs** — each spec is a focused unit of work:
|
|
56
|
+
- Sequential numbering continuing from the last spec in the previous phase
|
|
57
|
+
- Clear intent per spec
|
|
58
|
+
- Concrete acceptance criteria (strings, each independently checkable)
|
|
59
|
+
- Specs should be ordered by dependency — earlier specs don't depend on later ones
|
|
60
|
+
5. **Identify dependencies** — which phase numbers this phase depends on
|
|
61
|
+
6. **List artifacts produced** — file paths this phase will create or modify
|
|
62
|
+
|
|
63
|
+
### Sizing guidance
|
|
64
|
+
|
|
65
|
+
- Each spec should be completable by one agent in one context window
|
|
66
|
+
- If a spec needs more than ~5 files changed, split it
|
|
67
|
+
- If a spec has more than ~5 acceptance criteria, it might be doing too much
|
|
68
|
+
- Group related changes (e.g., schema + instance + validation test = one spec)
|
|
69
|
+
|
|
70
|
+
### Cross-reference gaps
|
|
71
|
+
|
|
72
|
+
Check if any existing open gaps are addressed by this phase. If so, note that in the spec intent — the gap can be marked resolved when the spec completes.
|
|
73
|
+
|
|
74
|
+
Produce a JSON object conforming to the phase schema.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
## Phase: {{ phase.name }}
|
|
2
|
+
|
|
3
|
+
### Intent
|
|
4
|
+
{{ phase.intent }}
|
|
5
|
+
|
|
6
|
+
### Success Criteria
|
|
7
|
+
{% for criterion in phase.success_criteria %}
|
|
8
|
+
- {{ criterion.criterion }} (verify: {{ criterion.verify_method }})
|
|
9
|
+
{% endfor %}
|
|
10
|
+
|
|
11
|
+
### Specs
|
|
12
|
+
{% if phase.specs %}
|
|
13
|
+
{% for spec in phase.specs %}
|
|
14
|
+
- **{{ spec.id }}**: {{ spec.name }}
|
|
15
|
+
{% endfor %}
|
|
16
|
+
{% endif %}
|
|
17
|
+
|
|
18
|
+
### Current Architecture
|
|
19
|
+
{% for module in architecture.modules %}
|
|
20
|
+
- **{{ module.name }}** ({{ module.file }}): {{ module.responsibility }}
|
|
21
|
+
{% endfor %}
|
|
22
|
+
|
|
23
|
+
### Conventions
|
|
24
|
+
{% for rule in conventions.rules %}
|
|
25
|
+
- {{ rule.id }}: {{ rule.description }} ({{ rule.enforcement }})
|
|
26
|
+
{% endfor %}
|
|
27
|
+
|
|
28
|
+
## Instructions
|
|
29
|
+
|
|
30
|
+
Decompose this phase into implementation plans. Each plan should be a focused unit of work that one agent can complete in a single context window.
|
|
31
|
+
|
|
32
|
+
Before creating plans:
|
|
33
|
+
1. Read source files referenced in the architecture to understand existing patterns
|
|
34
|
+
2. Identify logical boundaries — which specs or features are independent
|
|
35
|
+
3. Determine which plans can run in parallel (independent file sets)
|
|
36
|
+
|
|
37
|
+
For each plan, produce:
|
|
38
|
+
- **name**: short identifier for the plan
|
|
39
|
+
- **intent**: what this plan accomplishes and why
|
|
40
|
+
- **tasks**: concrete list of things to do (create files, add tests, wire up)
|
|
41
|
+
- **files_to_change**: paths that will be created or modified
|
|
42
|
+
- **acceptance_criteria**: how to know the plan is done
|
|
43
|
+
- **context_needed**: files or modules the implementing agent should read first
|
|
44
|
+
- **parallel_group**: group name — plans in the same group can run concurrently (independent file sets get the same group; dependent plans get different groups)
|
|
45
|
+
|
|
46
|
+
Output a JSON object with a `plans` array conforming to the plan-breakdown schema.
|
|
@@ -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,53 @@
|
|
|
1
|
+
## Plan: {{ plan.name }}
|
|
2
|
+
|
|
3
|
+
### Intent
|
|
4
|
+
{{ plan.intent }}
|
|
5
|
+
|
|
6
|
+
### Tasks
|
|
7
|
+
{% for task in plan.tasks %}
|
|
8
|
+
{{ loop.index }}. {{ task }}
|
|
9
|
+
{% endfor %}
|
|
10
|
+
|
|
11
|
+
### Files to Change
|
|
12
|
+
{% for f in plan.files_to_change %}
|
|
13
|
+
- `{{ f }}`
|
|
14
|
+
{% endfor %}
|
|
15
|
+
|
|
16
|
+
### Acceptance Criteria
|
|
17
|
+
{% for criterion in plan.acceptance_criteria %}
|
|
18
|
+
- {{ criterion }}
|
|
19
|
+
{% endfor %}
|
|
20
|
+
|
|
21
|
+
{% if plan.context_needed %}
|
|
22
|
+
### Context to Read First
|
|
23
|
+
{% for ctx in plan.context_needed %}
|
|
24
|
+
- `{{ ctx }}`
|
|
25
|
+
{% endfor %}
|
|
26
|
+
{% endif %}
|
|
27
|
+
|
|
28
|
+
### Architecture Reference
|
|
29
|
+
{% for module in architecture.modules %}
|
|
30
|
+
- **{{ module.name }}** ({{ module.file }}): {{ module.responsibility }}
|
|
31
|
+
{% endfor %}
|
|
32
|
+
|
|
33
|
+
### Conventions
|
|
34
|
+
{% for rule in conventions.rules %}
|
|
35
|
+
- {{ rule.id }}: {{ rule.description }} ({{ rule.enforcement }})
|
|
36
|
+
{% endfor %}
|
|
37
|
+
|
|
38
|
+
## Instructions
|
|
39
|
+
|
|
40
|
+
Implement this plan. Follow these steps:
|
|
41
|
+
|
|
42
|
+
1. **Read context first**: Read the files listed under "Context to Read First" and any related source files to understand existing patterns
|
|
43
|
+
2. **Implement each task**: Work through the task list in order, writing code that follows the project conventions
|
|
44
|
+
3. **Run tests**: After implementation, run the relevant test suite to verify your changes work
|
|
45
|
+
4. **Validate acceptance criteria**: Confirm each acceptance criterion is met
|
|
46
|
+
|
|
47
|
+
Produce a JSON result conforming to the execution-results schema with:
|
|
48
|
+
- **status**: "complete", "partial", or "failed"
|
|
49
|
+
- **tasks**: array of task results with name, status, files_modified
|
|
50
|
+
- **decisions**: any design decisions made during implementation
|
|
51
|
+
- **issues**: any problems encountered (with severity)
|
|
52
|
+
- **test_count**: number of tests passing after your changes
|
|
53
|
+
- **commit_hash**: empty string (commits are handled externally)
|
|
@@ -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,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.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: create-phase
|
|
2
|
+
description: Convert unstructured intent into a structured phase spec
|
|
3
|
+
version: "1"
|
|
4
|
+
|
|
5
|
+
input:
|
|
6
|
+
type: object
|
|
7
|
+
required: [intent]
|
|
8
|
+
properties:
|
|
9
|
+
intent:
|
|
10
|
+
type: string
|
|
11
|
+
description: Unstructured intent from conversation — what needs to be built and why
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
load-context:
|
|
15
|
+
command: |
|
|
16
|
+
node --experimental-strip-types -e "
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import { readBlock } from './src/block-api.ts';
|
|
19
|
+
import { PROJECT_DIR } from './src/project-dir.ts';
|
|
20
|
+
import path from 'path';
|
|
21
|
+
const phasesDir = path.join(PROJECT_DIR, 'phases');
|
|
22
|
+
const phases = fs.readdirSync(phasesDir)
|
|
23
|
+
.filter(f => f.endsWith('.json'))
|
|
24
|
+
.map(f => JSON.parse(fs.readFileSync(path.join(phasesDir, f), 'utf8')));
|
|
25
|
+
const arch = readBlock('.', 'architecture');
|
|
26
|
+
const conv = readBlock('.', 'conventions');
|
|
27
|
+
const gapsData = readBlock('.', 'gaps');
|
|
28
|
+
const inv = readBlock('.', 'inventory');
|
|
29
|
+
console.log(JSON.stringify({ phases, architecture: arch, conventions: conv, gaps: gapsData.gaps, inventory: inv }));
|
|
30
|
+
"
|
|
31
|
+
output:
|
|
32
|
+
format: json
|
|
33
|
+
|
|
34
|
+
author:
|
|
35
|
+
agent: phase-author
|
|
36
|
+
input:
|
|
37
|
+
intent: "${{ input.intent }}"
|
|
38
|
+
phases: "${{ steps.load-context.output.phases }}"
|
|
39
|
+
architecture: "${{ steps.load-context.output.architecture }}"
|
|
40
|
+
conventions: "${{ steps.load-context.output.conventions }}"
|
|
41
|
+
gaps: "${{ steps.load-context.output.gaps }}"
|
|
42
|
+
inventory: "${{ steps.load-context.output.inventory }}"
|
|
43
|
+
output:
|
|
44
|
+
format: json
|
|
45
|
+
schema: ../../.project/schemas/phase.schema.json
|
|
46
|
+
|
|
47
|
+
write-phase:
|
|
48
|
+
command: |
|
|
49
|
+
node --experimental-strip-types -e "
|
|
50
|
+
import fs from 'fs';
|
|
51
|
+
import { validateFromFile } from './src/schema-validator.ts';
|
|
52
|
+
const phase = JSON.parse(process.argv[1]);
|
|
53
|
+
validateFromFile('.project/schemas/phase.schema.json', phase, 'phase');
|
|
54
|
+
const filename = '.project/phases/' + String(phase.number).padStart(2, '0') + '-' + phase.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/-+$/, '') + '.json';
|
|
55
|
+
fs.writeFileSync(filename, JSON.stringify(phase, null, 2) + '\n');
|
|
56
|
+
console.log(JSON.stringify({ path: filename, phase_number: phase.number, spec_count: phase.specs.length }));
|
|
57
|
+
" '${{ steps.author.output | json }}'
|
|
58
|
+
output:
|
|
59
|
+
format: json
|
|
60
|
+
|
|
61
|
+
completion:
|
|
62
|
+
message: |
|
|
63
|
+
Phase ${{ steps.write-phase.output.phase_number }} created at ${{ steps.write-phase.output.path }}
|
|
64
|
+
Contains ${{ steps.write-phase.output.spec_count }} specs.
|
|
65
|
+
include:
|
|
66
|
+
- steps.author.output.success_criteria
|
|
67
|
+
- steps.author.output.specs
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
name: do-gap
|
|
2
|
+
description: Standard path from gap to implementation — investigate, research, decompose, implement, verify, route
|
|
3
|
+
version: "1"
|
|
4
|
+
|
|
5
|
+
input:
|
|
6
|
+
type: object
|
|
7
|
+
required: [gap_id]
|
|
8
|
+
properties:
|
|
9
|
+
gap_id:
|
|
10
|
+
type: string
|
|
11
|
+
description: ID of the gap to work on
|
|
12
|
+
source:
|
|
13
|
+
file: .project/gaps.json
|
|
14
|
+
array: gaps
|
|
15
|
+
filter: { status: open }
|
|
16
|
+
label: id
|
|
17
|
+
value: id
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
load:
|
|
21
|
+
command: |
|
|
22
|
+
node --experimental-strip-types -e "
|
|
23
|
+
import { readBlock } from './src/block-api.ts';
|
|
24
|
+
const gapId = process.argv[1];
|
|
25
|
+
const data = readBlock('.', 'gaps');
|
|
26
|
+
const gap = data.gaps.find(g => g.id === gapId);
|
|
27
|
+
if (!gap) { console.error('Gap not found: ' + gapId); process.exit(1); }
|
|
28
|
+
if (gap.status === 'resolved') { console.error('Gap already resolved: ' + gapId); process.exit(1); }
|
|
29
|
+
console.log(JSON.stringify({ gap }));
|
|
30
|
+
" '${{ input.gap_id }}'
|
|
31
|
+
output:
|
|
32
|
+
format: json
|
|
33
|
+
|
|
34
|
+
investigate:
|
|
35
|
+
agent: investigator
|
|
36
|
+
input:
|
|
37
|
+
gap: "${{ steps.load.output.gap }}"
|
|
38
|
+
output:
|
|
39
|
+
format: json
|
|
40
|
+
schema: schemas/investigation-findings.schema.json
|
|
41
|
+
|
|
42
|
+
research:
|
|
43
|
+
when: "${{ steps.investigate.output.needs_research }}"
|
|
44
|
+
agent: researcher
|
|
45
|
+
input:
|
|
46
|
+
gap: "${{ steps.load.output.gap }}"
|
|
47
|
+
research_questions: "${{ steps.investigate.output.research_questions }}"
|
|
48
|
+
output:
|
|
49
|
+
format: json
|
|
50
|
+
schema: schemas/research-findings.schema.json
|
|
51
|
+
|
|
52
|
+
decompose:
|
|
53
|
+
agent: decomposer
|
|
54
|
+
input:
|
|
55
|
+
gap: "${{ steps.load.output.gap }}"
|
|
56
|
+
investigation: "${{ steps.investigate.output }}"
|
|
57
|
+
research: "${{ steps.research.output }}"
|
|
58
|
+
output:
|
|
59
|
+
format: json
|
|
60
|
+
schema: schemas/decomposition-specs.schema.json
|
|
61
|
+
|
|
62
|
+
implement:
|
|
63
|
+
forEach: "${{ steps.decompose.output.specs }}"
|
|
64
|
+
as: spec
|
|
65
|
+
agent: spec-implementer
|
|
66
|
+
input:
|
|
67
|
+
spec: "${{ spec }}"
|
|
68
|
+
gap: "${{ steps.load.output.gap }}"
|
|
69
|
+
investigation: "${{ steps.investigate.output }}"
|
|
70
|
+
retry:
|
|
71
|
+
maxAttempts: 2
|
|
72
|
+
onExhausted: fail
|
|
73
|
+
output:
|
|
74
|
+
format: json
|
|
75
|
+
schema: schemas/execution-results.schema.json
|
|
76
|
+
|
|
77
|
+
verify:
|
|
78
|
+
command: |
|
|
79
|
+
node --experimental-strip-types -e "
|
|
80
|
+
import { execSync } from 'child_process';
|
|
81
|
+
const errors = [];
|
|
82
|
+
|
|
83
|
+
// Run tests
|
|
84
|
+
try {
|
|
85
|
+
execSync('node --experimental-strip-types --test src/*.test.ts', { stdio: 'pipe', timeout: 120000 });
|
|
86
|
+
} catch (e) {
|
|
87
|
+
errors.push('Tests failed: ' + (e.stderr?.toString().slice(-500) || 'unknown error'));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Run linter on changed files
|
|
91
|
+
try {
|
|
92
|
+
const diff = execSync('git diff --name-only HEAD', { encoding: 'utf8' }).trim();
|
|
93
|
+
const srcFiles = diff.split('\n').filter(f => f.startsWith('src/') && f.endsWith('.ts') && !f.endsWith('.test.ts'));
|
|
94
|
+
for (const f of srcFiles) {
|
|
95
|
+
try {
|
|
96
|
+
execSync('/Users/david/Projects/pi-extension-linter/pi-extension-lint.sh ' + f, { stdio: 'pipe' });
|
|
97
|
+
} catch (e) {
|
|
98
|
+
const stderr = e.stderr?.toString() || e.stdout?.toString() || '';
|
|
99
|
+
if (stderr.includes('error')) errors.push('Lint errors in ' + f);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} catch {}
|
|
103
|
+
|
|
104
|
+
// Validate blocks
|
|
105
|
+
try {
|
|
106
|
+
const fs = await import('fs');
|
|
107
|
+
const schemasDir = '.project/schemas';
|
|
108
|
+
const schemas = fs.readdirSync(schemasDir).filter(f => f.endsWith('.schema.json'));
|
|
109
|
+
for (const s of schemas) {
|
|
110
|
+
const blockName = s.replace('.schema.json', '');
|
|
111
|
+
const blockPath = '.project/' + blockName + '.json';
|
|
112
|
+
if (fs.existsSync(blockPath)) {
|
|
113
|
+
try {
|
|
114
|
+
execSync('node --experimental-strip-types -e \"import{validateFromFile}from' + String.fromCharCode(39) + './src/schema-validator.ts' + String.fromCharCode(39) + ';import fs from' + String.fromCharCode(39) + 'fs' + String.fromCharCode(39) + ';validateFromFile(' + String.fromCharCode(39) + schemasDir + '/' + s + String.fromCharCode(39) + ',JSON.parse(fs.readFileSync(' + String.fromCharCode(39) + blockPath + String.fromCharCode(39) + ',' + String.fromCharCode(39) + 'utf8' + String.fromCharCode(39) + ')),' + String.fromCharCode(39) + blockName + String.fromCharCode(39) + ')\"', { stdio: 'pipe' });
|
|
115
|
+
} catch { errors.push('Block validation failed: ' + blockPath); }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
} catch {}
|
|
119
|
+
|
|
120
|
+
const passed = errors.length === 0;
|
|
121
|
+
console.log(JSON.stringify({ status: passed ? 'passed' : 'failed', errors, passed }));
|
|
122
|
+
"
|
|
123
|
+
output:
|
|
124
|
+
format: json
|
|
125
|
+
|
|
126
|
+
route:
|
|
127
|
+
when: "${{ steps.verify.output.passed }}"
|
|
128
|
+
command: |
|
|
129
|
+
node --experimental-strip-types -e "
|
|
130
|
+
import { updateItemInBlock } from './src/block-api.ts';
|
|
131
|
+
const gapId = process.argv[1];
|
|
132
|
+
updateItemInBlock('.', 'gaps', 'gaps',
|
|
133
|
+
(g) => g.id === gapId,
|
|
134
|
+
{ status: 'resolved', resolved_by: 'do-gap-workflow' }
|
|
135
|
+
);
|
|
136
|
+
console.log(JSON.stringify({ routed: true, gap_id: gapId, status: 'resolved' }));
|
|
137
|
+
" '${{ input.gap_id }}'
|
|
138
|
+
output:
|
|
139
|
+
format: json
|
|
140
|
+
|
|
141
|
+
check:
|
|
142
|
+
when: "${{ steps.route.output.routed }}"
|
|
143
|
+
gate:
|
|
144
|
+
check: "test '${{ steps.verify.output.status }}' = 'passed'"
|
|
145
|
+
onFail: fail
|
|
146
|
+
|
|
147
|
+
completion:
|
|
148
|
+
message: |
|
|
149
|
+
Gap ${{ input.gap_id }} — ${{ steps.verify.output.status }}
|
|
150
|
+
Investigation complexity: ${{ steps.investigate.output.complexity }}
|
|
151
|
+
Specs implemented: ${{ steps.decompose.output.specs | length }}
|
|
152
|
+
include:
|
|
153
|
+
- steps.verify.output
|