gsd-pi 2.37.1 → 2.38.0-dev.29edcdc
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 +1 -1
- package/dist/app-paths.js +1 -1
- package/dist/cli.js +9 -0
- package/dist/extension-discovery.d.ts +5 -3
- package/dist/extension-discovery.js +14 -9
- package/dist/extension-registry.js +2 -2
- package/dist/onboarding.js +1 -0
- package/dist/remote-questions-config.js +2 -2
- package/dist/resource-loader.js +34 -1
- package/dist/resources/extensions/browser-tools/package.json +3 -1
- package/dist/resources/extensions/cmux/index.js +55 -1
- package/dist/resources/extensions/context7/package.json +1 -1
- 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/google-search/package.json +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +6 -23
- package/dist/resources/extensions/gsd/auto-dispatch.js +75 -10
- package/dist/resources/extensions/gsd/auto-loop.js +597 -588
- package/dist/resources/extensions/gsd/auto-post-unit.js +111 -68
- package/dist/resources/extensions/gsd/auto-prompts.js +114 -45
- package/dist/resources/extensions/gsd/auto-recovery.js +37 -1
- package/dist/resources/extensions/gsd/auto-start.js +13 -2
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +13 -5
- package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
- package/dist/resources/extensions/gsd/auto.js +143 -96
- package/dist/resources/extensions/gsd/captures.js +9 -1
- package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +16 -3
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands.js +24 -3
- 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-checks.js +82 -0
- package/dist/resources/extensions/gsd/doctor-environment.js +78 -0
- package/dist/resources/extensions/gsd/doctor-format.js +15 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +62 -12
- package/dist/resources/extensions/gsd/doctor.js +204 -12
- 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 +47 -2
- package/dist/resources/extensions/gsd/forensics.js +1 -1
- package/dist/resources/extensions/gsd/git-service.js +15 -12
- package/dist/resources/extensions/gsd/guided-flow.js +82 -32
- package/dist/resources/extensions/gsd/index.js +24 -20
- package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
- package/dist/resources/extensions/gsd/observability-validator.js +24 -0
- package/dist/resources/extensions/gsd/package.json +1 -1
- package/dist/resources/extensions/gsd/preferences-models.js +0 -12
- package/dist/resources/extensions/gsd/preferences-types.js +3 -2
- package/dist/resources/extensions/gsd/preferences-validation.js +101 -11
- package/dist/resources/extensions/gsd/preferences.js +8 -5
- package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -2
- 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-resume-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +44 -0
- package/dist/resources/extensions/gsd/prompts/run-uat.md +27 -10
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/dist/resources/extensions/gsd/reactive-graph.js +227 -0
- 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 +1 -1
- package/dist/resources/extensions/gsd/templates/task-plan.md +11 -3
- package/dist/resources/extensions/gsd/visualizer-data.js +1 -1
- package/dist/resources/extensions/gsd/worktree.js +35 -16
- package/dist/resources/extensions/mcp-client/index.js +14 -1
- package/dist/resources/extensions/remote-questions/status.js +2 -1
- package/dist/resources/extensions/remote-questions/store.js +2 -1
- package/dist/resources/extensions/search-the-web/provider.js +2 -1
- package/dist/resources/extensions/subagent/index.js +12 -3
- package/dist/resources/extensions/subagent/isolation.js +2 -1
- package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
- package/dist/resources/extensions/universal-config/package.json +1 -1
- package/dist/welcome-screen.d.ts +12 -0
- package/dist/welcome-screen.js +53 -0
- package/package.json +2 -1
- package/packages/pi-ai/dist/env-api-keys.js +13 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +172 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +172 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +64 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.js +668 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.d.ts +5 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.js +85 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts +4 -30
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +47 -764
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.js +6 -0
- package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -2
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +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/package.json +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +14 -0
- package/packages/pi-ai/src/models.generated.ts +172 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +761 -0
- package/packages/pi-ai/src/providers/anthropic-vertex.ts +130 -0
- package/packages/pi-ai/src/providers/anthropic.ts +76 -868
- package/packages/pi-ai/src/providers/register-builtins.ts +7 -0
- package/packages/pi-ai/src/types.ts +2 -0
- 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/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js +8 -4
- package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +223 -7
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/package-manager.ts +8 -4
- package/pkg/package.json +1 -1
- package/src/resources/extensions/cmux/index.ts +57 -1
- 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 +100 -9
- package/src/resources/extensions/gsd/auto-loop.ts +484 -546
- package/src/resources/extensions/gsd/auto-post-unit.ts +92 -42
- package/src/resources/extensions/gsd/auto-prompts.ts +150 -48
- package/src/resources/extensions/gsd/auto-recovery.ts +42 -0
- package/src/resources/extensions/gsd/auto-start.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +15 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
- package/src/resources/extensions/gsd/auto.ts +139 -101
- package/src/resources/extensions/gsd/captures.ts +10 -1
- package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +17 -2
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands.ts +26 -4
- 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-checks.ts +75 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +82 -1
- package/src/resources/extensions/gsd/doctor-format.ts +20 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +64 -10
- package/src/resources/extensions/gsd/doctor-types.ts +16 -1
- package/src/resources/extensions/gsd/doctor.ts +199 -14
- 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 +50 -3
- package/src/resources/extensions/gsd/forensics.ts +1 -1
- package/src/resources/extensions/gsd/git-service.ts +20 -10
- package/src/resources/extensions/gsd/guided-flow.ts +110 -38
- package/src/resources/extensions/gsd/index.ts +24 -17
- package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
- package/src/resources/extensions/gsd/observability-validator.ts +27 -0
- package/src/resources/extensions/gsd/preferences-models.ts +0 -12
- package/src/resources/extensions/gsd/preferences-types.ts +9 -5
- package/src/resources/extensions/gsd/preferences-validation.ts +92 -11
- package/src/resources/extensions/gsd/preferences.ts +8 -5
- package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -2
- 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-resume-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -1
- package/src/resources/extensions/gsd/prompts/queue.md +4 -8
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +44 -0
- package/src/resources/extensions/gsd/prompts/run-uat.md +27 -10
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/src/resources/extensions/gsd/reactive-graph.ts +289 -0
- 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 +1 -1
- package/src/resources/extensions/gsd/templates/task-plan.md +11 -3
- 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/cmux.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +266 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +191 -3
- package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +111 -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/reactive-executor.test.ts +511 -0
- package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +299 -0
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +11 -3
- package/src/resources/extensions/gsd/tests/worktree.test.ts +47 -0
- package/src/resources/extensions/gsd/types.ts +43 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
- package/src/resources/extensions/gsd/worktree.ts +35 -15
- package/src/resources/extensions/mcp-client/index.ts +17 -1
- package/src/resources/extensions/remote-questions/status.ts +3 -1
- package/src/resources/extensions/remote-questions/store.ts +3 -1
- package/src/resources/extensions/search-the-web/provider.ts +2 -1
- package/src/resources/extensions/subagent/index.ts +12 -3
- 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
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
resolveSkillDiscoveryMode,
|
|
21
21
|
getIsolationMode,
|
|
22
22
|
} from "./preferences.js";
|
|
23
|
-
import { ensureGsdSymlink } from "./repo-identity.js";
|
|
23
|
+
import { ensureGsdSymlink, validateProjectId } from "./repo-identity.js";
|
|
24
24
|
import { migrateToExternalState, recoverFailedMigration } from "./migrate-external.js";
|
|
25
25
|
import { collectSecretsFromManifest } from "../get-secrets-from-user.js";
|
|
26
26
|
import { gsdRoot, resolveMilestoneFile, milestonesDir } from "./paths.js";
|
|
@@ -130,6 +130,16 @@ export async function bootstrapAutoSession(
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
try {
|
|
133
|
+
// Validate GSD_PROJECT_ID early so the user gets immediate feedback
|
|
134
|
+
const customProjectId = process.env.GSD_PROJECT_ID;
|
|
135
|
+
if (customProjectId && !validateProjectId(customProjectId)) {
|
|
136
|
+
ctx.ui.notify(
|
|
137
|
+
`GSD_PROJECT_ID must contain only alphanumeric characters, hyphens, and underscores. Got: "${customProjectId}"`,
|
|
138
|
+
"error",
|
|
139
|
+
);
|
|
140
|
+
return releaseLockAndReturn();
|
|
141
|
+
}
|
|
142
|
+
|
|
133
143
|
// Ensure git repo exists
|
|
134
144
|
if (!nativeIsRepo(base)) {
|
|
135
145
|
const mainBranch =
|
|
@@ -429,10 +439,16 @@ export async function bootstrapAutoSession(
|
|
|
429
439
|
s.originalBasePath = base;
|
|
430
440
|
|
|
431
441
|
const isUnderGsdWorktrees = (p: string): boolean => {
|
|
442
|
+
// Direct layout: /.gsd/worktrees/
|
|
432
443
|
const marker = `${pathSep}.gsd${pathSep}worktrees${pathSep}`;
|
|
433
444
|
if (p.includes(marker)) return true;
|
|
434
445
|
const worktreesSuffix = `${pathSep}.gsd${pathSep}worktrees`;
|
|
435
|
-
|
|
446
|
+
if (p.endsWith(worktreesSuffix)) return true;
|
|
447
|
+
// Symlink-resolved layout: /.gsd/projects/<hash>/worktrees/
|
|
448
|
+
const symlinkRe = new RegExp(
|
|
449
|
+
`\\${pathSep}\\.gsd\\${pathSep}projects\\${pathSep}[a-f0-9]+\\${pathSep}worktrees(?:\\${pathSep}|$)`,
|
|
450
|
+
);
|
|
451
|
+
return symlinkRe.test(p);
|
|
436
452
|
};
|
|
437
453
|
|
|
438
454
|
if (
|
|
@@ -22,6 +22,8 @@ import { join, sep as pathSep } from "node:path";
|
|
|
22
22
|
import { homedir } from "node:os";
|
|
23
23
|
import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
|
|
24
24
|
|
|
25
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
26
|
+
|
|
25
27
|
// ─── Project Root → Worktree Sync ─────────────────────────────────────────
|
|
26
28
|
|
|
27
29
|
/**
|
|
@@ -111,7 +113,7 @@ export function syncStateToProjectRoot(
|
|
|
111
113
|
*/
|
|
112
114
|
export function readResourceVersion(): string | null {
|
|
113
115
|
const agentDir =
|
|
114
|
-
process.env.GSD_CODING_AGENT_DIR || join(
|
|
116
|
+
process.env.GSD_CODING_AGENT_DIR || join(gsdHome, "agent");
|
|
115
117
|
const manifestPath = join(agentDir, "managed-resources.json");
|
|
116
118
|
try {
|
|
117
119
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
@@ -153,9 +155,18 @@ export function checkResourcesStale(
|
|
|
153
155
|
* Returns the corrected base path.
|
|
154
156
|
*/
|
|
155
157
|
export function escapeStaleWorktree(base: string): string {
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
158
|
+
// Direct layout: /.gsd/worktrees/
|
|
159
|
+
const directMarker = `${pathSep}.gsd${pathSep}worktrees${pathSep}`;
|
|
160
|
+
let idx = base.indexOf(directMarker);
|
|
161
|
+
if (idx === -1) {
|
|
162
|
+
// Symlink-resolved layout: /.gsd/projects/<hash>/worktrees/
|
|
163
|
+
const symlinkRe = new RegExp(
|
|
164
|
+
`\\${pathSep}\\.gsd\\${pathSep}projects\\${pathSep}[a-f0-9]+\\${pathSep}worktrees\\${pathSep}`,
|
|
165
|
+
);
|
|
166
|
+
const match = base.match(symlinkRe);
|
|
167
|
+
if (!match || match.index === undefined) return base;
|
|
168
|
+
idx = match.index;
|
|
169
|
+
}
|
|
159
170
|
|
|
160
171
|
// base is inside .gsd/worktrees/<something> — extract the project root
|
|
161
172
|
const projectRoot = base.slice(0, idx);
|
|
@@ -37,13 +37,13 @@ import {
|
|
|
37
37
|
resolveGitHeadPath,
|
|
38
38
|
nudgeGitBranchCache,
|
|
39
39
|
} from "./worktree.js";
|
|
40
|
-
import { MergeConflictError, readIntegrationBranch } from "./git-service.js";
|
|
40
|
+
import { MergeConflictError, readIntegrationBranch, RUNTIME_EXCLUSION_PATHS } from "./git-service.js";
|
|
41
41
|
import { parseRoadmap } from "./files.js";
|
|
42
42
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
43
43
|
import {
|
|
44
44
|
nativeGetCurrentBranch,
|
|
45
45
|
nativeWorkingTreeStatus,
|
|
46
|
-
|
|
46
|
+
nativeAddAllWithExclusions,
|
|
47
47
|
nativeCommit,
|
|
48
48
|
nativeCheckoutBranch,
|
|
49
49
|
nativeMergeSquash,
|
|
@@ -768,7 +768,7 @@ function autoCommitDirtyState(cwd: string): boolean {
|
|
|
768
768
|
try {
|
|
769
769
|
const status = nativeWorkingTreeStatus(cwd);
|
|
770
770
|
if (!status) return false;
|
|
771
|
-
|
|
771
|
+
nativeAddAllWithExclusions(cwd, RUNTIME_EXCLUSION_PATHS);
|
|
772
772
|
const result = nativeCommit(
|
|
773
773
|
cwd,
|
|
774
774
|
"chore: auto-commit before milestone merge",
|
|
@@ -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
|
/**
|
|
@@ -59,8 +59,17 @@ const VALID_CLASSIFICATIONS: readonly string[] = [
|
|
|
59
59
|
*/
|
|
60
60
|
export function resolveCapturesPath(basePath: string): string {
|
|
61
61
|
const resolved = resolve(basePath);
|
|
62
|
+
// Direct layout: /.gsd/worktrees/
|
|
62
63
|
const worktreeMarker = `${sep}.gsd${sep}worktrees${sep}`;
|
|
63
|
-
|
|
64
|
+
let idx = resolved.indexOf(worktreeMarker);
|
|
65
|
+
if (idx === -1) {
|
|
66
|
+
// Symlink-resolved layout: /.gsd/projects/<hash>/worktrees/
|
|
67
|
+
const symlinkRe = new RegExp(
|
|
68
|
+
`\\${sep}\\.gsd\\${sep}projects\\${sep}[a-f0-9]+\\${sep}worktrees\\${sep}`,
|
|
69
|
+
);
|
|
70
|
+
const match = resolved.match(symlinkRe);
|
|
71
|
+
if (match && match.index !== undefined) idx = match.index;
|
|
72
|
+
}
|
|
64
73
|
if (idx !== -1) {
|
|
65
74
|
// basePath is inside a worktree — resolve to project root
|
|
66
75
|
const projectRoot = resolved.slice(0, idx);
|
|
@@ -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 {
|
|
@@ -15,6 +15,7 @@ import { appendOverride, appendKnowledge } from "./files.js";
|
|
|
15
15
|
import {
|
|
16
16
|
formatDoctorIssuesForPrompt,
|
|
17
17
|
formatDoctorReport,
|
|
18
|
+
formatDoctorReportJson,
|
|
18
19
|
runGSDDoctor,
|
|
19
20
|
selectDoctorScope,
|
|
20
21
|
filterDoctorIssues,
|
|
@@ -43,16 +44,30 @@ export function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined,
|
|
|
43
44
|
|
|
44
45
|
export async function handleDoctor(args: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<void> {
|
|
45
46
|
const trimmed = args.trim();
|
|
46
|
-
|
|
47
|
+
// Extract flags before positional parsing
|
|
48
|
+
const jsonMode = trimmed.includes("--json");
|
|
49
|
+
const dryRun = trimmed.includes("--dry-run");
|
|
50
|
+
const includeBuild = trimmed.includes("--build");
|
|
51
|
+
const includeTests = trimmed.includes("--test");
|
|
52
|
+
const stripped = trimmed.replace(/--json|--dry-run|--build|--test/g, "").trim();
|
|
53
|
+
const parts = stripped ? stripped.split(/\s+/) : [];
|
|
47
54
|
const mode = parts[0] === "fix" || parts[0] === "heal" || parts[0] === "audit" ? parts[0] : "doctor";
|
|
48
55
|
const requestedScope = mode === "doctor" ? parts[0] : parts[1];
|
|
49
56
|
const scope = await selectDoctorScope(projectRoot(), requestedScope);
|
|
50
57
|
const effectiveScope = mode === "audit" ? requestedScope : scope;
|
|
51
58
|
const report = await runGSDDoctor(projectRoot(), {
|
|
52
|
-
fix: mode === "fix" || mode === "heal",
|
|
59
|
+
fix: mode === "fix" || mode === "heal" || dryRun,
|
|
60
|
+
dryRun,
|
|
53
61
|
scope: effectiveScope,
|
|
62
|
+
includeBuild,
|
|
63
|
+
includeTests,
|
|
54
64
|
});
|
|
55
65
|
|
|
66
|
+
if (jsonMode) {
|
|
67
|
+
ctx.ui.notify(formatDoctorReportJson(report), "info");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
56
71
|
const reportText = formatDoctorReport(report, {
|
|
57
72
|
scope: effectiveScope,
|
|
58
73
|
includeWarnings: mode === "audit",
|
|
@@ -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";
|
|
@@ -159,7 +161,7 @@ async function guardRemoteSession(
|
|
|
159
161
|
|
|
160
162
|
export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
161
163
|
pi.registerCommand("gsd", {
|
|
162
|
-
description: "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|visualize|queue|quick|capture|triage|dispatch|history|undo|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|update",
|
|
164
|
+
description: "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|capture|triage|dispatch|history|undo|rate|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|inspect|extensions|update",
|
|
163
165
|
getArgumentCompletions: (prefix: string) => {
|
|
164
166
|
const subcommands = [
|
|
165
167
|
{ cmd: "help", desc: "Categorized command reference with descriptions" },
|
|
@@ -210,7 +212,11 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
210
212
|
{ cmd: "templates", desc: "List available workflow templates" },
|
|
211
213
|
{ cmd: "extensions", desc: "Manage extensions (list, enable, disable, info)" },
|
|
212
214
|
];
|
|
215
|
+
const hasTrailingSpace = prefix.endsWith(" ");
|
|
213
216
|
const parts = prefix.trim().split(/\s+/);
|
|
217
|
+
if (hasTrailingSpace && parts.length >= 1) {
|
|
218
|
+
parts.push("");
|
|
219
|
+
}
|
|
214
220
|
|
|
215
221
|
if (parts.length <= 1) {
|
|
216
222
|
return subcommands
|
|
@@ -478,7 +484,7 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
478
484
|
if (parts.length === 3 && ["enable", "disable", "info"].includes(parts[1])) {
|
|
479
485
|
const idPrefix = parts[2] ?? "";
|
|
480
486
|
try {
|
|
481
|
-
const extDir = join(
|
|
487
|
+
const extDir = join(gsdHome, "agent", "extensions");
|
|
482
488
|
const ids: { id: string; name: string }[] = [];
|
|
483
489
|
for (const entry of readdirSync(extDir, { withFileTypes: true })) {
|
|
484
490
|
if (!entry.isDirectory()) continue;
|
|
@@ -509,6 +515,10 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
509
515
|
{ cmd: "fix", desc: "Auto-fix detected issues" },
|
|
510
516
|
{ cmd: "heal", desc: "AI-driven deep healing" },
|
|
511
517
|
{ cmd: "audit", desc: "Run health audit without fixing" },
|
|
518
|
+
{ cmd: "--dry-run", desc: "Show what --fix would change without applying" },
|
|
519
|
+
{ cmd: "--json", desc: "Output report as JSON (CI/tooling friendly)" },
|
|
520
|
+
{ cmd: "--build", desc: "Include slow build health check (npm run build)" },
|
|
521
|
+
{ cmd: "--test", desc: "Include slow test health check (npm test)" },
|
|
512
522
|
];
|
|
513
523
|
|
|
514
524
|
if (parts.length <= 2) {
|
|
@@ -536,6 +546,18 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
536
546
|
.map((p) => ({ value: `dispatch ${p.cmd}`, label: p.cmd, description: p.desc }));
|
|
537
547
|
}
|
|
538
548
|
|
|
549
|
+
if (parts[0] === "rate" && parts.length <= 2) {
|
|
550
|
+
const tierPrefix = parts[1] ?? "";
|
|
551
|
+
const tiers = [
|
|
552
|
+
{ cmd: "over", desc: "Model was overqualified for this task" },
|
|
553
|
+
{ cmd: "ok", desc: "Model was appropriate for this task" },
|
|
554
|
+
{ cmd: "under", desc: "Model was underqualified for this task" },
|
|
555
|
+
];
|
|
556
|
+
return tiers
|
|
557
|
+
.filter((t) => t.cmd.startsWith(tierPrefix))
|
|
558
|
+
.map((t) => ({ value: `rate ${t.cmd}`, label: t.cmd, description: t.desc }));
|
|
559
|
+
}
|
|
560
|
+
|
|
539
561
|
return [];
|
|
540
562
|
},
|
|
541
563
|
|
|
@@ -563,7 +585,7 @@ export async function handleGSDCommand(
|
|
|
563
585
|
}
|
|
564
586
|
|
|
565
587
|
if (trimmed === "widget" || trimmed.startsWith("widget ")) {
|
|
566
|
-
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");
|
|
567
589
|
const arg = trimmed.replace(/^widget\s*/, "").trim();
|
|
568
590
|
if (arg === "full" || arg === "small" || arg === "min" || arg === "off") {
|
|
569
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:
|