gsd-pi 2.42.0-dev.eedc83f → 2.43.0-dev.5717b75

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.
Files changed (60) hide show
  1. package/dist/cli.js +3 -2
  2. package/dist/loader.js +3 -1
  3. package/dist/resources/extensions/async-jobs/await-tool.js +5 -0
  4. package/dist/resources/extensions/async-jobs/index.js +2 -0
  5. package/dist/resources/extensions/gsd/auto/phases.js +1 -3
  6. package/dist/resources/extensions/gsd/auto-prompts.js +3 -16
  7. package/dist/resources/extensions/gsd/auto-start.js +8 -11
  8. package/dist/resources/extensions/gsd/git-service.js +3 -69
  9. package/dist/resources/extensions/gsd/worktree.js +2 -2
  10. package/dist/web/standalone/.next/BUILD_ID +1 -1
  11. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  12. package/dist/web/standalone/.next/build-manifest.json +2 -2
  13. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  14. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  15. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  20. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/index.html +1 -1
  31. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  38. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  39. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  40. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  41. package/package.json +1 -1
  42. package/packages/pi-coding-agent/package.json +1 -1
  43. package/pkg/package.json +1 -1
  44. package/src/resources/extensions/async-jobs/await-tool.test.ts +47 -0
  45. package/src/resources/extensions/async-jobs/await-tool.ts +5 -0
  46. package/src/resources/extensions/async-jobs/index.ts +1 -0
  47. package/src/resources/extensions/async-jobs/job-manager.ts +2 -0
  48. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -1
  49. package/src/resources/extensions/gsd/auto/phases.ts +1 -3
  50. package/src/resources/extensions/gsd/auto-prompts.ts +2 -18
  51. package/src/resources/extensions/gsd/auto-start.ts +7 -10
  52. package/src/resources/extensions/gsd/git-service.ts +2 -72
  53. package/src/resources/extensions/gsd/gitignore.ts +1 -1
  54. package/src/resources/extensions/gsd/tests/git-service.test.ts +9 -14
  55. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +56 -3
  56. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +1 -2
  57. package/src/resources/extensions/gsd/worktree-resolver.ts +0 -1
  58. package/src/resources/extensions/gsd/worktree.ts +2 -2
  59. /package/dist/web/standalone/.next/static/{JUBX5FUR73jiViQU5a-Cx → 5ULZcR9XhHFzlAZFiSKRl}/_buildManifest.js +0 -0
  60. /package/dist/web/standalone/.next/static/{JUBX5FUR73jiViQU5a-Cx → 5ULZcR9XhHFzlAZFiSKRl}/_ssgManifest.js +0 -0
