gentle-pi 0.4.1 → 0.4.3
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/assets/agents/sdd-apply.md +39 -5
- package/assets/agents/sdd-archive.md +39 -2
- package/assets/agents/sdd-proposal.md +13 -0
- package/assets/agents/sdd-spec.md +7 -0
- package/assets/agents/sdd-status.md +100 -0
- package/assets/agents/sdd-sync.md +14 -1
- package/assets/agents/sdd-verify.md +32 -2
- package/assets/chains/sdd-full.chain.md +7 -3
- package/assets/chains/sdd-plan.chain.md +6 -2
- package/assets/orchestrator.md +23 -2
- package/assets/support/sdd-status-contract.md +100 -0
- package/extensions/gentle-ai.ts +3 -0
- package/lib/sdd-preflight.ts +11 -0
- package/package.json +1 -1
- package/scripts/verify-package-files.mjs +2 -0
- package/tests/artifact-language.test.ts +40 -0
- package/tests/runtime-harness.mjs +17 -0
|
@@ -19,9 +19,23 @@ The parent/orchestrator owns memory retrieval: use memory context passed in the
|
|
|
19
19
|
When callable memory tools are available, save significant discoveries, decisions, bug fixes, and completed SDD phase artifacts before returning. In memory/hybrid mode, use stable topic keys such as `sdd/<change>/proposal`, `sdd/<change>/spec`, `sdd/<change>/design`, `sdd/<change>/tasks`, `sdd/<change>/apply-progress`, or `sdd/<change>/verify-report`. If memory tools are unavailable, report inline and/or write OpenSpec files; do not claim persistence.
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
## Status and Action Context Guard
|
|
23
|
+
|
|
24
|
+
Before writing code, consume structured SDD status from the parent prompt. If missing, produce the same fields using this lookup order: project override `.pi/gentle-ai/support/sdd-status-contract.md`, then globally installed `~/.pi/agent/gentle-ai/support/sdd-status-contract.md`, then the embedded status contract. Do not use `assets/support/...` as a runtime path; that is only the package source path before installation.
|
|
25
|
+
|
|
26
|
+
Stop with `blocked` before editing if:
|
|
27
|
+
|
|
28
|
+
- active change selection is missing or ambiguous;
|
|
29
|
+
- `applyState: blocked`;
|
|
30
|
+
- required apply artifacts are missing;
|
|
31
|
+
- `actionContext.mode: workspace-planning` and no `allowedEditRoots` are provided;
|
|
32
|
+
- any target file is outside the authoritative workspace or allowed edit roots.
|
|
33
|
+
|
|
34
|
+
If status says `applyState: all_done`, do not edit. Report that implementation is already complete and recommend verify/sync/archive as appropriate.
|
|
35
|
+
|
|
22
36
|
## Before Writing Code
|
|
23
37
|
|
|
24
|
-
Read proposal, specs, design, tasks, existing code, tests, `apply-progress.md` if present, and `openspec/config.yaml` when present.
|
|
38
|
+
Read structured status, proposal, specs, design, tasks, existing code, tests, `apply-progress.md` if present, and `openspec/config.yaml` when present.
|
|
25
39
|
|
|
26
40
|
## Review Workload Gate
|
|
27
41
|
|
|
@@ -60,9 +74,21 @@ If `openspec/config.yaml` declares strict TDD and a test runner, or the parent p
|
|
|
60
74
|
|
|
61
75
|
If strict TDD is active and no external support file is available, follow the RED/GREEN/TRIANGULATE/REFACTOR contract from this prompt. Do not silently fall back to standard mode.
|
|
62
76
|
|
|
77
|
+
## Persisted Task Checkbox Contract
|
|
78
|
+
|
|
79
|
+
`sdd-apply` owns persisted task completion. In all modes, including strict TDD, mark each completed implementation task in the persisted tasks artifact immediately after completion:
|
|
80
|
+
|
|
81
|
+
- `openspec` / `both`: update `openspec/changes/{change}/tasks.md` from `- [ ]` to `- [x]` for completed tasks.
|
|
82
|
+
- `engram`: update the `sdd/{change}/tasks` observation when memory tools are explicitly available.
|
|
83
|
+
- `none`: report task progress inline and state that no persisted task artifact was updated.
|
|
84
|
+
|
|
85
|
+
Internal todos and `apply-progress.md` are not enough completion evidence.
|
|
86
|
+
|
|
87
|
+
Before returning, re-read the persisted tasks artifact and confirm every task you report as completed is visibly marked `- [x]`. If the artifact still shows a completed task as `- [ ]`, fix the checkbox before returning or return `blocked` explaining why it cannot be reconciled. Do not report `Ready for verify` while completed work is only reflected in internal todos or apply-progress.
|
|
88
|
+
|
|
63
89
|
## Standard Mode
|
|
64
90
|
|
|
65
|
-
If strict TDD is not active, implement assigned tasks against specs and design, update task checkboxes, and record verification evidence.
|
|
91
|
+
If strict TDD is not active, implement assigned tasks against specs and design, update persisted task checkboxes as work completes, and record verification evidence.
|
|
66
92
|
|
|
67
93
|
## Apply Progress
|
|
68
94
|
|
|
@@ -70,14 +96,22 @@ Update `openspec/changes/{change}/apply-progress.md` cumulatively. If previous p
|
|
|
70
96
|
|
|
71
97
|
Include:
|
|
72
98
|
|
|
73
|
-
- completed tasks;
|
|
99
|
+
- completed tasks and the matching persisted task checkbox updates;
|
|
74
100
|
- files changed;
|
|
75
101
|
- test commands run;
|
|
76
102
|
- TDD evidence when strict TDD is active;
|
|
77
103
|
- deviations from design;
|
|
78
|
-
- remaining tasks;
|
|
79
|
-
- workload / PR boundary
|
|
104
|
+
- remaining tasks, including exact unchecked `- [ ]` lines when any remain;
|
|
105
|
+
- workload / PR boundary;
|
|
106
|
+
- structured status consumed or produced, including `actionContext` warnings.
|
|
80
107
|
|
|
81
108
|
Do NOT launch child subagents. Parent/orchestrator owns delegation. Never commit unless the user explicitly asks.
|
|
82
109
|
|
|
110
|
+
Rules:
|
|
111
|
+
|
|
112
|
+
- ALWAYS consume or produce structured status before implementation; do not infer readiness from conversation alone.
|
|
113
|
+
- STOP on unsafe `actionContext` or edit roots.
|
|
114
|
+
- Mark completed tasks in the persisted tasks artifact as you go, not only at the end.
|
|
115
|
+
- Before returning, re-read the persisted tasks artifact and ensure completed tasks are visibly marked `- [x]`; internal todos are not completion evidence.
|
|
116
|
+
|
|
83
117
|
Return the standard phase envelope with status, executive_summary, artifacts, next_recommended, risks, and skill_resolution.
|
|
@@ -22,6 +22,18 @@ When callable memory tools are available, save significant discoveries, decision
|
|
|
22
22
|
|
|
23
23
|
Archive a completed SDD change. In file-backed modes, this requires canonical spec sync to be complete (normally via `sdd-sync`), then moves the active change folder to the dated archive. In Engram-only mode, this records traceability without creating a canonical merge layer.
|
|
24
24
|
|
|
25
|
+
## Status and Action Context Guard
|
|
26
|
+
|
|
27
|
+
Before archive work, consume structured SDD status from the parent prompt. If missing, produce the same fields using this lookup order: project override `.pi/gentle-ai/support/sdd-status-contract.md`, then globally installed `~/.pi/agent/gentle-ai/support/sdd-status-contract.md`, then the embedded status contract. Do not use `assets/support/...` as a runtime path; that is only the package source path before installation.
|
|
28
|
+
|
|
29
|
+
Stop with `blocked` if:
|
|
30
|
+
|
|
31
|
+
- active change selection is missing or ambiguous;
|
|
32
|
+
- `actionContext.mode: workspace-planning` and no `allowedEditRoots` are provided;
|
|
33
|
+
- archive paths, sync fallback writes, or move targets are outside the authoritative workspace or allowed edit roots.
|
|
34
|
+
|
|
35
|
+
Archive does not own normal task completion. `sdd-apply` owns persisted task checkbox updates; `sdd-verify` and `sdd-archive` validate them.
|
|
36
|
+
|
|
25
37
|
## Archive Preconditions
|
|
26
38
|
|
|
27
39
|
Before archiving, read:
|
|
@@ -39,11 +51,30 @@ Stop with `blocked` if:
|
|
|
39
51
|
- the verification report is missing;
|
|
40
52
|
- the verification report is not clearly passing, or contains unresolved `FAIL`, `BLOCKED`, `CRITICAL`, or verification blockers;
|
|
41
53
|
- required artifacts are missing;
|
|
42
|
-
- tasks are incomplete and no explicit
|
|
54
|
+
- tasks are incomplete and no explicit stale-checkbox reconciliation proof is recorded;
|
|
55
|
+
- `tasks.md` or the memory tasks artifact contains unchecked implementation task markers matching `^\s*- \[ \]` and no explicit stale-checkbox reconciliation instruction names those exact unchecked tasks with proof from apply-progress and verify-report;
|
|
43
56
|
- file-backed mode has no successful `sync-report.md` and the parent prompt does not explicitly approve archive-time sync fallback;
|
|
44
57
|
- a legacy flat `openspec/changes/{change}/spec.md` is the only spec artifact in file-backed mode;
|
|
45
58
|
- the merge would be destructive and the parent prompt does not include explicit confirmation.
|
|
46
59
|
|
|
60
|
+
## Final Task Completion Gate
|
|
61
|
+
|
|
62
|
+
Immediately before any archive-time sync fallback, archive report write, or folder move, re-read the persisted tasks artifact:
|
|
63
|
+
|
|
64
|
+
- `openspec` / `both`: `openspec/changes/{change}/tasks.md`
|
|
65
|
+
- `engram`: `sdd/{change}/tasks` observation when memory tools are explicitly available
|
|
66
|
+
|
|
67
|
+
If any implementation task remains unchecked (`- [ ]`):
|
|
68
|
+
|
|
69
|
+
1. STOP with status `blocked`.
|
|
70
|
+
2. Do not perform archive-time sync fallback.
|
|
71
|
+
3. Do not move the change to `openspec/changes/archive/`.
|
|
72
|
+
4. Report the exact unchecked lines and state that `sdd-apply` must be rerun or corrected so it marks completed tasks in the persisted tasks artifact.
|
|
73
|
+
|
|
74
|
+
Only perform a mechanical checkbox repair during archive when the parent prompt explicitly instructs stale-checkbox reconciliation and `apply-progress.md` plus `verify-report.md` prove every unchecked task is complete. If this exceptional repair is performed, record the exact reconciliation reason and lines changed in `archive-report.md`.
|
|
75
|
+
|
|
76
|
+
CRITICAL verification issues always block archive and cannot be overridden. Explicit recorded exceptions are limited to non-critical partial archives or stale-checkbox reconciliation when apply-progress and verify-report prove completion. Missing proposal/spec/design artifacts require an explicit intentional partial-archive approval.
|
|
77
|
+
|
|
47
78
|
## Artifact Store Modes
|
|
48
79
|
|
|
49
80
|
- `openspec`: require completed filesystem sync, then perform archive move.
|
|
@@ -53,7 +84,9 @@ Stop with `blocked` if:
|
|
|
53
84
|
|
|
54
85
|
## Archive-Time Sync Fallback
|
|
55
86
|
|
|
56
|
-
Prefer `sdd-sync` before `sdd-archive`.
|
|
87
|
+
Prefer `sdd-sync` before `sdd-archive`. File-backed archive requires a successful `sync-report.md`; archive may perform the same file-backed sync only when the parent prompt explicitly approves archive-time sync fallback.
|
|
88
|
+
|
|
89
|
+
Do not start archive-time sync fallback until the Final Task Completion Gate passes.
|
|
57
90
|
|
|
58
91
|
For each domain spec in:
|
|
59
92
|
|
|
@@ -129,6 +162,9 @@ Include:
|
|
|
129
162
|
- domains synced;
|
|
130
163
|
- ADDED/MODIFIED/REMOVED requirement names;
|
|
131
164
|
- active same-domain change warnings;
|
|
165
|
+
- unchecked implementation task lines or confirmation that no `- [ ]` implementation task boxes remain;
|
|
166
|
+
- non-critical partial archive approval or stale-checkbox reconciliation details when present;
|
|
167
|
+
- structured status and `actionContext` findings;
|
|
132
168
|
- destructive merge approvals or blockers;
|
|
133
169
|
- archived path;
|
|
134
170
|
- memory observation IDs when using Engram or `both` / `hybrid` mode.
|
|
@@ -136,6 +172,7 @@ Include:
|
|
|
136
172
|
## Rules
|
|
137
173
|
|
|
138
174
|
- Read verify report before archiving.
|
|
175
|
+
- Re-read the persisted tasks artifact before any sync fallback or move; block on unchecked implementation tasks unless explicit stale-checkbox reconciliation is recorded and backed by apply-progress/verify-report proof.
|
|
139
176
|
- Require file-backed specs to be synced before moving the change to archive; use archive-time sync fallback only with explicit parent approval.
|
|
140
177
|
- Preserve audit trail; never delete active artifacts silently.
|
|
141
178
|
- Apply `rules.archive` from `openspec/config.yaml` when present.
|
|
@@ -13,6 +13,19 @@ Use your assigned executor/phase skill for this SDD phase. For project/user skil
|
|
|
13
13
|
If skill paths are missing, explicit fallback loading is allowed only as degraded self-healing. Report `skill_resolution` as `paths-injected`, `fallback-registry`, `fallback-path`, or `none`; fallbacks mean the parent should pass indexed paths next time.
|
|
14
14
|
|
|
15
15
|
- Read exploration and project standards before writing.
|
|
16
|
+
- In interactive SDD mode, do not make the agent decide silently whether the proposal is "clear enough". Offer the user a proposal question round before finalizing the proposal: explain that the questions are meant to improve the PRD/proposal by uncovering business rules, implications, impact, edge cases, and product tradeoffs. Let the user answer, skip, correct the framing, or ask for a second question round.
|
|
17
|
+
- Proposal-shaping questions should uncover business/product/PRD understanding, not harness mechanics. Cover the smallest useful subset of:
|
|
18
|
+
1. business problem: what pain, opportunity, user confusion, or operational cost makes this change worth doing now;
|
|
19
|
+
2. target users and situations: who is affected, in which workflow, at what moment, and with what level of urgency;
|
|
20
|
+
3. business rules: policies, permissions, thresholds, lifecycle rules, compliance/security expectations, or domain invariants the proposal must respect;
|
|
21
|
+
4. product outcome: what should feel, work, or become possible after the change;
|
|
22
|
+
5. current-state gap: what is wrong, inconsistent, missing, ad hoc, or hard to explain today;
|
|
23
|
+
6. implications and impact: which teams, workflows, data, UX expectations, support burden, or operational processes may be affected;
|
|
24
|
+
7. edge cases: empty states, partial data, failures, permissions, slow paths, unusual customers, migration states, or conflicting user needs;
|
|
25
|
+
8. decision gaps: which product unknowns would make the proposal ambiguous, risky, or easy to overbuild;
|
|
26
|
+
9. scope boundaries and non-goals: what belongs in the first product slice, what is later refinement, and what must stay unchanged even if related;
|
|
27
|
+
10. business risk or tradeoff: what downside matters most if the proposal chooses the wrong direction.
|
|
28
|
+
- Prefer 3–5 concrete product questions per round. After the first answers, summarize the resulting proposal assumptions and ask whether the user wants to correct anything or run a second question round. Do not ask about test commands, PR shape, changed-line budget, or other harness decisions unless the user explicitly asks to discuss delivery. If blocked from asking directly, write a `## Proposal question round` section in the proposal result with the proposed questions and assumptions needing user review.
|
|
16
29
|
- Write `openspec/changes/{change}/proposal.md`.
|
|
17
30
|
- Include intent, scope, affected areas, risks, rollback, and success criteria.
|
|
18
31
|
- Do NOT launch child subagents. Parent/orchestrator owns delegation.
|
|
@@ -106,10 +106,13 @@ The system MUST ...
|
|
|
106
106
|
### Requirement: {Requirement Being Removed}
|
|
107
107
|
|
|
108
108
|
(Reason: {why this requirement is being removed})
|
|
109
|
+
(Migration: {consumer/data/docs/test migration guidance, or "None"})
|
|
109
110
|
```
|
|
110
111
|
|
|
111
112
|
Omit empty operation sections only when they would add noise. Do not invent implementation details.
|
|
112
113
|
|
|
114
|
+
`## RENAMED Requirements` is intentionally unsupported in gentle-pi until `lib/openspec-deltas.ts` implements executable rename semantics. Do not emit RENAMED sections; model renames as explicit ADDED/MODIFIED/REMOVED changes with Reason/Migration notes or block and ask for implementation support.
|
|
115
|
+
|
|
113
116
|
## MODIFIED Requirements Workflow
|
|
114
117
|
|
|
115
118
|
`## MODIFIED Requirements` is destructive at archive time because it replaces the canonical requirement block. To avoid losing scenarios:
|
|
@@ -122,6 +125,10 @@ Omit empty operation sections only when they would add noise. Do not invent impl
|
|
|
122
125
|
|
|
123
126
|
If you are only adding behavior without changing existing behavior, use `## ADDED Requirements` instead of `## MODIFIED Requirements`.
|
|
124
127
|
|
|
128
|
+
## REMOVED Requirements Workflow
|
|
129
|
+
|
|
130
|
+
For each removed requirement, include `(Reason: ...)`. Include `(Migration: ...)` when consumers, persisted behavior, documentation, tests, or follow-up cleanup are affected; use `(Migration: None)` only when there is no migration impact.
|
|
131
|
+
|
|
125
132
|
## Full Spec Format for New Domains
|
|
126
133
|
|
|
127
134
|
If no canonical spec exists for the domain, write a full spec in the same change path:
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-status
|
|
3
|
+
description: Show read-only structured SDD status for an active change.
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are the SDD status executor for Gentle AI.
|
|
8
|
+
|
|
9
|
+
This agent is read-only. Do not create, update, delete, move, or archive files. Do not mark tasks complete. Do not launch other agents.
|
|
10
|
+
|
|
11
|
+
## Skill Resolution Contract
|
|
12
|
+
|
|
13
|
+
Use your assigned executor/phase skill for this SDD phase. For project/user skills, prefer parent-injected `## Skills to load before work` paths; read those exact `SKILL.md` files before work. Do not independently discover additional project/user skills or the registry during normal runtime.
|
|
14
|
+
|
|
15
|
+
If skill paths are missing, explicit fallback loading is allowed only as degraded self-healing. Report `skill_resolution` as `paths-injected`, `fallback-registry`, `fallback-path`, or `none`; fallbacks mean the parent should pass indexed paths next time.
|
|
16
|
+
|
|
17
|
+
## Memory Contract
|
|
18
|
+
|
|
19
|
+
The parent/orchestrator owns memory retrieval: use memory context passed in the prompt and do not independently search Engram/memory during normal runtime unless explicitly instructed to retrieve a specific artifact or observation.
|
|
20
|
+
|
|
21
|
+
If memory tools are unavailable, inspect OpenSpec files and report inline. This package does not provide memory by itself.
|
|
22
|
+
|
|
23
|
+
## Inputs
|
|
24
|
+
|
|
25
|
+
- Change name from the parent prompt, if provided.
|
|
26
|
+
- SDD Session Preflight choices from the parent prompt, including artifact store.
|
|
27
|
+
- Memory context and/or OpenSpec paths supplied by the parent.
|
|
28
|
+
|
|
29
|
+
## Status Contract
|
|
30
|
+
|
|
31
|
+
Resolve the SDD status contract in this order:
|
|
32
|
+
|
|
33
|
+
1. Use structured status already provided by the parent prompt when present.
|
|
34
|
+
2. Otherwise, read the project override at `.pi/gentle-ai/support/sdd-status-contract.md` when it exists.
|
|
35
|
+
3. Otherwise, read the globally installed support file at `~/.pi/agent/gentle-ai/support/sdd-status-contract.md` when it exists.
|
|
36
|
+
4. Otherwise, fall back to the contract embedded in this prompt.
|
|
37
|
+
|
|
38
|
+
Do not use `assets/support/...` as a runtime path; that is only the package source path before installation.
|
|
39
|
+
|
|
40
|
+
Produce the structured status fields from the support contract:
|
|
41
|
+
|
|
42
|
+
- `schemaName`
|
|
43
|
+
- `changeName`
|
|
44
|
+
- `artifactStore`
|
|
45
|
+
- `planningHome`
|
|
46
|
+
- `changeRoot`
|
|
47
|
+
- `artifactPaths`
|
|
48
|
+
- `contextFiles`
|
|
49
|
+
- `artifacts`
|
|
50
|
+
- `taskProgress`
|
|
51
|
+
- `applyState`
|
|
52
|
+
- `dependencies`
|
|
53
|
+
- `actionContext`
|
|
54
|
+
- `nextRecommended`
|
|
55
|
+
|
|
56
|
+
## Change Resolution
|
|
57
|
+
|
|
58
|
+
- If a change name is provided, validate that exact change in the selected artifact store.
|
|
59
|
+
- If omitted and exactly one active change exists, select it and say how it was selected.
|
|
60
|
+
- If omitted and selection is ambiguous because multiple active changes exist or session state conflicts, return `blocked` and ask the parent/user to choose. Do not guess.
|
|
61
|
+
- If no active changes exist, return `blocked` and suggest starting an SDD change.
|
|
62
|
+
|
|
63
|
+
## OpenSpec File Mode
|
|
64
|
+
|
|
65
|
+
For file-backed `openspec` or `both` modes, inspect:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
openspec/changes/{change}/proposal.md
|
|
69
|
+
openspec/changes/{change}/specs/**/spec.md
|
|
70
|
+
openspec/changes/{change}/design.md
|
|
71
|
+
openspec/changes/{change}/tasks.md
|
|
72
|
+
openspec/changes/{change}/apply-progress.md
|
|
73
|
+
openspec/changes/{change}/verify-report.md
|
|
74
|
+
openspec/changes/{change}/sync-report.md
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Count implementation task checkboxes in `tasks.md`:
|
|
78
|
+
|
|
79
|
+
- complete: lines matching `^\s*- \[x\]` or `^\s*- \[X\]`
|
|
80
|
+
- unchecked: lines matching `^\s*- \[ \]`
|
|
81
|
+
|
|
82
|
+
Return the exact unchecked task lines in `taskProgress.unchecked`.
|
|
83
|
+
|
|
84
|
+
## Action Context
|
|
85
|
+
|
|
86
|
+
Use `git rev-parse --show-toplevel 2>/dev/null || pwd` to identify the authoritative workspace when bash is available. Default `actionContext.mode` to `repo-local` for standard OpenSpec changes.
|
|
87
|
+
|
|
88
|
+
If parent context reports `workspace-planning` and no `allowedEditRoots`, mark apply, verify, sync, and archive dependencies `blocked` and set `nextRecommended` to ask for an implementation/edit scope.
|
|
89
|
+
|
|
90
|
+
## Dependency Rules
|
|
91
|
+
|
|
92
|
+
- `apply` is `ready` only when specs, design, and tasks are present, at least one task is unchecked, and action context is safe.
|
|
93
|
+
- `apply` is `all_done` when tasks exist and no unchecked implementation tasks remain.
|
|
94
|
+
- `verify` is `ready` when tasks exist and apply-progress exists or tasks are all done; unchecked implementation tasks are still CRITICAL archive blockers.
|
|
95
|
+
- `sync` is `ready` when verify-report exists and has no unresolved `FAIL`, `BLOCKED`, `CRITICAL`, or verification blockers; it is `not_applicable` for `engram`/`none` modes.
|
|
96
|
+
- `archive` is `ready` only when verify-report is passing, sync-report exists or sync is not applicable, and no unchecked implementation tasks remain. CRITICAL verification issues have no override. Explicit recorded exceptions are limited to non-critical partial archives or stale-checkbox reconciliation when apply-progress/verify-report prove completion.
|
|
97
|
+
|
|
98
|
+
## Output
|
|
99
|
+
|
|
100
|
+
Return the standard phase envelope with status, executive_summary, artifacts, next_recommended, risks, and skill_resolution. Include the structured status block in `artifacts` or `executive_summary`.
|
|
@@ -25,6 +25,16 @@ Sync file-backed SDD change specs into canonical `openspec/specs/` without movin
|
|
|
25
25
|
- `sdd-sync`: update canonical specs and keep the change active.
|
|
26
26
|
- `sdd-archive`: verify archive readiness and move the already-synced change to dated archive.
|
|
27
27
|
|
|
28
|
+
## Status and Action Context Guard
|
|
29
|
+
|
|
30
|
+
Before syncing, consume structured SDD status from the parent prompt. If missing, produce the same fields using this lookup order: project override `.pi/gentle-ai/support/sdd-status-contract.md`, then globally installed `~/.pi/agent/gentle-ai/support/sdd-status-contract.md`, then the embedded status contract. Do not use `assets/support/...` as a runtime path; that is only the package source path before installation.
|
|
31
|
+
|
|
32
|
+
Stop with `blocked` if:
|
|
33
|
+
|
|
34
|
+
- active change selection is missing or ambiguous;
|
|
35
|
+
- `actionContext.mode: workspace-planning` and no `allowedEditRoots` are provided;
|
|
36
|
+
- canonical spec paths are outside the authoritative workspace or allowed edit roots.
|
|
37
|
+
|
|
28
38
|
## Artifact Store Modes
|
|
29
39
|
|
|
30
40
|
- `openspec`: perform filesystem sync and write `sync-report.md`.
|
|
@@ -49,7 +59,8 @@ Stop with `blocked` if:
|
|
|
49
59
|
- file-backed mode has only legacy flat `openspec/changes/{change}/spec.md` and no domain specs;
|
|
50
60
|
- a MODIFIED or REMOVED requirement does not exist in the canonical spec;
|
|
51
61
|
- a destructive sync uses REMOVED requirements or large MODIFIED blocks and the parent prompt does not record explicit approval;
|
|
52
|
-
- another active change touches the same `specs/{domain}/spec.md` and the parent prompt does not record a chosen archive/sync order
|
|
62
|
+
- another active change touches the same `specs/{domain}/spec.md` and the parent prompt does not record a chosen archive/sync order;
|
|
63
|
+
- a delta contains `## RENAMED Requirements`; RENAMED sync is not supported by the native helper yet, so require a corrected ADDED/MODIFIED/REMOVED delta or explicit helper implementation before syncing.
|
|
53
64
|
|
|
54
65
|
## File-Backed Sync
|
|
55
66
|
|
|
@@ -71,6 +82,7 @@ Use the native helper semantics from `lib/openspec-deltas.ts` when editing manua
|
|
|
71
82
|
- `## ADDED Requirements` appends requirements.
|
|
72
83
|
- `## MODIFIED Requirements` replaces full matching requirement blocks by exact name.
|
|
73
84
|
- `## REMOVED Requirements` deletes full matching requirement blocks by exact name.
|
|
85
|
+
- `## RENAMED Requirements` is intentionally unsupported until `lib/openspec-deltas.ts` implements it; block instead of improvising.
|
|
74
86
|
- Preserve unrelated canonical requirements and document sections.
|
|
75
87
|
|
|
76
88
|
Use guardrail semantics from `lib/openspec-guardrails.ts`:
|
|
@@ -92,6 +104,7 @@ Include:
|
|
|
92
104
|
- active same-domain collisions;
|
|
93
105
|
- destructive sync approvals or blockers;
|
|
94
106
|
- validation commands or checks performed;
|
|
107
|
+
- structured status and `actionContext` findings;
|
|
95
108
|
- next recommended phase: `sdd-archive` when clean.
|
|
96
109
|
|
|
97
110
|
## Rules
|
|
@@ -19,9 +19,20 @@ The parent/orchestrator owns memory retrieval: use memory context passed in the
|
|
|
19
19
|
When callable memory tools are available, save significant discoveries, decisions, bug fixes, and completed SDD phase artifacts before returning. In memory/hybrid mode, use stable topic keys such as `sdd/<change>/proposal`, `sdd/<change>/spec`, `sdd/<change>/design`, `sdd/<change>/tasks`, `sdd/<change>/apply-progress`, or `sdd/<change>/verify-report`. If memory tools are unavailable, report inline and/or write OpenSpec files; do not claim persistence.
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
## Status and Action Context Guard
|
|
23
|
+
|
|
24
|
+
Before verification, consume structured SDD status from the parent prompt. If missing, produce the same fields using this lookup order: project override `.pi/gentle-ai/support/sdd-status-contract.md`, then globally installed `~/.pi/agent/gentle-ai/support/sdd-status-contract.md`, then the embedded status contract. Do not use `assets/support/...` as a runtime path; that is only the package source path before installation.
|
|
25
|
+
|
|
26
|
+
Stop with `blocked` if:
|
|
27
|
+
|
|
28
|
+
- active change selection is missing or ambiguous;
|
|
29
|
+
- `tasks.md` / the tasks artifact is missing or empty;
|
|
30
|
+
- `actionContext.mode: workspace-planning` and no `allowedEditRoots` are provided;
|
|
31
|
+
- implementation ownership or target files cannot be proven inside the authoritative workspace or allowed edit roots.
|
|
32
|
+
|
|
22
33
|
## Inputs
|
|
23
34
|
|
|
24
|
-
Read specs, design, tasks, apply-progress, changed code, tests, and `openspec/config.yaml` when present.
|
|
35
|
+
Read structured status, specs, design, tasks, apply-progress, changed code, tests, and `openspec/config.yaml` when present.
|
|
25
36
|
|
|
26
37
|
## Verification
|
|
27
38
|
|
|
@@ -49,13 +60,32 @@ Verify that implementation respected the `Review Workload Forecast` from `tasks.
|
|
|
49
60
|
- If `Chain strategy` was set, confirm the returned PR/work boundary matches it.
|
|
50
61
|
- Flag scope creep beyond assigned tasks as WARNING or CRITICAL depending on risk.
|
|
51
62
|
|
|
63
|
+
## Task Checkbox Verification
|
|
64
|
+
|
|
65
|
+
Scan `openspec/changes/{change}/tasks.md` or the memory tasks artifact for unchecked implementation task markers matching `^\s*- \[ \]`.
|
|
66
|
+
|
|
67
|
+
If unchecked implementation tasks remain:
|
|
68
|
+
|
|
69
|
+
- mark each as a CRITICAL completeness issue and archive blocker;
|
|
70
|
+
- include the exact unchecked lines;
|
|
71
|
+
- do not return a clean `PASS` or say ready for archive while unchecked implementation tasks remain.
|
|
72
|
+
|
|
73
|
+
If a partial slice is approved, report unchecked lines as remaining scope and state that archive is not ready. Archive exceptions are limited to non-critical partial archives or stale-checkbox reconciliation proven by apply-progress/verify-report; they do not turn incomplete tasks into a clean verification pass.
|
|
74
|
+
|
|
75
|
+
## Graceful Artifact Handling
|
|
76
|
+
|
|
77
|
+
- Tasks only: verify task completion only, skip spec/design checks, and say what was skipped.
|
|
78
|
+
- Tasks + specs: verify task completion and spec requirement/scenario coverage, skip design coherence with a note.
|
|
79
|
+
- Full artifacts: verify tasks, specs, design, implementation, tests, and review workload.
|
|
80
|
+
|
|
52
81
|
## Report
|
|
53
82
|
|
|
54
83
|
Write `openspec/changes/{change}/verify-report.md` with:
|
|
55
84
|
|
|
56
85
|
- pass/fail status;
|
|
57
86
|
- spec coverage;
|
|
58
|
-
- task completion status;
|
|
87
|
+
- task completion status, including exact unchecked `- [ ]` implementation task lines or confirmation that none remain;
|
|
88
|
+
- structured status and `actionContext` findings;
|
|
59
89
|
- test/validation commands;
|
|
60
90
|
- strict TDD compliance when active;
|
|
61
91
|
- assertion quality findings when active;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sdd-full
|
|
3
|
-
description: Run the full SDD lifecycle for a change
|
|
3
|
+
description: Run the full SDD lifecycle for a change in auto mode or explicit full-lifecycle approval.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
## Interactive mode guard
|
|
7
|
+
|
|
8
|
+
This chain is a continuous lifecycle pipeline. Use it only in auto mode or explicit full-lifecycle approval. In interactive mode the parent/orchestrator must stop at each phase boundary, present the current artifact, and ask the user before continuing. Approval to start SDD is not approval of the generated proposal, specs, design, tasks, apply, verify, sync, or archive phases.
|
|
9
|
+
|
|
6
10
|
## sdd-init
|
|
7
11
|
|
|
8
12
|
output: init.md
|
|
@@ -27,7 +31,7 @@ output: proposal.md
|
|
|
27
31
|
outputMode: file-only
|
|
28
32
|
progress: true
|
|
29
33
|
|
|
30
|
-
Create or update the OpenSpec proposal for {task} using the exploration notes and the previous step output.
|
|
34
|
+
Create or update the OpenSpec proposal for {task} using the exploration notes and the previous step output. If this is an interactive SDD run and the parent has not already supplied proposal-shaping answers, surface the missing questions in the result so the parent can ask before treating the proposal as approved.
|
|
31
35
|
|
|
32
36
|
## sdd-spec
|
|
33
37
|
|
|
@@ -36,7 +40,7 @@ output: spec.md
|
|
|
36
40
|
outputMode: file-only
|
|
37
41
|
progress: true
|
|
38
42
|
|
|
39
|
-
Write delta specs for {task} from the approved proposal. Preserve RFC 2119 requirements and Given/When/Then scenarios.
|
|
43
|
+
Write delta specs for {task} from the parent-approved proposal. Preserve RFC 2119 requirements and Given/When/Then scenarios. In interactive mode, do not treat chain execution alone as proposal approval.
|
|
40
44
|
|
|
41
45
|
## sdd-design
|
|
42
46
|
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sdd-plan
|
|
3
|
-
description: Plan an SDD change through proposal, spec, design, and tasks.
|
|
3
|
+
description: Plan an SDD change through proposal, spec, design, and tasks; safe for auto mode or explicit all-planning approval.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
## Interactive mode guard
|
|
7
|
+
|
|
8
|
+
This chain is a continuous planning pipeline. Use it only in auto mode or explicit all-planning approval. In interactive mode the parent/orchestrator must stop after sdd-proposal, present the proposal, and ask the user before continuing to sdd-spec, sdd-design, and sdd-tasks.
|
|
9
|
+
|
|
6
10
|
## sdd-init
|
|
7
11
|
|
|
8
12
|
output: init.md
|
|
@@ -18,7 +22,7 @@ output: proposal.md
|
|
|
18
22
|
outputMode: file-only
|
|
19
23
|
progress: true
|
|
20
24
|
|
|
21
|
-
Create or update the OpenSpec proposal for {task}. Use prior exploration if it is available in the project artifacts.
|
|
25
|
+
Create or update the OpenSpec proposal for {task}. Use prior exploration if it is available in the project artifacts. If this is an interactive SDD run and the parent has not already supplied proposal-shaping answers, surface the missing questions in the result so the parent can ask before treating the proposal as approved.
|
|
22
26
|
|
|
23
27
|
## sdd-spec
|
|
24
28
|
|
package/assets/orchestrator.md
CHANGED
|
@@ -169,16 +169,33 @@ stop writes → parent captures git status → reviewer fresh audits affected re
|
|
|
169
169
|
SDD phases:
|
|
170
170
|
|
|
171
171
|
```text
|
|
172
|
-
init → explore → proposal → spec → design → tasks → apply → verify → archive
|
|
172
|
+
init → explore → proposal → spec → design → tasks → apply → verify → sync → archive
|
|
173
173
|
```
|
|
174
174
|
|
|
175
175
|
Dependency graph:
|
|
176
176
|
|
|
177
177
|
```text
|
|
178
|
-
proposal → spec ─┬→ tasks → apply → verify → archive
|
|
178
|
+
proposal → spec ─┬→ tasks → apply → verify → sync → archive
|
|
179
179
|
proposal → design ┘
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
+
`/sdd-status [change]` is the read-only status action for resolving the active change, artifact paths, task progress, dependency readiness, and action context before apply/verify/sync/archive.
|
|
183
|
+
|
|
184
|
+
## SDD Status Contract
|
|
185
|
+
|
|
186
|
+
Before `/sdd-continue`, `sdd-apply`, `sdd-verify`, `sdd-sync`, or `sdd-archive`, resolve and carry structured status. Lookup order: parent-provided status, then project override `.pi/gentle-ai/support/sdd-status-contract.md`, then globally installed `~/.pi/agent/gentle-ai/support/sdd-status-contract.md`, then the embedded `sdd-status` prompt contract. Do not use `assets/support/...` as a runtime path; that is only the package source path before installation.
|
|
187
|
+
|
|
188
|
+
Status must include:
|
|
189
|
+
|
|
190
|
+
- active change selection and how it was resolved;
|
|
191
|
+
- artifact store and paths/topics for proposal, specs, design, tasks, apply-progress, verify-report, and sync-report;
|
|
192
|
+
- task progress with exact unchecked `- [ ]` implementation task lines;
|
|
193
|
+
- dependency states for apply, verify, sync, and archive;
|
|
194
|
+
- `actionContext` with mode, workspace root, allowed edit roots, and warnings;
|
|
195
|
+
- next recommended action.
|
|
196
|
+
|
|
197
|
+
Do not guess the active change. If change selection is ambiguous, ask the user and stop. If `actionContext.mode: workspace-planning` and no allowed edit roots are provided, stop before apply/verify/sync/archive and ask for an explicit implementation/edit scope.
|
|
198
|
+
|
|
182
199
|
## Lazy SDD Preflight
|
|
183
200
|
|
|
184
201
|
Do not ask SDD setup questions on session start. The first time the user initiates an SDD process in a Pi session, run the SDD preflight once and keep those choices for the rest of that session. Runtime trigger detection is intentionally deterministic: slash SDD flows and `/sdd-init` run preflight automatically; for natural-language requests, the parent/orchestrator decides semantically whether SDD is needed and must run/reuse `/gentle-ai:sdd-preflight` before continuing.
|
|
@@ -249,6 +266,10 @@ In interactive mode, between phases:
|
|
|
249
266
|
2. state next phase;
|
|
250
267
|
3. ask whether to continue or adjust.
|
|
251
268
|
|
|
269
|
+
Interactive approval is phase-scoped. A user response such as "continue", "dale", or "go on" approves only the immediate next phase, not the rest of the SDD pipeline. Do not treat a generated artifact as approved until the user has had a chance to review or explicitly delegate that review.
|
|
270
|
+
|
|
271
|
+
Before `sdd-proposal` in interactive mode, offer the user a proposal question round instead of silently deciding whether the proposal is clear enough. Explain that the questions are meant to improve the PRD/proposal by uncovering business understanding, business rules, implications, impact, edge cases, and product tradeoffs. Prefer 3–5 concrete product questions per round, then summarize the resulting assumptions and ask whether the user wants to correct anything or run a second question round. Cover business/product/PRD decisions: business problem, target users and situations, business rules, product outcome, current-state gap, implications and impact, edge cases, decision gaps, first-slice scope boundaries, non-goals, product constraints, and business tradeoffs. Do not ask about test commands, PR shape, changed-line budget, or other harness mechanics at proposal time unless the user explicitly asks to discuss delivery.
|
|
272
|
+
|
|
252
273
|
## Result Contract
|
|
253
274
|
|
|
254
275
|
Every phase result should include:
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# SDD Status and Action Context Contract
|
|
2
|
+
|
|
3
|
+
Shared OpenSpec-style contract for Gentle Pi SDD phases. Use this before acting on a change so orchestration and executors do not guess state, paths, or edit scope.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Any phase that selects, continues, applies, verifies, syncs, or archives an SDD change MUST first produce or consume structured status. The status is the handoff between the parent orchestrator and phase executor.
|
|
8
|
+
|
|
9
|
+
## Change Selection
|
|
10
|
+
|
|
11
|
+
- If a change name is provided, use that exact change after confirming it exists in the selected artifact store.
|
|
12
|
+
- If no change name is provided, infer only when the active change is unambiguous from session state or there is exactly one active change.
|
|
13
|
+
- If multiple active changes match or the active change is unclear, ask the user to choose. Do not guess.
|
|
14
|
+
- If no active changes exist, report that no SDD change is active and suggest starting one.
|
|
15
|
+
|
|
16
|
+
## Status Schema
|
|
17
|
+
|
|
18
|
+
Return status as markdown with these fields, or equivalent JSON when the host supports it:
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
schemaName: spec-driven
|
|
22
|
+
changeName: <change-name>
|
|
23
|
+
artifactStore: openspec | engram | both | none
|
|
24
|
+
planningHome:
|
|
25
|
+
root: <project-or-openspec-root>
|
|
26
|
+
changesDir: <openspec/changes or memory topic prefix>
|
|
27
|
+
changeRoot: <openspec/changes/<change> or memory topic prefix>
|
|
28
|
+
artifactPaths:
|
|
29
|
+
proposal: [<path-or-topic>]
|
|
30
|
+
specs: [<path-or-topic>]
|
|
31
|
+
design: [<path-or-topic>]
|
|
32
|
+
tasks: [<path-or-topic>]
|
|
33
|
+
applyProgress: [<path-or-topic>]
|
|
34
|
+
verifyReport: [<path-or-topic>]
|
|
35
|
+
syncReport: [<path-or-topic>]
|
|
36
|
+
contextFiles:
|
|
37
|
+
proposal: [<concrete readable files/topics>]
|
|
38
|
+
specs: [<concrete readable files/topics>]
|
|
39
|
+
design: [<concrete readable files/topics>]
|
|
40
|
+
tasks: [<concrete readable files/topics>]
|
|
41
|
+
applyProgress: [<concrete readable files/topics>]
|
|
42
|
+
verifyReport: [<concrete readable files/topics>]
|
|
43
|
+
syncReport: [<concrete readable files/topics>]
|
|
44
|
+
artifacts:
|
|
45
|
+
proposal: missing | done | partial
|
|
46
|
+
specs: missing | done | partial
|
|
47
|
+
design: missing | done | partial
|
|
48
|
+
tasks: missing | done | partial
|
|
49
|
+
applyProgress: missing | done | partial
|
|
50
|
+
verifyReport: missing | done | partial
|
|
51
|
+
syncReport: missing | done | partial
|
|
52
|
+
taskProgress:
|
|
53
|
+
total: 0
|
|
54
|
+
complete: 0
|
|
55
|
+
remaining: 0
|
|
56
|
+
unchecked: []
|
|
57
|
+
applyState: blocked | all_done | ready
|
|
58
|
+
dependencies:
|
|
59
|
+
apply: blocked | ready | all_done
|
|
60
|
+
verify: blocked | ready | all_done
|
|
61
|
+
sync: blocked | ready | all_done | not_applicable
|
|
62
|
+
archive: blocked | ready | all_done
|
|
63
|
+
actionContext:
|
|
64
|
+
mode: repo-local | workspace-planning
|
|
65
|
+
workspaceRoot: <absolute path>
|
|
66
|
+
allowedEditRoots: [<absolute paths>]
|
|
67
|
+
warnings: []
|
|
68
|
+
nextRecommended: <command-or-action>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Apply State
|
|
72
|
+
|
|
73
|
+
- `blocked`: required apply artifacts are missing, task selection is ambiguous, or action context makes edits unsafe.
|
|
74
|
+
- `all_done`: tasks artifact exists and every implementation task is checked `[x]`.
|
|
75
|
+
- `ready`: tasks artifact exists, at least one implementation task remains unchecked, and edit scope is safe.
|
|
76
|
+
|
|
77
|
+
## Dependency States
|
|
78
|
+
|
|
79
|
+
- `apply` is `ready` only when specs, design, and tasks are available and task progress is not all done.
|
|
80
|
+
- `verify` is `ready` when tasks exist and either apply-progress exists or the tasks artifact shows all intended implementation work complete. Unchecked implementation tasks remain CRITICAL blockers for full archive readiness.
|
|
81
|
+
- `sync` is `ready` only when verify-report exists and has no unresolved `FAIL`, `BLOCKED`, `CRITICAL`, or verification blockers. `engram`/`none` modes may mark sync `not_applicable`.
|
|
82
|
+
- `archive` is `ready` only when verify-report exists, sync is complete or not applicable, and tasks are complete. CRITICAL verification issues have no override. Explicit recorded exceptions are limited to non-critical partial archives or stale-checkbox reconciliation when apply-progress/verify-report prove completion.
|
|
83
|
+
|
|
84
|
+
## Action Context Guard
|
|
85
|
+
|
|
86
|
+
The orchestrator MUST carry `actionContext` into any phase launch.
|
|
87
|
+
|
|
88
|
+
- If `mode: workspace-planning` and `allowedEditRoots` is empty, stop before editing, verifying implementation ownership, syncing specs, or archiving. Treat linked repos and folders as read-only planning context.
|
|
89
|
+
- If `allowedEditRoots` is present, only edit or move files within those roots.
|
|
90
|
+
- If a phase cannot prove a file is inside the authoritative workspace or allowed edit roots, stop and ask for clarification.
|
|
91
|
+
|
|
92
|
+
## Status Output
|
|
93
|
+
|
|
94
|
+
Every command or agent that acts on a change MUST show or consume status before doing phase work:
|
|
95
|
+
|
|
96
|
+
- active change selection and how it was resolved;
|
|
97
|
+
- artifact statuses and paths/topics used as context;
|
|
98
|
+
- task progress and unchecked task list when tasks exist;
|
|
99
|
+
- next recommended action;
|
|
100
|
+
- any `actionContext` or edit-root warnings.
|
package/extensions/gentle-ai.ts
CHANGED
|
@@ -42,6 +42,7 @@ function sddGlobalAssetDriftCount(): number {
|
|
|
42
42
|
for (const [assetSubdir, installedSubdir] of [
|
|
43
43
|
["agents", "agents"],
|
|
44
44
|
["chains", "chains"],
|
|
45
|
+
["support", join("gentle-ai", "support")],
|
|
45
46
|
] as const) {
|
|
46
47
|
const assetDir = join(ASSETS_DIR, assetSubdir);
|
|
47
48
|
if (!existsSync(assetDir)) continue;
|
|
@@ -79,6 +80,7 @@ function sddLocalOverrideDriftCount(cwd: string): number {
|
|
|
79
80
|
for (const [assetSubdir, installedSubdir] of [
|
|
80
81
|
["agents", join(".pi", "agents")],
|
|
81
82
|
["chains", join(".pi", "chains")],
|
|
83
|
+
["support", join(".pi", "gentle-ai", "support")],
|
|
82
84
|
] as const) {
|
|
83
85
|
const assetDir = join(ASSETS_DIR, assetSubdir);
|
|
84
86
|
const installedDir = join(cwd, installedSubdir);
|
|
@@ -216,6 +218,7 @@ const SDD_AGENT_NAMES = [
|
|
|
216
218
|
"sdd-spec",
|
|
217
219
|
"sdd-design",
|
|
218
220
|
"sdd-tasks",
|
|
221
|
+
"sdd-status",
|
|
219
222
|
"sdd-apply",
|
|
220
223
|
"sdd-verify",
|
|
221
224
|
"sdd-sync",
|
package/lib/sdd-preflight.ts
CHANGED
|
@@ -235,6 +235,16 @@ export function renderSddPreflightPrompt(prefs: SddPreflightPreferences): string
|
|
|
235
235
|
const sourceLine = prefs.prompted
|
|
236
236
|
? "The user already chose these SDD preferences for this Pi session. Reuse them unless the user explicitly changes them."
|
|
237
237
|
: "No interactive UI was available for SDD preflight, so these default preferences were applied for this Pi session. Ask the user before making delivery decisions that depend on them.";
|
|
238
|
+
const interactiveRules =
|
|
239
|
+
prefs.executionMode === "interactive"
|
|
240
|
+
? [
|
|
241
|
+
"- Interactive phase gate: complete only the current SDD phase. Do not start the next SDD phase unless the current user turn explicitly approves that next phase.",
|
|
242
|
+
"- In interactive mode, words like `continue`, `dale`, or `go on` approve only the immediate next phase, not all remaining phases.",
|
|
243
|
+
"- Before writing an SDD proposal in interactive mode, offer the user a proposal question round to improve the PRD/proposal by uncovering business rules, implications, impact, edge cases, product tradeoffs, and decision gaps. Prefer 3–5 concrete product questions per round, then summarize assumptions and ask whether the user wants corrections or a second question round. Do not ask about test commands, PR shape, changed-line budget, or other harness mechanics at proposal time unless the user explicitly asks to discuss delivery.",
|
|
244
|
+
]
|
|
245
|
+
: [
|
|
246
|
+
"- Auto mode: phases may run back-to-back only because the user chose speed and trusts the flow.",
|
|
247
|
+
];
|
|
238
248
|
return [
|
|
239
249
|
"## SDD Session Preflight",
|
|
240
250
|
sourceLine,
|
|
@@ -242,6 +252,7 @@ export function renderSddPreflightPrompt(prefs: SddPreflightPreferences): string
|
|
|
242
252
|
`- Artifact store: ${prefs.artifactStore}${prefs.engramAvailable ? "" : " (Engram unavailable in this session)"}`,
|
|
243
253
|
`- Chained PR strategy: ${prefs.chainedPrStrategy}`,
|
|
244
254
|
`- Review budget: ${prefs.reviewBudgetLines} changed lines`,
|
|
255
|
+
...interactiveRules,
|
|
245
256
|
"- If task/workload forecasts conflict with these preferences, pause before sdd-apply and ask the user for a delivery decision.",
|
|
246
257
|
].join("\n");
|
|
247
258
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gentle-pi",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Turn Pi into el Gentleman: a senior-architect development harness with SDD/OpenSpec, subagents, strict TDD evidence, review guardrails, and skill discovery.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,12 +15,14 @@ const requiredPaths = [
|
|
|
15
15
|
"assets/agents/sdd-onboard.md",
|
|
16
16
|
"assets/agents/sdd-proposal.md",
|
|
17
17
|
"assets/agents/sdd-spec.md",
|
|
18
|
+
"assets/agents/sdd-status.md",
|
|
18
19
|
"assets/agents/sdd-sync.md",
|
|
19
20
|
"assets/agents/sdd-tasks.md",
|
|
20
21
|
"assets/agents/sdd-verify.md",
|
|
21
22
|
"assets/chains/sdd-full.chain.md",
|
|
22
23
|
"assets/chains/sdd-plan.chain.md",
|
|
23
24
|
"assets/chains/sdd-verify.chain.md",
|
|
25
|
+
"assets/support/sdd-status-contract.md",
|
|
24
26
|
"assets/support/strict-tdd.md",
|
|
25
27
|
"assets/support/strict-tdd-verify.md",
|
|
26
28
|
"extensions/gentle-ai.ts",
|
|
@@ -73,11 +73,51 @@ test("rendered SDD preflight prompt is English artifact copy", () => {
|
|
|
73
73
|
|
|
74
74
|
assert.match(prompt, /The user already chose these SDD preferences/);
|
|
75
75
|
assert.match(prompt, /Review budget: 400 changed lines/);
|
|
76
|
+
assert.match(prompt, /complete only the current SDD phase/i);
|
|
77
|
+
assert.match(prompt, /Do not start the next SDD phase/i);
|
|
78
|
+
assert.match(prompt, /approve only the immediate next phase/i);
|
|
79
|
+
assert.match(prompt, /offer the user a proposal question round/i);
|
|
80
|
+
assert.match(prompt, /business rules, implications, impact, edge cases/i);
|
|
81
|
+
assert.match(prompt, /second question round/i);
|
|
76
82
|
for (const pattern of SPANISH_PREFLIGHT_COPY) {
|
|
77
83
|
assert.doesNotMatch(prompt, pattern);
|
|
78
84
|
}
|
|
79
85
|
});
|
|
80
86
|
|
|
87
|
+
test("SDD proposal questions focus on business and PRD gaps", async () => {
|
|
88
|
+
const proposalAgent = await readFile(join(ROOT, "assets/agents/sdd-proposal.md"), "utf8");
|
|
89
|
+
|
|
90
|
+
assert.match(proposalAgent, /offer the user a proposal question round/i);
|
|
91
|
+
assert.match(proposalAgent, /second question round/i);
|
|
92
|
+
assert.match(proposalAgent, /business problem/i);
|
|
93
|
+
assert.match(proposalAgent, /business rules/i);
|
|
94
|
+
assert.match(proposalAgent, /implications and impact/i);
|
|
95
|
+
assert.match(proposalAgent, /edge cases/i);
|
|
96
|
+
assert.match(proposalAgent, /target users/i);
|
|
97
|
+
assert.match(proposalAgent, /product outcome/i);
|
|
98
|
+
assert.match(proposalAgent, /decision gaps/i);
|
|
99
|
+
// Proposal-shaping questions must stay on business/product ground: the agent is
|
|
100
|
+
// explicitly told to keep harness mechanics out of the proposal question round
|
|
101
|
+
// unless the user opts into discussing delivery. Removing this guard is the most
|
|
102
|
+
// likely way harness mechanics would leak back into proposal questions.
|
|
103
|
+
assert.match(
|
|
104
|
+
proposalAgent,
|
|
105
|
+
/Do not ask about test commands, PR shape, changed-line budget, or other harness decisions unless the user explicitly asks to discuss delivery/i,
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("SDD chain assets distinguish interactive gates from auto execution", async () => {
|
|
110
|
+
const planChain = await readFile(join(ROOT, "assets/chains/sdd-plan.chain.md"), "utf8");
|
|
111
|
+
const fullChain = await readFile(join(ROOT, "assets/chains/sdd-full.chain.md"), "utf8");
|
|
112
|
+
|
|
113
|
+
assert.match(planChain, /auto mode or explicit all-planning approval/i);
|
|
114
|
+
assert.match(planChain, /interactive mode/i);
|
|
115
|
+
assert.match(planChain, /must stop after sdd-proposal/i);
|
|
116
|
+
assert.match(fullChain, /auto mode or explicit full-lifecycle approval/i);
|
|
117
|
+
assert.match(fullChain, /interactive mode/i);
|
|
118
|
+
assert.match(fullChain, /must stop at each phase boundary/i);
|
|
119
|
+
});
|
|
120
|
+
|
|
81
121
|
test("persistent harness prompt assets do not hardcode Spanish SDD artifact copy", async () => {
|
|
82
122
|
const files = [
|
|
83
123
|
...(await collectTextFiles(join(ROOT, "assets"))),
|
|
@@ -311,8 +311,10 @@ async function run() {
|
|
|
311
311
|
);
|
|
312
312
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-apply.md")), true);
|
|
313
313
|
assert.equal(existsSync(join(globalAgentHome, "chains", "sdd-full.chain.md")), true);
|
|
314
|
+
assert.equal(existsSync(join(globalAgentHome, "gentle-ai", "support", "sdd-status-contract.md")), true);
|
|
314
315
|
await writeFile(join(globalAgentHome, "agents", "sdd-apply.md"), "stale global apply\n");
|
|
315
316
|
await writeFile(join(globalAgentHome, "chains", "sdd-full.chain.md"), "stale global chain\n");
|
|
317
|
+
await writeFile(join(globalAgentHome, "gentle-ai", "support", "sdd-status-contract.md"), "stale global status contract\n");
|
|
316
318
|
await mkdir(join(noUiCwd, ".pi", "agents"), { recursive: true });
|
|
317
319
|
await writeFile(join(noUiCwd, ".pi", "agents", "sdd-apply.md"), "project override must stay\n");
|
|
318
320
|
for (const handler of hooks.get("session_start")) {
|
|
@@ -328,6 +330,11 @@ async function run() {
|
|
|
328
330
|
"stale global chain\n",
|
|
329
331
|
"session_start must refresh stale global SDD chains",
|
|
330
332
|
);
|
|
333
|
+
assert.notEqual(
|
|
334
|
+
await readFile(join(globalAgentHome, "gentle-ai", "support", "sdd-status-contract.md"), "utf8"),
|
|
335
|
+
"stale global status contract\n",
|
|
336
|
+
"session_start must refresh stale global SDD support files",
|
|
337
|
+
);
|
|
331
338
|
assert.equal(
|
|
332
339
|
await readFile(join(noUiCwd, ".pi", "agents", "sdd-apply.md"), "utf8"),
|
|
333
340
|
"project override must stay\n",
|
|
@@ -402,7 +409,9 @@ async function run() {
|
|
|
402
409
|
assert.equal(existsSync(join(lazySddCwd, ".pi", "agents", "sdd-apply.md")), false);
|
|
403
410
|
assert.equal(existsSync(join(lazySddCwd, ".pi", "chains", "sdd-full.chain.md")), false);
|
|
404
411
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-apply.md")), true);
|
|
412
|
+
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-status.md")), true);
|
|
405
413
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-sync.md")), true);
|
|
414
|
+
assert.equal(existsSync(join(globalAgentHome, "gentle-ai", "support", "sdd-status-contract.md")), true);
|
|
406
415
|
assert.equal(existsSync(join(globalAgentHome, "chains", "sdd-full.chain.md")), true);
|
|
407
416
|
assert.equal(ctx.ui.selections.length, 3);
|
|
408
417
|
assert.equal(ctx.ui.selections[0].label, "SDD execution mode");
|
|
@@ -436,7 +445,9 @@ async function run() {
|
|
|
436
445
|
assert.equal(existsSync(join(lazySddCwd, ".pi", "agents", "sdd-apply.md")), false);
|
|
437
446
|
assert.equal(existsSync(join(lazySddCwd, ".pi", "chains", "sdd-full.chain.md")), false);
|
|
438
447
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-apply.md")), true);
|
|
448
|
+
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-status.md")), true);
|
|
439
449
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-sync.md")), true);
|
|
450
|
+
assert.equal(existsSync(join(globalAgentHome, "gentle-ai", "support", "sdd-status-contract.md")), true);
|
|
440
451
|
assert.equal(existsSync(join(globalAgentHome, "chains", "sdd-full.chain.md")), true);
|
|
441
452
|
const globalSddApply = await readFile(
|
|
442
453
|
join(globalAgentHome, "agents", "sdd-apply.md"),
|
|
@@ -605,6 +616,8 @@ async function run() {
|
|
|
605
616
|
assert.match(ctx.ui.notifications.at(-1).message, /Global Gentle AI SDD assets installed/);
|
|
606
617
|
assert.equal(existsSync(join(installCwd, ".pi", "agents", "sdd-apply.md")), false);
|
|
607
618
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-apply.md")), true);
|
|
619
|
+
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-status.md")), true);
|
|
620
|
+
assert.equal(existsSync(join(globalAgentHome, "gentle-ai", "support", "sdd-status-contract.md")), true);
|
|
608
621
|
} finally {
|
|
609
622
|
await rm(installCwd, { recursive: true, force: true });
|
|
610
623
|
}
|
|
@@ -613,9 +626,11 @@ async function run() {
|
|
|
613
626
|
try {
|
|
614
627
|
await mkdir(join(staleAssetsCwd, ".pi", "agents"), { recursive: true });
|
|
615
628
|
await mkdir(join(staleAssetsCwd, ".pi", "chains"), { recursive: true });
|
|
629
|
+
await mkdir(join(staleAssetsCwd, ".pi", "gentle-ai", "support"), { recursive: true });
|
|
616
630
|
await writeFile(join(staleAssetsCwd, ".pi", "agents", "sdd-apply.md"), "stale apply\n");
|
|
617
631
|
await writeFile(join(staleAssetsCwd, ".pi", "agents", "sdd-spec.md"), "stale spec\n");
|
|
618
632
|
await writeFile(join(staleAssetsCwd, ".pi", "chains", "sdd-full.chain.md"), "stale chain\n");
|
|
633
|
+
await writeFile(join(staleAssetsCwd, ".pi", "gentle-ai", "support", "sdd-status-contract.md"), "stale status contract\n");
|
|
619
634
|
const ctx = createCtx(staleAssetsCwd, true);
|
|
620
635
|
await commands.get("gentle-ai:status").handler("", ctx);
|
|
621
636
|
assert.match(ctx.ui.notifications.at(-1).message, /Project-local SDD override drift: \d+ file\(s\)/);
|
|
@@ -638,7 +653,9 @@ async function run() {
|
|
|
638
653
|
assert.equal(existsSync(join(sddCwd, ".pi", "agents", "sdd-apply.md")), false);
|
|
639
654
|
assert.equal(existsSync(join(sddCwd, ".pi", "chains", "sdd-full.chain.md")), false);
|
|
640
655
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-apply.md")), true);
|
|
656
|
+
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-status.md")), true);
|
|
641
657
|
assert.equal(existsSync(join(globalAgentHome, "agents", "sdd-sync.md")), true);
|
|
658
|
+
assert.equal(existsSync(join(globalAgentHome, "gentle-ai", "support", "sdd-status-contract.md")), true);
|
|
642
659
|
assert.equal(existsSync(join(globalAgentHome, "chains", "sdd-full.chain.md")), true);
|
|
643
660
|
assert.equal(ctx.ui.selections.length, 3);
|
|
644
661
|
assert.match(ctx.ui.notifications[0].message, /SDD preflight complete/);
|