gsd-pi 2.38.0-dev.96dc7fb → 2.38.0-dev.98b44dc
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/README.md +15 -11
- package/dist/app-paths.js +1 -1
- package/dist/extension-registry.js +2 -2
- package/dist/remote-questions-config.js +2 -2
- package/dist/resource-loader.js +34 -1
- package/dist/resources/extensions/browser-tools/index.js +3 -1
- package/dist/resources/extensions/browser-tools/tools/verify.js +97 -0
- package/dist/resources/extensions/env-utils.js +29 -0
- package/dist/resources/extensions/get-secrets-from-user.js +5 -24
- package/dist/resources/extensions/github-sync/cli.js +284 -0
- package/dist/resources/extensions/github-sync/index.js +73 -0
- package/dist/resources/extensions/github-sync/mapping.js +67 -0
- package/dist/resources/extensions/github-sync/sync.js +424 -0
- package/dist/resources/extensions/github-sync/templates.js +118 -0
- package/dist/resources/extensions/github-sync/types.js +7 -0
- package/dist/resources/extensions/gsd/auto/session.js +6 -23
- package/dist/resources/extensions/gsd/auto-dispatch.js +8 -9
- package/dist/resources/extensions/gsd/auto-loop.js +636 -594
- package/dist/resources/extensions/gsd/auto-post-unit.js +99 -70
- package/dist/resources/extensions/gsd/auto-prompts.js +202 -48
- package/dist/resources/extensions/gsd/auto-start.js +7 -1
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +2 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
- package/dist/resources/extensions/gsd/auto.js +143 -96
- package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands.js +4 -2
- package/dist/resources/extensions/gsd/context-budget.js +2 -10
- package/dist/resources/extensions/gsd/detection.js +1 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -2
- package/dist/resources/extensions/gsd/doctor-providers.js +30 -11
- package/dist/resources/extensions/gsd/doctor.js +20 -1
- package/dist/resources/extensions/gsd/exit-command.js +2 -1
- package/dist/resources/extensions/gsd/export.js +1 -1
- package/dist/resources/extensions/gsd/files.js +48 -9
- package/dist/resources/extensions/gsd/forensics.js +1 -1
- package/dist/resources/extensions/gsd/git-service.js +30 -12
- package/dist/resources/extensions/gsd/gitignore.js +16 -3
- package/dist/resources/extensions/gsd/guided-flow.js +149 -38
- package/dist/resources/extensions/gsd/health-widget-core.js +32 -70
- package/dist/resources/extensions/gsd/health-widget.js +3 -86
- package/dist/resources/extensions/gsd/index.js +24 -20
- package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
- package/dist/resources/extensions/gsd/migrate-external.js +18 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
- package/dist/resources/extensions/gsd/paths.js +3 -0
- package/dist/resources/extensions/gsd/preferences-models.js +0 -12
- package/dist/resources/extensions/gsd/preferences-types.js +1 -1
- package/dist/resources/extensions/gsd/preferences-validation.js +59 -11
- package/dist/resources/extensions/gsd/preferences.js +22 -11
- package/dist/resources/extensions/gsd/prompt-loader.js +6 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -3
- package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
- package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +28 -11
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/dist/resources/extensions/gsd/repo-identity.js +21 -4
- package/dist/resources/extensions/gsd/resource-version.js +2 -1
- package/dist/resources/extensions/gsd/roadmap-mutations.js +24 -0
- package/dist/resources/extensions/gsd/state.js +42 -23
- package/dist/resources/extensions/gsd/templates/runtime.md +21 -0
- package/dist/resources/extensions/gsd/templates/task-plan.md +3 -0
- package/dist/resources/extensions/gsd/visualizer-data.js +1 -1
- package/dist/resources/extensions/mcp-client/index.js +14 -1
- package/dist/resources/extensions/remote-questions/status.js +4 -1
- package/dist/resources/extensions/remote-questions/store.js +4 -1
- package/dist/resources/extensions/search-the-web/provider.js +2 -1
- package/dist/resources/extensions/shared/frontmatter.js +1 -1
- package/dist/resources/extensions/subagent/isolation.js +2 -1
- package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
- package/package.json +1 -1
- package/packages/pi-ai/dist/utils/oauth/anthropic.js +2 -2
- package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
- package/packages/pi-ai/src/utils/oauth/anthropic.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +205 -7
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +6 -1
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- 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/src/core/extensions/loader.ts +223 -7
- package/packages/pi-coding-agent/src/core/skills.ts +9 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/src/resources/extensions/browser-tools/index.ts +3 -0
- package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
- package/src/resources/extensions/env-utils.ts +31 -0
- package/src/resources/extensions/get-secrets-from-user.ts +5 -24
- package/src/resources/extensions/github-sync/cli.ts +364 -0
- package/src/resources/extensions/github-sync/index.ts +93 -0
- package/src/resources/extensions/github-sync/mapping.ts +81 -0
- package/src/resources/extensions/github-sync/sync.ts +556 -0
- package/src/resources/extensions/github-sync/templates.ts +183 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +20 -0
- package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +39 -0
- package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
- package/src/resources/extensions/github-sync/tests/templates.test.ts +110 -0
- package/src/resources/extensions/github-sync/types.ts +47 -0
- package/src/resources/extensions/gsd/auto/session.ts +7 -25
- package/src/resources/extensions/gsd/auto-dispatch.ts +7 -9
- package/src/resources/extensions/gsd/auto-loop.ts +526 -545
- package/src/resources/extensions/gsd/auto-post-unit.ts +80 -44
- package/src/resources/extensions/gsd/auto-prompts.ts +247 -50
- package/src/resources/extensions/gsd/auto-start.ts +11 -1
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +3 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
- package/src/resources/extensions/gsd/auto.ts +139 -101
- package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands.ts +5 -3
- package/src/resources/extensions/gsd/context-budget.ts +2 -12
- package/src/resources/extensions/gsd/detection.ts +2 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -2
- package/src/resources/extensions/gsd/doctor-providers.ts +30 -9
- package/src/resources/extensions/gsd/doctor.ts +22 -1
- package/src/resources/extensions/gsd/exit-command.ts +2 -2
- package/src/resources/extensions/gsd/export.ts +1 -1
- package/src/resources/extensions/gsd/files.ts +51 -11
- package/src/resources/extensions/gsd/forensics.ts +1 -1
- package/src/resources/extensions/gsd/git-service.ts +44 -10
- package/src/resources/extensions/gsd/gitignore.ts +17 -3
- package/src/resources/extensions/gsd/guided-flow.ts +177 -44
- package/src/resources/extensions/gsd/health-widget-core.ts +28 -80
- package/src/resources/extensions/gsd/health-widget.ts +3 -89
- package/src/resources/extensions/gsd/index.ts +24 -17
- package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
- package/src/resources/extensions/gsd/migrate-external.ts +18 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
- package/src/resources/extensions/gsd/paths.ts +4 -0
- package/src/resources/extensions/gsd/preferences-models.ts +0 -12
- package/src/resources/extensions/gsd/preferences-types.ts +4 -4
- package/src/resources/extensions/gsd/preferences-validation.ts +51 -11
- package/src/resources/extensions/gsd/preferences.ts +25 -11
- package/src/resources/extensions/gsd/prompt-loader.ts +7 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/src/resources/extensions/gsd/prompts/execute-task.md +5 -3
- package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
- package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +4 -8
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- 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 +28 -11
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/src/resources/extensions/gsd/repo-identity.ts +23 -4
- package/src/resources/extensions/gsd/resource-version.ts +3 -1
- package/src/resources/extensions/gsd/roadmap-mutations.ts +29 -0
- package/src/resources/extensions/gsd/state.ts +39 -21
- package/src/resources/extensions/gsd/templates/runtime.md +21 -0
- package/src/resources/extensions/gsd/templates/task-plan.md +3 -0
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +21 -18
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +122 -68
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +86 -3
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +16 -54
- package/src/resources/extensions/gsd/tests/parsers.test.ts +131 -14
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -7
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +140 -0
- package/src/resources/extensions/gsd/types.ts +18 -1
- package/src/resources/extensions/gsd/verification-evidence.ts +16 -0
- package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
- package/src/resources/extensions/mcp-client/index.ts +17 -1
- package/src/resources/extensions/remote-questions/status.ts +5 -1
- package/src/resources/extensions/remote-questions/store.ts +5 -1
- package/src/resources/extensions/search-the-web/provider.ts +2 -1
- package/src/resources/extensions/shared/frontmatter.ts +1 -1
- package/src/resources/extensions/subagent/isolation.ts +3 -1
- package/src/resources/extensions/ttsr/rule-loader.ts +3 -1
- package/dist/resources/extensions/gsd/prompt-compressor.js +0 -393
- package/dist/resources/extensions/gsd/semantic-chunker.js +0 -254
- package/dist/resources/extensions/gsd/summary-distiller.js +0 -212
- package/src/resources/extensions/gsd/prompt-compressor.ts +0 -508
- package/src/resources/extensions/gsd/semantic-chunker.ts +0 -336
- package/src/resources/extensions/gsd/summary-distiller.ts +0 -258
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +0 -193
- package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +0 -529
- package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +0 -426
- package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +0 -323
- package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +0 -1272
- package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +0 -164
|
@@ -10,7 +10,7 @@ All relevant context has been preloaded below. Start working immediately without
|
|
|
10
10
|
|
|
11
11
|
{{inlinedContext}}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
{{skillActivation}}
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
@@ -18,32 +18,49 @@ If a `GSD Skill Preferences` block is present in system context, use it to decid
|
|
|
18
18
|
|
|
19
19
|
**UAT file:** `{{uatPath}}`
|
|
20
20
|
**Result file to write:** `{{uatResultPath}}`
|
|
21
|
+
**Detected UAT mode:** `{{uatType}}`
|
|
21
22
|
|
|
22
|
-
You are the
|
|
23
|
+
You are the UAT runner. Execute every check defined in `{{uatPath}}` as deeply as this mode truthfully allows. Do not collapse live or subjective checks into cheap artifact checks just to get a PASS.
|
|
24
|
+
|
|
25
|
+
### Automation rules by mode
|
|
26
|
+
|
|
27
|
+
- `artifact-driven` — verify with shell commands, scripts, file reads, and artifact structure checks.
|
|
28
|
+
- `browser-executable` — use browser tools to navigate to the target URL and verify expected behavior. Capture screenshots as evidence. Record pass/fail with specific assertions.
|
|
29
|
+
- `runtime-executable` — execute the specified command or script. Capture stdout/stderr as evidence. Record pass/fail based on exit code and output.
|
|
30
|
+
- `live-runtime` — exercise the real runtime path. Start or connect to the app/service if needed, use browser/runtime/network checks, and verify observable behavior.
|
|
31
|
+
- `mixed` — run all automatable artifact-driven and live-runtime checks. Separate any remaining human-only checks explicitly.
|
|
32
|
+
- `human-experience` — automate setup, preconditions, screenshots, logs, and objective checks, but do **not** invent subjective PASS results. Mark taste-based, experiential, or purely human-judgment checks as `NEEDS-HUMAN` and use an overall verdict of `PARTIAL` unless every required check was objective and passed.
|
|
33
|
+
|
|
34
|
+
### Evidence tools
|
|
35
|
+
|
|
36
|
+
Choose the lightest tool that proves the check honestly:
|
|
23
37
|
|
|
24
38
|
- Run shell commands with `bash`
|
|
25
39
|
- Run `grep` / `rg` checks against files
|
|
26
|
-
- Run `node` / script invocations
|
|
40
|
+
- Run `node` / other script invocations
|
|
27
41
|
- Read files and verify their contents
|
|
28
42
|
- Check that expected artifacts exist and have correct structure
|
|
43
|
+
- For live/runtime/UI checks, exercise the real flow in the browser when applicable and inspect runtime/network/console state
|
|
44
|
+
- When a check cannot be honestly automated, gather the best objective evidence you can and mark it `NEEDS-HUMAN`
|
|
29
45
|
|
|
30
46
|
For each check, record:
|
|
31
47
|
- The check description (from the UAT file)
|
|
48
|
+
- The evidence mode used: `artifact`, `runtime`, or `human-follow-up`
|
|
32
49
|
- The command or action taken
|
|
33
50
|
- The actual result observed
|
|
34
|
-
- PASS or
|
|
51
|
+
- `PASS`, `FAIL`, or `NEEDS-HUMAN`
|
|
35
52
|
|
|
36
53
|
After running all checks, compute the **overall verdict**:
|
|
37
|
-
- `PASS` — all checks passed
|
|
54
|
+
- `PASS` — all required checks passed and no human-only checks remain
|
|
38
55
|
- `FAIL` — one or more checks failed
|
|
39
|
-
- `PARTIAL` — some checks passed,
|
|
56
|
+
- `PARTIAL` — some checks passed, but one or more checks were skipped, inconclusive, or still require human judgment
|
|
40
57
|
|
|
41
58
|
Write `{{uatResultPath}}` with:
|
|
42
59
|
|
|
43
60
|
```markdown
|
|
44
61
|
---
|
|
45
62
|
sliceId: {{sliceId}}
|
|
46
|
-
uatType:
|
|
63
|
+
uatType: {{uatType}}
|
|
47
64
|
verdict: PASS | FAIL | PARTIAL
|
|
48
65
|
date: <ISO 8601 timestamp>
|
|
49
66
|
---
|
|
@@ -52,9 +69,9 @@ date: <ISO 8601 timestamp>
|
|
|
52
69
|
|
|
53
70
|
## Checks
|
|
54
71
|
|
|
55
|
-
| Check | Result | Notes |
|
|
56
|
-
|
|
57
|
-
| <check description> | PASS / FAIL | <observed output or reason> |
|
|
72
|
+
| Check | Mode | Result | Notes |
|
|
73
|
+
|-------|------|--------|-------|
|
|
74
|
+
| <check description> | artifact / runtime / human-follow-up | PASS / FAIL / NEEDS-HUMAN | <observed output, evidence, or reason> |
|
|
58
75
|
|
|
59
76
|
## Overall Verdict
|
|
60
77
|
|
|
@@ -62,7 +79,7 @@ date: <ISO 8601 timestamp>
|
|
|
62
79
|
|
|
63
80
|
## Notes
|
|
64
81
|
|
|
65
|
-
<any additional context, errors encountered, or follow-up
|
|
82
|
+
<any additional context, errors encountered, screenshots/logs gathered, or manual follow-up still required>
|
|
66
83
|
```
|
|
67
84
|
|
|
68
85
|
---
|
|
@@ -14,7 +14,7 @@ You are executing a **{{templateName}}** workflow (template: `{{templateId}}`).
|
|
|
14
14
|
|
|
15
15
|
## Workflow Definition
|
|
16
16
|
|
|
17
|
-
Follow the workflow defined below. Execute each phase in order, completing one before moving to the next.
|
|
17
|
+
Follow the workflow defined below. Execute each phase in order, completing one before moving to the next. For low and medium complexity workflows, keep moving by default — pause only at true decision gates (user must choose between materially different directions, outward-facing actions need approval, or the workflow explicitly requires a human checkpoint). For high complexity workflows, confirm at phase transitions unless the workflow explicitly marks a gate as skip-safe.
|
|
18
18
|
|
|
19
19
|
{{workflowContent}}
|
|
20
20
|
|
|
@@ -24,5 +24,5 @@ Follow the workflow defined below. Execute each phase in order, completing one b
|
|
|
24
24
|
2. **Artifact discipline.** If an artifact directory is specified, write all planning/summary documents there.
|
|
25
25
|
3. **Atomic commits.** Commit working code after each meaningful change. Use conventional commit format: `<type>(<scope>): <description>`.
|
|
26
26
|
4. **Verify before shipping.** Run the project's test suite and build before marking the workflow complete.
|
|
27
|
-
5. **
|
|
27
|
+
5. **Decision gates, not ceremony.** After each phase, summarize what changed. For low/medium complexity, ask for confirmation only when the next phase depends on a real user choice or external approval. For high complexity, confirm before proceeding to each new phase.
|
|
28
28
|
6. **Stay focused.** This is a {{complexity}}-complexity workflow. Match your ceremony level to the task — don't over-engineer or under-deliver.
|
|
@@ -12,6 +12,8 @@ import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, rmSync, s
|
|
|
12
12
|
import { homedir } from "node:os";
|
|
13
13
|
import { join, resolve } from "node:path";
|
|
14
14
|
|
|
15
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
16
|
+
|
|
15
17
|
// ─── Repo Identity ──────────────────────────────────────────────────────────
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -90,14 +92,31 @@ function resolveGitRoot(basePath: string): string {
|
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Validate a GSD_PROJECT_ID value.
|
|
97
|
+
*
|
|
98
|
+
* Must contain only alphanumeric characters, hyphens, and underscores.
|
|
99
|
+
* Call this once at startup so the user gets immediate feedback on bad values.
|
|
100
|
+
*/
|
|
101
|
+
export function validateProjectId(id: string): boolean {
|
|
102
|
+
return /^[a-zA-Z0-9_-]+$/.test(id);
|
|
103
|
+
}
|
|
104
|
+
|
|
93
105
|
/**
|
|
94
106
|
* Compute a stable identity for a repository.
|
|
95
107
|
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
108
|
+
* If `GSD_PROJECT_ID` is set, returns it directly (validation is expected
|
|
109
|
+
* to have already happened at startup via `validateProjectId`).
|
|
110
|
+
*
|
|
111
|
+
* Otherwise returns SHA-256 of `${remoteUrl}\n${resolvedRoot}`, truncated
|
|
112
|
+
* to 12 hex chars. Deterministic: same repo always produces the same hash
|
|
113
|
+
* regardless of which worktree the caller is inside.
|
|
99
114
|
*/
|
|
100
115
|
export function repoIdentity(basePath: string): string {
|
|
116
|
+
const projectId = process.env.GSD_PROJECT_ID;
|
|
117
|
+
if (projectId) {
|
|
118
|
+
return projectId;
|
|
119
|
+
}
|
|
101
120
|
const remoteUrl = getRemoteUrl(basePath);
|
|
102
121
|
const root = resolveGitRoot(basePath);
|
|
103
122
|
const input = `${remoteUrl}\n${root}`;
|
|
@@ -113,7 +132,7 @@ export function repoIdentity(basePath: string): string {
|
|
|
113
132
|
* otherwise `~/.gsd/projects/<hash>`.
|
|
114
133
|
*/
|
|
115
134
|
export function externalGsdRoot(basePath: string): string {
|
|
116
|
-
const base = process.env.GSD_STATE_DIR ||
|
|
135
|
+
const base = process.env.GSD_STATE_DIR || gsdHome;
|
|
117
136
|
return join(base, "projects", repoIdentity(basePath));
|
|
118
137
|
}
|
|
119
138
|
|
|
@@ -11,6 +11,8 @@ import { join } from "node:path";
|
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
12
|
import { resolveProjectRoot } from "./worktree.js";
|
|
13
13
|
|
|
14
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
15
|
+
|
|
14
16
|
// ─── Resource Staleness ───────────────────────────────────────────────────
|
|
15
17
|
|
|
16
18
|
/**
|
|
@@ -23,7 +25,7 @@ function isManifestWithVersion(data: unknown): data is { gsdVersion: string } {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export function readResourceVersion(): string | null {
|
|
26
|
-
const agentDir = process.env.GSD_CODING_AGENT_DIR || join(
|
|
28
|
+
const agentDir = process.env.GSD_CODING_AGENT_DIR || join(gsdHome, "agent");
|
|
27
29
|
const manifestPath = join(agentDir, "managed-resources.json");
|
|
28
30
|
const manifest = loadJsonFileOrNull(manifestPath, isManifestWithVersion);
|
|
29
31
|
return manifest?.gsdVersion ?? null;
|
|
@@ -39,6 +39,35 @@ export function markSliceDoneInRoadmap(basePath: string, mid: string, sid: strin
|
|
|
39
39
|
return true;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Mark a slice as not done ([ ]) in the milestone roadmap.
|
|
44
|
+
* Idempotent — no-op if already unchecked or if the slice isn't found.
|
|
45
|
+
*
|
|
46
|
+
* @returns true if the roadmap was modified, false if no change was needed
|
|
47
|
+
*/
|
|
48
|
+
export function markSliceUndoneInRoadmap(basePath: string, mid: string, sid: string): boolean {
|
|
49
|
+
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
50
|
+
if (!roadmapFile) return false;
|
|
51
|
+
|
|
52
|
+
let content: string;
|
|
53
|
+
try {
|
|
54
|
+
content = readFileSync(roadmapFile, "utf-8");
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const updated = content.replace(
|
|
60
|
+
new RegExp(`^(\\s*-\\s+)\\[x\\]\\s+\\*\\*${sid}:`, "m"),
|
|
61
|
+
`$1[ ] **${sid}:`,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (updated === content) return false;
|
|
65
|
+
|
|
66
|
+
atomicWriteSync(roadmapFile, updated);
|
|
67
|
+
clearParseCache();
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
42
71
|
/**
|
|
43
72
|
* Mark a task as done ([x]) in the slice plan.
|
|
44
73
|
* Idempotent — no-op if already checked or if the task isn't found.
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
gsdRoot,
|
|
32
32
|
} from './paths.js';
|
|
33
33
|
|
|
34
|
-
import { milestoneIdSort, findMilestoneIds } from './
|
|
34
|
+
import { milestoneIdSort, findMilestoneIds } from './milestone-ids.js';
|
|
35
35
|
import { nativeBatchParseGsdFiles, type BatchParsedFile } from './native-parser-bridge.js';
|
|
36
36
|
|
|
37
37
|
import { join, resolve } from 'path';
|
|
@@ -126,7 +126,12 @@ export async function getActiveMilestoneId(basePath: string): Promise<string | n
|
|
|
126
126
|
// A draft milestone is still "active" — this function only determines which milestone is current.
|
|
127
127
|
}
|
|
128
128
|
const roadmap = parseRoadmap(content);
|
|
129
|
-
if (!isMilestoneComplete(roadmap))
|
|
129
|
+
if (!isMilestoneComplete(roadmap)) {
|
|
130
|
+
// Summary is the terminal artifact — if it exists, the milestone is
|
|
131
|
+
// complete even when roadmap checkboxes weren't ticked (#864).
|
|
132
|
+
const summaryFile = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
133
|
+
if (!summaryFile) return mid;
|
|
134
|
+
}
|
|
130
135
|
}
|
|
131
136
|
return null;
|
|
132
137
|
}
|
|
@@ -258,7 +263,13 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
258
263
|
}
|
|
259
264
|
const rmap = parseRoadmap(rc);
|
|
260
265
|
roadmapCache.set(mid, rmap);
|
|
261
|
-
if (!isMilestoneComplete(rmap))
|
|
266
|
+
if (!isMilestoneComplete(rmap)) {
|
|
267
|
+
// Summary is the terminal artifact — if it exists, the milestone is
|
|
268
|
+
// complete even when roadmap checkboxes weren't ticked (#864).
|
|
269
|
+
const sf = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
270
|
+
if (sf) completeMilestoneIds.add(mid);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
262
273
|
const sf = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
263
274
|
if (sf) completeMilestoneIds.add(mid);
|
|
264
275
|
}
|
|
@@ -357,26 +368,33 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
357
368
|
} else {
|
|
358
369
|
registry.push({ id: mid, title, status: 'complete' });
|
|
359
370
|
}
|
|
360
|
-
} else
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (
|
|
367
|
-
|
|
368
|
-
|
|
371
|
+
} else {
|
|
372
|
+
// Roadmap slices not all checked — but if a summary exists, the milestone
|
|
373
|
+
// is still complete. The summary is the terminal artifact (#864).
|
|
374
|
+
const summaryFile = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
375
|
+
if (summaryFile) {
|
|
376
|
+
registry.push({ id: mid, title, status: 'complete' });
|
|
377
|
+
} else if (!activeMilestoneFound) {
|
|
378
|
+
// Check milestone-level dependencies before promoting to active
|
|
379
|
+
const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
|
|
380
|
+
const contextContent = contextFile ? await cachedLoadFile(contextFile) : null;
|
|
381
|
+
const deps = parseContextDependsOn(contextContent);
|
|
382
|
+
const depsUnmet = deps.some(dep => !completeMilestoneIds.has(dep));
|
|
383
|
+
if (depsUnmet) {
|
|
384
|
+
registry.push({ id: mid, title, status: 'pending', dependsOn: deps });
|
|
385
|
+
// Do NOT set activeMilestoneFound — let the loop continue to the next milestone
|
|
386
|
+
} else {
|
|
387
|
+
activeMilestone = { id: mid, title };
|
|
388
|
+
activeRoadmap = roadmap;
|
|
389
|
+
activeMilestoneFound = true;
|
|
390
|
+
registry.push({ id: mid, title, status: 'active', ...(deps.length > 0 ? { dependsOn: deps } : {}) });
|
|
391
|
+
}
|
|
369
392
|
} else {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
registry.push({ id: mid, title, status: '
|
|
393
|
+
const contextFile2 = resolveMilestoneFile(basePath, mid, "CONTEXT");
|
|
394
|
+
const contextContent2 = contextFile2 ? await cachedLoadFile(contextFile2) : null;
|
|
395
|
+
const deps2 = parseContextDependsOn(contextContent2);
|
|
396
|
+
registry.push({ id: mid, title, status: 'pending', ...(deps2.length > 0 ? { dependsOn: deps2 } : {}) });
|
|
374
397
|
}
|
|
375
|
-
} else {
|
|
376
|
-
const contextFile2 = resolveMilestoneFile(basePath, mid, "CONTEXT");
|
|
377
|
-
const contextContent2 = contextFile2 ? await cachedLoadFile(contextFile2) : null;
|
|
378
|
-
const deps2 = parseContextDependsOn(contextContent2);
|
|
379
|
-
registry.push({ id: mid, title, status: 'pending', ...(deps2.length > 0 ? { dependsOn: deps2 } : {}) });
|
|
380
398
|
}
|
|
381
399
|
}
|
|
382
400
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Runtime Context
|
|
2
|
+
|
|
3
|
+
## Stack
|
|
4
|
+
- **Language:** (e.g., TypeScript, Python, Go)
|
|
5
|
+
- **Framework:** (e.g., Next.js, FastAPI, Gin)
|
|
6
|
+
- **Build:** (e.g., npm run build, cargo build)
|
|
7
|
+
- **Test:** (e.g., npm run test, pytest)
|
|
8
|
+
- **Lint:** (e.g., npm run lint, ruff check)
|
|
9
|
+
|
|
10
|
+
## Environment
|
|
11
|
+
- **Node version:** (e.g., 20.x)
|
|
12
|
+
- **Package manager:** (e.g., npm, pnpm, yarn)
|
|
13
|
+
- **Required env vars:** (list any needed for local dev)
|
|
14
|
+
|
|
15
|
+
## Dev Server
|
|
16
|
+
- **Start command:** (e.g., npm run dev)
|
|
17
|
+
- **Default port:** (e.g., 3000)
|
|
18
|
+
- **Health check:** (e.g., curl http://localhost:3000/health)
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
(Any runtime-specific context the executor needs to know)
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
# Tasks with 10+ estimated steps or 12+ estimated files trigger a warning to consider splitting.
|
|
4
4
|
estimated_steps: {{estimatedSteps}}
|
|
5
5
|
estimated_files: {{estimatedFiles}}
|
|
6
|
+
# Installed skills the planner expects the executor to load before coding.
|
|
7
|
+
skills_used:
|
|
8
|
+
- {{skillName}}
|
|
6
9
|
---
|
|
7
10
|
|
|
8
11
|
# {{taskId}}: {{taskTitle}}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* agent-end-retry.test.ts — Regression checks for the
|
|
2
|
+
* agent-end-retry.test.ts — Regression checks for the agent_end model.
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The per-unit one-shot resolve function lives at module level in auto-loop.ts
|
|
5
|
+
* (_currentResolve). handleAgentEnd is a thin compatibility wrapper around
|
|
6
|
+
* resolveAgentEnd().
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import test from "node:test";
|
|
@@ -14,40 +14,43 @@ import { fileURLToPath } from "node:url";
|
|
|
14
14
|
|
|
15
15
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
16
|
const AUTO_TS_PATH = join(__dirname, "..", "auto.ts");
|
|
17
|
+
const AUTO_LOOP_TS_PATH = join(__dirname, "..", "auto-loop.ts");
|
|
17
18
|
const SESSION_TS_PATH = join(__dirname, "..", "auto", "session.ts");
|
|
18
19
|
|
|
19
20
|
function getAutoTsSource(): string {
|
|
20
21
|
return readFileSync(AUTO_TS_PATH, "utf-8");
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
function getAutoLoopTsSource(): string {
|
|
25
|
+
return readFileSync(AUTO_LOOP_TS_PATH, "utf-8");
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
function getSessionTsSource(): string {
|
|
24
29
|
return readFileSync(SESSION_TS_PATH, "utf-8");
|
|
25
30
|
}
|
|
26
31
|
|
|
27
|
-
test("
|
|
28
|
-
const source =
|
|
32
|
+
test("auto-loop.ts declares _currentResolve for per-unit one-shot promises", () => {
|
|
33
|
+
const source = getAutoLoopTsSource();
|
|
29
34
|
assert.ok(
|
|
30
|
-
source.includes("
|
|
31
|
-
"
|
|
35
|
+
source.includes("_currentResolve"),
|
|
36
|
+
"auto-loop.ts must declare _currentResolve for the per-unit resolve function",
|
|
32
37
|
);
|
|
33
38
|
assert.ok(
|
|
34
|
-
source.includes("
|
|
35
|
-
"
|
|
39
|
+
source.includes("_sessionSwitchInFlight"),
|
|
40
|
+
"auto-loop.ts must declare _sessionSwitchInFlight guard",
|
|
36
41
|
);
|
|
37
42
|
});
|
|
38
43
|
|
|
39
|
-
test("AutoSession
|
|
44
|
+
test("AutoSession no longer holds promise state (moved to auto-loop.ts module scope)", () => {
|
|
40
45
|
const source = getSessionTsSource();
|
|
41
|
-
|
|
42
|
-
assert.ok(resetIdx > -1, "AutoSession must have a reset() method");
|
|
43
|
-
const resetBlock = source.slice(resetIdx, resetIdx + 4000);
|
|
46
|
+
// Properties should NOT exist as class fields
|
|
44
47
|
assert.ok(
|
|
45
|
-
|
|
46
|
-
"
|
|
48
|
+
!source.includes("pendingResolve:"),
|
|
49
|
+
"AutoSession must not declare pendingResolve (moved to auto-loop.ts)",
|
|
47
50
|
);
|
|
48
51
|
assert.ok(
|
|
49
|
-
|
|
50
|
-
"
|
|
52
|
+
!source.includes("pendingAgentEndQueue:"),
|
|
53
|
+
"AutoSession must not declare pendingAgentEndQueue (removed — events are dropped)",
|
|
51
54
|
);
|
|
52
55
|
});
|
|
53
56
|
|