gsd-pi 2.8.1 → 2.8.2
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/dist/loader.js +5 -0
- package/node_modules/@gsd/pi-coding-agent/dist/core/bash-executor.js +2 -2
- package/node_modules/@gsd/pi-coding-agent/dist/core/bash-executor.js.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash.js +2 -2
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.d.ts +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.d.ts.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.js +13 -2
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.js.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.test.d.ts +2 -0
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.test.d.ts.map +1 -0
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.test.js +57 -0
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -0
- package/node_modules/@gsd/pi-coding-agent/dist/index.d.ts +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/index.js +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/index.js.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -5
- package/node_modules/@gsd/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/utils/shell.d.ts +7 -0
- package/node_modules/@gsd/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/utils/shell.js +11 -0
- package/node_modules/@gsd/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/src/core/bash-executor.ts +2 -2
- package/node_modules/@gsd/pi-coding-agent/src/core/tools/bash.ts +2 -2
- package/node_modules/@gsd/pi-coding-agent/src/core/tools/path-utils.test.ts +66 -0
- package/node_modules/@gsd/pi-coding-agent/src/core/tools/path-utils.ts +14 -2
- package/node_modules/@gsd/pi-coding-agent/src/index.ts +1 -1
- package/node_modules/@gsd/pi-coding-agent/src/modes/interactive/interactive-mode.ts +6 -4
- package/node_modules/@gsd/pi-coding-agent/src/utils/shell.ts +11 -0
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/bash-executor.js +2 -2
- package/packages/pi-coding-agent/dist/core/bash-executor.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.js +13 -2
- package/packages/pi-coding-agent/dist/core/tools/path-utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +57 -0
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -5
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +7 -0
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +11 -0
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/src/core/bash-executor.ts +2 -2
- package/packages/pi-coding-agent/src/core/tools/bash.ts +2 -2
- package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +66 -0
- package/packages/pi-coding-agent/src/core/tools/path-utils.ts +14 -2
- package/packages/pi-coding-agent/src/index.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +6 -4
- package/packages/pi-coding-agent/src/utils/shell.ts +11 -0
- package/src/resources/extensions/bg-shell/index.ts +2 -1
- package/src/resources/extensions/gsd/auto.ts +18 -36
- package/src/resources/extensions/gsd/docs/preferences-reference.md +76 -0
- package/src/resources/extensions/gsd/gitignore.ts +27 -0
- package/src/resources/extensions/gsd/guided-flow.ts +10 -9
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -3
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +4 -4
- package/src/resources/extensions/gsd/tests/git-service.test.ts +53 -1
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +5 -5
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +2 -4
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import { join } from "node:path";
|
|
22
22
|
import { readFileSync, existsSync, mkdirSync, readdirSync, rmSync } from "node:fs";
|
|
23
23
|
import { execSync, execFileSync } from "node:child_process";
|
|
24
|
-
import { ensureGitignore, ensurePreferences } from "./gitignore.js";
|
|
24
|
+
import { ensureGitignore, ensurePreferences, untrackRuntimeFiles } from "./gitignore.js";
|
|
25
25
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
26
26
|
import { showConfirm } from "../shared/confirm-ui.js";
|
|
27
27
|
|
|
@@ -87,13 +87,13 @@ function dispatchWorkflow(pi: ExtensionAPI, note: string, customType = "gsd-run"
|
|
|
87
87
|
* Build the discuss-and-plan prompt for a new milestone.
|
|
88
88
|
* Used by all three "new milestone" paths (first ever, no active, all complete).
|
|
89
89
|
*/
|
|
90
|
-
function buildDiscussPrompt(nextId: string, preamble: string,
|
|
91
|
-
const
|
|
90
|
+
function buildDiscussPrompt(nextId: string, preamble: string, _basePath: string): string {
|
|
91
|
+
const milestoneRel = `.gsd/milestones/${nextId}`;
|
|
92
92
|
return loadPrompt("discuss", {
|
|
93
93
|
milestoneId: nextId,
|
|
94
94
|
preamble,
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
contextPath: `${milestoneRel}/${nextId}-CONTEXT.md`,
|
|
96
|
+
roadmapPath: `${milestoneRel}/${nextId}-ROADMAP.md`,
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -345,16 +345,16 @@ async function buildDiscussSlicePrompt(
|
|
|
345
345
|
? `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`
|
|
346
346
|
: `## Inlined Context\n\n_(no context files found yet — go in blind and ask broad questions)_`;
|
|
347
347
|
|
|
348
|
-
const
|
|
349
|
-
const
|
|
348
|
+
const sliceDirPath = `.gsd/milestones/${mid}/slices/${sid}`;
|
|
349
|
+
const sliceContextPath = `${sliceDirPath}/${sid}-CONTEXT.md`;
|
|
350
350
|
|
|
351
351
|
return loadPrompt("guided-discuss-slice", {
|
|
352
352
|
milestoneId: mid,
|
|
353
353
|
sliceId: sid,
|
|
354
354
|
sliceTitle: sTitle,
|
|
355
355
|
inlinedContext,
|
|
356
|
-
|
|
357
|
-
|
|
356
|
+
sliceDirPath,
|
|
357
|
+
contextPath: sliceContextPath,
|
|
358
358
|
projectRoot: base,
|
|
359
359
|
});
|
|
360
360
|
}
|
|
@@ -457,6 +457,7 @@ export async function showSmartEntry(
|
|
|
457
457
|
|
|
458
458
|
// ── Ensure .gitignore has baseline patterns ──────────────────────────
|
|
459
459
|
ensureGitignore(basePath);
|
|
460
|
+
untrackRuntimeFiles(basePath);
|
|
460
461
|
|
|
461
462
|
// ── No GSD project OR no milestone → Create first/next milestone ────
|
|
462
463
|
if (!existsSync(join(basePath, ".gsd"))) {
|
|
@@ -12,7 +12,7 @@ Then:
|
|
|
12
12
|
3. Verify each **success criterion** from the milestone definition in `{{roadmapPath}}`. For each criterion, confirm it was met with specific evidence from slice summaries, test results, or observable behavior. List any criterion that was NOT met.
|
|
13
13
|
4. Verify the milestone's **definition of done** — all slices are `[x]`, all slice summaries exist, and any cross-slice integration points work correctly.
|
|
14
14
|
5. Validate **requirement status transitions**. For each requirement that changed status during this milestone, confirm the transition is supported by evidence. Requirements can move between Active, Validated, Deferred, Blocked, or Out of Scope — but only with proof.
|
|
15
|
-
6. Write `{{
|
|
15
|
+
6. Write `{{milestoneSummaryPath}}` using the milestone-summary template. Fill all frontmatter fields and narrative sections. The `requirement_outcomes` field must list every requirement that changed status with `from_status`, `to_status`, and `proof`.
|
|
16
16
|
7. Update `.gsd/REQUIREMENTS.md` if any requirement status transitions were validated in step 5.
|
|
17
17
|
8. Update `.gsd/PROJECT.md` to reflect milestone completion and current project state.
|
|
18
18
|
9. Do not commit manually — the system auto-commits your changes after this unit completes.
|
|
@@ -20,6 +20,6 @@ Then:
|
|
|
20
20
|
|
|
21
21
|
**Important:** Do NOT skip the success criteria and definition of done verification (steps 3-4). The milestone summary must reflect actual verified outcomes, not assumed success. If any criterion was not met, document it clearly in the summary and do not mark the milestone as passing verification.
|
|
22
22
|
|
|
23
|
-
**You MUST write `{{
|
|
23
|
+
**You MUST write `{{milestoneSummaryPath}}` AND update PROJECT.md before finishing.**
|
|
24
24
|
|
|
25
25
|
When done, say: "Milestone {{milestoneId}} complete."
|
|
@@ -16,14 +16,14 @@ Then:
|
|
|
16
16
|
3. Run all slice-level verification checks defined in the slice plan. All must pass before marking the slice done. If any fail, fix them first.
|
|
17
17
|
4. If the slice plan includes observability/diagnostic surfaces, confirm they work. Skip this for simple slices that don't have observability sections.
|
|
18
18
|
5. If `.gsd/REQUIREMENTS.md` exists, update it based on what this slice actually proved. Move requirements between Active, Validated, Deferred, Blocked, or Out of Scope only when the evidence from execution supports that change.
|
|
19
|
-
6. Write `{{
|
|
20
|
-
7. Write `{{
|
|
19
|
+
6. Write `{{sliceSummaryPath}}` (compress all task summaries).
|
|
20
|
+
7. Write `{{sliceUatPath}}` — a concrete UAT script with real test cases derived from the slice plan and task summaries. Include preconditions, numbered steps with expected outcomes, and edge cases. This must NOT be a placeholder or generic template — tailor every test case to what this slice actually built.
|
|
21
21
|
8. Review task summaries for `key_decisions`. Append any significant decisions to `.gsd/DECISIONS.md` if missing.
|
|
22
22
|
9. Mark {{sliceId}} done in `{{roadmapPath}}` (change `[ ]` to `[x]`)
|
|
23
23
|
10. Do not commit or squash-merge manually — the system auto-commits your changes and handles the merge after this unit succeeds.
|
|
24
24
|
11. Update `.gsd/PROJECT.md` if it exists — refresh current state if needed.
|
|
25
25
|
12. Update `.gsd/STATE.md`
|
|
26
26
|
|
|
27
|
-
**You MUST do ALL THREE before finishing: (1) write `{{
|
|
27
|
+
**You MUST do ALL THREE before finishing: (1) write `{{sliceSummaryPath}}`, (2) write `{{sliceUatPath}}`, (3) mark {{sliceId}} as `[x]` in `{{roadmapPath}}`. The unit will not be marked complete if any of these files are missing.**
|
|
28
28
|
|
|
29
29
|
When done, say: "Slice {{sliceId}} complete."
|
|
@@ -191,8 +191,8 @@ Once the user is satisfied, in a single pass:
|
|
|
191
191
|
**Depth-Preservation Guidance for context.md:**
|
|
192
192
|
When writing context.md, preserve the user's exact terminology, emphasis, and specific framing from the discussion. Do not paraphrase user nuance into generic summaries. If the user said "craft feel," write "craft feel" — not "high-quality user experience." If they emphasized a specific constraint or negative requirement, carry that emphasis through verbatim. The context file is downstream agents' only window into this conversation — flattening specifics into generics loses the signal that shaped every decision.
|
|
193
193
|
|
|
194
|
-
4. Write `{{
|
|
195
|
-
5. Write `{{
|
|
194
|
+
4. Write `{{contextPath}}` — read the template at `~/.gsd/agent/extensions/gsd/templates/context.md` first. Preserve key risks, unknowns, existing codebase constraints, integration points, and relevant requirements surfaced during discussion.
|
|
195
|
+
5. Write `{{roadmapPath}}` — read the template at `~/.gsd/agent/extensions/gsd/templates/roadmap.md` first. Decompose into demoable vertical slices with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, requirement coverage, and a boundary map. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment.
|
|
196
196
|
6. Seed `.gsd/DECISIONS.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/decisions.md` first. Append rows for any architectural or pattern decisions made during discussion.
|
|
197
197
|
7. Update `.gsd/STATE.md`
|
|
198
198
|
8. Commit: `docs({{milestoneId}}): context, requirements, and roadmap`
|
|
@@ -49,13 +49,13 @@ Then:
|
|
|
49
49
|
11. **Blocker discovery:** If execution reveals that the remaining slice plan is fundamentally invalid — not just a bug or minor deviation, but a plan-invalidating finding like a wrong API, missing capability, or architectural mismatch — set `blocker_discovered: true` in the task summary frontmatter and describe the blocker clearly in the summary narrative. Do NOT set `blocker_discovered: true` for ordinary debugging, minor deviations, or issues that can be fixed within the current task or the remaining plan. This flag triggers an automatic replan of the slice.
|
|
50
50
|
12. If you made an architectural, pattern, library, or observability decision during this task that downstream work should know about, append it to `.gsd/DECISIONS.md` (read the template at `~/.gsd/agent/extensions/gsd/templates/decisions.md` if the file doesn't exist yet). Not every task produces decisions — only append when a meaningful choice was made.
|
|
51
51
|
13. Read the template at `~/.gsd/agent/extensions/gsd/templates/task-summary.md`
|
|
52
|
-
14. Write `{{
|
|
52
|
+
14. Write `{{taskSummaryPath}}`
|
|
53
53
|
15. Mark {{taskId}} done in `{{planPath}}` (change `[ ]` to `[x]`)
|
|
54
54
|
16. Do not commit manually — the system auto-commits your changes after this unit completes.
|
|
55
55
|
17. Update `.gsd/STATE.md`
|
|
56
56
|
|
|
57
57
|
You are on the slice branch. All work stays here.
|
|
58
58
|
|
|
59
|
-
**You MUST mark {{taskId}} as `[x]` in `{{planPath}}` AND write `{{
|
|
59
|
+
**You MUST mark {{taskId}} as `[x]` in `{{planPath}}` AND write `{{taskSummaryPath}}` before finishing.**
|
|
60
60
|
|
|
61
61
|
When done, say: "Task {{taskId}} complete."
|
|
@@ -46,8 +46,8 @@ If the user wants to keep going, keep asking. Stop when they say wrap up.
|
|
|
46
46
|
Once the user is ready to wrap up:
|
|
47
47
|
|
|
48
48
|
1. Read the slice context template at `~/.gsd/agent/extensions/gsd/templates/slice-context.md`
|
|
49
|
-
2. `mkdir -p {{
|
|
50
|
-
3. Write `{{
|
|
49
|
+
2. `mkdir -p {{sliceDirPath}}`
|
|
50
|
+
3. Write `{{contextPath}}` — use the template structure, filling in:
|
|
51
51
|
- **Goal** — one sentence: what this slice delivers
|
|
52
52
|
- **Why this Slice** — why now, what it unblocks
|
|
53
53
|
- **Scope / In Scope** — what was confirmed in scope during the interview
|
|
@@ -55,5 +55,5 @@ Once the user is ready to wrap up:
|
|
|
55
55
|
- **Constraints** — anything the user flagged as a hard constraint
|
|
56
56
|
- **Integration Points** — what this slice consumes and produces
|
|
57
57
|
- **Open Questions** — anything still unresolved, with current thinking
|
|
58
|
-
4. Commit: `git -C {{projectRoot}} add {{
|
|
58
|
+
4. Commit: `git -C {{projectRoot}} add {{contextPath}} && git -C {{projectRoot}} commit -m "docs({{milestoneId}}/{{sliceId}}): slice context from discuss"`
|
|
59
59
|
5. Say exactly: `"{{sliceId}} context written."` — nothing else.
|
|
@@ -76,6 +76,6 @@ If this milestone requires any external API keys or secrets:
|
|
|
76
76
|
|
|
77
77
|
If this milestone does not require any external API keys or secrets, skip this step entirely — do not create an empty manifest.
|
|
78
78
|
|
|
79
|
-
**You MUST write the file `{{
|
|
79
|
+
**You MUST write the file `{{outputPath}}` before finishing.**
|
|
80
80
|
|
|
81
81
|
When done, say: "Milestone {{milestoneId}} planned."
|
|
@@ -37,7 +37,7 @@ Then:
|
|
|
37
37
|
- a matching task plan file with description, steps, must-haves, verification, inputs, and expected output
|
|
38
38
|
- Observability Impact section **only if the task touches runtime boundaries, async flows, or error paths** — omit it otherwise
|
|
39
39
|
6. Write `{{outputPath}}`
|
|
40
|
-
7. Write individual task plans in `{{
|
|
40
|
+
7. Write individual task plans in `{{slicePath}}/tasks/`: `T01-PLAN.md`, `T02-PLAN.md`, etc.
|
|
41
41
|
8. **Self-audit the plan.** Walk through each check — if any fail, fix the plan files before moving on:
|
|
42
42
|
- **Completion semantics:** If every task were completed exactly as written, the slice goal/demo should actually be true.
|
|
43
43
|
- **Requirement coverage:** Every must-have in the slice maps to at least one task. No must-have is orphaned. If `REQUIREMENTS.md` exists, every Active requirement this slice owns maps to at least one task.
|
|
@@ -52,6 +52,6 @@ Then:
|
|
|
52
52
|
|
|
53
53
|
The slice directory and tasks/ subdirectory already exist. Do NOT mkdir. You are on the slice branch; all work stays here.
|
|
54
54
|
|
|
55
|
-
**You MUST write the file `{{
|
|
55
|
+
**You MUST write the file `{{outputPath}}` before finishing.**
|
|
56
56
|
|
|
57
57
|
When done, say: "Slice {{sliceId}} planned."
|
|
@@ -34,15 +34,15 @@ If all criteria have at least one remaining owning slice, the coverage check pas
|
|
|
34
34
|
|
|
35
35
|
**If the roadmap is still good:**
|
|
36
36
|
|
|
37
|
-
Write `{{
|
|
37
|
+
Write `{{assessmentPath}}` with a brief confirmation that roadmap coverage still holds after {{completedSliceId}}. If requirements exist, explicitly note whether requirement coverage remains sound.
|
|
38
38
|
|
|
39
39
|
**If changes are needed:**
|
|
40
40
|
|
|
41
41
|
1. Rewrite the remaining (unchecked) slices in `{{roadmapPath}}`. Keep completed slices exactly as they are (`[x]`). Update the boundary map for changed slices. Update the proof strategy if risks changed. Update requirement coverage if ownership or scope changed.
|
|
42
|
-
2. Write `{{
|
|
42
|
+
2. Write `{{assessmentPath}}` explaining what changed and why — keep it brief and concrete.
|
|
43
43
|
3. If `.gsd/REQUIREMENTS.md` exists and requirement ownership or status changed, update it.
|
|
44
44
|
4. Commit: `docs({{milestoneId}}): reassess roadmap after {{completedSliceId}}`
|
|
45
45
|
|
|
46
|
-
**You MUST write the file `{{
|
|
46
|
+
**You MUST write the file `{{assessmentPath}}` before finishing.**
|
|
47
47
|
|
|
48
48
|
When done, say: "Roadmap reassessed."
|
|
@@ -20,7 +20,7 @@ All relevant context has been preloaded below — the roadmap, current slice pla
|
|
|
20
20
|
|
|
21
21
|
1. Read the blocker task summary carefully. Understand exactly what was discovered and why it blocks the current plan.
|
|
22
22
|
2. Analyze the remaining `[ ]` tasks in the slice plan. Determine which are still valid, which need modification, and which should be replaced.
|
|
23
|
-
3. Write `{{
|
|
23
|
+
3. Write `{{replanPath}}` documenting:
|
|
24
24
|
- What blocker was discovered and in which task
|
|
25
25
|
- What changed in the plan and why
|
|
26
26
|
- Which incomplete tasks were modified, added, or removed
|
|
@@ -34,6 +34,6 @@ All relevant context has been preloaded below — the roadmap, current slice pla
|
|
|
34
34
|
6. Do not commit manually — the system auto-commits your changes after this unit completes.
|
|
35
35
|
7. Update `.gsd/STATE.md`
|
|
36
36
|
|
|
37
|
-
**You MUST write `{{
|
|
37
|
+
**You MUST write `{{replanPath}}` and the updated slice plan before finishing.**
|
|
38
38
|
|
|
39
39
|
When done, say: "Slice {{sliceId}} replanned."
|
|
@@ -32,6 +32,6 @@ Then research the codebase and relevant technologies. Narrate key findings and s
|
|
|
32
32
|
|
|
33
33
|
**Research is advisory, not auto-binding.** Surface candidate requirements clearly instead of silently expanding scope.
|
|
34
34
|
|
|
35
|
-
**You MUST write the file `{{
|
|
35
|
+
**You MUST write the file `{{outputPath}}` before finishing.**
|
|
36
36
|
|
|
37
37
|
When done, say: "Milestone {{milestoneId}} researched."
|
|
@@ -23,6 +23,6 @@ Then research what this slice needs. Narrate key findings and surprises as you g
|
|
|
23
23
|
|
|
24
24
|
The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir — just write the file.
|
|
25
25
|
|
|
26
|
-
**You MUST write the file `{{
|
|
26
|
+
**You MUST write the file `{{outputPath}}` before finishing.**
|
|
27
27
|
|
|
28
28
|
When done, say: "Slice {{sliceId}} researched."
|
|
@@ -14,7 +14,7 @@ If a `GSD Skill Preferences` block is present in system context, use it to decid
|
|
|
14
14
|
|
|
15
15
|
**UAT file:** `{{uatPath}}`
|
|
16
16
|
**UAT type:** `{{uatType}}`
|
|
17
|
-
**Result file to write:** `{{
|
|
17
|
+
**Result file to write:** `{{uatResultPath}}`
|
|
18
18
|
|
|
19
19
|
### If UAT type is `artifact-driven`
|
|
20
20
|
|
|
@@ -37,7 +37,7 @@ After running all checks, compute the **overall verdict**:
|
|
|
37
37
|
- `FAIL` — one or more checks failed
|
|
38
38
|
- `PARTIAL` — some checks passed, some failed or were skipped
|
|
39
39
|
|
|
40
|
-
Write `{{
|
|
40
|
+
Write `{{uatResultPath}}` with:
|
|
41
41
|
|
|
42
42
|
```markdown
|
|
43
43
|
---
|
|
@@ -68,7 +68,7 @@ date: <ISO 8601 timestamp>
|
|
|
68
68
|
|
|
69
69
|
This UAT type requires human execution or live-runtime observation that you cannot perform mechanically. Your role is to surface it clearly for review.
|
|
70
70
|
|
|
71
|
-
Write `{{
|
|
71
|
+
Write `{{uatResultPath}}` with:
|
|
72
72
|
|
|
73
73
|
```markdown
|
|
74
74
|
---
|
|
@@ -104,6 +104,6 @@ Once updated, run `/gsd auto` to resume auto-mode.
|
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
|
107
|
-
**You MUST write `{{
|
|
107
|
+
**You MUST write `{{uatResultPath}}` before finishing.**
|
|
108
108
|
|
|
109
109
|
When done, say: "UAT {{sliceId}} complete."
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
1
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync } from "node:fs";
|
|
2
2
|
import { join, dirname } from "node:path";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { execSync } from "node:child_process";
|
|
@@ -1370,6 +1370,58 @@ async function main(): Promise<void> {
|
|
|
1370
1370
|
assert(true, "PreMergeCheckResult type exported and usable");
|
|
1371
1371
|
}
|
|
1372
1372
|
|
|
1373
|
+
// ─── untrackRuntimeFiles: removes tracked runtime files from index ───
|
|
1374
|
+
|
|
1375
|
+
console.log("\n=== untrackRuntimeFiles ===");
|
|
1376
|
+
|
|
1377
|
+
{
|
|
1378
|
+
const { untrackRuntimeFiles } = await import("../gitignore.ts");
|
|
1379
|
+
const repo = mkdtempSync(join(tmpdir(), "gsd-untrack-"));
|
|
1380
|
+
run("git init -b main", repo);
|
|
1381
|
+
run("git config user.email test@test.com", repo);
|
|
1382
|
+
run("git config user.name Test", repo);
|
|
1383
|
+
|
|
1384
|
+
// Create and track runtime files (simulates pre-.gitignore state)
|
|
1385
|
+
mkdirSync(join(repo, ".gsd", "activity"), { recursive: true });
|
|
1386
|
+
mkdirSync(join(repo, ".gsd", "runtime"), { recursive: true });
|
|
1387
|
+
writeFileSync(join(repo, ".gsd", "completed-units.json"), '["u1"]');
|
|
1388
|
+
writeFileSync(join(repo, ".gsd", "metrics.json"), '{}');
|
|
1389
|
+
writeFileSync(join(repo, ".gsd", "STATE.md"), "# State");
|
|
1390
|
+
writeFileSync(join(repo, ".gsd", "activity", "log.jsonl"), "{}");
|
|
1391
|
+
writeFileSync(join(repo, ".gsd", "runtime", "data.json"), "{}");
|
|
1392
|
+
writeFileSync(join(repo, "src.ts"), "code");
|
|
1393
|
+
run("git add -A", repo);
|
|
1394
|
+
run("git commit -m init", repo);
|
|
1395
|
+
|
|
1396
|
+
// Precondition: runtime files are tracked
|
|
1397
|
+
const trackedBefore = run("git ls-files .gsd/", repo);
|
|
1398
|
+
assert(trackedBefore.includes("completed-units.json"), "untrack: precondition — completed-units tracked");
|
|
1399
|
+
assert(trackedBefore.includes("metrics.json"), "untrack: precondition — metrics tracked");
|
|
1400
|
+
|
|
1401
|
+
// Run untrackRuntimeFiles
|
|
1402
|
+
untrackRuntimeFiles(repo);
|
|
1403
|
+
|
|
1404
|
+
// Runtime files should be removed from the index
|
|
1405
|
+
const trackedAfter = run("git ls-files .gsd/", repo);
|
|
1406
|
+
assertEq(trackedAfter, "", "untrack: all runtime files removed from index");
|
|
1407
|
+
|
|
1408
|
+
// Non-runtime files remain tracked
|
|
1409
|
+
const srcTracked = run("git ls-files src.ts", repo);
|
|
1410
|
+
assert(srcTracked.includes("src.ts"), "untrack: non-runtime files remain tracked");
|
|
1411
|
+
|
|
1412
|
+
// Files still exist on disk
|
|
1413
|
+
assert(existsSync(join(repo, ".gsd", "completed-units.json")),
|
|
1414
|
+
"untrack: completed-units.json still on disk");
|
|
1415
|
+
assert(existsSync(join(repo, ".gsd", "metrics.json")),
|
|
1416
|
+
"untrack: metrics.json still on disk");
|
|
1417
|
+
|
|
1418
|
+
// Idempotent — running again doesn't error
|
|
1419
|
+
untrackRuntimeFiles(repo);
|
|
1420
|
+
assert(true, "untrack: second call is idempotent (no error)");
|
|
1421
|
+
|
|
1422
|
+
rmSync(repo, { recursive: true, force: true });
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1373
1425
|
console.log(`\nResults: ${passed} passed, ${failed} failed`);
|
|
1374
1426
|
if (failed > 0) process.exit(1);
|
|
1375
1427
|
console.log("All tests passed ✓");
|
|
@@ -54,7 +54,7 @@ async function main(): Promise<void> {
|
|
|
54
54
|
const testVars = {
|
|
55
55
|
milestoneId: "M099",
|
|
56
56
|
completedSliceId: "S03",
|
|
57
|
-
|
|
57
|
+
assessmentPath: ".gsd/milestones/M099/slices/S03/S03-ASSESSMENT.md",
|
|
58
58
|
roadmapPath: ".gsd/milestones/M099/M099-ROADMAP.md",
|
|
59
59
|
inlinedContext: "--- test inlined context block ---",
|
|
60
60
|
};
|
|
@@ -75,14 +75,14 @@ async function main(): Promise<void> {
|
|
|
75
75
|
// Verify all test variables were substituted into the output
|
|
76
76
|
assert(result.includes("M099"), "prompt contains milestoneId 'M099'");
|
|
77
77
|
assert(result.includes("S03"), "prompt contains completedSliceId 'S03'");
|
|
78
|
-
assert(result.includes(".gsd/milestones/M099/slices/S03/S03-ASSESSMENT.md"), "prompt contains
|
|
78
|
+
assert(result.includes(".gsd/milestones/M099/slices/S03/S03-ASSESSMENT.md"), "prompt contains assessmentPath");
|
|
79
79
|
assert(result.includes(".gsd/milestones/M099/M099-ROADMAP.md"), "prompt contains roadmapPath");
|
|
80
80
|
assert(result.includes("--- test inlined context block ---"), "prompt contains inlinedContext");
|
|
81
81
|
|
|
82
82
|
// Verify no un-substituted variables remain
|
|
83
83
|
assert(!result.includes("{{milestoneId}}"), "no un-substituted {{milestoneId}}");
|
|
84
84
|
assert(!result.includes("{{completedSliceId}}"), "no un-substituted {{completedSliceId}}");
|
|
85
|
-
assert(!result.includes("{{
|
|
85
|
+
assert(!result.includes("{{assessmentPath}}"), "no un-substituted {{assessmentPath}}");
|
|
86
86
|
assert(!result.includes("{{roadmapPath}}"), "no un-substituted {{roadmapPath}}");
|
|
87
87
|
assert(!result.includes("{{inlinedContext}}"), "no un-substituted {{inlinedContext}}");
|
|
88
88
|
}
|
|
@@ -93,7 +93,7 @@ async function main(): Promise<void> {
|
|
|
93
93
|
const prompt = loadPromptFromWorktree("reassess-roadmap", {
|
|
94
94
|
milestoneId: "M001",
|
|
95
95
|
completedSliceId: "S01",
|
|
96
|
-
|
|
96
|
+
assessmentPath: ".gsd/milestones/M001/slices/S01/S01-ASSESSMENT.md",
|
|
97
97
|
roadmapPath: ".gsd/milestones/M001/M001-ROADMAP.md",
|
|
98
98
|
inlinedContext: "context",
|
|
99
99
|
});
|
|
@@ -132,7 +132,7 @@ async function main(): Promise<void> {
|
|
|
132
132
|
const prompt = loadPromptFromWorktree("reassess-roadmap", {
|
|
133
133
|
milestoneId: "M001",
|
|
134
134
|
completedSliceId: "S01",
|
|
135
|
-
|
|
135
|
+
assessmentPath: ".gsd/milestones/M001/slices/S01/S01-ASSESSMENT.md",
|
|
136
136
|
roadmapPath: ".gsd/milestones/M001/M001-ROADMAP.md",
|
|
137
137
|
inlinedContext: "context",
|
|
138
138
|
});
|
|
@@ -404,12 +404,13 @@ console.log('\n=== prompt: replan-slice contains preserve-completed-tasks instru
|
|
|
404
404
|
slicePath: '.gsd/milestones/M001/slices/S01',
|
|
405
405
|
planPath: '.gsd/milestones/M001/slices/S01/S01-PLAN.md',
|
|
406
406
|
blockerTaskId: 'T01',
|
|
407
|
+
replanPath: '.gsd/milestones/M001/slices/S01/S01-REPLAN.md',
|
|
407
408
|
inlinedContext: '',
|
|
408
409
|
});
|
|
409
410
|
|
|
410
411
|
assert(prompt.includes('Do NOT renumber or remove completed tasks'), 'prompt contains preserve-completed-tasks instruction');
|
|
411
412
|
assert(prompt.includes('[x]'), 'prompt mentions [x] checkmarks');
|
|
412
|
-
assert(prompt.includes('
|
|
413
|
+
assert(prompt.includes('REPLAN'), 'prompt references replan output path');
|
|
413
414
|
assert(prompt.includes('blocker_discovered'), 'prompt mentions blocker_discovered');
|
|
414
415
|
}
|
|
415
416
|
|
|
@@ -226,7 +226,6 @@ async function main(): Promise<void> {
|
|
|
226
226
|
const milestoneId = 'M001';
|
|
227
227
|
const sliceId = 'S01';
|
|
228
228
|
const uatPath = '.gsd/milestones/M001/slices/S01/S01-UAT.md';
|
|
229
|
-
const uatResultAbsPath = '/tmp/gsd-test/S01-UAT-RESULT.md';
|
|
230
229
|
const uatResultPath = '.gsd/milestones/M001/slices/S01/S01-UAT-RESULT.md';
|
|
231
230
|
const uatType = 'artifact-driven';
|
|
232
231
|
const inlinedContext = '<!-- no context -->';
|
|
@@ -238,7 +237,6 @@ async function main(): Promise<void> {
|
|
|
238
237
|
milestoneId,
|
|
239
238
|
sliceId,
|
|
240
239
|
uatPath,
|
|
241
|
-
uatResultAbsPath,
|
|
242
240
|
uatResultPath,
|
|
243
241
|
uatType,
|
|
244
242
|
inlinedContext,
|
|
@@ -261,8 +259,8 @@ async function main(): Promise<void> {
|
|
|
261
259
|
`prompt contains sliceId value "${sliceId}" after substitution`,
|
|
262
260
|
);
|
|
263
261
|
assert(
|
|
264
|
-
promptResult?.includes(
|
|
265
|
-
`prompt contains
|
|
262
|
+
promptResult?.includes(uatResultPath) ?? false,
|
|
263
|
+
`prompt contains uatResultPath value after substitution`,
|
|
266
264
|
);
|
|
267
265
|
assert(
|
|
268
266
|
!/\{\{[^}]+\}\}/.test(promptResult ?? ''),
|