gsd-pi 2.19.0 → 2.20.0
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 +5 -1
- package/dist/cli.js +3 -3
- package/dist/onboarding.d.ts +3 -1
- package/dist/onboarding.js +77 -3
- package/dist/remote-questions-config.d.ts +1 -1
- package/dist/resources/extensions/google-search/index.ts +164 -47
- package/dist/resources/extensions/gsd/auto-prompts.ts +103 -24
- package/dist/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/dist/resources/extensions/gsd/auto.ts +424 -30
- package/dist/resources/extensions/gsd/commands.ts +518 -36
- package/dist/resources/extensions/gsd/context-budget.ts +243 -0
- package/dist/resources/extensions/gsd/context-store.ts +195 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +41 -3
- package/dist/resources/extensions/gsd/db-writer.ts +341 -0
- package/dist/resources/extensions/gsd/debug-logger.ts +178 -0
- package/dist/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/dist/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/dist/resources/extensions/gsd/doctor.ts +283 -2
- package/dist/resources/extensions/gsd/export.ts +81 -2
- package/dist/resources/extensions/gsd/files.ts +39 -9
- package/dist/resources/extensions/gsd/git-service.ts +6 -0
- package/dist/resources/extensions/gsd/gsd-db.ts +752 -0
- package/dist/resources/extensions/gsd/guided-flow.ts +26 -1
- package/dist/resources/extensions/gsd/history.ts +0 -1
- package/dist/resources/extensions/gsd/index.ts +277 -1
- package/dist/resources/extensions/gsd/md-importer.ts +526 -0
- package/dist/resources/extensions/gsd/metrics.ts +39 -3
- package/dist/resources/extensions/gsd/notifications.ts +0 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +70 -1
- package/dist/resources/extensions/gsd/preferences.ts +125 -150
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/dist/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/dist/resources/extensions/gsd/prompts/system.md +2 -1
- package/dist/resources/extensions/gsd/quick.ts +156 -0
- package/dist/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/dist/resources/extensions/gsd/skill-health.ts +417 -0
- package/dist/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/dist/resources/extensions/gsd/state.ts +30 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
- package/dist/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/dist/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/dist/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/dist/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/dist/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/dist/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/dist/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/dist/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/dist/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/dist/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/dist/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/dist/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/dist/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/dist/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/dist/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/dist/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/dist/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/dist/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +262 -1
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/dist/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/dist/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/dist/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/dist/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +92 -0
- package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +228 -5
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/dist/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/dist/resources/extensions/gsd/types.ts +29 -0
- package/dist/resources/extensions/gsd/undo.ts +0 -1
- package/dist/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/dist/resources/extensions/gsd/visualizer-data.ts +352 -1
- package/dist/resources/extensions/gsd/visualizer-overlay.ts +166 -22
- package/dist/resources/extensions/gsd/visualizer-views.ts +464 -2
- package/dist/resources/extensions/gsd/worktree-command.ts +18 -0
- package/dist/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/dist/resources/extensions/remote-questions/config.ts +4 -2
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +2 -4
- package/dist/resources/extensions/remote-questions/format.ts +154 -8
- package/dist/resources/extensions/remote-questions/manager.ts +9 -7
- package/dist/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/dist/resources/extensions/remote-questions/types.ts +2 -1
- package/dist/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/dist/resources/extensions/voice/index.ts +4 -3
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +12 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -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 +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +25 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +106 -3
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts +35 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/types.js +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.js +45 -0
- package/packages/pi-coding-agent/dist/core/lsp/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +43 -11
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +7 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +13 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +26 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +157 -2
- package/packages/pi-coding-agent/src/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/src/core/lsp/types.ts +53 -0
- package/packages/pi-coding-agent/src/core/lsp/utils.ts +56 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +41 -11
- package/packages/pi-coding-agent/src/core/system-prompt.ts +7 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +3 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +3 -0
- package/src/resources/extensions/google-search/index.ts +164 -47
- package/src/resources/extensions/gsd/auto-prompts.ts +103 -24
- package/src/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/src/resources/extensions/gsd/auto.ts +424 -30
- package/src/resources/extensions/gsd/commands.ts +518 -36
- package/src/resources/extensions/gsd/context-budget.ts +243 -0
- package/src/resources/extensions/gsd/context-store.ts +195 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +41 -3
- package/src/resources/extensions/gsd/db-writer.ts +341 -0
- package/src/resources/extensions/gsd/debug-logger.ts +178 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/src/resources/extensions/gsd/doctor.ts +283 -2
- package/src/resources/extensions/gsd/export.ts +81 -2
- package/src/resources/extensions/gsd/files.ts +39 -9
- package/src/resources/extensions/gsd/git-service.ts +6 -0
- package/src/resources/extensions/gsd/gsd-db.ts +752 -0
- package/src/resources/extensions/gsd/guided-flow.ts +26 -1
- package/src/resources/extensions/gsd/history.ts +0 -1
- package/src/resources/extensions/gsd/index.ts +277 -1
- package/src/resources/extensions/gsd/md-importer.ts +526 -0
- package/src/resources/extensions/gsd/metrics.ts +39 -3
- package/src/resources/extensions/gsd/notifications.ts +0 -1
- package/src/resources/extensions/gsd/post-unit-hooks.ts +70 -1
- package/src/resources/extensions/gsd/preferences.ts +125 -150
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/src/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/src/resources/extensions/gsd/prompts/system.md +2 -1
- package/src/resources/extensions/gsd/quick.ts +156 -0
- package/src/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/src/resources/extensions/gsd/skill-health.ts +417 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/src/resources/extensions/gsd/state.ts +30 -0
- package/src/resources/extensions/gsd/templates/preferences.md +1 -0
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/src/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +262 -1
- package/src/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/src/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +228 -5
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/src/resources/extensions/gsd/types.ts +29 -0
- package/src/resources/extensions/gsd/undo.ts +0 -1
- package/src/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +352 -1
- package/src/resources/extensions/gsd/visualizer-overlay.ts +166 -22
- package/src/resources/extensions/gsd/visualizer-views.ts +464 -2
- package/src/resources/extensions/gsd/worktree-command.ts +18 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/src/resources/extensions/remote-questions/config.ts +4 -2
- package/src/resources/extensions/remote-questions/discord-adapter.ts +2 -4
- package/src/resources/extensions/remote-questions/format.ts +154 -8
- package/src/resources/extensions/remote-questions/manager.ts +9 -7
- package/src/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/src/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/src/resources/extensions/remote-questions/types.ts +2 -1
- package/src/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/src/resources/extensions/voice/index.ts +4 -3
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for model config isolation between concurrent instances (#650).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { mkdirSync, writeFileSync, rmSync, existsSync, readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
|
|
11
|
+
// ─── Test helpers ─────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
function makeTmpDir(suffix: string): string {
|
|
14
|
+
const dir = join(tmpdir(), `gsd-test-650-${suffix}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
15
|
+
mkdirSync(dir, { recursive: true });
|
|
16
|
+
return dir;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ─── Settings Manager Model Scoping ───────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
describe("model config isolation (#650)", () => {
|
|
22
|
+
let tmpGlobal: string;
|
|
23
|
+
let tmpProjectA: string;
|
|
24
|
+
let tmpProjectB: string;
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
tmpGlobal = makeTmpDir("global");
|
|
28
|
+
tmpProjectA = makeTmpDir("project-a");
|
|
29
|
+
tmpProjectB = makeTmpDir("project-b");
|
|
30
|
+
// Create .pi directories for project settings
|
|
31
|
+
mkdirSync(join(tmpProjectA, ".pi"), { recursive: true });
|
|
32
|
+
mkdirSync(join(tmpProjectB, ".pi"), { recursive: true });
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
try { rmSync(tmpGlobal, { recursive: true, force: true }); } catch {}
|
|
37
|
+
try { rmSync(tmpProjectA, { recursive: true, force: true }); } catch {}
|
|
38
|
+
try { rmSync(tmpProjectB, { recursive: true, force: true }); } catch {}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("project settings file isolates model from global", async () => {
|
|
42
|
+
// Write project settings for project A
|
|
43
|
+
const projectSettingsPath = join(tmpProjectA, ".pi", "settings.json");
|
|
44
|
+
writeFileSync(projectSettingsPath, JSON.stringify({
|
|
45
|
+
defaultProvider: "anthropic",
|
|
46
|
+
defaultModel: "claude-opus-4-6",
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
// Write global settings with a different model
|
|
50
|
+
const globalSettingsPath = join(tmpGlobal, "settings.json");
|
|
51
|
+
writeFileSync(globalSettingsPath, JSON.stringify({
|
|
52
|
+
defaultProvider: "openai",
|
|
53
|
+
defaultModel: "gpt-5.4",
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
// Verify project settings exist and have independent data
|
|
57
|
+
const projectData = JSON.parse(readFileSync(projectSettingsPath, "utf-8"));
|
|
58
|
+
const globalData = JSON.parse(readFileSync(globalSettingsPath, "utf-8"));
|
|
59
|
+
|
|
60
|
+
assert.equal(projectData.defaultModel, "claude-opus-4-6");
|
|
61
|
+
assert.equal(globalData.defaultModel, "gpt-5.4");
|
|
62
|
+
assert.notEqual(projectData.defaultModel, globalData.defaultModel,
|
|
63
|
+
"Project and global should have different models");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("two projects have independent model configs", () => {
|
|
67
|
+
const settingsA = join(tmpProjectA, ".pi", "settings.json");
|
|
68
|
+
const settingsB = join(tmpProjectB, ".pi", "settings.json");
|
|
69
|
+
|
|
70
|
+
writeFileSync(settingsA, JSON.stringify({
|
|
71
|
+
defaultProvider: "anthropic",
|
|
72
|
+
defaultModel: "claude-opus-4-6",
|
|
73
|
+
}));
|
|
74
|
+
writeFileSync(settingsB, JSON.stringify({
|
|
75
|
+
defaultProvider: "openai-codex",
|
|
76
|
+
defaultModel: "gpt-5.4",
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
const dataA = JSON.parse(readFileSync(settingsA, "utf-8"));
|
|
80
|
+
const dataB = JSON.parse(readFileSync(settingsB, "utf-8"));
|
|
81
|
+
|
|
82
|
+
assert.equal(dataA.defaultModel, "claude-opus-4-6");
|
|
83
|
+
assert.equal(dataB.defaultModel, "gpt-5.4");
|
|
84
|
+
assert.notEqual(dataA.defaultProvider, dataB.defaultProvider);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("autoModeStartModel concept prevents model drift", () => {
|
|
88
|
+
// Simulate the auto-mode start model capture pattern
|
|
89
|
+
const autoModeStartModel = { provider: "anthropic", id: "claude-opus-4-6" };
|
|
90
|
+
|
|
91
|
+
// Simulate another instance writing to global settings
|
|
92
|
+
const globalSettings = { defaultProvider: "openai-codex", defaultModel: "gpt-5.4" };
|
|
93
|
+
|
|
94
|
+
// The captured model should be used, not the global settings
|
|
95
|
+
assert.notEqual(autoModeStartModel.id, globalSettings.defaultModel);
|
|
96
|
+
assert.equal(autoModeStartModel.id, "claude-opus-4-6",
|
|
97
|
+
"Captured model should be preserved regardless of global settings changes");
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -1661,4 +1661,44 @@ console.log('\n=== LLM round-trip: extra blank lines ===');
|
|
|
1661
1661
|
assertTrue(consecutiveBlanks === null, 'blank-lines: formatted output has no 4+ consecutive newlines');
|
|
1662
1662
|
}
|
|
1663
1663
|
|
|
1664
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1665
|
+
// parseRoadmap: boundary map with embedded code fences (#468)
|
|
1666
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1667
|
+
|
|
1668
|
+
console.log('\n=== parseRoadmap: boundary map with code fences (#468) ===');
|
|
1669
|
+
{
|
|
1670
|
+
const content = `# M001: Test
|
|
1671
|
+
|
|
1672
|
+
**Vision:** Test
|
|
1673
|
+
|
|
1674
|
+
## Slices
|
|
1675
|
+
|
|
1676
|
+
- [ ] **S01: Core** \`risk:low\` \`depends:[]\`
|
|
1677
|
+
- [ ] **S02: API** \`risk:low\` \`depends:[S01]\`
|
|
1678
|
+
|
|
1679
|
+
## Boundary Map
|
|
1680
|
+
|
|
1681
|
+
### S01 → S02
|
|
1682
|
+
|
|
1683
|
+
Produces:
|
|
1684
|
+
types.ts — all types
|
|
1685
|
+
\`\`\`
|
|
1686
|
+
const x = 1;
|
|
1687
|
+
\`\`\`
|
|
1688
|
+
|
|
1689
|
+
Consumes: nothing
|
|
1690
|
+
`;
|
|
1691
|
+
|
|
1692
|
+
// This test ensures the boundary map parser does not hang or
|
|
1693
|
+
// catastrophically backtrack when content contains code fences.
|
|
1694
|
+
const start = Date.now();
|
|
1695
|
+
const r = parseRoadmap(content);
|
|
1696
|
+
const elapsed = Date.now() - start;
|
|
1697
|
+
|
|
1698
|
+
assertTrue(elapsed < 1000, `boundary map with code fences parsed in ${elapsed}ms (should be < 1s)`);
|
|
1699
|
+
assertEq(r.slices.length, 2, 'code-fence roadmap: slice count');
|
|
1700
|
+
// Boundary map should still parse (may not capture perfectly with code fences, but must not hang)
|
|
1701
|
+
assertTrue(r.boundaryMap.length >= 0, 'code-fence roadmap: boundary map parsed without hanging');
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1664
1704
|
report();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// GSD Extension — Hook Engine Tests (Post-Unit, Pre-Dispatch, State Persistence)
|
|
2
|
-
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
2
|
|
|
4
3
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync, readFileSync } from "node:fs";
|
|
5
4
|
import { join } from "node:path";
|
|
@@ -18,6 +17,7 @@ import {
|
|
|
18
17
|
clearPersistedHookState,
|
|
19
18
|
getHookStatus,
|
|
20
19
|
formatHookStatus,
|
|
20
|
+
triggerHookManually,
|
|
21
21
|
} from "../post-unit-hooks.ts";
|
|
22
22
|
|
|
23
23
|
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
@@ -294,4 +294,44 @@ console.log("\n=== Hook status: no hooks ===");
|
|
|
294
294
|
assertMatch(formatted, /No hooks configured/, "status message says no hooks");
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
298
|
+
// Phase 4: Manual Hook Trigger Tests
|
|
299
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
300
|
+
|
|
301
|
+
console.log("\n=== triggerHookManually: hook not found ===");
|
|
302
|
+
|
|
303
|
+
{
|
|
304
|
+
resetHookState();
|
|
305
|
+
const base = createFixtureBase();
|
|
306
|
+
try {
|
|
307
|
+
const result = triggerHookManually("nonexistent-hook", "execute-task", "M001/S01/T01", base);
|
|
308
|
+
assertEq(result, null, "returns null when hook not found");
|
|
309
|
+
} finally {
|
|
310
|
+
rmSync(base, { recursive: true, force: true });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
console.log("\n=== triggerHookManually: with configured hook ===");
|
|
315
|
+
|
|
316
|
+
{
|
|
317
|
+
resetHookState();
|
|
318
|
+
const base = createFixtureBase();
|
|
319
|
+
try {
|
|
320
|
+
// This test will work when preferences are configured
|
|
321
|
+
// For now, just verify the function exists and handles missing hooks
|
|
322
|
+
const result = triggerHookManually("code-review", "execute-task", "M001/S01/T01", base);
|
|
323
|
+
// Result depends on whether code-review hook is configured in preferences
|
|
324
|
+
// The function should either return null or a valid HookDispatchResult
|
|
325
|
+
assertTrue(result === null || typeof result === "object", "returns null or object");
|
|
326
|
+
if (result) {
|
|
327
|
+
assertEq(result.hookName, "code-review", "hook name in result");
|
|
328
|
+
assertEq(result.unitType, "hook/code-review", "unit type is hook-prefixed");
|
|
329
|
+
assertEq(result.unitId, "M001/S01/T01", "unit ID preserved");
|
|
330
|
+
assertTrue(typeof result.prompt === "string", "prompt is a string");
|
|
331
|
+
}
|
|
332
|
+
} finally {
|
|
333
|
+
rmSync(base, { recursive: true, force: true });
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
297
337
|
report();
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// GSD Workflow Mode Tests — validates mode defaults, overrides, and validation
|
|
2
|
+
|
|
3
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
4
|
+
import { validatePreferences, applyModeDefaults } from "../preferences.ts";
|
|
5
|
+
import type { GSDPreferences } from "../preferences.ts";
|
|
6
|
+
|
|
7
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
8
|
+
|
|
9
|
+
async function main(): Promise<void> {
|
|
10
|
+
console.log("\n=== mode: solo defaults ===");
|
|
11
|
+
|
|
12
|
+
{
|
|
13
|
+
const prefs: GSDPreferences = { mode: "solo" };
|
|
14
|
+
const result = applyModeDefaults("solo", prefs);
|
|
15
|
+
assertEq(result.git?.auto_push, true, "solo — auto_push defaults to true");
|
|
16
|
+
assertEq(result.git?.push_branches, false, "solo — push_branches defaults to false");
|
|
17
|
+
assertEq(result.git?.pre_merge_check, false, "solo — pre_merge_check defaults to false");
|
|
18
|
+
assertEq(result.git?.merge_strategy, "squash", "solo — merge_strategy defaults to squash");
|
|
19
|
+
assertEq(result.git?.isolation, "worktree", "solo — isolation defaults to worktree");
|
|
20
|
+
assertEq(result.git?.commit_docs, true, "solo — commit_docs defaults to true");
|
|
21
|
+
assertEq(result.unique_milestone_ids, false, "solo — unique_milestone_ids defaults to false");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log("\n=== mode: team defaults ===");
|
|
25
|
+
|
|
26
|
+
{
|
|
27
|
+
const prefs: GSDPreferences = { mode: "team" };
|
|
28
|
+
const result = applyModeDefaults("team", prefs);
|
|
29
|
+
assertEq(result.git?.auto_push, false, "team — auto_push defaults to false");
|
|
30
|
+
assertEq(result.git?.push_branches, true, "team — push_branches defaults to true");
|
|
31
|
+
assertEq(result.git?.pre_merge_check, true, "team — pre_merge_check defaults to true");
|
|
32
|
+
assertEq(result.git?.merge_strategy, "squash", "team — merge_strategy defaults to squash");
|
|
33
|
+
assertEq(result.git?.isolation, "worktree", "team — isolation defaults to worktree");
|
|
34
|
+
assertEq(result.git?.commit_docs, true, "team — commit_docs defaults to true");
|
|
35
|
+
assertEq(result.unique_milestone_ids, true, "team — unique_milestone_ids defaults to true");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log("\n=== explicit override wins over mode default ===");
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
const prefs: GSDPreferences = {
|
|
42
|
+
mode: "solo",
|
|
43
|
+
git: { auto_push: false },
|
|
44
|
+
};
|
|
45
|
+
const result = applyModeDefaults("solo", prefs);
|
|
46
|
+
assertEq(result.git?.auto_push, false, "solo + explicit auto_push=false — override wins");
|
|
47
|
+
assertEq(result.git?.push_branches, false, "solo + override — other defaults still apply");
|
|
48
|
+
assertEq(result.git?.merge_strategy, "squash", "solo + override — merge_strategy still defaults");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log("\n=== no mode set — no defaults injected ===");
|
|
52
|
+
|
|
53
|
+
{
|
|
54
|
+
const prefs: GSDPreferences = { git: { auto_push: true } };
|
|
55
|
+
const { preferences } = validatePreferences(prefs);
|
|
56
|
+
assertEq(preferences.mode, undefined, "no mode — mode is undefined");
|
|
57
|
+
assertEq(preferences.git?.push_branches, undefined, "no mode — push_branches not injected");
|
|
58
|
+
assertEq(preferences.unique_milestone_ids, undefined, "no mode — unique_milestone_ids not injected");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log("\n=== invalid mode value → validation error ===");
|
|
62
|
+
|
|
63
|
+
{
|
|
64
|
+
const { errors } = validatePreferences({ mode: "invalid" as any });
|
|
65
|
+
assertTrue(errors.length > 0, "invalid mode — produces error");
|
|
66
|
+
assertTrue(errors[0].includes("solo, team"), "invalid mode — error mentions valid values");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log("\n=== valid mode values pass validation ===");
|
|
70
|
+
|
|
71
|
+
{
|
|
72
|
+
const { errors: soloErrors, preferences: soloPrefs } = validatePreferences({ mode: "solo" });
|
|
73
|
+
assertEq(soloErrors.length, 0, "mode: solo — no errors");
|
|
74
|
+
assertEq(soloPrefs.mode, "solo", "mode: solo — value preserved");
|
|
75
|
+
}
|
|
76
|
+
{
|
|
77
|
+
const { errors: teamErrors, preferences: teamPrefs } = validatePreferences({ mode: "team" });
|
|
78
|
+
assertEq(teamErrors.length, 0, "mode: team — no errors");
|
|
79
|
+
assertEq(teamPrefs.mode, "team", "mode: team — value preserved");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log("\n=== deep merge: mode + explicit git.remote ===");
|
|
83
|
+
|
|
84
|
+
{
|
|
85
|
+
const prefs: GSDPreferences = {
|
|
86
|
+
mode: "team",
|
|
87
|
+
git: { remote: "upstream" },
|
|
88
|
+
};
|
|
89
|
+
const result = applyModeDefaults("team", prefs);
|
|
90
|
+
assertEq(result.git?.remote, "upstream", "team + git.remote — custom remote preserved");
|
|
91
|
+
assertEq(result.git?.auto_push, false, "team + git.remote — team auto_push default applied");
|
|
92
|
+
assertEq(result.git?.push_branches, true, "team + git.remote — team push_branches default applied");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log("\n=== mode + unique_milestone_ids explicit override ===");
|
|
96
|
+
|
|
97
|
+
{
|
|
98
|
+
const prefs: GSDPreferences = {
|
|
99
|
+
mode: "team",
|
|
100
|
+
unique_milestone_ids: false,
|
|
101
|
+
};
|
|
102
|
+
const result = applyModeDefaults("team", prefs);
|
|
103
|
+
assertEq(result.unique_milestone_ids, false, "team + explicit unique_milestone_ids=false — override wins");
|
|
104
|
+
assertEq(result.git?.push_branches, true, "team + override — other team defaults still apply");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
report();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
main();
|