gsd-pi 2.78.1-dev.eccf86e27 → 2.79.0-dev.579e14e9b

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 (96) hide show
  1. package/README.md +94 -47
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/gsd/auto-prompts.js +52 -29
  4. package/dist/resources/extensions/gsd/auto-recovery.js +18 -3
  5. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  6. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -37
  7. package/dist/resources/extensions/gsd/commands/context.js +1 -1
  8. package/dist/resources/extensions/gsd/preferences-types.js +20 -2
  9. package/dist/resources/extensions/gsd/preferences-validation.js +3 -3
  10. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +41 -2
  11. package/dist/resources/extensions/gsd/unit-context-composer.js +32 -0
  12. package/dist/resources/extensions/gsd/unit-context-manifest.js +21 -0
  13. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  14. package/dist/web/standalone/.next/BUILD_ID +1 -1
  15. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  16. package/dist/web/standalone/.next/build-manifest.json +2 -2
  17. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  18. package/dist/web/standalone/.next/required-server-files.json +1 -1
  19. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  20. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  28. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/index.html +1 -1
  36. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  43. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  45. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  46. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  47. package/dist/web/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +1 -0
  48. package/dist/web/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  49. package/dist/web/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +42 -0
  50. package/dist/web/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +30 -0
  51. package/dist/web/standalone/node_modules/@img/sharp-linuxmusl-x64/LICENSE +191 -0
  52. package/dist/web/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
  53. package/dist/web/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +46 -0
  54. package/dist/web/standalone/server.js +1 -1
  55. package/package.json +1 -1
  56. package/packages/daemon/package.json +2 -2
  57. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
  58. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  59. package/packages/mcp-server/dist/workflow-tools.js +53 -0
  60. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  61. package/packages/mcp-server/package.json +2 -2
  62. package/packages/mcp-server/src/workflow-tools.test.ts +116 -0
  63. package/packages/mcp-server/src/workflow-tools.ts +81 -0
  64. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  65. package/packages/native/package.json +1 -1
  66. package/packages/pi-agent-core/package.json +1 -1
  67. package/packages/pi-ai/package.json +1 -1
  68. package/packages/pi-coding-agent/package.json +1 -1
  69. package/packages/pi-tui/package.json +1 -1
  70. package/packages/rpc-client/package.json +1 -1
  71. package/pkg/package.json +1 -1
  72. package/src/resources/extensions/gsd/auto-prompts.ts +106 -28
  73. package/src/resources/extensions/gsd/auto-recovery.ts +17 -3
  74. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  75. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +38 -38
  76. package/src/resources/extensions/gsd/commands/context.ts +1 -1
  77. package/src/resources/extensions/gsd/preferences-types.ts +23 -4
  78. package/src/resources/extensions/gsd/preferences-validation.ts +3 -3
  79. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +68 -1
  80. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -2
  81. package/src/resources/extensions/gsd/tests/current-directory-root-homedir-fallback.test.ts +63 -0
  82. package/src/resources/extensions/gsd/tests/guided-flow-prompt-consolidation.test.ts +14 -0
  83. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +8 -0
  84. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +3 -0
  85. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +85 -0
  86. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +2 -0
  87. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +59 -0
  88. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +38 -0
  89. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +32 -0
  90. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +100 -0
  91. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +3 -0
  92. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +41 -1
  93. package/src/resources/extensions/gsd/unit-context-composer.ts +49 -0
  94. package/src/resources/extensions/gsd/unit-context-manifest.ts +34 -0
  95. /package/dist/web/standalone/.next/static/{Y5UeGFkXTYM9WIQOWHkot → X6D0ObmOxuQCMG5piZpbE}/_buildManifest.js +0 -0
  96. /package/dist/web/standalone/.next/static/{Y5UeGFkXTYM9WIQOWHkot → X6D0ObmOxuQCMG5piZpbE}/_ssgManifest.js +0 -0
