gsd-pi 2.29.0-dev.49d972f → 2.29.0-dev.4c155ee
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 +24 -17
- package/dist/headless.js +4 -0
- package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +217 -65
- package/dist/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/dist/resources/extensions/gsd/auto-post-unit.ts +44 -12
- package/dist/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/dist/resources/extensions/gsd/auto-recovery.ts +2 -1
- package/dist/resources/extensions/gsd/auto-start.ts +18 -32
- package/dist/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/dist/resources/extensions/gsd/auto.ts +2 -9
- package/dist/resources/extensions/gsd/captures.ts +4 -10
- package/dist/resources/extensions/gsd/commands-handlers.ts +2 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/dist/resources/extensions/gsd/commands.ts +55 -2
- package/dist/resources/extensions/gsd/detection.ts +2 -1
- package/dist/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/dist/resources/extensions/gsd/doctor-types.ts +3 -1
- package/dist/resources/extensions/gsd/forensics.ts +2 -2
- package/dist/resources/extensions/gsd/git-service.ts +3 -2
- package/dist/resources/extensions/gsd/gitignore.ts +9 -63
- package/dist/resources/extensions/gsd/gsd-db.ts +1 -165
- package/dist/resources/extensions/gsd/guided-flow.ts +8 -5
- package/dist/resources/extensions/gsd/index.ts +3 -3
- package/dist/resources/extensions/gsd/md-importer.ts +3 -2
- package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/dist/resources/extensions/gsd/migrate/command.ts +3 -2
- package/dist/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/dist/resources/extensions/gsd/migrate-external.ts +123 -0
- package/dist/resources/extensions/gsd/paths.ts +24 -2
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/dist/resources/extensions/gsd/preferences-models.ts +7 -1
- package/dist/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/dist/resources/extensions/gsd/preferences.ts +10 -5
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/dist/resources/extensions/gsd/repo-identity.ts +148 -0
- package/dist/resources/extensions/gsd/resource-version.ts +99 -0
- package/dist/resources/extensions/gsd/session-forensics.ts +4 -3
- package/dist/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/dist/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/dist/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/dist/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/dist/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/dist/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/dist/resources/extensions/gsd/types.ts +2 -0
- package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +1 -11
- package/dist/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/dist/resources/extensions/gsd/worktree.ts +42 -5
- package/dist/resources/extensions/mcp-client/index.ts +459 -0
- package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/dist/resources/skills/create-skill/SKILL.md +184 -0
- package/dist/resources/skills/create-skill/references/api-security.md +226 -0
- package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
- package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/dist/resources/skills/react-best-practices/SKILL.md +1 -1
- package/package.json +1 -1
- package/packages/native/dist/native.d.ts +2 -0
- package/packages/native/dist/native.js +19 -5
- package/packages/native/src/native.ts +23 -9
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
- package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +217 -65
- package/src/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/src/resources/extensions/gsd/auto-post-unit.ts +44 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/src/resources/extensions/gsd/auto-recovery.ts +2 -1
- package/src/resources/extensions/gsd/auto-start.ts +18 -32
- package/src/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/src/resources/extensions/gsd/auto.ts +2 -9
- package/src/resources/extensions/gsd/captures.ts +4 -10
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/src/resources/extensions/gsd/commands.ts +55 -2
- package/src/resources/extensions/gsd/detection.ts +2 -1
- package/src/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +3 -2
- package/src/resources/extensions/gsd/gitignore.ts +9 -63
- package/src/resources/extensions/gsd/gsd-db.ts +1 -165
- package/src/resources/extensions/gsd/guided-flow.ts +8 -5
- package/src/resources/extensions/gsd/index.ts +3 -3
- package/src/resources/extensions/gsd/md-importer.ts +3 -2
- package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/src/resources/extensions/gsd/migrate-external.ts +123 -0
- package/src/resources/extensions/gsd/paths.ts +24 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/src/resources/extensions/gsd/preferences-models.ts +7 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +10 -5
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/src/resources/extensions/gsd/repo-identity.ts +148 -0
- package/src/resources/extensions/gsd/resource-version.ts +99 -0
- package/src/resources/extensions/gsd/session-forensics.ts +4 -3
- package/src/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/src/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/src/resources/extensions/gsd/types.ts +2 -0
- package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/src/resources/extensions/gsd/worktree-command.ts +1 -11
- package/src/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/src/resources/extensions/gsd/worktree.ts +42 -5
- package/src/resources/extensions/mcp-client/index.ts +459 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/src/resources/skills/create-skill/SKILL.md +184 -0
- package/src/resources/skills/create-skill/references/api-security.md +226 -0
- package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/src/resources/skills/create-skill/references/core-principles.md +437 -0
- package/src/resources/skills/create-skill/references/executable-code.md +175 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/src/resources/skills/create-skill/references/using-templates.md +112 -0
- package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/src/resources/skills/react-best-practices/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/auto-worktree-sync.ts +0 -199
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
- package/dist/resources/extensions/mcporter/index.ts +0 -525
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -199
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
- package/src/resources/extensions/mcporter/index.ts +0 -525
|
@@ -254,13 +254,19 @@ export function resolveProfileDefaults(profile: TokenProfile): Partial<GSDPrefer
|
|
|
254
254
|
subagent: "claude-sonnet-4-5-20250514",
|
|
255
255
|
},
|
|
256
256
|
phases: {
|
|
257
|
+
skip_research: true,
|
|
258
|
+
skip_reassess: true,
|
|
257
259
|
skip_slice_research: true,
|
|
258
260
|
},
|
|
259
261
|
};
|
|
260
262
|
case "quality":
|
|
261
263
|
return {
|
|
262
264
|
models: {},
|
|
263
|
-
phases: {
|
|
265
|
+
phases: {
|
|
266
|
+
skip_research: true,
|
|
267
|
+
skip_slice_research: true,
|
|
268
|
+
skip_reassess: true,
|
|
269
|
+
},
|
|
264
270
|
};
|
|
265
271
|
}
|
|
266
272
|
}
|
|
@@ -172,9 +172,10 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
172
172
|
if (p.skip_reassess !== undefined) validatedPhases.skip_reassess = !!p.skip_reassess;
|
|
173
173
|
if (p.skip_slice_research !== undefined) validatedPhases.skip_slice_research = !!p.skip_slice_research;
|
|
174
174
|
if (p.skip_milestone_validation !== undefined) validatedPhases.skip_milestone_validation = !!p.skip_milestone_validation;
|
|
175
|
+
if (p.reassess_after_slice !== undefined) validatedPhases.reassess_after_slice = !!p.reassess_after_slice;
|
|
175
176
|
if ((p as any).require_slice_discussion !== undefined) (validatedPhases as any).require_slice_discussion = !!(p as any).require_slice_discussion;
|
|
176
177
|
// Warn on unknown phase keys
|
|
177
|
-
const knownPhaseKeys = new Set(["skip_research", "skip_reassess", "skip_slice_research", "skip_milestone_validation", "require_slice_discussion"]);
|
|
178
|
+
const knownPhaseKeys = new Set(["skip_research", "skip_reassess", "skip_slice_research", "skip_milestone_validation", "reassess_after_slice", "require_slice_discussion"]);
|
|
178
179
|
for (const key of Object.keys(p)) {
|
|
179
180
|
if (!knownPhaseKeys.has(key)) {
|
|
180
181
|
warnings.push(`unknown phases key "${key}" — ignored`);
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { existsSync, readFileSync } from "node:fs";
|
|
14
14
|
import { homedir } from "node:os";
|
|
15
15
|
import { join } from "node:path";
|
|
16
|
+
import { gsdRoot } from "./paths.js";
|
|
16
17
|
import { parse as parseYaml } from "yaml";
|
|
17
18
|
import type { PostUnitHookConfig, PreDispatchHookConfig } from "./types.js";
|
|
18
19
|
import type { DynamicRoutingConfig } from "./model-router.js";
|
|
@@ -81,11 +82,15 @@ export {
|
|
|
81
82
|
|
|
82
83
|
const GLOBAL_PREFERENCES_PATH = join(homedir(), ".gsd", "preferences.md");
|
|
83
84
|
const LEGACY_GLOBAL_PREFERENCES_PATH = join(homedir(), ".pi", "agent", "gsd-preferences.md");
|
|
84
|
-
|
|
85
|
+
function projectPreferencesPath(): string {
|
|
86
|
+
return join(gsdRoot(process.cwd()), "preferences.md");
|
|
87
|
+
}
|
|
85
88
|
// Bootstrap in gitignore.ts historically created PREFERENCES.md (uppercase) by mistake.
|
|
86
89
|
// Check uppercase as a fallback so those files aren't silently ignored.
|
|
87
90
|
const GLOBAL_PREFERENCES_PATH_UPPERCASE = join(homedir(), ".gsd", "PREFERENCES.md");
|
|
88
|
-
|
|
91
|
+
function projectPreferencesPathUppercase(): string {
|
|
92
|
+
return join(gsdRoot(process.cwd()), "PREFERENCES.md");
|
|
93
|
+
}
|
|
89
94
|
|
|
90
95
|
export function getGlobalGSDPreferencesPath(): string {
|
|
91
96
|
return GLOBAL_PREFERENCES_PATH;
|
|
@@ -96,7 +101,7 @@ export function getLegacyGlobalGSDPreferencesPath(): string {
|
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
export function getProjectGSDPreferencesPath(): string {
|
|
99
|
-
return
|
|
104
|
+
return projectPreferencesPath();
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
// ─── Loading ────────────────────────────────────────────────────────────────
|
|
@@ -108,8 +113,8 @@ export function loadGlobalGSDPreferences(): LoadedGSDPreferences | null {
|
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
export function loadProjectGSDPreferences(): LoadedGSDPreferences | null {
|
|
111
|
-
return loadPreferencesFile(
|
|
112
|
-
?? loadPreferencesFile(
|
|
116
|
+
return loadPreferencesFile(projectPreferencesPath(), "project")
|
|
117
|
+
?? loadPreferencesFile(projectPreferencesPathUppercase(), "project");
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
export function loadEffectiveGSDPreferences(): LoadedGSDPreferences | null {
|
|
@@ -16,13 +16,15 @@ Summarize your understanding of the specification concretely:
|
|
|
16
16
|
- Scope estimate (how many milestones × slices)
|
|
17
17
|
- Any ambiguities or gaps you notice
|
|
18
18
|
|
|
19
|
-
### Step 2: Investigate
|
|
19
|
+
### Step 2: Investigate (brief)
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Quickly scout the codebase to understand what already exists — spend no more than 5-6 tool calls here:
|
|
22
22
|
- `ls` the project root and key directories
|
|
23
23
|
- Search for relevant existing code, patterns, dependencies
|
|
24
24
|
- Check library docs if needed (`resolve_library` / `get_library_docs`)
|
|
25
25
|
|
|
26
|
+
Then move on to writing artifacts. Do not explore exhaustively — the research phase will do deeper investigation later.
|
|
27
|
+
|
|
26
28
|
### Step 3: Make Decisions
|
|
27
29
|
|
|
28
30
|
For any ambiguities or gaps in the specification:
|
|
@@ -91,7 +91,7 @@ Before moving to the wrap-up gate, verify you have covered:
|
|
|
91
91
|
- options: "Yes, you got it (Recommended)", "Not quite — let me clarify"
|
|
92
92
|
- **The question ID must contain `depth_verification`** (e.g. `depth_verification_confirm`) — this enables the write-gate downstream.
|
|
93
93
|
|
|
94
|
-
**If `{{structuredQuestionsAvailable}}` is `false`:** ask in plain text: "Did I capture that correctly?
|
|
94
|
+
**If `{{structuredQuestionsAvailable}}` is `false`:** ask in plain text: "Did I capture that correctly? If not, tell me what I missed." Wait for confirmation before proceeding.
|
|
95
95
|
|
|
96
96
|
If they clarify, absorb the correction and re-verify.
|
|
97
97
|
|
|
@@ -12,9 +12,33 @@ All relevant context has been preloaded below — start working immediately with
|
|
|
12
12
|
|
|
13
13
|
## Your Role in the Pipeline
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
You are the first deep look at this milestone. You have full tool access — explore the codebase, look up docs, investigate technology choices. Your job is to understand the landscape and then strategically decompose the work into demoable slices.
|
|
16
16
|
|
|
17
|
-
After you finish, each slice goes through its own
|
|
17
|
+
After you finish, each slice goes through its own plan → execute cycle. Slice planners decompose into tasks. Executors build each task. Your roadmap sets the strategic frame for all of them.
|
|
18
|
+
|
|
19
|
+
### Explore First, Then Decompose
|
|
20
|
+
|
|
21
|
+
Before decomposing, build your understanding:
|
|
22
|
+
|
|
23
|
+
1. **Codebase exploration.** For small/familiar codebases, use `rg`, `find`, and targeted reads. For large or unfamiliar codebases, use `scout` to build a broad map efficiently before diving in.
|
|
24
|
+
2. **Library docs.** Use `resolve_library` / `get_library_docs` for unfamiliar libraries — skip this for libraries already used in the codebase.
|
|
25
|
+
3. **Skill Discovery ({{skillDiscoveryMode}}):**{{skillDiscoveryInstructions}}
|
|
26
|
+
4. **Requirements analysis.** If `.gsd/REQUIREMENTS.md` exists, research against it. Identify which Active requirements are table stakes, likely omissions, overbuilt risks, or domain-standard behaviors.
|
|
27
|
+
|
|
28
|
+
### Strategic Questions to Answer
|
|
29
|
+
|
|
30
|
+
- What should be proven first?
|
|
31
|
+
- What existing patterns should be reused?
|
|
32
|
+
- What boundary contracts matter?
|
|
33
|
+
- What constraints does the existing codebase impose?
|
|
34
|
+
- Are there known failure modes that should shape slice ordering?
|
|
35
|
+
- If requirements exist: what table stakes, expected behaviors, continuity expectations, launchability expectations, or failure-visibility expectations are missing, optional, or clearly out of scope?
|
|
36
|
+
|
|
37
|
+
### Source Files
|
|
38
|
+
|
|
39
|
+
{{sourceFilePaths}}
|
|
40
|
+
|
|
41
|
+
If milestone research exists (inlined above), trust those findings and skip redundant exploration. If findings are significant and no research file exists yet, write `{{researchOutputPath}}`.
|
|
18
42
|
|
|
19
43
|
Narrate your decomposition reasoning — why you're grouping work this way, what risks are driving the order, what verification strategy you're choosing and why. Use complete sentences rather than planner shorthand or fragmentary notes.
|
|
20
44
|
|
|
@@ -18,7 +18,21 @@ Pay particular attention to **Forward Intelligence** sections — they contain h
|
|
|
18
18
|
|
|
19
19
|
## Your Role in the Pipeline
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
You have full tool access. Before decomposing, explore the relevant code to ground your plan in reality.
|
|
22
|
+
|
|
23
|
+
### Verify Roadmap Assumptions
|
|
24
|
+
|
|
25
|
+
Check prior slice summaries (inlined above as dependency summaries, if present). If prior slices discovered constraints, changed approaches, or flagged fragility, adjust your plan accordingly. The roadmap description may be stale — verify it against the current codebase state.
|
|
26
|
+
|
|
27
|
+
### Explore Slice Scope
|
|
28
|
+
|
|
29
|
+
Read the code files relevant to this slice. Confirm the roadmap's description of what exists, what needs to change, and what boundaries apply. Use `rg`, `find`, and targeted reads.
|
|
30
|
+
|
|
31
|
+
### Source Files
|
|
32
|
+
|
|
33
|
+
{{sourceFilePaths}}
|
|
34
|
+
|
|
35
|
+
If slice research exists (inlined above), trust those findings and skip redundant exploration.
|
|
22
36
|
|
|
23
37
|
After you finish, **executor agents** implement each task in isolated fresh context windows. They see only their task plan, the slice plan excerpt (goal/demo/verification), and compressed summaries of prior tasks. They do not see the research doc, the roadmap, or REQUIREMENTS.md. Everything an executor needs must be in the task plan itself — file paths, specific steps, expected inputs and outputs.
|
|
24
38
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Workflow Template: {{templateName}}
|
|
2
|
+
|
|
3
|
+
You are executing a **{{templateName}}** workflow (template: `{{templateId}}`).
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
- **Description:** {{description}}
|
|
8
|
+
- **Issue reference:** {{issueRef}}
|
|
9
|
+
- **Date:** {{date}}
|
|
10
|
+
- **Branch:** {{branch}}
|
|
11
|
+
- **Artifact directory:** {{artifactDir}}
|
|
12
|
+
- **Phases:** {{phases}}
|
|
13
|
+
- **Complexity:** {{complexity}}
|
|
14
|
+
|
|
15
|
+
## Workflow Definition
|
|
16
|
+
|
|
17
|
+
Follow the workflow defined below. Execute each phase in order, completing one before moving to the next. At each phase gate, confirm with the user before proceeding.
|
|
18
|
+
|
|
19
|
+
{{workflowContent}}
|
|
20
|
+
|
|
21
|
+
## Execution Rules
|
|
22
|
+
|
|
23
|
+
1. **Follow the phases in order.** Do not skip phases unless the workflow explicitly allows it.
|
|
24
|
+
2. **Artifact discipline.** If an artifact directory is specified, write all planning/summary documents there.
|
|
25
|
+
3. **Atomic commits.** Commit working code after each meaningful change. Use conventional commit format: `<type>(<scope>): <description>`.
|
|
26
|
+
4. **Verify before shipping.** Run the project's test suite and build before marking the workflow complete.
|
|
27
|
+
5. **Gate between phases.** After each phase, summarize what was done and ask the user to confirm before moving to the next phase.
|
|
28
|
+
6. **Stay focused.** This is a {{complexity}}-complexity workflow. Match your ceremony level to the task — don't over-engineer or under-deliver.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSD Repo Identity — external state directory primitives.
|
|
3
|
+
*
|
|
4
|
+
* Computes a stable per-repo identity hash, resolves the external
|
|
5
|
+
* `~/.gsd/projects/<hash>/` state directory, and manages the
|
|
6
|
+
* `<project>/.gsd → external` symlink.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { execFileSync } from "node:child_process";
|
|
11
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, symlinkSync } from "node:fs";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { join, resolve } from "node:path";
|
|
14
|
+
|
|
15
|
+
// ─── Repo Identity ──────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get the git remote URL for "origin", or "" if no remote is configured.
|
|
19
|
+
* Uses `git config` rather than `git remote get-url` for broader compat.
|
|
20
|
+
*/
|
|
21
|
+
function getRemoteUrl(basePath: string): string {
|
|
22
|
+
try {
|
|
23
|
+
return execFileSync("git", ["config", "--get", "remote.origin.url"], {
|
|
24
|
+
cwd: basePath,
|
|
25
|
+
encoding: "utf-8",
|
|
26
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
27
|
+
timeout: 5_000,
|
|
28
|
+
}).trim();
|
|
29
|
+
} catch {
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolve the git toplevel (real root) for the given path.
|
|
36
|
+
* For worktrees this returns the main repo root, not the worktree path.
|
|
37
|
+
*/
|
|
38
|
+
function resolveGitRoot(basePath: string): string {
|
|
39
|
+
try {
|
|
40
|
+
return execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
41
|
+
cwd: basePath,
|
|
42
|
+
encoding: "utf-8",
|
|
43
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
44
|
+
timeout: 5_000,
|
|
45
|
+
}).trim();
|
|
46
|
+
} catch {
|
|
47
|
+
return resolve(basePath);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Compute a stable identity for a repository.
|
|
53
|
+
*
|
|
54
|
+
* SHA-256 of `${remoteUrl}\n${resolvedRoot}`, truncated to 12 hex chars.
|
|
55
|
+
* Deterministic: same repo always produces the same hash regardless of
|
|
56
|
+
* which worktree the caller is inside.
|
|
57
|
+
*/
|
|
58
|
+
export function repoIdentity(basePath: string): string {
|
|
59
|
+
const remoteUrl = getRemoteUrl(basePath);
|
|
60
|
+
const root = resolveGitRoot(basePath);
|
|
61
|
+
const input = `${remoteUrl}\n${root}`;
|
|
62
|
+
return createHash("sha256").update(input).digest("hex").slice(0, 12);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ─── External State Directory ───────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Compute the external GSD state directory for a repository.
|
|
69
|
+
*
|
|
70
|
+
* Returns `$GSD_STATE_DIR/projects/<hash>` if `GSD_STATE_DIR` is set,
|
|
71
|
+
* otherwise `~/.gsd/projects/<hash>`.
|
|
72
|
+
*/
|
|
73
|
+
export function externalGsdRoot(basePath: string): string {
|
|
74
|
+
const base = process.env.GSD_STATE_DIR || join(homedir(), ".gsd");
|
|
75
|
+
return join(base, "projects", repoIdentity(basePath));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ─── Symlink Management ─────────────────────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Ensure the `<project>/.gsd` symlink points to the external state directory.
|
|
82
|
+
*
|
|
83
|
+
* 1. mkdir -p the external dir
|
|
84
|
+
* 2. If `<project>/.gsd` doesn't exist → create symlink
|
|
85
|
+
* 3. If `<project>/.gsd` is already the correct symlink → no-op
|
|
86
|
+
* 4. If `<project>/.gsd` is a real directory → return as-is (migration handles later)
|
|
87
|
+
*
|
|
88
|
+
* Returns the resolved external path.
|
|
89
|
+
*/
|
|
90
|
+
export function ensureGsdSymlink(projectPath: string): string {
|
|
91
|
+
const externalPath = externalGsdRoot(projectPath);
|
|
92
|
+
const localGsd = join(projectPath, ".gsd");
|
|
93
|
+
|
|
94
|
+
// Ensure external directory exists
|
|
95
|
+
mkdirSync(externalPath, { recursive: true });
|
|
96
|
+
|
|
97
|
+
if (!existsSync(localGsd)) {
|
|
98
|
+
// Nothing exists yet — create symlink
|
|
99
|
+
symlinkSync(externalPath, localGsd, "junction");
|
|
100
|
+
return externalPath;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const stat = lstatSync(localGsd);
|
|
105
|
+
|
|
106
|
+
if (stat.isSymbolicLink()) {
|
|
107
|
+
// Already a symlink — verify it points to the right place
|
|
108
|
+
const target = realpathSync(localGsd);
|
|
109
|
+
if (target === externalPath) {
|
|
110
|
+
return externalPath; // correct symlink, no-op
|
|
111
|
+
}
|
|
112
|
+
// Symlink exists but points elsewhere — leave it for now
|
|
113
|
+
// (could be a custom override or stale symlink)
|
|
114
|
+
return target;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (stat.isDirectory()) {
|
|
118
|
+
// Real directory — migration will handle this later.
|
|
119
|
+
// Return the local path so existing code still works.
|
|
120
|
+
return localGsd;
|
|
121
|
+
}
|
|
122
|
+
} catch {
|
|
123
|
+
// lstat failed — path exists but we can't stat it
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return localGsd;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ─── Worktree Detection ─────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Check if the given directory is a git worktree (not the main repo).
|
|
133
|
+
*
|
|
134
|
+
* Git worktrees have a `.git` *file* (not directory) containing a
|
|
135
|
+
* `gitdir:` pointer. This is git's native worktree indicator — no
|
|
136
|
+
* string marker parsing needed.
|
|
137
|
+
*/
|
|
138
|
+
export function isInsideWorktree(cwd: string): boolean {
|
|
139
|
+
const gitPath = join(cwd, ".git");
|
|
140
|
+
try {
|
|
141
|
+
const stat = lstatSync(gitPath);
|
|
142
|
+
if (!stat.isFile()) return false;
|
|
143
|
+
const content = readFileSync(gitPath, "utf-8").trim();
|
|
144
|
+
return content.startsWith("gitdir:");
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource version tracking and stale worktree detection.
|
|
3
|
+
*
|
|
4
|
+
* Staleness detection for managed GSD resources and utilities
|
|
5
|
+
* for escaping stale worktree cwd after milestone teardown.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readdirSync, unlinkSync } from "node:fs";
|
|
9
|
+
import { loadJsonFileOrNull } from "./json-persistence.js";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { homedir } from "node:os";
|
|
12
|
+
import { resolveProjectRoot } from "./worktree.js";
|
|
13
|
+
|
|
14
|
+
// ─── Resource Staleness ───────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Read the resource version (semver) from the managed-resources manifest.
|
|
18
|
+
* Uses gsdVersion instead of syncedAt so that launching a second session
|
|
19
|
+
* doesn't falsely trigger staleness (#804).
|
|
20
|
+
*/
|
|
21
|
+
function isManifestWithVersion(data: unknown): data is { gsdVersion: string } {
|
|
22
|
+
return data !== null && typeof data === "object" && "gsdVersion" in data! && typeof (data as Record<string, unknown>).gsdVersion === "string";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function readResourceVersion(): string | null {
|
|
26
|
+
const agentDir = process.env.GSD_CODING_AGENT_DIR || join(homedir(), ".gsd", "agent");
|
|
27
|
+
const manifestPath = join(agentDir, "managed-resources.json");
|
|
28
|
+
const manifest = loadJsonFileOrNull(manifestPath, isManifestWithVersion);
|
|
29
|
+
return manifest?.gsdVersion ?? null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Check if managed resources have been updated since session start.
|
|
34
|
+
* Returns a warning message if stale, null otherwise.
|
|
35
|
+
*/
|
|
36
|
+
export function checkResourcesStale(versionOnStart: string | null): string | null {
|
|
37
|
+
if (versionOnStart === null) return null;
|
|
38
|
+
const current = readResourceVersion();
|
|
39
|
+
if (current === null) return null;
|
|
40
|
+
if (current !== versionOnStart) {
|
|
41
|
+
return "GSD resources were updated since this session started. Restart gsd to load the new code.";
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─── Stale Worktree Escape ────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Detect and escape a stale worktree cwd (#608).
|
|
50
|
+
*
|
|
51
|
+
* After milestone completion + merge, the worktree directory is removed but
|
|
52
|
+
* the process cwd may still point inside `.gsd/worktrees/<MID>/`.
|
|
53
|
+
* When a new session starts, `process.cwd()` is passed as `base` to startAuto
|
|
54
|
+
* and all subsequent writes land in the wrong directory. This function detects
|
|
55
|
+
* that scenario and chdir back to the project root.
|
|
56
|
+
*
|
|
57
|
+
* Returns the corrected base path.
|
|
58
|
+
*/
|
|
59
|
+
export function escapeStaleWorktree(base: string): string {
|
|
60
|
+
const projectRoot = resolveProjectRoot(base);
|
|
61
|
+
if (projectRoot === base) return base;
|
|
62
|
+
try {
|
|
63
|
+
process.chdir(projectRoot);
|
|
64
|
+
} catch {
|
|
65
|
+
return base;
|
|
66
|
+
}
|
|
67
|
+
return projectRoot;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Clean stale runtime unit files for completed milestones.
|
|
72
|
+
*
|
|
73
|
+
* After restart, stale runtime/units/*.json from prior milestones can
|
|
74
|
+
* cause deriveState to resume the wrong milestone (#887). Removes files
|
|
75
|
+
* for milestones that have a SUMMARY (fully complete).
|
|
76
|
+
*/
|
|
77
|
+
export function cleanStaleRuntimeUnits(
|
|
78
|
+
gsdRootPath: string,
|
|
79
|
+
hasMilestoneSummary: (mid: string) => boolean,
|
|
80
|
+
): number {
|
|
81
|
+
const runtimeUnitsDir = join(gsdRootPath, "runtime", "units");
|
|
82
|
+
if (!existsSync(runtimeUnitsDir)) return 0;
|
|
83
|
+
|
|
84
|
+
let cleaned = 0;
|
|
85
|
+
try {
|
|
86
|
+
for (const file of readdirSync(runtimeUnitsDir)) {
|
|
87
|
+
if (!file.endsWith(".json")) continue;
|
|
88
|
+
const midMatch = file.match(/(M\d+(?:-[a-z0-9]{6})?)/);
|
|
89
|
+
if (!midMatch) continue;
|
|
90
|
+
if (hasMilestoneSummary(midMatch[1])) {
|
|
91
|
+
try {
|
|
92
|
+
unlinkSync(join(runtimeUnitsDir, file));
|
|
93
|
+
cleaned++;
|
|
94
|
+
} catch { /* non-fatal */ }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} catch { /* non-fatal */ }
|
|
98
|
+
return cleaned;
|
|
99
|
+
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { readFileSync, readdirSync, existsSync, statSync } from "node:fs";
|
|
22
22
|
import { basename, join } from "node:path";
|
|
23
|
+
import { gsdRoot } from "./paths.js";
|
|
23
24
|
import { truncateWithEllipsis } from "../shared/format-utils.js";
|
|
24
25
|
import { nativeParseJsonlTail } from "./native-parser-bridge.js";
|
|
25
26
|
import { MAX_JSONL_BYTES, parseJSONL } from "./jsonl-utils.js";
|
|
@@ -292,7 +293,7 @@ export function getDeepDiagnostic(basePath: string): string | null {
|
|
|
292
293
|
if (mid) {
|
|
293
294
|
const wtPath = getAutoWorktreePath(basePath, mid);
|
|
294
295
|
if (wtPath) {
|
|
295
|
-
const wtActivityDir = join(wtPath, "
|
|
296
|
+
const wtActivityDir = join(gsdRoot(wtPath), "activity");
|
|
296
297
|
trace = readLastActivityLog(wtActivityDir);
|
|
297
298
|
}
|
|
298
299
|
}
|
|
@@ -300,7 +301,7 @@ export function getDeepDiagnostic(basePath: string): string | null {
|
|
|
300
301
|
|
|
301
302
|
// Fall back to root activity logs
|
|
302
303
|
if (!trace || trace.toolCallCount === 0) {
|
|
303
|
-
const activityDir = join(basePath, "
|
|
304
|
+
const activityDir = join(gsdRoot(basePath), "activity");
|
|
304
305
|
trace = readLastActivityLog(activityDir);
|
|
305
306
|
}
|
|
306
307
|
|
|
@@ -314,7 +315,7 @@ export function getDeepDiagnostic(basePath: string): string | null {
|
|
|
314
315
|
*/
|
|
315
316
|
function readActiveMilestoneId(basePath: string): string | null {
|
|
316
317
|
try {
|
|
317
|
-
const statePath = join(basePath, "
|
|
318
|
+
const statePath = join(gsdRoot(basePath), "STATE.md");
|
|
318
319
|
if (!existsSync(statePath)) return null;
|
|
319
320
|
const content = readFileSync(statePath, "utf-8");
|
|
320
321
|
const match = /\*\*Active Milestone:\*\*\s*(\S+)/i.exec(content);
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import test from "node:test";
|
|
8
8
|
import assert from "node:assert/strict";
|
|
9
|
-
import { existsSync, mkdtempSync, mkdirSync, readdirSync, rmSync, utimesSync, writeFileSync, readFileSync } from "node:fs";
|
|
9
|
+
import { existsSync, mkdtempSync, mkdirSync, readdirSync, realpathSync, rmSync, utimesSync, writeFileSync, readFileSync } from "node:fs";
|
|
10
10
|
import { join, dirname } from "node:path";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
@@ -18,7 +18,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
18
18
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
19
19
|
|
|
20
20
|
function createTmpDir(): string {
|
|
21
|
-
return mkdtempSync(join(tmpdir(), "gsd-activity-test-"));
|
|
21
|
+
return realpathSync(mkdtempSync(join(tmpdir(), "gsd-activity-test-")));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function writeActivityFile(dir: string, seq: string, name: string): string {
|
|
@@ -308,8 +308,8 @@ test("loadPersistedKeys unions keys from project root and worktree", () => {
|
|
|
308
308
|
});
|
|
309
309
|
|
|
310
310
|
test("completed-units.json set-union merge produces correct result", () => {
|
|
311
|
-
// Verify that a manual set-union merge
|
|
312
|
-
//
|
|
311
|
+
// Verify that a manual set-union merge correctly merges two JSON arrays
|
|
312
|
+
// of completed-unit keys.
|
|
313
313
|
const projectRoot = makeTmpBase();
|
|
314
314
|
const worktree = makeTmpBase();
|
|
315
315
|
try {
|
|
@@ -320,7 +320,7 @@ test("completed-units.json set-union merge produces correct result", () => {
|
|
|
320
320
|
writeFileSync(prKeysFile, JSON.stringify(["a", "b"]));
|
|
321
321
|
writeFileSync(wtKeysFile, JSON.stringify(["b", "c", "d"]));
|
|
322
322
|
|
|
323
|
-
// Perform
|
|
323
|
+
// Perform a set-union merge of two JSON key arrays
|
|
324
324
|
const srcKeys: string[] = JSON.parse(readFileSync(wtKeysFile, "utf8"));
|
|
325
325
|
let dstKeys: string[] = [];
|
|
326
326
|
if (existsSync(prKeysFile)) {
|
|
@@ -153,64 +153,6 @@ async function main(): Promise<void> {
|
|
|
153
153
|
// After teardown, originalBase should be null
|
|
154
154
|
assertEq(getAutoWorktreeOriginalBase(), null, "no split-brain: originalBase cleared");
|
|
155
155
|
|
|
156
|
-
// ─── #778: reconcile plan checkboxes on re-attach ─────────────────
|
|
157
|
-
console.log("\n=== #778: reconcile plan checkboxes on re-attach ===");
|
|
158
|
-
{
|
|
159
|
-
// Simulate: T01 [x] was committed to milestone branch, T02 [x] was
|
|
160
|
-
// written to project root by syncStateToProjectRoot() but the
|
|
161
|
-
// auto-commit crashed before it fired. On restart the worktree is
|
|
162
|
-
// re-created from the milestone branch HEAD (T02 still [ ]).
|
|
163
|
-
// reconcilePlanCheckboxes should forward-apply T02 [x] from the root.
|
|
164
|
-
|
|
165
|
-
const planRelPath = join(".gsd", "milestones", "M004", "slices", "S01", "S01-PLAN.md");
|
|
166
|
-
const planDir = join(tempDir, ".gsd", "milestones", "M004", "slices", "S01");
|
|
167
|
-
const { mkdirSync: mkdir, writeFileSync: write, readFileSync: read } = await import("node:fs");
|
|
168
|
-
|
|
169
|
-
// Plan on integration branch (project root): T01 [x], T02 [x]
|
|
170
|
-
mkdir(planDir, { recursive: true });
|
|
171
|
-
write(
|
|
172
|
-
join(tempDir, planRelPath),
|
|
173
|
-
"# S01 Plan\n- [x] **T01:** task one\n- [x] **T02:** task two\n- [ ] **T03:** task three\n",
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
// Write integration-branch plan to git so milestone branch starts from it
|
|
177
|
-
run(`git add .`, tempDir);
|
|
178
|
-
run(`git commit -m "add plan with T01 and T02 checked" --allow-empty`, tempDir);
|
|
179
|
-
|
|
180
|
-
// Create milestone branch with only T01 [x] (simulating crash before T02 commit)
|
|
181
|
-
const milestoneBranch = "milestone/M004";
|
|
182
|
-
run(`git checkout -b ${milestoneBranch}`, tempDir);
|
|
183
|
-
mkdir(planDir, { recursive: true });
|
|
184
|
-
write(
|
|
185
|
-
join(tempDir, planRelPath),
|
|
186
|
-
"# S01 Plan\n- [x] **T01:** task one\n- [ ] **T02:** task two\n- [ ] **T03:** task three\n",
|
|
187
|
-
);
|
|
188
|
-
run(`git add .`, tempDir);
|
|
189
|
-
run(`git commit -m "milestone: only T01 checked"`, tempDir);
|
|
190
|
-
run(`git checkout main`, tempDir);
|
|
191
|
-
|
|
192
|
-
// Restore project root plan (T01+T02 [x]) — simulates syncStateToProjectRoot
|
|
193
|
-
write(
|
|
194
|
-
join(tempDir, planRelPath),
|
|
195
|
-
"# S01 Plan\n- [x] **T01:** task one\n- [x] **T02:** task two\n- [ ] **T03:** task three\n",
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
// Create worktree re-attached to existing milestone branch (T02 still [ ] in branch)
|
|
199
|
-
const wtPath = createAutoWorktree(tempDir, "M004");
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
const wtPlanPath = join(wtPath, planRelPath);
|
|
203
|
-
assertTrue(existsSync(wtPlanPath), "plan file exists in worktree after re-attach");
|
|
204
|
-
|
|
205
|
-
const wtPlan = read(wtPlanPath, "utf-8");
|
|
206
|
-
assertTrue(wtPlan.includes("- [x] **T02:"), "T02 should be [x] after reconciliation (was [ ] on branch)");
|
|
207
|
-
assertTrue(wtPlan.includes("- [x] **T01:"), "T01 stays [x]");
|
|
208
|
-
assertTrue(wtPlan.includes("- [ ] **T03:"), "T03 stays [ ] (not in root either)");
|
|
209
|
-
} finally {
|
|
210
|
-
teardownAutoWorktree(tempDir, "M004");
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
156
|
} finally {
|
|
215
157
|
// Always restore cwd and clean up
|
|
216
158
|
process.chdir(savedCwd);
|
|
@@ -231,15 +231,14 @@ None
|
|
|
231
231
|
const detect = await runGSDDoctor(dir);
|
|
232
232
|
const gitignoreIssues = detect.issues.filter(i => i.code === "gitignore_missing_patterns");
|
|
233
233
|
assertTrue(gitignoreIssues.length > 0, "detects missing gitignore patterns");
|
|
234
|
-
assertTrue(gitignoreIssues[0]?.message.includes(".gsd
|
|
234
|
+
assertTrue(gitignoreIssues[0]?.message.includes(".gsd"), "message lists missing .gsd pattern");
|
|
235
235
|
|
|
236
236
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
237
237
|
assertTrue(fixed.fixesApplied.some(f => f.includes("added missing GSD runtime patterns")), "fix adds patterns");
|
|
238
238
|
|
|
239
|
-
// Verify
|
|
239
|
+
// Verify .gsd entry was added (external state symlink)
|
|
240
240
|
const content = readFileSync(join(dir, ".gitignore"), "utf-8");
|
|
241
|
-
assertTrue(content.includes(".gsd
|
|
242
|
-
assertTrue(content.includes(".gsd/auto.lock"), "gitignore now has auto.lock pattern");
|
|
241
|
+
assertTrue(content.includes(".gsd"), "gitignore now has .gsd entry");
|
|
243
242
|
}
|
|
244
243
|
} else {
|
|
245
244
|
console.log("\n=== gitignore_missing_patterns (skipped on Windows) ===");
|