gsd-pi 2.35.0-dev.30eec3f → 2.35.0-dev.640d5c7
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/dist/cli.js +2 -7
- package/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +1 -13
- package/dist/resources/extensions/async-jobs/await-tool.js +2 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +6 -0
- package/dist/resources/extensions/bg-shell/output-formatter.js +19 -1
- package/dist/resources/extensions/bg-shell/process-manager.js +4 -0
- package/dist/resources/extensions/bg-shell/types.js +2 -0
- package/dist/resources/extensions/context7/index.js +0 -5
- package/dist/resources/extensions/get-secrets-from-user.js +30 -2
- package/dist/resources/extensions/google-search/index.js +0 -5
- package/dist/resources/extensions/gsd/auto-dispatch.js +1 -43
- package/dist/resources/extensions/gsd/auto-loop.js +1 -10
- package/dist/resources/extensions/gsd/auto-recovery.js +0 -35
- package/dist/resources/extensions/gsd/auto-start.js +2 -35
- package/dist/resources/extensions/gsd/auto.js +4 -59
- package/dist/resources/extensions/gsd/commands-handlers.js +2 -2
- package/dist/resources/extensions/gsd/doctor-environment.js +17 -26
- package/dist/resources/extensions/gsd/files.js +1 -9
- package/dist/resources/extensions/gsd/gitignore.js +7 -54
- package/dist/resources/extensions/gsd/guided-flow.js +1 -1
- package/dist/resources/extensions/gsd/health-widget.js +46 -97
- package/dist/resources/extensions/gsd/index.js +1 -10
- package/dist/resources/extensions/gsd/migrate-external.js +2 -55
- package/dist/resources/extensions/gsd/paths.js +7 -74
- package/dist/resources/extensions/gsd/post-unit-hooks.js +1 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +1 -16
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +0 -2
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +0 -2
- package/dist/resources/extensions/gsd/session-lock.js +2 -26
- package/dist/resources/extensions/gsd/templates/plan.md +0 -8
- package/dist/resources/extensions/gsd/worktree-resolver.js +0 -12
- package/dist/resources/extensions/remote-questions/remote-command.js +22 -2
- package/dist/resources/extensions/shared/mod.js +1 -1
- package/dist/resources/extensions/shared/sanitize.js +0 -30
- package/dist/resources/extensions/shared/wizard-ui.js +478 -0
- package/dist/resources/extensions/subagent/index.js +14 -6
- package/package.json +1 -2
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +2 -13
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/src/core/resource-loader.ts +2 -13
- package/src/resources/extensions/async-jobs/await-tool.ts +2 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +7 -0
- package/src/resources/extensions/bg-shell/output-formatter.ts +17 -0
- package/src/resources/extensions/bg-shell/process-manager.ts +4 -0
- package/src/resources/extensions/bg-shell/types.ts +12 -0
- package/src/resources/extensions/context7/index.ts +0 -7
- package/src/resources/extensions/get-secrets-from-user.ts +35 -2
- package/src/resources/extensions/google-search/index.ts +0 -7
- package/src/resources/extensions/gsd/auto-dispatch.ts +1 -49
- package/src/resources/extensions/gsd/auto-loop.ts +1 -11
- package/src/resources/extensions/gsd/auto-recovery.ts +0 -39
- package/src/resources/extensions/gsd/auto-start.ts +2 -42
- package/src/resources/extensions/gsd/auto.ts +3 -61
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -2
- package/src/resources/extensions/gsd/doctor-environment.ts +16 -26
- package/src/resources/extensions/gsd/files.ts +1 -10
- package/src/resources/extensions/gsd/gitignore.ts +7 -54
- package/src/resources/extensions/gsd/guided-flow.ts +1 -1
- package/src/resources/extensions/gsd/health-widget.ts +59 -103
- package/src/resources/extensions/gsd/index.ts +1 -10
- package/src/resources/extensions/gsd/migrate-external.ts +2 -47
- package/src/resources/extensions/gsd/paths.ts +7 -73
- package/src/resources/extensions/gsd/post-unit-hooks.ts +1 -5
- package/src/resources/extensions/gsd/preferences-validation.ts +1 -16
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +0 -2
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +0 -2
- package/src/resources/extensions/gsd/session-lock.ts +2 -29
- package/src/resources/extensions/gsd/templates/plan.md +0 -8
- package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -12
- package/src/resources/extensions/gsd/tests/validate-directory.test.ts +0 -15
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +0 -2
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +0 -32
- package/src/resources/extensions/gsd/worktree-resolver.ts +0 -11
- package/src/resources/extensions/remote-questions/remote-command.ts +23 -2
- package/src/resources/extensions/shared/mod.ts +1 -1
- package/src/resources/extensions/shared/sanitize.ts +0 -36
- package/src/resources/extensions/shared/wizard-ui.ts +551 -0
- package/src/resources/extensions/subagent/index.ts +12 -6
- package/dist/resources/extensions/gsd/health-widget-core.js +0 -96
- package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -55
- package/src/resources/extensions/gsd/health-widget-core.ts +0 -129
- package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -66
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +0 -214
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +0 -158
- package/src/resources/extensions/gsd/tests/paths.test.ts +0 -113
- package/src/resources/extensions/gsd/tests/test-utils.ts +0 -165
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync, mkdirSync, rmSync, realpathSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { spawnSync } from "node:child_process";
|
|
5
|
-
|
|
6
|
-
import { gsdRoot, _clearGsdRootCache } from "../paths.ts";
|
|
7
|
-
import { createTestContext } from "./test-helpers.ts";
|
|
8
|
-
|
|
9
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
10
|
-
|
|
11
|
-
/** Create a tmp dir and resolve symlinks + 8.3 short names (macOS /var→/private/var, Windows RUNNER~1→runneradmin). */
|
|
12
|
-
function tmp(): string {
|
|
13
|
-
const p = mkdtempSync(join(tmpdir(), "gsd-paths-test-"));
|
|
14
|
-
try { return realpathSync.native(p); } catch { return p; }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function cleanup(dir: string): void {
|
|
18
|
-
try { rmSync(dir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function initGit(dir: string): void {
|
|
22
|
-
spawnSync("git", ["init"], { cwd: dir });
|
|
23
|
-
spawnSync("git", ["commit", "--allow-empty", "-m", "init"], { cwd: dir });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// ── tests ──────────────────────────────────────────────────────────────────
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
// Case 1: .gsd exists at basePath — fast path
|
|
30
|
-
const root = tmp();
|
|
31
|
-
try {
|
|
32
|
-
mkdirSync(join(root, ".gsd"));
|
|
33
|
-
_clearGsdRootCache();
|
|
34
|
-
const result = gsdRoot(root);
|
|
35
|
-
assertEq(result, join(root, ".gsd"), "fast path: returns basePath/.gsd");
|
|
36
|
-
} finally { cleanup(root); }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
// Case 2: .gsd exists at git root, cwd is a subdirectory
|
|
41
|
-
const root = tmp();
|
|
42
|
-
try {
|
|
43
|
-
initGit(root);
|
|
44
|
-
mkdirSync(join(root, ".gsd"));
|
|
45
|
-
const sub = join(root, "src", "deep");
|
|
46
|
-
mkdirSync(sub, { recursive: true });
|
|
47
|
-
_clearGsdRootCache();
|
|
48
|
-
const result = gsdRoot(sub);
|
|
49
|
-
assertEq(result, join(root, ".gsd"), "git-root probe: finds .gsd at git root from subdirectory");
|
|
50
|
-
} finally { cleanup(root); }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
// Case 3: .gsd in an ancestor — walk-up finds it (git repo with no .gsd at root)
|
|
55
|
-
const root = tmp();
|
|
56
|
-
try {
|
|
57
|
-
// Init a git repo so git probe returns root — but put .gsd one level deeper
|
|
58
|
-
// to force the walk-up path: root/project/.gsd, cwd = root/project/src/deep
|
|
59
|
-
initGit(root);
|
|
60
|
-
const project = join(root, "project");
|
|
61
|
-
mkdirSync(join(project, ".gsd"), { recursive: true });
|
|
62
|
-
const deep = join(project, "src", "deep");
|
|
63
|
-
mkdirSync(deep, { recursive: true });
|
|
64
|
-
_clearGsdRootCache();
|
|
65
|
-
// git probe returns root (no .gsd there), so walk-up takes over and finds project/.gsd
|
|
66
|
-
const result = gsdRoot(deep);
|
|
67
|
-
assertEq(result, join(project, ".gsd"), "walk-up: finds .gsd in ancestor when git root has none");
|
|
68
|
-
} finally { cleanup(root); }
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
{
|
|
72
|
-
// Case 4: .gsd nowhere — fallback returns original basePath/.gsd
|
|
73
|
-
// Use an isolated git repo so we fully control the environment above basePath
|
|
74
|
-
const root = tmp();
|
|
75
|
-
try {
|
|
76
|
-
initGit(root); // git root = root, no .gsd anywhere
|
|
77
|
-
const sub = join(root, "src");
|
|
78
|
-
mkdirSync(sub, { recursive: true });
|
|
79
|
-
_clearGsdRootCache();
|
|
80
|
-
const result = gsdRoot(sub);
|
|
81
|
-
// git probe finds root (no .gsd), walk-up finds nothing → fallback = sub/.gsd
|
|
82
|
-
assertEq(result, join(sub, ".gsd"), "fallback: returns basePath/.gsd when .gsd not found anywhere");
|
|
83
|
-
} finally { cleanup(root); }
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
{
|
|
87
|
-
// Case 5: cache — second call returns same value without re-probing
|
|
88
|
-
const root = tmp();
|
|
89
|
-
try {
|
|
90
|
-
mkdirSync(join(root, ".gsd"));
|
|
91
|
-
_clearGsdRootCache();
|
|
92
|
-
const first = gsdRoot(root);
|
|
93
|
-
const second = gsdRoot(root);
|
|
94
|
-
assertEq(first, second, "cache: same result returned on second call");
|
|
95
|
-
assertTrue(first === second, "cache: identity check (same string)");
|
|
96
|
-
} finally { cleanup(root); }
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
{
|
|
100
|
-
// Case 6: .gsd at basePath takes precedence over ancestor .gsd
|
|
101
|
-
const outer = tmp();
|
|
102
|
-
try {
|
|
103
|
-
initGit(outer);
|
|
104
|
-
mkdirSync(join(outer, ".gsd"));
|
|
105
|
-
const inner = join(outer, "nested");
|
|
106
|
-
mkdirSync(join(inner, ".gsd"), { recursive: true });
|
|
107
|
-
_clearGsdRootCache();
|
|
108
|
-
const result = gsdRoot(inner);
|
|
109
|
-
assertEq(result, join(inner, ".gsd"), "precedence: nearest .gsd wins over ancestor");
|
|
110
|
-
} finally { cleanup(outer); }
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
report();
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared test utilities for GSD extension tests.
|
|
3
|
-
*
|
|
4
|
-
* Provides cross-platform helpers for creating temporary git repos,
|
|
5
|
-
* safe cleanup, file creation, and shell-free git operations.
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* import { git, makeTempRepo, cleanup, createFile } from "./test-utils.ts";
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { execFileSync } from "node:child_process";
|
|
12
|
-
import {
|
|
13
|
-
existsSync,
|
|
14
|
-
mkdirSync,
|
|
15
|
-
mkdtempSync,
|
|
16
|
-
readFileSync,
|
|
17
|
-
rmSync,
|
|
18
|
-
statSync,
|
|
19
|
-
writeFileSync,
|
|
20
|
-
} from "node:fs";
|
|
21
|
-
import { dirname, join } from "node:path";
|
|
22
|
-
import { tmpdir } from "node:os";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Shell-free git helper — uses execFileSync to bypass shell entirely.
|
|
26
|
-
* No quoting issues, no Windows cmd.exe incompatibilities.
|
|
27
|
-
*
|
|
28
|
-
* @param cwd - Working directory for git command
|
|
29
|
-
* @param args - Git arguments (e.g., "add", "-A")
|
|
30
|
-
* @returns trimmed stdout
|
|
31
|
-
*/
|
|
32
|
-
export function git(cwd: string, ...args: string[]): string {
|
|
33
|
-
return execFileSync("git", args, {
|
|
34
|
-
cwd,
|
|
35
|
-
encoding: "utf-8",
|
|
36
|
-
stdio: "pipe",
|
|
37
|
-
}).trim();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Create a temporary git repository with an initial commit.
|
|
42
|
-
* Configures user.email, user.name, and core.autocrlf=false for
|
|
43
|
-
* consistent behavior across platforms.
|
|
44
|
-
*
|
|
45
|
-
* @param prefix - Optional prefix for the temp directory name
|
|
46
|
-
* @returns absolute path to the temp repo
|
|
47
|
-
*/
|
|
48
|
-
export function makeTempRepo(prefix: string = "gsd-test-"): string {
|
|
49
|
-
const dir = mkdtempSync(join(tmpdir(), prefix));
|
|
50
|
-
git(dir, "init");
|
|
51
|
-
git(dir, "config", "user.email", "test@test.com");
|
|
52
|
-
git(dir, "config", "user.name", "Test");
|
|
53
|
-
git(dir, "config", "core.autocrlf", "false");
|
|
54
|
-
writeFileSync(join(dir, "README.md"), "# init\n");
|
|
55
|
-
git(dir, "add", "-A");
|
|
56
|
-
git(dir, "commit", "-m", "init");
|
|
57
|
-
git(dir, "branch", "-M", "main");
|
|
58
|
-
return dir;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Create a temporary directory (not a git repo).
|
|
63
|
-
*
|
|
64
|
-
* @param prefix - Optional prefix for the temp directory name
|
|
65
|
-
* @returns absolute path to the temp directory
|
|
66
|
-
*/
|
|
67
|
-
export function makeTempDir(prefix: string = "gsd-test-"): string {
|
|
68
|
-
return mkdtempSync(join(tmpdir(), prefix));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Safely clean up a temporary directory.
|
|
73
|
-
* Non-fatal — Windows may hold file descriptors briefly.
|
|
74
|
-
*/
|
|
75
|
-
export function cleanup(dir: string): void {
|
|
76
|
-
try {
|
|
77
|
-
rmSync(dir, { recursive: true, force: true });
|
|
78
|
-
} catch {
|
|
79
|
-
// ignore — Windows may hold file descriptors briefly after test
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Create a file with intermediate directories.
|
|
85
|
-
*
|
|
86
|
-
* @param base - Base directory
|
|
87
|
-
* @param relativePath - Relative path within base (e.g., "src/index.ts")
|
|
88
|
-
* @param content - File content (defaults to empty string)
|
|
89
|
-
* @returns absolute path to the created file
|
|
90
|
-
*/
|
|
91
|
-
export function createFile(base: string, relativePath: string, content: string = ""): string {
|
|
92
|
-
const fullPath = join(base, relativePath);
|
|
93
|
-
mkdirSync(dirname(fullPath), { recursive: true });
|
|
94
|
-
writeFileSync(fullPath, content, "utf-8");
|
|
95
|
-
return fullPath;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Safely read a file, returning null if it doesn't exist or is a directory.
|
|
100
|
-
* Prevents EISDIR errors.
|
|
101
|
-
*/
|
|
102
|
-
export function safeReadFile(filePath: string): string | null {
|
|
103
|
-
try {
|
|
104
|
-
if (!existsSync(filePath)) return null;
|
|
105
|
-
if (!statSync(filePath).isFile()) return null;
|
|
106
|
-
return readFileSync(filePath, "utf-8");
|
|
107
|
-
} catch {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Create a minimal GSD milestone structure in a temp directory.
|
|
114
|
-
*
|
|
115
|
-
* @param base - Base directory (should have .gsd/ or be a temp repo)
|
|
116
|
-
* @param mid - Milestone ID (e.g., "M001")
|
|
117
|
-
* @param options - What to create
|
|
118
|
-
*/
|
|
119
|
-
export function writeMilestoneFixture(
|
|
120
|
-
base: string,
|
|
121
|
-
mid: string,
|
|
122
|
-
options: {
|
|
123
|
-
roadmap?: string;
|
|
124
|
-
context?: string;
|
|
125
|
-
summary?: string;
|
|
126
|
-
validation?: string;
|
|
127
|
-
slices?: Array<{
|
|
128
|
-
id: string;
|
|
129
|
-
plan?: string;
|
|
130
|
-
summary?: string;
|
|
131
|
-
uat?: string;
|
|
132
|
-
}>;
|
|
133
|
-
} = {},
|
|
134
|
-
): void {
|
|
135
|
-
const milestoneDir = join(base, ".gsd", "milestones", mid);
|
|
136
|
-
mkdirSync(milestoneDir, { recursive: true });
|
|
137
|
-
|
|
138
|
-
if (options.roadmap) {
|
|
139
|
-
writeFileSync(join(milestoneDir, `${mid}-ROADMAP.md`), options.roadmap);
|
|
140
|
-
}
|
|
141
|
-
if (options.context) {
|
|
142
|
-
writeFileSync(join(milestoneDir, `${mid}-CONTEXT.md`), options.context);
|
|
143
|
-
}
|
|
144
|
-
if (options.summary) {
|
|
145
|
-
writeFileSync(join(milestoneDir, `${mid}-SUMMARY.md`), options.summary);
|
|
146
|
-
}
|
|
147
|
-
if (options.validation) {
|
|
148
|
-
writeFileSync(join(milestoneDir, `${mid}-VALIDATION.md`), options.validation);
|
|
149
|
-
}
|
|
150
|
-
if (options.slices) {
|
|
151
|
-
for (const slice of options.slices) {
|
|
152
|
-
const sliceDir = join(milestoneDir, "slices", slice.id);
|
|
153
|
-
mkdirSync(sliceDir, { recursive: true });
|
|
154
|
-
if (slice.plan) {
|
|
155
|
-
writeFileSync(join(sliceDir, `${slice.id}-PLAN.md`), slice.plan);
|
|
156
|
-
}
|
|
157
|
-
if (slice.summary) {
|
|
158
|
-
writeFileSync(join(sliceDir, `${slice.id}-SUMMARY.md`), slice.summary);
|
|
159
|
-
}
|
|
160
|
-
if (slice.uat) {
|
|
161
|
-
writeFileSync(join(sliceDir, `${slice.id}-UAT.md`), slice.uat);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|