@@ -51,6 +51,34 @@ async function applyDisabledModelProviderPolicy(ctx) {
51
51
  // Non-fatal: keep default provider visibility if preferences cannot be loaded.
52
52
  }
53
53
  }
54
+ async function writeContextModeCompactionSnapshot(basePath) {
55
+ try {
56
+ const { loadEffectiveGSDPreferences } = await import("../preferences.js");
57
+ const { isContextModeEnabled } = await import("../preferences-types.js");
58
+ const prefs = loadEffectiveGSDPreferences(basePath);
59
+ if (!isContextModeEnabled(prefs?.preferences))
60
+ return;
61
+ const { writeCompactionSnapshot } = await import("../compaction-snapshot.js");
62
+ const { ensureDbOpen } = await import("./dynamic-tools.js");
63
+ await ensureDbOpen(basePath);
64
+ let activeContext = null;
65
+ try {
66
+ const state = await deriveGsdState(basePath);
67
+ if (state.activeMilestone && state.activeSlice && state.activeTask) {
68
+ activeContext =
69
+ `Active: ${state.activeMilestone.id} / ${state.activeSlice.id} / ${state.activeTask.id}` +
70
+ (state.activeTask.title ? ` - ${state.activeTask.title}` : "");
71
+ }
72
+ }
73
+ catch {
74
+ /* non-fatal */
75
+ }
76
+ writeCompactionSnapshot(basePath, { activeContext });
77
+ }
78
+ catch (err) {
79
+ safetyLogWarning("context-mode", `failed to write compaction snapshot: ${err instanceof Error ? err.message : String(err)}`);
80
+ }
81
+ }
54
82
  export function registerHooks(pi, ecosystemHandlers) {
55
83
  pi.on("session_start", async (_event, ctx) => {
56
84
  initNotificationStore(process.cwd());
@@ -204,15 +232,18 @@ export function registerHooks(pi, ecosystemHandlers) {
204
232
  }
205
233
  });
206
234
  pi.on("session_before_compact", async () => {
235
+ const basePath = process.cwd();
236
+ // Context Mode is default-on. Write the resumable snapshot before any
237
+ // active-auto cancel return so auto sessions still leave re-entry context.
238
+ await writeContextModeCompactionSnapshot(basePath);
207
239
  // Only cancel compaction while auto-mode is actively running.
208
240
  // Paused auto-mode should allow compaction — the user may be doing
209
241
  // interactive work (#3165).
210
242
  if (isAutoActive()) {
211
243
  return { cancel: true };
212
244
  }
213
- const basePath = process.cwd();
214
245
  const { ensureDbOpen } = await import("./dynamic-tools.js");
215
- await ensureDbOpen();
246
+ await ensureDbOpen(basePath);
216
247
  const state = await deriveGsdState(basePath);
217
248
  if (!state.activeMilestone || !state.activeSlice)
218
249
  return;
@@ -256,41 +287,6 @@ export function registerHooks(pi, ecosystemHandlers) {
256
287
  : `Resume ${phaseLabel} work for slice ${state.activeSlice.id}.`,
257
288
  }));
258
289
  });
