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
|
@@ -29,7 +29,11 @@ const worktreePromptsDir = join(__dirname, '..', 'prompts');
|
|
|
29
29
|
function loadPromptFromWorktree(name: string, vars: Record<string, string> = {}): string {
|
|
30
30
|
const path = join(worktreePromptsDir, `${name}.md`);
|
|
31
31
|
let content = readFileSync(path, 'utf-8');
|
|
32
|
-
|
|
32
|
+
const effectiveVars = {
|
|
33
|
+
skillActivation: 'If no installed skill clearly matches this unit, skip explicit skill activation and continue with the required workflow.',
|
|
34
|
+
...vars,
|
|
35
|
+
};
|
|
36
|
+
for (const [key, value] of Object.entries(effectiveVars)) {
|
|
33
37
|
content = content.replaceAll(`{{${key}}}`, value);
|
|
34
38
|
}
|
|
35
39
|
return content.trim();
|
|
@@ -210,7 +214,7 @@ async function main(): Promise<void> {
|
|
|
210
214
|
const sliceId = 'S01';
|
|
211
215
|
const uatPath = '.gsd/milestones/M001/slices/S01/S01-UAT.md';
|
|
212
216
|
const uatResultPath = '.gsd/milestones/M001/slices/S01/S01-UAT-RESULT.md';
|
|
213
|
-
const uatType = '
|
|
217
|
+
const uatType = 'live-runtime';
|
|
214
218
|
const inlinedContext = '<!-- no context -->';
|
|
215
219
|
|
|
216
220
|
let promptResult: string | undefined;
|
|
@@ -246,13 +250,21 @@ async function main(): Promise<void> {
|
|
|
246
250
|
promptResult?.includes(uatResultPath) ?? false,
|
|
247
251
|
`prompt contains uatResultPath value after substitution`,
|
|
248
252
|
);
|
|
253
|
+
assertTrue(
|
|
254
|
+
promptResult?.includes(`Detected UAT mode:** \`${uatType}\``) ?? false,
|
|
255
|
+
`prompt contains detected dynamic uatType value "${uatType}" after substitution`,
|
|
256
|
+
);
|
|
257
|
+
assertTrue(
|
|
258
|
+
promptResult?.includes(`uatType: ${uatType}`) ?? false,
|
|
259
|
+
`prompt contains dynamic uatType frontmatter value "${uatType}" after substitution`,
|
|
260
|
+
);
|
|
249
261
|
assertTrue(
|
|
250
262
|
!/\{\{[^}]+\}\}/.test(promptResult ?? ''),
|
|
251
263
|
'no unreplaced {{...}} tokens remain after variable substitution',
|
|
252
264
|
);
|
|
253
265
|
assertTrue(
|
|
254
|
-
/
|
|
255
|
-
'prompt contains
|
|
266
|
+
/browser|runtime|execute|run/i.test(promptResult ?? ''),
|
|
267
|
+
'prompt contains runtime execution language (browser/runtime/execute/run)',
|
|
256
268
|
);
|
|
257
269
|
assertTrue(
|
|
258
270
|
!/surfaced for human review/i.test(promptResult ?? ''),
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { loadSkills } from "@gsd/pi-coding-agent";
|
|
7
|
+
import { buildSkillActivationBlock } from "../auto-prompts.js";
|
|
8
|
+
import type { GSDPreferences } from "../preferences.js";
|
|
9
|
+
|
|
10
|
+
function makeTempBase(): string {
|
|
11
|
+
return mkdtempSync(join(tmpdir(), "gsd-skill-activation-"));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function cleanup(base: string): void {
|
|
15
|
+
rmSync(base, { recursive: true, force: true });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function writeSkill(base: string, name: string, description: string): void {
|
|
19
|
+
const dir = join(base, "skills", name);
|
|
20
|
+
mkdirSync(dir, { recursive: true });
|
|
21
|
+
writeFileSync(join(dir, "SKILL.md"), `---\nname: ${name}\ndescription: ${description}\n---\n\n# ${name}\n`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function loadOnlyTestSkills(base: string): void {
|
|
25
|
+
loadSkills({ cwd: base, includeDefaults: false, skillPaths: [join(base, "skills")] });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function buildBlock(
|
|
29
|
+
base: string,
|
|
30
|
+
params: Partial<Parameters<typeof buildSkillActivationBlock>[0]> = {},
|
|
31
|
+
preferences: GSDPreferences = {},
|
|
32
|
+
): string {
|
|
33
|
+
return buildSkillActivationBlock({
|
|
34
|
+
base,
|
|
35
|
+
milestoneId: "M001",
|
|
36
|
+
sliceId: "S01",
|
|
37
|
+
...params,
|
|
38
|
+
preferences,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
test("buildSkillActivationBlock matches installed skills from task context", () => {
|
|
43
|
+
const base = makeTempBase();
|
|
44
|
+
try {
|
|
45
|
+
writeSkill(base, "react", "Use for React components, hooks, JSX, and frontend UI work.");
|
|
46
|
+
writeSkill(base, "swiftui", "Use for SwiftUI views, iOS layout, and Apple platform UI work.");
|
|
47
|
+
loadOnlyTestSkills(base);
|
|
48
|
+
|
|
49
|
+
const result = buildBlock(base, {
|
|
50
|
+
sliceTitle: "Build React dashboard",
|
|
51
|
+
taskId: "T01",
|
|
52
|
+
taskTitle: "Implement React settings panel",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
assert.match(result, /<skill_activation>/);
|
|
56
|
+
assert.match(result, /Call Skill\('react'\)/);
|
|
57
|
+
assert.doesNotMatch(result, /swiftui/);
|
|
58
|
+
} finally {
|
|
59
|
+
cleanup(base);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("buildSkillActivationBlock includes always_use_skills from preferences", () => {
|
|
64
|
+
const base = makeTempBase();
|
|
65
|
+
try {
|
|
66
|
+
writeSkill(base, "testing", "Use for test setup, assertions, and verification patterns.");
|
|
67
|
+
loadOnlyTestSkills(base);
|
|
68
|
+
|
|
69
|
+
const result = buildBlock(base, { taskTitle: "Unrelated task title" }, {
|
|
70
|
+
always_use_skills: ["testing"],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
assert.match(result, /Call Skill\('testing'\)/);
|
|
74
|
+
} finally {
|
|
75
|
+
cleanup(base);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("buildSkillActivationBlock includes skill_rules matches and task-plan skills_used", () => {
|
|
80
|
+
const base = makeTempBase();
|
|
81
|
+
try {
|
|
82
|
+
writeSkill(base, "prisma", "Use for Prisma schema, migrations, and ORM queries.");
|
|
83
|
+
writeSkill(base, "accessibility", "Use for accessibility, aria attributes, and keyboard support.");
|
|
84
|
+
loadOnlyTestSkills(base);
|
|
85
|
+
|
|
86
|
+
const taskPlan = [
|
|
87
|
+
"---",
|
|
88
|
+
"skills_used:",
|
|
89
|
+
" - accessibility",
|
|
90
|
+
"---",
|
|
91
|
+
"# T01: Example",
|
|
92
|
+
].join("\n");
|
|
93
|
+
|
|
94
|
+
const result = buildBlock(base, {
|
|
95
|
+
taskTitle: "Update prisma schema",
|
|
96
|
+
taskPlanContent: taskPlan,
|
|
97
|
+
}, {
|
|
98
|
+
skill_rules: [{ when: "prisma database schema", use: ["prisma"] }],
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
assert.match(result, /Call Skill\('accessibility'\)/);
|
|
102
|
+
assert.match(result, /Call Skill\('prisma'\)/);
|
|
103
|
+
} finally {
|
|
104
|
+
cleanup(base);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("buildSkillActivationBlock honors avoid_skills", () => {
|
|
109
|
+
const base = makeTempBase();
|
|
110
|
+
try {
|
|
111
|
+
writeSkill(base, "react", "Use for React components and frontend UI work.");
|
|
112
|
+
loadOnlyTestSkills(base);
|
|
113
|
+
|
|
114
|
+
const result = buildBlock(base, {
|
|
115
|
+
taskTitle: "Implement React settings panel",
|
|
116
|
+
}, {
|
|
117
|
+
avoid_skills: ["react"],
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
assert.equal(result, "");
|
|
121
|
+
} finally {
|
|
122
|
+
cleanup(base);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("buildSkillActivationBlock falls back cleanly when nothing matches", () => {
|
|
127
|
+
const base = makeTempBase();
|
|
128
|
+
try {
|
|
129
|
+
writeSkill(base, "swiftui", "Use for SwiftUI apps.");
|
|
130
|
+
loadOnlyTestSkills(base);
|
|
131
|
+
|
|
132
|
+
const result = buildBlock(base, {
|
|
133
|
+
taskTitle: "Plain text docs task",
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
assert.equal(result, "");
|
|
137
|
+
} finally {
|
|
138
|
+
cleanup(base);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
@@ -61,6 +61,16 @@ export interface TaskPlanEntry {
|
|
|
61
61
|
verify?: string; // e.g. "run tests" — extracted from "- Verify:" subline
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
export interface TaskPlanFrontmatter {
|
|
65
|
+
estimated_steps?: number; // optional scope estimate for plan quality validator
|
|
66
|
+
estimated_files?: number; // optional file-count estimate for scope warning heuristics
|
|
67
|
+
skills_used: string[]; // installed skill slugs/names to hand off to execute-task prompts
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface TaskPlanFile {
|
|
71
|
+
frontmatter: TaskPlanFrontmatter;
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
// ─── Verification Gate ─────────────────────────────────────────────────────
|
|
65
75
|
|
|
66
76
|
/** Result of a single verification command execution */
|
|
@@ -423,7 +433,6 @@ export interface Requirement {
|
|
|
423
433
|
|
|
424
434
|
// ─── Parallel Orchestration Types ────────────────────────────────────────
|
|
425
435
|
|
|
426
|
-
export type CompressionStrategy = "truncate" | "compress";
|
|
427
436
|
export type ContextSelectionMode = "full" | "smart";
|
|
428
437
|
|
|
429
438
|
export type MergeStrategy = "per-slice" | "per-milestone";
|
|
@@ -479,3 +488,11 @@ export interface ReactiveExecutionState {
|
|
|
479
488
|
};
|
|
480
489
|
updatedAt: string;
|
|
481
490
|
}
|
|
491
|
+
|
|
492
|
+
export interface BrowserFlowResult {
|
|
493
|
+
url: string;
|
|
494
|
+
passed: boolean;
|
|
495
|
+
checksTotal: number;
|
|
496
|
+
checksPassed: number;
|
|
497
|
+
duration: number;
|
|
498
|
+
}
|
|
@@ -37,6 +37,21 @@ export interface AuditWarningJSON {
|
|
|
37
37
|
fixAvailable: boolean;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export interface BrowserEvidenceCheckJSON {
|
|
41
|
+
description: string;
|
|
42
|
+
passed: boolean;
|
|
43
|
+
actual?: string;
|
|
44
|
+
evidence?: string;
|
|
45
|
+
error?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface BrowserEvidenceJSON {
|
|
49
|
+
url: string;
|
|
50
|
+
passed: boolean;
|
|
51
|
+
checks: BrowserEvidenceCheckJSON[];
|
|
52
|
+
duration: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
40
55
|
export interface EvidenceJSON {
|
|
41
56
|
schemaVersion: 1;
|
|
42
57
|
taskId: string;
|
|
@@ -49,6 +64,7 @@ export interface EvidenceJSON {
|
|
|
49
64
|
maxRetries?: number;
|
|
50
65
|
runtimeErrors?: RuntimeErrorJSON[];
|
|
51
66
|
auditWarnings?: AuditWarningJSON[];
|
|
67
|
+
browser?: BrowserEvidenceJSON;
|
|
52
68
|
}
|
|
53
69
|
|
|
54
70
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
4
4
|
import { deriveState } from './state.js';
|
|
5
5
|
import { parseRoadmap, parsePlan, parseSummary, loadFile } from './files.js';
|
|
6
|
-
import { findMilestoneIds } from './
|
|
6
|
+
import { findMilestoneIds } from './milestone-ids.js';
|
|
7
7
|
import { resolveMilestoneFile, resolveSliceFile, resolveGsdRootFile } from './paths.js';
|
|
8
8
|
import {
|
|
9
9
|
getLedger,
|
|
@@ -114,6 +114,22 @@ function getServerConfig(name: string): McpServerConfig | undefined {
|
|
|
114
114
|
return readConfigs().find((s) => s.name === name);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/** Resolve ${VAR} references in env values against process.env. */
|
|
118
|
+
function resolveEnv(env: Record<string, string>): Record<string, string> {
|
|
119
|
+
const resolved: Record<string, string> = {};
|
|
120
|
+
for (const [key, value] of Object.entries(env)) {
|
|
121
|
+
if (typeof value === "string") {
|
|
122
|
+
resolved[key] = value.replace(
|
|
123
|
+
/\$\{([^}]+)\}/g,
|
|
124
|
+
(_match, varName) => process.env[varName] ?? "",
|
|
125
|
+
);
|
|
126
|
+
} else {
|
|
127
|
+
resolved[key] = value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return resolved;
|
|
131
|
+
}
|
|
132
|
+
|
|
117
133
|
async function getOrConnect(name: string, signal?: AbortSignal): Promise<Client> {
|
|
118
134
|
const existing = connections.get(name);
|
|
119
135
|
if (existing) return existing.client;
|
|
@@ -128,7 +144,7 @@ async function getOrConnect(name: string, signal?: AbortSignal): Promise<Client>
|
|
|
128
144
|
transport = new StdioClientTransport({
|
|
129
145
|
command: config.command,
|
|
130
146
|
args: config.args,
|
|
131
|
-
env: config.env ? { ...process.env, ...config.env } as Record<string, string> : undefined,
|
|
147
|
+
env: config.env ? { ...process.env, ...resolveEnv(config.env) } as Record<string, string> : undefined,
|
|
132
148
|
cwd: config.cwd,
|
|
133
149
|
stderr: "pipe",
|
|
134
150
|
});
|
|
@@ -7,6 +7,10 @@ import { join } from "node:path";
|
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { readPromptRecord } from "./store.js";
|
|
9
9
|
|
|
10
|
+
function getGsdHome(): string {
|
|
11
|
+
return process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
export interface LatestPromptSummary {
|
|
11
15
|
id: string;
|
|
12
16
|
status: string;
|
|
@@ -14,7 +18,7 @@ export interface LatestPromptSummary {
|
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export function getLatestPromptSummary(): LatestPromptSummary | null {
|
|
17
|
-
const runtimeDir = join(
|
|
21
|
+
const runtimeDir = join(getGsdHome(), "runtime", "remote-questions");
|
|
18
22
|
if (!existsSync(runtimeDir)) return null;
|
|
19
23
|
const files = readdirSync(runtimeDir).filter((f) => f.endsWith(".json"));
|
|
20
24
|
if (files.length === 0) return null;
|
|
@@ -7,8 +7,12 @@ import { join } from "node:path";
|
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import type { RemotePrompt, RemotePromptRecord, RemotePromptRef, RemoteAnswer, RemotePromptStatus } from "./types.js";
|
|
9
9
|
|
|
10
|
+
function getGsdHome(): string {
|
|
11
|
+
return process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
function runtimeDir(): string {
|
|
11
|
-
return join(
|
|
15
|
+
return join(getGsdHome(), "runtime", "remote-questions");
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
function recordPath(id: string): string {
|
|
@@ -17,7 +17,8 @@ import { resolveSearchProviderFromPreferences } from '../gsd/preferences.js'
|
|
|
17
17
|
// Compute authFilePath locally instead of importing from app-paths.ts,
|
|
18
18
|
// because extensions are copied to ~/.gsd/agent/extensions/ at runtime
|
|
19
19
|
// where the relative import '../../../app-paths.ts' doesn't resolve.
|
|
20
|
-
const
|
|
20
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), '.gsd')
|
|
21
|
+
const authFilePath = join(gsdHome, 'agent', 'auth.json')
|
|
21
22
|
|
|
22
23
|
export type SearchProvider = 'tavily' | 'brave' | 'ollama'
|
|
23
24
|
export type SearchProviderPreference = SearchProvider | 'auto'
|
|
@@ -50,7 +50,7 @@ export function parseFrontmatterMap(lines: string[]): Record<string, unknown> {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// Array item (2-space indent)
|
|
53
|
-
const arrayMatch = line.match(/^ - (.*)$/);
|
|
53
|
+
const arrayMatch = line.match(/^ - ?(.*)$/);
|
|
54
54
|
if (arrayMatch && currentKey) {
|
|
55
55
|
// If there's a pending nested object, push it
|
|
56
56
|
if (currentObj && Object.keys(currentObj).length > 0) {
|
|
@@ -57,8 +57,10 @@ function encodeCwd(cwd: string): string {
|
|
|
57
57
|
return cwd.replace(/\//g, "--");
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
const gsdHome = process.env.GSD_HOME || path.join(os.homedir(), ".gsd");
|
|
61
|
+
|
|
60
62
|
function getIsolationBaseDir(cwd: string, taskId: string): string {
|
|
61
|
-
return path.join(
|
|
63
|
+
return path.join(gsdHome, "wt", encodeCwd(cwd), taskId);
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
// Track active isolation dirs for cleanup on exit
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
import { readdirSync, readFileSync, existsSync } from "node:fs";
|
|
9
9
|
import { join, basename } from "node:path";
|
|
10
10
|
import { homedir } from "node:os";
|
|
11
|
+
|
|
12
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
11
13
|
import type { Rule } from "./ttsr-manager.js";
|
|
12
14
|
import { splitFrontmatter, parseFrontmatterMap } from "../shared/frontmatter.js";
|
|
13
15
|
|
|
@@ -59,7 +61,7 @@ function scanDir(dir: string): Rule[] {
|
|
|
59
61
|
* Project rules override global rules with the same name.
|
|
60
62
|
*/
|
|
61
63
|
export function loadRules(cwd: string): Rule[] {
|
|
62
|
-
const globalDir = join(
|
|
64
|
+
const globalDir = join(gsdHome, "agent", "rules");
|
|
63
65
|
const projectDir = join(cwd, ".gsd", "rules");
|
|
64
66
|
|
|
65
67
|
const globalRules = scanDir(globalDir);
|