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
|
@@ -536,129 +536,167 @@ export async function stopAuto(
|
|
|
536
536
|
if (!s.active && !s.paused) return;
|
|
537
537
|
const loadedPreferences = loadEffectiveGSDPreferences()?.preferences;
|
|
538
538
|
const reasonSuffix = reason ? ` — ${reason}` : "";
|
|
539
|
-
clearUnitTimeout();
|
|
540
|
-
if (lockBase()) clearLock(lockBase());
|
|
541
|
-
if (lockBase()) releaseSessionLock(lockBase());
|
|
542
|
-
clearSkillSnapshot();
|
|
543
|
-
resetSkillTelemetry();
|
|
544
539
|
|
|
545
|
-
|
|
546
|
-
|
|
540
|
+
try {
|
|
541
|
+
// ── Step 1: Timers and locks ──
|
|
542
|
+
try {
|
|
543
|
+
clearUnitTimeout();
|
|
544
|
+
if (lockBase()) clearLock(lockBase());
|
|
545
|
+
if (lockBase()) releaseSessionLock(lockBase());
|
|
546
|
+
} catch (e) {
|
|
547
|
+
debugLog("stop-cleanup-locks", { error: e instanceof Error ? e.message : String(e) });
|
|
548
|
+
}
|
|
547
549
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
});
|
|
556
|
-
}
|
|
550
|
+
// ── Step 2: Skill state ──
|
|
551
|
+
try {
|
|
552
|
+
clearSkillSnapshot();
|
|
553
|
+
resetSkillTelemetry();
|
|
554
|
+
} catch (e) {
|
|
555
|
+
debugLog("stop-cleanup-skills", { error: e instanceof Error ? e.message : String(e) });
|
|
556
|
+
}
|
|
557
557
|
|
|
558
|
-
|
|
559
|
-
if (isDbAvailable()) {
|
|
558
|
+
// ── Step 3: SIGTERM handler ──
|
|
560
559
|
try {
|
|
561
|
-
|
|
562
|
-
closeDatabase();
|
|
560
|
+
deregisterSigtermHandler();
|
|
563
561
|
} catch (e) {
|
|
564
|
-
debugLog("
|
|
565
|
-
error: e instanceof Error ? e.message : String(e),
|
|
566
|
-
});
|
|
562
|
+
debugLog("stop-cleanup-sigterm", { error: e instanceof Error ? e.message : String(e) });
|
|
567
563
|
}
|
|
568
|
-
}
|
|
569
564
|
|
|
570
|
-
|
|
571
|
-
s.basePath = s.originalBasePath;
|
|
565
|
+
// ── Step 4: Auto-worktree exit ──
|
|
572
566
|
try {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
567
|
+
if (s.currentMilestoneId) {
|
|
568
|
+
const notifyCtx = ctx
|
|
569
|
+
? { notify: ctx.ui.notify.bind(ctx.ui) }
|
|
570
|
+
: { notify: () => {} };
|
|
571
|
+
buildResolver().exitMilestone(s.currentMilestoneId, notifyCtx, {
|
|
572
|
+
preserveBranch: true,
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
} catch (e) {
|
|
576
|
+
debugLog("stop-cleanup-worktree", { error: e instanceof Error ? e.message : String(e) });
|
|
576
577
|
}
|
|
577
|
-
}
|
|
578
578
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
579
|
+
// ── Step 5: DB cleanup ──
|
|
580
|
+
if (isDbAvailable()) {
|
|
581
|
+
try {
|
|
582
|
+
const { closeDatabase } = await import("./gsd-db.js");
|
|
583
|
+
closeDatabase();
|
|
584
|
+
} catch (e) {
|
|
585
|
+
debugLog("db-close-failed", {
|
|
586
|
+
error: e instanceof Error ? e.message : String(e),
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
589
590
|
|
|
590
|
-
|
|
591
|
+
// ── Step 6: Restore basePath and chdir ──
|
|
591
592
|
try {
|
|
592
|
-
|
|
593
|
+
if (s.originalBasePath) {
|
|
594
|
+
s.basePath = s.originalBasePath;
|
|
595
|
+
try {
|
|
596
|
+
process.chdir(s.basePath);
|
|
597
|
+
} catch {
|
|
598
|
+
/* best-effort */
|
|
599
|
+
}
|
|
600
|
+
}
|
|
593
601
|
} catch (e) {
|
|
594
|
-
debugLog("stop-
|
|
595
|
-
error: e instanceof Error ? e.message : String(e),
|
|
596
|
-
});
|
|
602
|
+
debugLog("stop-cleanup-basepath", { error: e instanceof Error ? e.message : String(e) });
|
|
597
603
|
}
|
|
598
|
-
}
|
|
599
604
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
605
|
+
// ── Step 7: Ledger notification ──
|
|
606
|
+
try {
|
|
607
|
+
const ledger = getLedger();
|
|
608
|
+
if (ledger && ledger.units.length > 0) {
|
|
609
|
+
const totals = getProjectTotals(ledger.units);
|
|
610
|
+
ctx?.ui.notify(
|
|
611
|
+
`Auto-mode stopped${reasonSuffix}. Session: ${formatCost(totals.cost)} · ${formatTokenCount(totals.tokens.total)} tokens · ${ledger.units.length} units`,
|
|
612
|
+
"info",
|
|
613
|
+
);
|
|
614
|
+
} else {
|
|
615
|
+
ctx?.ui.notify(`Auto-mode stopped${reasonSuffix}.`, "info");
|
|
616
|
+
}
|
|
617
|
+
} catch (e) {
|
|
618
|
+
debugLog("stop-cleanup-ledger", { error: e instanceof Error ? e.message : String(e) });
|
|
619
|
+
}
|
|
606
620
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
621
|
+
// ── Step 8: Rebuild state ──
|
|
622
|
+
if (s.basePath) {
|
|
623
|
+
try {
|
|
624
|
+
await rebuildState(s.basePath);
|
|
625
|
+
} catch (e) {
|
|
626
|
+
debugLog("stop-rebuild-state-failed", {
|
|
627
|
+
error: e instanceof Error ? e.message : String(e),
|
|
628
|
+
});
|
|
629
|
+
}
|
|
611
630
|
}
|
|
612
|
-
}
|
|
613
631
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
632
|
+
// ── Step 9: Cmux sidebar / event log ──
|
|
633
|
+
try {
|
|
634
|
+
clearCmuxSidebar(loadedPreferences);
|
|
635
|
+
logCmuxEvent(
|
|
636
|
+
loadedPreferences,
|
|
637
|
+
`Auto-mode stopped${reasonSuffix || ""}.`,
|
|
638
|
+
reason?.startsWith("Blocked:") ? "warning" : "info",
|
|
639
|
+
);
|
|
640
|
+
} catch (e) {
|
|
641
|
+
debugLog("stop-cleanup-cmux", { error: e instanceof Error ? e.message : String(e) });
|
|
642
|
+
}
|
|
618
643
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
644
|
+
// ── Step 10: Debug summary ──
|
|
645
|
+
try {
|
|
646
|
+
if (isDebugEnabled()) {
|
|
647
|
+
const logPath = writeDebugSummary();
|
|
648
|
+
if (logPath) {
|
|
649
|
+
ctx?.ui.notify(`Debug log written → ${logPath}`, "info");
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
} catch (e) {
|
|
653
|
+
debugLog("stop-cleanup-debug", { error: e instanceof Error ? e.message : String(e) });
|
|
654
|
+
}
|
|
624
655
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
s.currentUnit = null;
|
|
635
|
-
s.autoModeStartModel = null;
|
|
636
|
-
s.currentMilestoneId = null;
|
|
637
|
-
s.originalBasePath = "";
|
|
638
|
-
s.completedUnits = [];
|
|
639
|
-
s.pendingQuickTasks = [];
|
|
640
|
-
clearSliceProgressCache();
|
|
641
|
-
clearActivityLogState();
|
|
642
|
-
resetProactiveHealing();
|
|
643
|
-
s.pendingCrashRecovery = null;
|
|
644
|
-
s.pendingVerificationRetry = null;
|
|
645
|
-
s.verificationRetryCount.clear();
|
|
646
|
-
s.pausedSessionFile = null;
|
|
647
|
-
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
648
|
-
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
649
|
-
ctx?.ui.setFooter(undefined);
|
|
656
|
+
// ── Step 11: Reset metrics, routing, hooks ──
|
|
657
|
+
try {
|
|
658
|
+
resetMetrics();
|
|
659
|
+
resetRoutingHistory();
|
|
660
|
+
resetHookState();
|
|
661
|
+
if (s.basePath) clearPersistedHookState(s.basePath);
|
|
662
|
+
} catch (e) {
|
|
663
|
+
debugLog("stop-cleanup-metrics", { error: e instanceof Error ? e.message : String(e) });
|
|
664
|
+
}
|
|
650
665
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
s.
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
if (original) await pi.setModel(original);
|
|
657
|
-
s.originalModelId = null;
|
|
658
|
-
s.originalModelProvider = null;
|
|
659
|
-
}
|
|
666
|
+
// ── Step 12: Remove paused-session metadata (#1383) ──
|
|
667
|
+
try {
|
|
668
|
+
const pausedPath = join(gsdRoot(s.originalBasePath || s.basePath), "runtime", "paused-session.json");
|
|
669
|
+
if (existsSync(pausedPath)) unlinkSync(pausedPath);
|
|
670
|
+
} catch { /* non-fatal */ }
|
|
660
671
|
|
|
661
|
-
|
|
672
|
+
// ── Step 13: Restore original model (before reset clears IDs) ──
|
|
673
|
+
try {
|
|
674
|
+
if (pi && ctx && s.originalModelId && s.originalModelProvider) {
|
|
675
|
+
const original = ctx.modelRegistry.find(
|
|
676
|
+
s.originalModelProvider,
|
|
677
|
+
s.originalModelId,
|
|
678
|
+
);
|
|
679
|
+
if (original) await pi.setModel(original);
|
|
680
|
+
}
|
|
681
|
+
} catch (e) {
|
|
682
|
+
debugLog("stop-cleanup-model", { error: e instanceof Error ? e.message : String(e) });
|
|
683
|
+
}
|
|
684
|
+
} finally {
|
|
685
|
+
// ── Critical invariants: these MUST execute regardless of errors ──
|
|
686
|
+
// External cleanup (not covered by session reset)
|
|
687
|
+
clearInFlightTools();
|
|
688
|
+
clearSliceProgressCache();
|
|
689
|
+
clearActivityLogState();
|
|
690
|
+
resetProactiveHealing();
|
|
691
|
+
|
|
692
|
+
// UI cleanup
|
|
693
|
+
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
694
|
+
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
695
|
+
ctx?.ui.setFooter(undefined);
|
|
696
|
+
|
|
697
|
+
// Reset all session state in one call
|
|
698
|
+
s.reset();
|
|
699
|
+
}
|
|
662
700
|
}
|
|
663
701
|
|
|
664
702
|
/**
|
|
@@ -11,6 +11,8 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFile
|
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
12
|
import { homedir } from "node:os";
|
|
13
13
|
|
|
14
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
15
|
+
|
|
14
16
|
// ─── Types (mirrored from extension-registry.ts) ────────────────────────────
|
|
15
17
|
|
|
16
18
|
interface ExtensionManifest {
|
|
@@ -48,11 +50,11 @@ interface ExtensionRegistry {
|
|
|
48
50
|
// ─── Registry I/O ───────────────────────────────────────────────────────────
|
|
49
51
|
|
|
50
52
|
function getRegistryPath(): string {
|
|
51
|
-
return join(
|
|
53
|
+
return join(gsdHome, "extensions", "registry.json");
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
function getAgentExtensionsDir(): string {
|
|
55
|
-
return join(
|
|
57
|
+
return join(gsdHome, "agent", "extensions");
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
function loadRegistry(): ExtensionRegistry {
|
|
@@ -745,7 +745,7 @@ export function serializePreferencesToFrontmatter(prefs: Record<string, unknown>
|
|
|
745
745
|
"dynamic_routing", "token_profile", "phases", "parallel",
|
|
746
746
|
"auto_visualize", "auto_report",
|
|
747
747
|
"verification_commands", "verification_auto_fix", "verification_max_retries",
|
|
748
|
-
"search_provider", "
|
|
748
|
+
"search_provider", "context_selection",
|
|
749
749
|
];
|
|
750
750
|
|
|
751
751
|
const seen = new Set<string>();
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* One command, one wizard. Routes to smart entry or status.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type
|
|
7
|
+
import { importExtensionModule, type ExtensionAPI, type ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
8
8
|
import type { GSDState } from "./types.js";
|
|
9
9
|
import { existsSync, readFileSync, readdirSync, unlinkSync } from "node:fs";
|
|
10
10
|
import { homedir } from "node:os";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import { gsdRoot } from "./paths.js";
|
|
13
|
+
|
|
14
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
13
15
|
import { enableDebug } from "./debug-logger.js";
|
|
14
16
|
import { deriveState } from "./state.js";
|
|
15
17
|
import { GSDDashboardOverlay } from "./dashboard-overlay.js";
|
|
@@ -482,7 +484,7 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
482
484
|
if (parts.length === 3 && ["enable", "disable", "info"].includes(parts[1])) {
|
|
483
485
|
const idPrefix = parts[2] ?? "";
|
|
484
486
|
try {
|
|
485
|
-
const extDir = join(
|
|
487
|
+
const extDir = join(gsdHome, "agent", "extensions");
|
|
486
488
|
const ids: { id: string; name: string }[] = [];
|
|
487
489
|
for (const entry of readdirSync(extDir, { withFileTypes: true })) {
|
|
488
490
|
if (!entry.isDirectory()) continue;
|
|
@@ -583,7 +585,7 @@ export async function handleGSDCommand(
|
|
|
583
585
|
}
|
|
584
586
|
|
|
585
587
|
if (trimmed === "widget" || trimmed.startsWith("widget ")) {
|
|
586
|
-
const { cycleWidgetMode, setWidgetMode, getWidgetMode } = await import("./auto-dashboard.js");
|
|
588
|
+
const { cycleWidgetMode, setWidgetMode, getWidgetMode } = await importExtensionModule<typeof import("./auto-dashboard.js")>(import.meta.url, "./auto-dashboard.js");
|
|
587
589
|
const arg = trimmed.replace(/^widget\s*/, "").trim();
|
|
588
590
|
if (arg === "full" || arg === "small" || arg === "min" || arg === "off") {
|
|
589
591
|
setWidgetMode(arg);
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { type TokenProvider, getCharsPerToken } from "./token-counter.js";
|
|
12
|
-
import { compressToTarget } from "./prompt-compressor.js";
|
|
13
12
|
|
|
14
13
|
// ─── Budget ratio constants ──────────────────────────────────────────────────
|
|
15
14
|
// Percentages of total context window allocated to each budget category.
|
|
@@ -202,22 +201,13 @@ export function resolveExecutorContextWindow(
|
|
|
202
201
|
}
|
|
203
202
|
|
|
204
203
|
/**
|
|
205
|
-
*
|
|
206
|
-
* Returns the content within budget with maximum information preservation.
|
|
204
|
+
* Reduce content to fit within budget using section-boundary truncation.
|
|
207
205
|
*/
|
|
208
206
|
export function reduceToFit(content: string, budgetChars: number): TruncationResult {
|
|
209
207
|
if (!content || content.length <= budgetChars) {
|
|
210
208
|
return { content, droppedSections: 0 };
|
|
211
209
|
}
|
|
212
|
-
|
|
213
|
-
// Step 1: Try compression
|
|
214
|
-
const compressed = compressToTarget(content, budgetChars);
|
|
215
|
-
if (compressed.compressedChars <= budgetChars) {
|
|
216
|
-
return { content: compressed.content, droppedSections: 0 };
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Step 2: Truncate the compressed content at section boundaries
|
|
220
|
-
return truncateAtSectionBoundary(compressed.content, budgetChars);
|
|
210
|
+
return truncateAtSectionBoundary(content, budgetChars);
|
|
221
211
|
}
|
|
222
212
|
|
|
223
213
|
// ─── Internal helpers ────────────────────────────────────────────────────────
|
|
@@ -11,6 +11,8 @@ import { join } from "node:path";
|
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
12
|
import { gsdRoot } from "./paths.js";
|
|
13
13
|
|
|
14
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
15
|
+
|
|
14
16
|
// ─── Types ──────────────────────────────────────────────────────────────────────
|
|
15
17
|
|
|
16
18
|
export interface ProjectDetection {
|
|
@@ -400,7 +402,6 @@ function detectVerificationCommands(
|
|
|
400
402
|
* Check if global GSD setup exists (has ~/.gsd/ with preferences).
|
|
401
403
|
*/
|
|
402
404
|
export function hasGlobalSetup(): boolean {
|
|
403
|
-
const gsdHome = join(homedir(), ".gsd");
|
|
404
405
|
return (
|
|
405
406
|
existsSync(join(gsdHome, "preferences.md")) ||
|
|
406
407
|
existsSync(join(gsdHome, "PREFERENCES.md"))
|
|
@@ -412,7 +413,6 @@ export function hasGlobalSetup(): boolean {
|
|
|
412
413
|
* Returns true if ~/.gsd/ doesn't exist or has no preferences or auth.
|
|
413
414
|
*/
|
|
414
415
|
export function isFirstEverLaunch(): boolean {
|
|
415
|
-
const gsdHome = join(homedir(), ".gsd");
|
|
416
416
|
if (!existsSync(gsdHome)) return true;
|
|
417
417
|
|
|
418
418
|
// If we have preferences, not first launch
|
|
@@ -194,8 +194,6 @@ Setting `prefer_skills: []` does **not** disable skill discovery — it just mea
|
|
|
194
194
|
|
|
195
195
|
- `search_provider`: `"brave"`, `"tavily"`, `"ollama"`, `"native"`, or `"auto"` — selects the search backend for research phases. `"native"` forces Anthropic's built-in web search only; provider values force that backend and disable native search; `"auto"` uses the default heuristic. Default: `"auto"`.
|
|
196
196
|
|
|
197
|
-
- `compression_strategy`: `"truncate"` or `"compress"` — controls how context that exceeds the budget is reduced. `"truncate"` (default) drops sections from the end. `"compress"` applies heuristic compression before truncating, preserving more content at the cost of some fidelity. Default: `"truncate"`.
|
|
198
|
-
|
|
199
197
|
- `context_selection`: `"full"` or `"smart"` — controls how files are inlined into context. `"full"` inlines entire files; `"smart"` uses semantic chunking to include only the most relevant sections. Default is derived from `token_profile`.
|
|
200
198
|
|
|
201
199
|
- `parallel`: configures parallel orchestration for running multiple slices concurrently. Keys:
|
|
@@ -51,10 +51,12 @@ function modelToProviderId(model: string): string | null {
|
|
|
51
51
|
const prefix = model.split("/")[0].toLowerCase();
|
|
52
52
|
// Map known prefixes to registry IDs
|
|
53
53
|
const prefixMap: Record<string, string> = {
|
|
54
|
+
"anthropic-vertex": "anthropic-vertex",
|
|
54
55
|
openrouter: "openrouter",
|
|
55
56
|
groq: "groq",
|
|
56
57
|
mistral: "mistral",
|
|
57
58
|
google: "google",
|
|
59
|
+
"google-vertex": "google-vertex",
|
|
58
60
|
anthropic: "anthropic",
|
|
59
61
|
openai: "openai",
|
|
60
62
|
"github-copilot": "github-copilot",
|
|
@@ -88,11 +90,20 @@ function collectConfiguredModelProviders(): Set<string> {
|
|
|
88
90
|
|
|
89
91
|
const modelEntries = typeof models === "object" ? Object.values(models) : [];
|
|
90
92
|
for (const entry of modelEntries) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
if (typeof entry === "string") {
|
|
94
|
+
const pid = modelToProviderId(entry);
|
|
95
|
+
if (pid) providers.add(pid);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (typeof entry === "object" && entry !== null && "model" in entry) {
|
|
100
|
+
const configuredProvider = "provider" in entry ? (entry as { provider?: unknown }).provider : undefined;
|
|
101
|
+
if (typeof configuredProvider === "string" && configuredProvider.trim().length > 0) {
|
|
102
|
+
providers.add(configuredProvider);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const modelId = String((entry as { model: unknown }).model);
|
|
96
107
|
const pid = modelToProviderId(modelId);
|
|
97
108
|
if (pid) providers.add(pid);
|
|
98
109
|
}
|
|
@@ -117,6 +128,10 @@ interface KeyLookup {
|
|
|
117
128
|
function resolveKey(providerId: string): KeyLookup {
|
|
118
129
|
const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
|
|
119
130
|
|
|
131
|
+
if (providerId === "anthropic-vertex" && process.env.ANTHROPIC_VERTEX_PROJECT_ID) {
|
|
132
|
+
return { found: true, source: "env", backedOff: false };
|
|
133
|
+
}
|
|
134
|
+
|
|
120
135
|
// Check auth.json
|
|
121
136
|
const authPath = getAuthPath();
|
|
122
137
|
if (existsSync(authPath)) {
|
|
@@ -175,7 +190,9 @@ function checkLlmProviders(): ProviderCheckResult[] {
|
|
|
175
190
|
|
|
176
191
|
for (const providerId of required) {
|
|
177
192
|
const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
|
|
178
|
-
const label =
|
|
193
|
+
const label = providerId === "anthropic-vertex"
|
|
194
|
+
? "Anthropic Vertex"
|
|
195
|
+
: info?.label ?? providerId;
|
|
179
196
|
const lookup = resolveKey(providerId);
|
|
180
197
|
|
|
181
198
|
if (!lookup.found) {
|
|
@@ -196,14 +213,18 @@ function checkLlmProviders(): ProviderCheckResult[] {
|
|
|
196
213
|
continue;
|
|
197
214
|
}
|
|
198
215
|
|
|
199
|
-
const envVar =
|
|
216
|
+
const envVar = providerId === "anthropic-vertex"
|
|
217
|
+
? "ANTHROPIC_VERTEX_PROJECT_ID"
|
|
218
|
+
: info?.envVar ?? `${providerId.toUpperCase()}_API_KEY`;
|
|
200
219
|
results.push({
|
|
201
220
|
name: providerId,
|
|
202
221
|
label,
|
|
203
222
|
category: "llm",
|
|
204
223
|
status: "error",
|
|
205
|
-
message: `${label} —
|
|
206
|
-
detail:
|
|
224
|
+
message: `${label} — not configured`,
|
|
225
|
+
detail: providerId === "anthropic-vertex"
|
|
226
|
+
? "Set ANTHROPIC_VERTEX_PROJECT_ID and authenticate with Google ADC"
|
|
227
|
+
: info?.hasOAuth
|
|
207
228
|
? `Run /gsd keys to authenticate`
|
|
208
229
|
: `Set ${envVar} or run /gsd keys`,
|
|
209
230
|
required: true,
|
|
@@ -280,9 +280,24 @@ async function markSliceDoneInRoadmap(basePath: string, milestoneId: string, sli
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
async function markSliceUndoneInRoadmap(basePath: string, milestoneId: string, sliceId: string, fixesApplied: string[]): Promise<void> {
|
|
284
|
+
const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
285
|
+
if (!roadmapPath) return;
|
|
286
|
+
const content = await loadFile(roadmapPath);
|
|
287
|
+
if (!content) return;
|
|
288
|
+
const updated = content.replace(
|
|
289
|
+
new RegExp(`^(\\s*-\\s+)\\[x\\]\\s+\\*\\*${sliceId}:`, "m"),
|
|
290
|
+
`$1[ ] **${sliceId}:`,
|
|
291
|
+
);
|
|
292
|
+
if (updated !== content) {
|
|
293
|
+
await saveFile(roadmapPath, updated);
|
|
294
|
+
fixesApplied.push(`unmarked ${sliceId} in ${roadmapPath} (premature completion)`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
283
298
|
function matchesScope(unitId: string, scope?: string): boolean {
|
|
284
299
|
if (!scope) return true;
|
|
285
|
-
return unitId === scope || unitId.startsWith(`${scope}/`)
|
|
300
|
+
return unitId === scope || unitId.startsWith(`${scope}/`);
|
|
286
301
|
}
|
|
287
302
|
|
|
288
303
|
function auditRequirements(content: string | null): DoctorIssue[] {
|
|
@@ -863,6 +878,12 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean;
|
|
|
863
878
|
file: relSliceFile(basePath, milestoneId, slice.id, "SUMMARY"),
|
|
864
879
|
fixable: true,
|
|
865
880
|
});
|
|
881
|
+
if (!allTasksDone) {
|
|
882
|
+
dryRunCanFix("slice_checked_missing_summary", `uncheck ${slice.id} in roadmap (tasks incomplete)`);
|
|
883
|
+
if (shouldFix("slice_checked_missing_summary")) {
|
|
884
|
+
await markSliceUndoneInRoadmap(basePath, milestoneId, slice.id, fixesApplied);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
866
887
|
}
|
|
867
888
|
|
|
868
889
|
if (slice.done && !hasSliceUat) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { importExtensionModule, type ExtensionAPI, type ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
2
2
|
|
|
3
3
|
type StopAutoFn = (ctx: ExtensionCommandContext, pi: ExtensionAPI, reason?: string) => Promise<void>;
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ export function registerExitCommand(
|
|
|
10
10
|
description: "Exit GSD gracefully",
|
|
11
11
|
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
12
12
|
// Stop auto-mode first so locks and activity state are cleaned up before shutdown.
|
|
13
|
-
const stopAuto = deps.stopAuto ?? (await import("./auto.js")).stopAuto;
|
|
13
|
+
const stopAuto = deps.stopAuto ?? (await importExtensionModule<typeof import("./auto.js")>(import.meta.url, "./auto.js")).stopAuto;
|
|
14
14
|
await stopAuto(ctx, pi, "Graceful exit");
|
|
15
15
|
ctx.shutdown();
|
|
16
16
|
},
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./metrics.js";
|
|
12
12
|
import type { UnitMetrics } from "./metrics.js";
|
|
13
13
|
import { gsdRoot } from "./paths.js";
|
|
14
|
-
import { formatDuration, fileLink } from "../shared/
|
|
14
|
+
import { formatDuration, fileLink } from "../shared/format-utils.js";
|
|
15
15
|
import { getErrorMessage } from "./error-utils.js";
|
|
16
16
|
|
|
17
17
|
/**
|