259
- // Context-mode snapshot: write .gsd/last-snapshot.md before compaction so
260
- // agents can call gsd_resume (or Read the file) to re-orient. Opt-in via
261
- // preferences.context_mode.enabled. Runs after the auto-cancel handler
262
- // above — if that one returned cancel:true, pi still fires us but the
263
- // compaction won't actually happen; the snapshot is still useful then,
264
- // since auto may pause and resume later.
265
- pi.on("session_before_compact", async () => {
266
- try {
267
- const { loadEffectiveGSDPreferences } = await import("../preferences.js");
268
- const { isContextModeEnabled } = await import("../preferences-types.js");
269
- const prefs = loadEffectiveGSDPreferences();
270
- if (!isContextModeEnabled(prefs?.preferences))
271
- return;
272
- const { writeCompactionSnapshot } = await import("../compaction-snapshot.js");
273
- const { ensureDbOpen } = await import("./dynamic-tools.js");
274
- await ensureDbOpen();
275
- const basePath = process.cwd();
276
- let activeContext = null;
277
- try {
278
- const state = await deriveGsdState(basePath);
279
- if (state.activeMilestone && state.activeSlice && state.activeTask) {
280
- activeContext =
281
- `Active: ${state.activeMilestone.id} / ${state.activeSlice.id} / ${state.activeTask.id}` +
282
- (state.activeTask.title ? ` — ${state.activeTask.title}` : "");
283
- }
284
- }
285
- catch {
286
- /* non-fatal */
287
- }
288
- writeCompactionSnapshot(basePath, { activeContext });
289
- }
290
- catch (err) {
291
- safetyLogWarning("context-mode", `failed to write compaction snapshot: ${err instanceof Error ? err.message : String(err)}`);
292
- }
293
- });
294
290
  pi.on("message_update", async (event, ctx) => {
295
291
  if (approvalQuestionAbortInFlight)
296
292
  return;
@@ -57,7 +57,7 @@ export function currentDirectoryRoot() {
57
57
  cwd = process.cwd();
58
58
  }
59
59
  catch {
60
- cwd = process.env.HOME ?? "/";
60
+ cwd = homedir();
61
61
  }
62
62
  }
63
63
  const result = validateDirectory(cwd);
@@ -100,8 +100,26 @@ export const KNOWN_PREFERENCE_KEYS = new Set([
100
100
  "context_mode",
101
101
  "planning_depth",
102
102
  ]);
103
- /** Canonical list of all dispatch unit types. */
104
- export const KNOWN_UNIT_TYPES = [
103
+ /**
104
+ * Broad union of every recognized unit-type *label* used across the codebase.
105
+ *
106
+ * This intentionally covers more than the manifest-tracked dispatch units in
107
+ * `unit-context-manifest.ts:KNOWN_UNIT_TYPES`. Examples that live here but not
108
+ * in the manifest:
109
+ * - `discuss-slice` — dispatched by `guided-flow.ts` rather than auto-mode;
110
+ * composer falls through to default behavior via `resolveManifest()` null path.
111
+ * - `worktree-merge` — used as a model-routing case, prompt-template name, and
112
+ * commit-message label, not as an LLM-dispatched unit.
113
+ *
114
+ * Used by `preferences-validation.ts` to validate user-provided unit-type
115
+ * references in preferences (model overrides, skill rules, etc.) — preferences
116
+ * may legitimately reference any label, including non-dispatched ones.
117
+ *
118
+ * The manifest-strict subset lives in `unit-context-manifest.ts:KNOWN_UNIT_TYPES`
119
+ * and is enforced 1:1 against `UNIT_MANIFESTS` by the parity test in
120
+ * `tests/unit-context-manifest.test.ts`.
121
+ */
122
+ export const KNOWN_UNIT_LABELS = [
105
123
  "research-milestone", "plan-milestone", "research-slice", "plan-slice", "refine-slice",
106
124
  "execute-task", "reactive-execute", "gate-evaluate", "complete-slice", "replan-slice", "reassess-roadmap",
107
125
  "run-uat", "complete-milestone", "validate-milestone", "rewrite-docs",
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { VALID_BRANCH_NAME } from "./git-service.js";
9
9
  import { normalizeStringArray } from "../shared/format-utils.js";
10
- import { KNOWN_PREFERENCE_KEYS, KNOWN_UNIT_TYPES, SKILL_ACTIONS, } from "./preferences-types.js";
10
+ import { KNOWN_PREFERENCE_KEYS, KNOWN_UNIT_LABELS, SKILL_ACTIONS, } from "./preferences-types.js";
11
11
  const VALID_TOKEN_PROFILES = new Set(["budget", "balanced", "quality", "burn-max"]);
12
12
  const VALID_UOK_TURN_ACTIONS = new Set([
13
13
  "commit",
@@ -432,7 +432,7 @@ export function validatePreferences(preferences) {
432
432
  if (preferences.post_unit_hooks && Array.isArray(preferences.post_unit_hooks)) {
433
433
  const validHooks = [];
434
434
  const seenNames = new Set();
435
- const knownUnitTypes = new Set(KNOWN_UNIT_TYPES);
435
+ const knownUnitTypes = new Set(KNOWN_UNIT_LABELS);
436
436
  for (const hook of preferences.post_unit_hooks) {
437
437
  if (!hook || typeof hook !== "object") {
438
438
  errors.push("post_unit_hooks entry must be an object");
@@ -493,7 +493,7 @@ export function validatePreferences(preferences) {
493
493
  if (preferences.pre_dispatch_hooks && Array.isArray(preferences.pre_dispatch_hooks)) {
494
494
  const validPreHooks = [];
495
495
  const seenPreNames = new Set();
496
- const knownUnitTypes = new Set(KNOWN_UNIT_TYPES);
496
+ const knownUnitTypes = new Set(KNOWN_UNIT_LABELS);
497
497
  const validActions = new Set(["modify", "skip", "replace"]);
498
498
  for (const hook of preferences.pre_dispatch_hooks) {
499
499
  if (!hook || typeof hook !== "object") {
@@ -1,7 +1,7 @@
1
1
  import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
2
2
  import { sanitizeCompleteMilestoneParams } from "../bootstrap/sanitize-complete-milestone.js";
3
3
  import { loadWriteGateSnapshot, shouldBlockContextArtifactSaveInSnapshot, shouldBlockRootArtifactSaveInSnapshot } from "../bootstrap/write-gate.js";
4
- import { getActiveRequirements, getMilestone, getSliceStatusSummary, getSliceTaskCounts, readTransaction, saveGateResult, } from "../gsd-db.js";
4
+ import { getActiveRequirements, insertMilestone, getMilestone, getSliceStatusSummary, getSliceTaskCounts, readTransaction, saveGateResult, } from "../gsd-db.js";
5
5
  import { GATE_REGISTRY } from "../gate-registry.js";
6
6
  import { generateRequirementsMd, saveArtifactToDb } from "../db-writer.js";
7
7
  import { resolveMilestoneFile, resolveSliceFile } from "../paths.js";
@@ -17,6 +17,7 @@ import { handleValidateMilestone } from "./validate-milestone.js";
17
17
  import { logError, logWarning } from "../workflow-logger.js";
18
18
  import { invalidateStateCache } from "../state.js";
19
19
  import { loadEffectiveGSDPreferences } from "../preferences.js";
20
+ import { parseProject } from "../schemas/parsers.js";
20
21
  export const SUPPORTED_SUMMARY_ARTIFACT_TYPES = [
21
22
  "SUMMARY",
22
23
  "RESEARCH",
@@ -37,6 +38,19 @@ function isRootSummaryArtifactType(artifactType) {
37
38
  artifactType === "REQUIREMENTS" ||
38
39
  artifactType === "REQUIREMENTS-DRAFT";
39
40
  }
41
+ function registerProjectMilestoneSequence(content) {
42
+ const parsed = parseProject(content);
43
+ const registered = [];
44
+ for (const milestone of parsed.milestones) {
45
+ insertMilestone({
46
+ id: milestone.id,
47
+ title: milestone.title,
48
+ status: milestone.done ? "complete" : "queued",
49
+ });
50
+ registered.push(milestone.id);
51
+ }
52
+ return registered;
53
+ }
40
54
  export async function executeSummarySave(params, basePath = process.cwd()) {
41
55
  const dbAvailable = await ensureDbOpen(basePath);
42
56
  if (!dbAvailable) {
@@ -126,6 +140,24 @@ export async function executeSummarySave(params, basePath = process.cwd()) {
126
140
  slice_id: isRootArtifact ? undefined : params.slice_id,
127
141
  task_id: isRootArtifact ? undefined : params.task_id,
128
142
  }, basePath);
143
+ let registeredMilestones = [];
144
+ let registrationWarning;
145
+ if (params.artifact_type === "PROJECT") {
146
+ try {
147
+ registeredMilestones = registerProjectMilestoneSequence(contentToSave);
148
+ if (registeredMilestones.length > 0)
149
+ invalidateStateCache();
150
+ }
151
+ catch (err) {
152
+ const msg = err instanceof Error ? err.message : String(err);
153
+ registrationWarning = `PROJECT artifact saved, but milestone registration failed: ${msg}`;
154
+ logWarning("tool", registrationWarning, {
155
+ tool: "gsd_summary_save",
156
+ error: String(err),
157
+ stack: err instanceof Error ? err.stack ?? "" : "",
158
+ });
159
+ }
160
+ }
129
161
  if (params.artifact_type === "CONTEXT" && !params.task_id) {
130
162
  try {
131
163
  const draftFile = params.slice_id
@@ -140,7 +172,14 @@ export async function executeSummarySave(params, basePath = process.cwd()) {
140
172
  }
141
173
  return {
142
174
  content: [{ type: "text", text: `Saved ${params.artifact_type} artifact to ${relativePath}` }],
143
- details: { operation: "save_summary", path: relativePath, artifact_type: params.artifact_type, content_source: contentSource },
175
+ details: {
176
+ operation: "save_summary",
177
+ path: relativePath,
178
+ artifact_type: params.artifact_type,
179
+ content_source: contentSource,
180
+ ...(registeredMilestones.length > 0 ? { registeredMilestones } : {}),
181
+ ...(registrationWarning ? { warning: registrationWarning } : {}),
182
+ },
144
183
  };
145
184
  }
146
185
  catch (err) {
@@ -71,6 +71,38 @@ export function manifestBudgetChars(unitType) {
71
71
  const manifest = resolveManifest(unitType);
72
72
  return manifest ? manifest.maxSystemPromptChars : null;
73
73
  }
74
+ const CONTEXT_MODE_LANE_LABELS = {
75
+ interview: "interview",
76
+ research: "research",
77
+ planning: "planning",
78
+ execution: "execution",
79
+ verification: "verification",
80
+ orchestration: "orchestration",
81
+ docs: "documentation",
82
+ };
83
+ const CONTEXT_MODE_GUIDANCE = "Use `gsd_exec` for noisy scans, builds, and tests so full output stays out of prompt context; call `gsd_exec_search` before repeating prior runs; call `gsd_resume` after compaction or resume to recover stored execution context.";
84
+ /**
85
+ * Render the Context Mode instruction lane for a unit type. Unknown unit
86
+ * types, disabled config, and explicit `contextMode: "none"` all omit the
87
+ * block so callers can prefix this safely without extra branching.
88
+ */
89
+ export function composeContextModeInstructions(unitType, opts) {
90
+ if (!opts.enabled)
91
+ return "";
92
+ const manifest = resolveManifest(unitType);
93
+ if (!manifest || manifest.contextMode === "none")
94
+ return "";
95
+ const lane = CONTEXT_MODE_LANE_LABELS[manifest.contextMode];
96
+ if (opts.renderMode === "nested") {
97
+ return `Context Mode (${lane} lane): ${CONTEXT_MODE_GUIDANCE}`;
98
+ }
99
+ return [
100
+ "## Context Mode",
101
+ "",
102
+ `Lane: **${lane} lane**.`,
103
+ CONTEXT_MODE_GUIDANCE,
104
+ ].join("\n");
105
+ }
74
106
  const SECTION_SEPARATOR = "\n\n---\n\n";
75
107
  /**
76
108
  * Compose all manifest-declared context for a unit type using the v2
@@ -137,6 +137,7 @@ export const UNIT_MANIFESTS = {
137
137
  memory: "prompt-relevant",
138
138
  codebaseMap: true,
139
139
  preferences: "active-only",
140
+ contextMode: "research",
140
141
  tools: TOOLS_PLANNING,
141
142
  artifacts: {
142
143
  // Phase 3 migration (#4782): matches today's actual
@@ -153,6 +154,7 @@ export const UNIT_MANIFESTS = {
153
154
  memory: "prompt-relevant",
154
155
  codebaseMap: true,
155
156
  preferences: "active-only",
157
+ contextMode: "planning",
156
158
  tools: TOOLS_PLANNING,
157
159
  artifacts: {
158
160
  inline: ["project", "requirements", "decisions", "milestone-research", "templates"],
@@ -167,6 +169,7 @@ export const UNIT_MANIFESTS = {
167
169
  memory: "prompt-relevant",
168
170
  codebaseMap: true,
169
171
  preferences: "active-only",
172
+ contextMode: "interview",
170
173
  tools: TOOLS_PLANNING,
171
174
  artifacts: {
172
175
  inline: ["project", "requirements", "decisions", "milestone-context", "templates"],
@@ -181,6 +184,7 @@ export const UNIT_MANIFESTS = {
181
184
  memory: "prompt-relevant",
182
185
  codebaseMap: false,
183
186
  preferences: "active-only",
187
+ contextMode: "verification",
184
188
  // planning-dispatch: validation is a verification-fan-out unit. It reads
185
189
  // the milestone surface and dispatches reviewer/security/tester subagents
186
190
  // to report findings without touching user source. Mirrors
@@ -199,6 +203,7 @@ export const UNIT_MANIFESTS = {
199
203
  memory: "prompt-relevant",
200
204
  codebaseMap: false,
201
205
  preferences: "active-only",
206
+ contextMode: "verification",
202
207
  // planning-dispatch: completion is a high-leverage place to fan out to
203
208
  // reviewer / security / tester subagents. They read the diff and report
204
209
  // findings; they do not write user source. Write isolation to .gsd/ is
@@ -221,6 +226,7 @@ export const UNIT_MANIFESTS = {
221
226
  memory: "prompt-relevant",
222
227
  codebaseMap: true,
223
228
  preferences: "active-only",
229
+ contextMode: "research",
224
230
  tools: TOOLS_PLANNING,
225
231
  artifacts: {
226
232
  inline: ["roadmap", "milestone-research", "dependency-summaries", "templates"],
@@ -235,6 +241,7 @@ export const UNIT_MANIFESTS = {
235
241
  memory: "prompt-relevant",
236
242
  codebaseMap: true,
237
243
  preferences: "active-only",
244
+ contextMode: "planning",
238
245
  // planning-dispatch: allows subagent dispatch so the planner can fan out
239
246
  // to scout for codebase recon and to planner/decompose-style specialists
240
247
  // for sub-decomposition. Write-isolation to .gsd/ is preserved.
@@ -252,6 +259,7 @@ export const UNIT_MANIFESTS = {
252
259
  memory: "prompt-relevant",
253
260
  codebaseMap: true,
254
261
  preferences: "active-only",
262
+ contextMode: "planning",
255
263
  // See plan-slice — same rationale: dispatch to scout/planner-style
256
264
  // specialists during refinement is materially better than re-doing recon
257
265
  // inline.
@@ -269,6 +277,7 @@ export const UNIT_MANIFESTS = {
269
277
  memory: "prompt-relevant",
270
278
  codebaseMap: true,
271
279
  preferences: "active-only",
280
+ contextMode: "planning",
272
281
  tools: TOOLS_PLANNING,
273
282
  artifacts: {
274
283
  inline: ["slice-plan", "slice-research", "dependency-summaries", "prior-task-summaries", "templates"],
@@ -283,6 +292,7 @@ export const UNIT_MANIFESTS = {
283
292
  memory: "prompt-relevant",
284
293
  codebaseMap: false,
285
294
  preferences: "active-only",
295
+ contextMode: "verification",
286
296
  // See complete-milestone — same rationale: dispatch to reviewer / security /
287
297
  // tester subagents to fan out review work without bloating this unit's
288
298
  // context.
@@ -304,6 +314,7 @@ export const UNIT_MANIFESTS = {
304
314
  memory: "critical-only",
305
315
  codebaseMap: false,
306
316
  preferences: "none",
317
+ contextMode: "planning",
307
318
  tools: TOOLS_PLANNING,
308
319
  artifacts: {
309
320
  // Phase 2 pilot (#4782): manifest now matches today's actual
@@ -322,6 +333,7 @@ export const UNIT_MANIFESTS = {
322
333
  memory: "prompt-relevant",
323
334
  codebaseMap: true,
324
335
  preferences: "active-only",
336
+ contextMode: "execution",
325
337
  tools: TOOLS_ALL,
326
338
  artifacts: {
327
339
  inline: ["task-plan", "slice-plan", "prior-task-summaries", "templates"],
@@ -336,6 +348,7 @@ export const UNIT_MANIFESTS = {
336
348
  memory: "prompt-relevant",
337
349
  codebaseMap: true,
338
350
  preferences: "active-only",
351
+ contextMode: "execution",
339
352
  tools: TOOLS_ALL,
340
353
  artifacts: {
341
354
  inline: ["slice-plan", "prior-task-summaries", "templates"],
@@ -351,6 +364,7 @@ export const UNIT_MANIFESTS = {
351
364
  memory: "critical-only",
352
365
  codebaseMap: false,
353
366
  preferences: "active-only",
367
+ contextMode: "verification",
354
368
  tools: TOOLS_PLANNING,
355
369
  artifacts: {
356
370
  // Phase 3 migration (#4782): manifest matches today's actual
@@ -369,6 +383,7 @@ export const UNIT_MANIFESTS = {
369
383
  memory: "critical-only",
370
384
  codebaseMap: false,
371
385
  preferences: "active-only",
386
+ contextMode: "verification",
372
387
  tools: TOOLS_PLANNING,
373
388
  artifacts: {
374
389
  inline: ["slice-plan", "prior-task-summaries"],
@@ -383,6 +398,7 @@ export const UNIT_MANIFESTS = {
383
398
  memory: "prompt-relevant",
384
399
  codebaseMap: true,
385
400
  preferences: "active-only",
401
+ contextMode: "docs",
386
402
  tools: TOOLS_DOCS,
387
403
  artifacts: {
388
404
  inline: ["project", "requirements", "decisions", "templates"],
@@ -401,6 +417,7 @@ export const UNIT_MANIFESTS = {
401
417
  memory: "none",
402
418
  codebaseMap: false,
403
419
  preferences: "none",
420
+ contextMode: "none",
404
421
  tools: TOOLS_PLANNING,
405
422
  artifacts: {
406
423
  inline: [],
@@ -418,6 +435,7 @@ export const UNIT_MANIFESTS = {
418
435
  memory: "prompt-relevant",
419
436
  codebaseMap: true,
420
437
  preferences: "active-only",
438
+ contextMode: "interview",
421
439
  tools: TOOLS_PLANNING,
422
440
  artifacts: {
423
441
  inline: ["templates"],
@@ -434,6 +452,7 @@ export const UNIT_MANIFESTS = {
434
452
  memory: "prompt-relevant",
435
453
  codebaseMap: true,
436
454
  preferences: "active-only",
455
+ contextMode: "interview",
437
456
  tools: TOOLS_PLANNING,
438
457
  artifacts: {
439
458
  inline: ["project", "templates"],
@@ -450,6 +469,7 @@ export const UNIT_MANIFESTS = {
450
469
  memory: "none",
451
470
  codebaseMap: false,
452
471
  preferences: "none",
472
+ contextMode: "none",
453
473
  tools: TOOLS_PLANNING,
454
474
  artifacts: {
455
475
  inline: [],
@@ -468,6 +488,7 @@ export const UNIT_MANIFESTS = {
468
488
  memory: "prompt-relevant",
469
489
  codebaseMap: true,
470
490
  preferences: "active-only",
491
+ contextMode: "research",
471
492
  tools: { mode: "planning-dispatch", allowedSubagents: ["scout"] },
472
493
  artifacts: {
473
494
  inline: ["project", "requirements", "templates"],