@@ -42,6 +42,7 @@ export default function AsyncJobs(pi: ExtensionAPI) {
42
42
 
43
43
  manager = new AsyncJobManager({
44
44
  onJobComplete: (job) => {
45
+ if (job.awaited) return;
45
46
  const statusEmoji = job.status === "completed" ? "done" : "error";
46
47
  const elapsed = ((Date.now() - job.startTime) / 1000).toFixed(1);
47
48
  const output = job.status === "completed"
@@ -22,6 +22,8 @@ export interface Job {
22
22
  promise: Promise<void>;
23
23
  resultText?: string;
24
24
  errorText?: string;
25
+ /** Set by await_job when results are consumed. Suppresses follow-up delivery. */
26
+ awaited?: boolean;
25
27
  }
26
28
 
27
29
  export interface JobManagerOptions {
@@ -109,7 +109,6 @@ export interface LoopDeps {
109
109
  captureIntegrationBranch: (
110
110
  basePath: string,
111
111
  mid: string,
112
- opts?: { commitDocs?: boolean },
113
112
  ) => void;
114
113
  getIsolationMode: () => string;
115
114
  getCurrentBranch: (basePath: string) => string;
@@ -261,9 +261,7 @@ export async function runPreDispatch(
261
261
 
262
262
  if (mid) {
263
263
  if (deps.getIsolationMode() !== "none") {
264
- deps.captureIntegrationBranch(s.basePath, mid, {
265
- commitDocs: prefs?.git?.commit_docs,
266
- });
264
+ deps.captureIntegrationBranch(s.basePath, mid);
267
265
  }
268
266
  deps.resolver.enterMilestone(mid, ctx.ui);
269
267
  } else {
@@ -420,8 +420,6 @@ export function buildSkillActivationBlock(params: {
420
420
  params.sliceTitle,
421
421
  params.taskId,
422
422
  params.taskTitle,
423
- ...(params.extraContext ?? []),
424
- params.taskPlanContent ?? undefined,
425
423
  );
426
424
 
427
425
  const visibleSkills = (typeof getLoadedSkills === 'function' ? getLoadedSkills() : []).filter(skill => !skill.disableModelInvocation);
@@ -452,12 +450,6 @@ export function buildSkillActivationBlock(params: {
452
450
  }
453
451
  }
454
452
 
455
- for (const skill of visibleSkills) {
456
- if (skillMatchesContext(skill, contextTokens)) {
457
- matched.add(normalizeSkillReference(skill.name));
458
- }
459
- }
460
-
461
453
  const ordered = [...matched]
462
454
  .filter(name => installedNames.has(name) && !avoided.has(name))
463
455
  .sort();
@@ -983,11 +975,7 @@ export async function buildPlanSlicePrompt(
983
975
  const executorContextConstraints = formatExecutorConstraints();
984
976
 
985
977
  const outputRelPath = relSliceFile(base, mid, sid, "PLAN");
986
- const prefs = loadEffectiveGSDPreferences();
987
- const commitDocsEnabled = prefs?.preferences?.git?.commit_docs !== false;
988
- const commitInstruction = commitDocsEnabled
989
- ? `Commit the plan files only: \`git add --force ${relSlicePath(base, mid, sid)}/ .gsd/DECISIONS.md .gitignore && git commit -m "docs(${sid}): add slice plan"\`. Do not stage .gsd/STATE.md or other runtime files — the system manages those.`
990
- : "Do not commit — planning docs are not tracked in git for this project.";
978
+ const commitInstruction = "Do not commit — .gsd/ planning docs are managed externally and not tracked in git.";
991
979
  return loadPrompt("plan-slice", {
992
980
  workingDirectory: base,
993
981
  milestoneId: mid, sliceId: sid, sliceTitle: sTitle,
@@ -1485,11 +1473,7 @@ export async function buildReassessRoadmapPrompt(
1485
1473
  // Non-fatal — captures module may not be available
1486
1474
  }
1487
1475
 
1488
- const reassessPrefs = loadEffectiveGSDPreferences();
1489
- const reassessCommitDocsEnabled = reassessPrefs?.preferences?.git?.commit_docs !== false;
1490
- const reassessCommitInstruction = reassessCommitDocsEnabled
1491
- ? `Commit: \`docs(${mid}): reassess roadmap after ${completedSliceId}\`. Stage only the .gsd/milestones/ files you changed — do not stage .gsd/STATE.md or other runtime files.`
1492
- : "Do not commit — planning docs are not tracked in git for this project.";
1476
+ const reassessCommitInstruction = "Do not commit — .gsd/ planning docs are managed externally and not tracked in git.";
1493
1477
 
1494
1478
  return loadPrompt("reassess-roadmap", {
1495
1479
  workingDirectory: base,
@@ -167,22 +167,19 @@ export async function bootstrapAutoSession(
167
167
  // ensureGitignore checks for git-tracked .gsd/ files and skips the
168
168
  // ".gsd" pattern if the project intentionally tracks .gsd/ in git.
169
169
  const gitPrefs = loadEffectiveGSDPreferences()?.preferences?.git;
170
- const commitDocs = gitPrefs?.commit_docs;
171
170
  const manageGitignore = gitPrefs?.manage_gitignore;
172
- ensureGitignore(base, { commitDocs, manageGitignore });
171
+ ensureGitignore(base, { manageGitignore });
173
172
  if (manageGitignore !== false) untrackRuntimeFiles(base);
174
173
 
175
174
  // Bootstrap .gsd/ if it doesn't exist
176
175
  const gsdDir = join(base, ".gsd");
177
176
  if (!existsSync(gsdDir)) {
178
177
  mkdirSync(join(gsdDir, "milestones"), { recursive: true });
179
- if (commitDocs !== false) {
180
- try {
181
- nativeAddAll(base);
182
- nativeCommit(base, "chore: init gsd");
183
- } catch {
184
- /* nothing to commit */
185
- }
178
+ try {
179
+ nativeAddAll(base);
180
+ nativeCommit(base, "chore: init gsd");
181
+ } catch {
182
+ /* nothing to commit */
186
183
  }
187
184
  }
188
185
 
@@ -487,7 +484,7 @@ export async function bootstrapAutoSession(
487
484
  // Capture integration branch
488
485
  if (s.currentMilestoneId) {
489
486
  if (getIsolationMode() !== "none") {
490
- captureIntegrationBranch(base, s.currentMilestoneId, { commitDocs });
487
+ captureIntegrationBranch(base, s.currentMilestoneId);
491
488
  }
492
489
  setActiveMilestoneId(base, s.currentMilestoneId);
493
490
  }
@@ -9,8 +9,8 @@
9
9
  */
10
10
 
11
11
  import { execFileSync, execSync } from "node:child_process";
12
- import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
13
- import { join, relative } from "node:path";
12
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
14
  import { gsdRoot } from "./paths.js";
15
15
  import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
16
16
  import { loadEffectiveGSDPreferences } from "./preferences.js";
@@ -245,7 +245,6 @@ export function writeIntegrationBranch(
245
245
  basePath: string,
246
246
  milestoneId: string,
247
247
  branch: string,
248
- _options?: { commitDocs?: boolean },
249
248
  ): void {
250
249
  // Don't record slice branches as the integration target
251
250
  if (SLICE_BRANCH_RE.test(branch)) return;
@@ -486,80 +485,11 @@ export class GitServiceImpl {
486
485
  // git add -A already skips it and the exclusions are harmless no-ops.
487
486
  const allExclusions = [...RUNTIME_EXCLUSION_PATHS, ...extraExclusions];
488
487
  nativeAddAllWithExclusions(this.basePath, allExclusions);
489
-
490
- // Force-add .gsd/milestones/ when .gsd is a symlink (#2104).
491
- // When .gsd is a symlink (external state projects), ensureGitignore adds
492
- // `.gsd` to .gitignore. The nativeAddAllWithExclusions call above falls
493
- // back to plain `git add -A` (symlink pathspec rejection), which respects
494
- // .gitignore and silently skips new .gsd/milestones/ files.
495
- //
496
- // `git add -f` also fails with "beyond a symbolic link", so we use
497
- // `git hash-object -w` + `git update-index --add --cacheinfo` to bypass
498
- // the symlink restriction entirely. This stages each milestone artifact
499
- // individually by hashing the file content and updating the index directly.
500
- const gsdPath = join(this.basePath, ".gsd");
501
- const milestonesDir = join(gsdPath, "milestones");
502
- try {
503
- if (
504
- existsSync(gsdPath) &&
505
- lstatSync(gsdPath).isSymbolicLink() &&
506
- existsSync(milestonesDir)
507
- ) {
508
- this._forceAddMilestoneArtifacts(milestonesDir);
509
- }
510
- } catch {
511
- // Non-fatal: if force-add fails, the commit proceeds without these files.
512
- // This matches existing behavior where milestone artifacts were silently
513
- // omitted — but now we at least attempt to include them.
514
- }
515
488
  }
516
489
 
517
490
  /** Tracks whether runtime file cleanup has run this session. */
518
491
  private _runtimeFilesCleanedUp = false;
519
492
 
520
- /**
521
- * Recursively collect all files under a directory.
522
- * Returns paths relative to `basePath` (e.g. ".gsd/milestones/M009/SUMMARY.md").
523
- */
524
- private _collectFiles(dir: string): string[] {
525
- const files: string[] = [];
526
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
527
- const full = join(dir, entry.name);
528
- if (entry.isDirectory()) {
529
- files.push(...this._collectFiles(full));
530
- } else if (entry.isFile()) {
531
- files.push(relative(this.basePath, full));
532
- }
533
- }
534
- return files;
535
- }
536
-
537
- /**
538
- * Stage milestone artifacts through a symlinked .gsd directory (#2104).
539
- *
540
- * `git add` (even with `-f`) refuses to stage files "beyond a symbolic link".
541
- * This method bypasses that restriction by hashing each file with
542
- * `git hash-object -w` and inserting the blob into the index with
543
- * `git update-index --add --cacheinfo 100644 <hash> <path>`.
544
- */
545
- private _forceAddMilestoneArtifacts(milestonesDir: string): void {
546
- const files = this._collectFiles(milestonesDir);
547
- for (const filePath of files) {
548
- const hash = execFileSync("git", ["hash-object", "-w", filePath], {
549
- cwd: this.basePath,
550
- stdio: ["ignore", "pipe", "pipe"],
551
- encoding: "utf-8",
552
- env: GIT_NO_PROMPT_ENV,
553
- }).trim();
554
- execFileSync("git", ["update-index", "--add", "--cacheinfo", "100644", hash, filePath], {
555
- cwd: this.basePath,
556
- stdio: ["ignore", "pipe", "pipe"],
557
- encoding: "utf-8",
558
- env: GIT_NO_PROMPT_ENV,
559
- });
560
- }
561
- }
562
-
563
493
  /**
564
494
  * Stage files (smart staging) and commit.
565
495
  * Returns the commit message string on success, or null if nothing to commit.
@@ -137,7 +137,7 @@ export function hasGitTrackedGsdFiles(basePath: string): boolean {
137
137
  */
138
138
  export function ensureGitignore(
139
139
  basePath: string,
140
- options?: { manageGitignore?: boolean; commitDocs?: boolean },
140
+ options?: { manageGitignore?: boolean },
141
141
  ): boolean {
142
142
  // If manage_gitignore is explicitly false, do not touch .gitignore at all
143
143
  if (options?.manageGitignore === false) return false;
@@ -1411,16 +1411,14 @@ async function main(): Promise<void> {
1411
1411
  rmSync(repo, { recursive: true, force: true });
1412
1412
  }
1413
1413
 
1414
- // ─── autoCommit: symlinked .gsd stages new milestone artifacts (#2104) ──
1414
+ // ─── autoCommit: symlinked .gsd does NOT stage milestone artifacts (#2247) ──
1415
1415
 
1416
- console.log("\n=== autoCommit: symlinked .gsd stages new milestone artifacts (#2104) ===");
1416
+ console.log("\n=== autoCommit: symlinked .gsd does NOT stage milestone artifacts (#2247) ===");
1417
1417
 
1418
1418
  {
1419
- // Reproduction: when .gsd is a symlink (external state project),
1420
- // autoCommit silently fails to stage NEW .gsd/milestones/ files because:
1421
- // 1. nativeAddAllWithExclusions falls back to plain `git add -A` (symlink)
1422
- // 2. `.gsd` is in .gitignore → new .gsd/ files are invisible to `git add`
1423
- // The fix: smartStage() force-adds .gsd/milestones/ after the normal staging.
1419
+ // When .gsd is a symlink (external state project), .gsd/ files live outside
1420
+ // the repo by design. smartStage() must NOT force-stage them into git — the
1421
+ // .gitignore exclusion is correct and intentional.
1424
1422
  const repo = initTempRepo();
1425
1423
 
1426
1424
  // Create an external .gsd directory and symlink it into the repo
@@ -1433,7 +1431,8 @@ async function main(): Promise<void> {
1433
1431
 
1434
1432
  // .gitignore blocks .gsd (as ensureGitignore would do for symlink projects)
1435
1433
  writeFileSync(join(repo, ".gitignore"), ".gsd\n");
1436
- run("git add .gitignore && git commit -m 'add gitignore'", repo);
1434
+ run('git add .gitignore', repo);
1435
+ run('git commit -m "add gitignore"', repo);
1437
1436
 
1438
1437
  // Simulate new milestone artifacts created during execution
1439
1438
  writeFileSync(join(externalGsd, "milestones", "M009", "M009-SUMMARY.md"), "# M009 Summary");
@@ -1449,12 +1448,8 @@ async function main(): Promise<void> {
1449
1448
 
1450
1449
  const committed = run("git show --name-only HEAD", repo);
1451
1450
  assertTrue(committed.includes("src/feature.ts"), "symlink autoCommit: source file committed");
1452
- assertTrue(committed.includes(".gsd/milestones/M009/M009-SUMMARY.md"),
1453
- "symlink autoCommit: new M009-SUMMARY.md is committed (not silently dropped)");
1454
- assertTrue(committed.includes(".gsd/milestones/M009/S01-SUMMARY.md"),
1455
- "symlink autoCommit: new S01-SUMMARY.md is committed");
1456
- assertTrue(committed.includes(".gsd/milestones/M009/T01-VERIFY.json"),
1457
- "symlink autoCommit: new T01-VERIFY.json is committed");
1451
+ assertTrue(!committed.includes(".gsd/milestones/"),
1452
+ "symlink autoCommit: .gsd/milestones/ files are NOT staged (external state stays external)");
1458
1453
 
1459
1454
  try { rmSync(repo, { recursive: true, force: true }); } catch {}
1460
1455
  try { rmSync(externalGsd, { recursive: true, force: true }); } catch {}
@@ -39,7 +39,7 @@ function buildBlock(
39
39
  });
40
40
  }
41
41
 
42
- test("buildSkillActivationBlock matches installed skills from task context", () => {
42
+ test("buildSkillActivationBlock does not auto-activate skills via broad context heuristic", () => {
43
43
  const base = makeTempBase();
44
44
  try {
45
45
  writeSkill(base, "react", "Use for React components, hooks, JSX, and frontend UI work.");
@@ -52,7 +52,29 @@ test("buildSkillActivationBlock matches installed skills from task context", ()
52
52
  taskTitle: "Implement React settings panel",
53
53
  });
54
54
 
55
- assert.match(result, /<skill_activation>/);
55
+ // Skills should not be activated just because their name appears in task context.
56
+ // Activation requires explicit preference sources (always_use, skill_rules, prefer_skills, skills_used).
57
+ assert.equal(result, "");
58
+ } finally {
59
+ cleanup(base);
60
+ }
61
+ });
62
+
63
+ test("buildSkillActivationBlock activates skills via prefer_skills when context matches", () => {
64
+ const base = makeTempBase();
65
+ try {
66
+ writeSkill(base, "react", "Use for React components, hooks, JSX, and frontend UI work.");
67
+ writeSkill(base, "swiftui", "Use for SwiftUI views, iOS layout, and Apple platform UI work.");
68
+ loadOnlyTestSkills(base);
69
+
70
+ const result = buildBlock(base, {
71
+ sliceTitle: "Build React dashboard",
72
+ taskId: "T01",
73
+ taskTitle: "Implement React settings panel",
74
+ }, {
75
+ prefer_skills: ["react"],
76
+ });
77
+
56
78
  assert.match(result, /Call Skill\('react'\)/);
57
79
  assert.doesNotMatch(result, /swiftui/);
58
80
  } finally {
@@ -105,7 +127,7 @@ test("buildSkillActivationBlock includes skill_rules matches and task-plan skill
105
127
  }
106
128
  });
107
129
 
108
- test("buildSkillActivationBlock honors avoid_skills", () => {
130
+ test("buildSkillActivationBlock honors avoid_skills against always_use_skills", () => {
109
131
  const base = makeTempBase();
110
132
  try {
111
133
  writeSkill(base, "react", "Use for React components and frontend UI work.");
@@ -114,6 +136,7 @@ test("buildSkillActivationBlock honors avoid_skills", () => {
114
136
  const result = buildBlock(base, {
115
137
  taskTitle: "Implement React settings panel",
116
138
  }, {
139
+ always_use_skills: ["react"],
117
140
  avoid_skills: ["react"],
118
141
  });
119
142
 
@@ -138,3 +161,33 @@ test("buildSkillActivationBlock falls back cleanly when nothing matches", () =>
138
161
  cleanup(base);
139
162
  }
140
163
  });
164
+
165
+ test("buildSkillActivationBlock does not activate skills from extraContext or taskPlanContent body", () => {
166
+ const base = makeTempBase();
167
+ try {
168
+ writeSkill(base, "xcode-build", "Use for Xcode build workflows and iOS compilation.");
169
+ writeSkill(base, "ableton-lom", "Use for Ableton Live Object Model scripting.");
170
+ writeSkill(base, "frontend-design", "Use for frontend design systems and UI components.");
171
+ loadOnlyTestSkills(base);
172
+
173
+ const taskPlan = [
174
+ "---",
175
+ "skills_used: []",
176
+ "---",
177
+ "# T01: Build the API endpoint",
178
+ "Use xcode-build patterns and frontend-design tokens.",
179
+ ].join("\n");
180
+
181
+ const result = buildBlock(base, {
182
+ taskTitle: "Build REST API",
183
+ extraContext: ["Build workflow for iOS and Ableton integration testing"],
184
+ taskPlanContent: taskPlan,
185
+ });
186
+
187
+ // None of these skills should activate — extraContext and taskPlanContent body
188
+ // must not be used for heuristic matching.
189
+ assert.equal(result, "");
190
+ } finally {
191
+ cleanup(base);
192
+ }
193
+ });
@@ -139,11 +139,10 @@ function makeDeps(
139
139
  captureIntegrationBranch: (
140
140
  basePath: string,
141
141
  mid: string | undefined,
142
- opts?: { commitDocs?: boolean },
143
142
  ) => {
144
143
  calls.push({
145
144
  fn: "captureIntegrationBranch",
146
- args: [basePath, mid, opts],
145
+ args: [basePath, mid],
147
146
  });
148
147
  },
149
148
  ...overrides,
@@ -63,7 +63,6 @@ export interface WorktreeResolverDeps {
63
63
  captureIntegrationBranch: (
64
64
  basePath: string,
65
65
  mid: string,
66
- opts?: { commitDocs?: boolean },
67
66
  ) => void;
68
67
  }
69
68
 
@@ -57,13 +57,13 @@ export function setActiveMilestoneId(basePath: string, milestoneId: string | nul
57
57
  * record when the user starts from a different branch (#300). Always a no-op
58
58
  * if on a GSD slice branch.
59
59
  */
60
- export function captureIntegrationBranch(basePath: string, milestoneId: string, options?: { commitDocs?: boolean }): void {
60
+ export function captureIntegrationBranch(basePath: string, milestoneId: string): void {
61
61
  // In a worktree, the base branch is implicit (worktree/<name>).
62
62
  // Writing it to META.json would leave stale metadata after merge back to main.
63
63
  if (detectWorktreeName(basePath)) return;
64
64
  const svc = getService(basePath);
65
65
  const current = svc.getCurrentBranch();
66
- writeIntegrationBranch(basePath, milestoneId, current, options);
66
+ writeIntegrationBranch(basePath, milestoneId, current);
67
67
  }
68
68
 
69
69
  // ─── Pure Utility Functions (unchanged) ────────────────────────────────────