teamshare-bridge 0.21.9 → 0.21.11

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.
@@ -35,51 +35,138 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.cmdPlanner = cmdPlanner;
37
37
  /**
38
- * `planner` command: decompose a task into subtasks using the agent's
39
- * harness. The agent receives a planning brief, uses the `submit_plan`
40
- * MCP tool to return structured subtasks, and the result is written to
41
- * a temp file for the bridge to read and emit back to the backend.
38
+ * `planner` command: run a REAL planning session with the planner agent's
39
+ * harness (plan-mode parity). Two modes:
42
40
  *
43
- * The `submit_plan` MCP tool validates the plan (cycle detection, index
44
- * checks) but does NOT persist the backend's `createChildren()` handles
45
- * all persistence after receiving the validated plan.
41
+ * - `task` plan a SINGLE task: read the full task, research the project,
42
+ * rewrite the description + acceptance criteria, add checklist
43
+ * items, write `plan.md`, and (optionally) propose sub-tasks.
44
+ * NEVER creates replacement tasks.
45
+ * - `overview` — plan the WHOLE dispatched batch: read every queued task,
46
+ * produce the shared plan on the plan task, the execution
47
+ * ORDER and the dependency edges. NEVER invents tasks.
46
48
  *
47
- * Falls back to headless LLM (complete()) when no harness is available.
49
+ * The agent returns its plan via the `submit_plan` MCP tool, which writes a
50
+ * temp file for the bridge to read and emit back to the backend. The backend
51
+ * applies it (ordering, nested sub-tasks, plan note) — this CLI only plans.
48
52
  */
49
53
  const node_fs_1 = require("node:fs");
50
54
  const node_path_1 = require("node:path");
51
55
  const node_os_1 = require("node:os");
52
56
  const api_1 = require("../../lib/api");
53
- const llm_1 = require("../../lib/llm/llm");
57
+ const brief_1 = require("../../lib/brief");
54
58
  const lock_1 = require("../../lib/lock");
55
59
  const daemon_reporter_1 = require("../../lib/chat/daemon-reporter");
56
60
  const session_stream_1 = require("../../lib/chat/session-stream");
57
- const brief_1 = require("../../lib/brief");
58
61
  const utils_1 = require("../utils");
59
62
  const harness_1 = require("./harness");
60
63
  const shared_1 = require("./shared");
61
64
  const presence_1 = require("../../lib/workspace/presence");
62
- const PLANNER_PROMPT_TEMPLATE = `You are a software build planner. Break the task below into 2-5 concrete,
63
- independently verifiable subtasks, in dependency order.
64
-
65
- For each subtask, include a "verification" array with 2-4 concrete, checkable criteria
66
- (e.g. "build succeeds with no errors", "all tests pass", "endpoint returns 200", "docs updated").
67
- These become checklist items the agent must verify.
68
-
69
- Use the submit_plan MCP tool to submit your decomposition. Return ONLY the tool call,
70
- no prose explanation.
71
-
72
- TASK: {description}`;
65
+ function sanitizeTitle(raw, fallback) {
66
+ const firstLine = (raw ?? "")
67
+ .split(/\r?\n/)
68
+ .map((l) => l.trim())
69
+ .find((l) => l.length > 0);
70
+ const cleaned = (firstLine ?? "")
71
+ .replace(/^[#>*\-\s]+/, "")
72
+ .replace(/[*_`#>]/g, "")
73
+ .replace(/\s+/g, " ")
74
+ .trim();
75
+ const title = cleaned ||
76
+ (raw ?? "")
77
+ .replace(/[*_`#>]/g, "")
78
+ .replace(/\s+/g, " ")
79
+ .trim();
80
+ if (!title)
81
+ return fallback;
82
+ return title.length > 120 ? `${title.slice(0, 117)}…` : title;
83
+ }
84
+ /** Shared planning rules: plan only, never execute, never invent tasks. */
85
+ const PLANNING_RULES = `You are a planning agent working in PLAN MODE. You must NOT execute or implement anything - no code edits, no build commands, no file writes outside the plan note.
86
+
87
+ ## Rules
88
+ - Plan ONLY. There is an execution queue that runs after you; you are the overview.
89
+ - NEVER invent replacement tasks or restate a task that already exists. If a task already covers a step, reference it by name.
90
+ - Use the TeamShare MCP tools to read (get_task, read_document, list_documents, list_checklist_items) and write (update_task, create_checklist_item, create_document, submit_plan).
91
+ - ALWAYS finish by calling the **submit_plan** MCP tool with \`planTaskId\` set to the EXACT task id given below. Without that call your plan is lost.`;
92
+ function buildTaskPrompt(planTaskId, task, projectName, brief) {
93
+ return (`${PLANNING_RULES}\n\n` +
94
+ `## Plan task (this is the task id you MUST pass to submit_plan)\n` +
95
+ `- **planTaskId:** ${planTaskId}\n` +
96
+ `- **Project:** ${projectName}\n` +
97
+ `- **Title:** ${task.title}\n` +
98
+ `- **Status:** ${task.status} · **Priority:** ${task.priority}\n` +
99
+ (task.tags?.length ? `- **Tags:** ${task.tags.join(", ")}\n` : "") +
100
+ `\n## Current description\n${task.description?.trim() || "(none)"}\n` +
101
+ `\n## Current acceptance criteria\n${task.acceptanceCriteria?.trim() || "(none)"}\n` +
102
+ `\n## What to do (plan only)\n` +
103
+ `1. Read the task and its context: use get_task with include comments/subtasks/checklist, and read linked documents with read_document.\n` +
104
+ `2. Research: consult the project context, \`docs/**\` notes and the relevant source files so the plan is grounded in the real codebase.\n` +
105
+ `3. Rewrite the description into a clear specification: goal, context, scope, out-of-scope, technical approach, risks.\n` +
106
+ `4. Write concrete, testable acceptance criteria and persist them with update_task (description, acceptanceCriteria).\n` +
107
+ `5. Add a verification checklist: call create_checklist_item once per acceptance criterion (task-scoped, no subtaskId).\n` +
108
+ `6. Write the plan note: create_document with a note named \`plan.md\` under \`agents/<you>/tasks/${planTaskId}\` explaining the approach, key files and risks.\n` +
109
+ `7. Finish by calling **submit_plan** with:\n` +
110
+ ` - planTaskId: \`${planTaskId}\`\n` +
111
+ ` - mode: "task"\n` +
112
+ ` - acceptanceCriteria: your final criteria (markdown bullets)\n` +
113
+ ` - planMarkdown: the \`plan.md\` body you wrote\n` +
114
+ ` - tasks: [] unless the work genuinely needs extra sub-tasks (only then, 1-5 items with title/description/verification).\n` +
115
+ `8. Post a one-paragraph summary comment, then STOP. Do NOT change the task status, do NOT execute.\n` +
116
+ `\n## TeamShare brief\n${brief || "(no brief available)"}`);
117
+ }
118
+ function buildOverviewPrompt(planTaskId, projectName, queue) {
119
+ const queueBlock = queue
120
+ .map((t, i) => `${i + 1}. id=\`${t.id}\` — **${t.title}**\n` +
121
+ (t.description
122
+ ? ` - ${t.description.replace(/\s+/g, " ").slice(0, 600)}\n`
123
+ : "") +
124
+ (t.acceptanceCriteria
125
+ ? ` - acceptance: ${t.acceptanceCriteria.replace(/\s+/g, " ").slice(0, 400)}\n`
126
+ : ""))
127
+ .join("\n");
128
+ return (`${PLANNING_RULES}\n\n` +
129
+ `## Plan task (pass this exact id to submit_plan)\n` +
130
+ `- **planTaskId:** ${planTaskId}\n` +
131
+ `- **Project:** ${projectName}\n` +
132
+ `- **This is an OVERVIEW plan for a whole batch.** The tasks below are the execution queue and ALREADY EXIST.\n` +
133
+ `\n## Execution queue (${queue.length} tasks — these are the queue, do NOT create replacements)\n${queueBlock}\n` +
134
+ `\n## What to do (plan only)\n` +
135
+ `1. Read every task above (get_task with include comments/subtasks/checklist). Read linked documents and the project context.\n` +
136
+ `2. Research the codebase enough to sequence the work correctly (shared files, ordering constraints, risks).\n` +
137
+ `3. Decide the execution ORDER of the given task ids and any dependency edges between them.\n` +
138
+ `4. Write the shared plan: goal, the ordered steps (referencing the existing tasks by title), cross-task risks, and how each task will be verified.\n` +
139
+ `5. Persist it: create_document with a note named \`plan.md\` under \`agents/<you>/tasks/${planTaskId}\`, and update_task on the plan task with the description + acceptance criteria.\n` +
140
+ `6. Finish by calling **submit_plan** with:\n` +
141
+ ` - planTaskId: \`${planTaskId}\`\n` +
142
+ ` - mode: "overview"\n` +
143
+ ` - orderedTaskIds: the given task ids in execution order (use the EXACT ids above)\n` +
144
+ ` - dependencies: [[taskId, dependsOnTaskId], ...] between the given ids (may be empty)\n` +
145
+ ` - acceptanceCriteria: criteria for the whole plan\n` +
146
+ ` - planMarkdown: the \`plan.md\` body\n` +
147
+ ` - tasks: [] — do NOT propose replacement tasks.\n` +
148
+ `7. Post a one-paragraph summary comment on the plan task, then STOP.\n`);
149
+ }
73
150
  async function cmdPlanner(flags) {
74
- const agentId = (0, utils_1.need)(flags, 'agent');
75
- const projectId = (0, utils_1.need)(flags, 'project');
76
- const parentTaskId = (0, utils_1.need)(flags, 'task');
151
+ const agentId = (0, utils_1.need)(flags, "agent");
152
+ const projectId = (0, utils_1.need)(flags, "project");
153
+ const planTaskId = (0, utils_1.need)(flags, "task");
154
+ const mode = flags.get("mode") === "overview" ? "overview" : "task";
155
+ const queueIds = (flags.get("tasks") ?? "")
156
+ .split(",")
157
+ .map((s) => s.trim())
158
+ .filter(Boolean);
77
159
  const apiKey = (0, utils_1.resolveApiKey)(flags);
78
- const selfMode = flags.get('self') === 'true';
79
- const resultPath = flags.get('result-file') ?? (0, node_path_1.join)((0, node_os_1.homedir)(), '.teamshare', 'state', `planner-${parentTaskId.slice(0, 8)}.json`);
160
+ const resultPath = flags.get("result-file") ??
161
+ (0, node_path_1.join)((0, node_os_1.homedir)(), ".teamshare", "state", `planner-${planTaskId.slice(0, 8)}.json`);
80
162
  let exitCode = 0;
81
- const sessionId = flags.get('session') ?? (0, session_stream_1.newSessionId)();
82
- const reporter = new daemon_reporter_1.DaemonReporter({ sessionId, agentId, projectId, mode: 'run' });
163
+ const sessionId = flags.get("session") ?? (0, session_stream_1.newSessionId)();
164
+ const reporter = new daemon_reporter_1.DaemonReporter({
165
+ sessionId,
166
+ agentId,
167
+ projectId,
168
+ mode: "run",
169
+ });
83
170
  reporter.connect();
84
171
  const log = (0, utils_1.makeLog)(reporter);
85
172
  const api = new api_1.TeamshareApi(process.env.TEAMSHARE_API_URL, apiKey);
@@ -89,7 +176,7 @@ async function cmdPlanner(flags) {
89
176
  const settings = await (0, utils_1.fetchAgentSettings)(api, agentId, log);
90
177
  const harness = (0, utils_1.harnessOf)(flags, settings);
91
178
  (0, utils_1.applyOpenCodeKey)(agentId, log, settings);
92
- const lock = await (0, lock_1.acquireLock)(agentId, 'orchestrator', { projectId, taskId: parentTaskId }, {
179
+ const lock = await (0, lock_1.acquireLock)(agentId, "orchestrator", { projectId, taskId: planTaskId }, {
93
180
  onWaiting: (busy) => log(`[lock] agent ${agentId} is busy (pid ${busy.pid}, since ${busy.startedAt}, ${busy.kind}) - waiting...`),
94
181
  });
95
182
  if (!lock) {
@@ -98,80 +185,101 @@ async function cmdPlanner(flags) {
98
185
  return;
99
186
  }
100
187
  try {
101
- (0, presence_1.registerPresence)(cwd, { agentId, kind: 'orchestrator', projectId });
102
- await (0, brief_1.reportStatus)(api, agentId, 'working', parentTaskId, sessionId);
103
- log(`[planner] decomposing task ${parentTaskId.slice(0, 8)} in ${cwd}`);
104
- // Fetch the task brief for context.
105
- const brief = await (0, brief_1.fetchTaskBrief)(api, parentTaskId).catch(() => '');
106
- const description = brief || `Task ${parentTaskId}`;
107
- const prompt = PLANNER_PROMPT_TEMPLATE.replace('{description}', description);
188
+ (0, presence_1.registerPresence)(cwd, { agentId, kind: "orchestrator", projectId });
189
+ await (0, brief_1.reportStatus)(api, agentId, "working", planTaskId, sessionId);
190
+ const project = await api.getProject(projectId).catch(() => null);
191
+ const projectName = project?.name ?? projectId;
192
+ // Fetch the plan task for context.
193
+ const task = await api.getTask(planTaskId).catch(() => null);
194
+ if (!task) {
195
+ log(`[planner] cannot fetch plan task ${planTaskId}`, "stderr");
196
+ process.exitCode = 1;
197
+ return;
198
+ }
199
+ // Build the prompt.
200
+ let prompt;
201
+ if (mode === "overview") {
202
+ const queue = await Promise.all(queueIds.map(async (id) => {
203
+ const t = await api.getTask(id).catch(() => null);
204
+ return {
205
+ id,
206
+ title: t?.title ?? id,
207
+ description: t?.description ?? null,
208
+ acceptanceCriteria: t?.acceptanceCriteria ?? null,
209
+ };
210
+ }));
211
+ prompt = buildOverviewPrompt(planTaskId, projectName, queue);
212
+ log(`[planner] overview mode: planning a queue of ${queue.length} tasks`);
213
+ }
214
+ else {
215
+ const brief = await (0, brief_1.fetchTaskBrief)(api, planTaskId).catch(() => "");
216
+ prompt = buildTaskPrompt(planTaskId, task, projectName, brief);
217
+ log(`[planner] task mode: planning task ${planTaskId.slice(0, 8)} in ${cwd}`);
218
+ }
219
+ // Mirror the prompt locally so it can be inspected.
220
+ if (cwd) {
221
+ try {
222
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(cwd, "teamshare", "plans", planTaskId), {
223
+ recursive: true,
224
+ });
225
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(cwd, "teamshare", "plans", planTaskId, "plan-prompt.md"), prompt, "utf8");
226
+ }
227
+ catch {
228
+ /* best-effort */
229
+ }
230
+ }
231
+ // Clear any stale result file so we never read a previous plan.
232
+ try {
233
+ if ((0, node_fs_1.existsSync)(resultPath))
234
+ (0, node_fs_1.unlinkSync)(resultPath);
235
+ }
236
+ catch {
237
+ /* ignore */
238
+ }
108
239
  const heartbeatTimer = setInterval(() => {
109
- void (0, brief_1.reportStatus)(api, agentId, 'working', parentTaskId, sessionId);
240
+ void (0, brief_1.reportStatus)(api, agentId, "working", planTaskId, sessionId);
110
241
  }, 120_000);
111
242
  try {
112
- const endpoint = (0, utils_1.llmEndpoint)(flags, settings);
113
- let plan = null;
114
- if (harness && harness !== 'none') {
115
- log(`[planner] spawning ${harness} harness for decomposition`);
116
- // Spawn the harness. The agent will call submit_plan which writes
117
- // the validated plan to a temp file. We wait for the file to appear.
243
+ if (harness && harness !== "none") {
244
+ log(`[planner] spawning ${harness} harness for ${mode} planning`);
118
245
  const exit = await (0, harness_1.spawnHarness)(harness, prompt, log, {
119
246
  model: (0, utils_1.modelOf)(flags, settings),
120
247
  temperature: (0, utils_1.temperatureOf)(flags, settings),
121
248
  effort: (0, utils_1.effortOf)(flags, settings) ?? (0, utils_1.defaultEffort)(harness),
122
249
  cwd,
123
250
  timeoutMin: (0, utils_1.sessionTimeoutMin)(flags),
124
- title: `Planner decomposition for task ${parentTaskId.slice(0, 8)}`,
251
+ title: `Planner ${mode} for task ${planTaskId.slice(0, 8)}`,
125
252
  agentKey: apiKey,
126
253
  apiBaseUrl: api.baseUrl,
127
254
  providerKey: settings.providerKey ?? undefined,
128
- sessionMode: 'run',
255
+ sessionMode: "run",
129
256
  sessionId,
130
257
  });
131
- // Read the result file written by submit_plan.
132
- plan = readResultFile(resultPath, log);
133
- if (!plan && exit !== 0) {
134
- log(`[planner] WARNING: harness exited with code ${exit} and no plan file found at ${resultPath}`, 'stderr');
135
- }
136
- else if (!plan) {
137
- log(`[planner] WARNING: harness exited successfully but no plan file found at ${resultPath}`, 'stderr');
258
+ if (exit !== 0) {
259
+ log(`[planner] WARNING: harness exited with code ${exit}`, "stderr");
138
260
  }
139
261
  }
140
262
  else {
141
- log(`[planner] WARNING: no harness binary found on PATH — falling back to headless LLM (install opencode or set harness in agent settings)`, 'stderr');
142
- }
143
- // Fall back to headless LLM if harness didn't produce a plan.
144
- if (!plan) {
145
- log(`[planner] falling back to headless LLM (harness did not produce a plan)`);
146
- plan = await runHeadlessPlanner(prompt, {
147
- baseUrl: endpoint.baseUrl,
148
- apiKey: (0, utils_1.sessionLlmApiKey)(settings),
149
- model: endpoint.model,
150
- temperature: (0, utils_1.temperatureOf)(flags, settings),
151
- maxTokens: (0, utils_1.maxTokensOf)(flags, settings),
152
- }, log);
153
- }
154
- if (plan && plan.length > 0) {
155
- // Write the final result for the bridge to read.
156
- (0, node_fs_1.writeFileSync)(resultPath, JSON.stringify({ tasks: plan }), 'utf-8');
157
- log(`[planner] plan ready: ${plan.length} subtasks -> ${resultPath}`);
158
- }
159
- else {
160
- // Single-node fallback.
161
- const fallback = [{ title: description.slice(0, 200), description, dependencies: [], verification: [] }];
162
- (0, node_fs_1.writeFileSync)(resultPath, JSON.stringify({ tasks: fallback }), 'utf-8');
163
- log(`[planner] fallback: single node -> ${resultPath}`);
263
+ log(`[planner] WARNING: no harness binary found on PATH — the planner cannot run (install opencode or set the harness in agent settings)`, "stderr");
164
264
  }
265
+ // Read the plan the agent submitted. If it did not submit one, keep the
266
+ // given queue unchanged — never invent replacement tasks.
267
+ const result = readResultFile(resultPath, mode, queueIds, log);
268
+ (0, node_fs_1.writeFileSync)(resultPath, JSON.stringify(result), "utf-8");
269
+ log(`[planner] plan ready: mode=${mode} tasks=${result.tasks.length} ordered=${result.orderedTaskIds.length} -> ${resultPath}`);
270
+ await (0, brief_1.postClosingComment)(api, planTaskId, mode === "overview"
271
+ ? `[plan] Overview plan ready for ${queueIds.length} queued task(s); execution order set.`
272
+ : `[plan] Planning pass finished; description, acceptance criteria, checklist and plan.md updated.`).catch(() => undefined);
165
273
  }
166
274
  finally {
167
275
  clearInterval(heartbeatTimer);
168
276
  void api.releaseSessionClaims(sessionId).catch(() => { });
169
- await (0, brief_1.reportStatus)(api, agentId, 'online', parentTaskId, sessionId);
277
+ await (0, brief_1.reportStatus)(api, agentId, "online", planTaskId, sessionId);
170
278
  }
171
279
  }
172
280
  catch (err) {
173
- const { msg } = await Promise.resolve().then(() => __importStar(require('../../lib/config')));
174
- log(`[error] ${msg(err)}`, 'stderr');
281
+ const { msg } = await Promise.resolve().then(() => __importStar(require("../../lib/config")));
282
+ log(`[error] ${msg(err)}`, "stderr");
175
283
  exitCode = 1;
176
284
  }
177
285
  finally {
@@ -180,68 +288,65 @@ async function cmdPlanner(flags) {
180
288
  await reporter.end(exitCode);
181
289
  }
182
290
  }
183
- /** Read the plan from the result file written by submit_plan MCP tool. */
184
- function readResultFile(resultPath, log) {
185
- try {
186
- const raw = (0, node_fs_1.readFileSync)(resultPath, 'utf-8');
187
- const parsed = JSON.parse(raw);
188
- const tasks = parsed?.tasks;
189
- if (!Array.isArray(tasks) || tasks.length === 0)
190
- return null;
191
- // Validate and normalize.
192
- return tasks.map((node, i) => ({
193
- title: String(node.title ?? `Step ${i + 1}`).slice(0, 200),
194
- description: String(node.description ?? ''),
195
- dependencies: Array.isArray(node.dependencies)
196
- ? node.dependencies.filter((d) => Number.isInteger(d) && d >= 0 && d < tasks.length && d !== i)
197
- : [],
198
- verification: Array.isArray(node.verification)
199
- ? node.verification.filter((v) => v.trim().length > 0)
200
- : [],
201
- }));
202
- }
203
- catch {
204
- log(`[planner] result file not found or invalid: ${resultPath}`, 'stderr');
205
- return null;
206
- }
207
- }
291
+ /** Resolve the agent API key from flags (mirrors the shared helper). */
208
292
  /**
209
- * Headless planner fallback: uses the complete() LLM call directly (no
210
- * harness, no MCP tools). Returns the parsed plan.
293
+ * Read + normalize the plan the agent submitted via `submit_plan`. When no
294
+ * plan was submitted the given queue is preserved untouched (no invented
295
+ * tasks) so the run still proceeds.
211
296
  */
212
- async function runHeadlessPlanner(prompt, llmOpts, log) {
297
+ function readResultFile(resultPath, mode, queueIds, log) {
298
+ const fallback = {
299
+ tasks: [],
300
+ orderedTaskIds: queueIds,
301
+ dependencies: [],
302
+ };
303
+ if (!(0, node_fs_1.existsSync)(resultPath)) {
304
+ log(`[planner] no plan submitted - keeping the given queue order`, "stderr");
305
+ return fallback;
306
+ }
213
307
  try {
214
- const raw = await (0, llm_1.complete)(prompt, {
215
- baseUrl: llmOpts.baseUrl,
216
- apiKey: llmOpts.apiKey,
217
- model: llmOpts.model,
218
- temperature: llmOpts.temperature ?? 0.2,
219
- maxTokens: llmOpts.maxTokens ?? 2000,
220
- });
221
- const cleaned = raw.replace(/```json/gi, '').replace(/```/g, '').trim();
222
- const start = cleaned.indexOf('[');
223
- const end = cleaned.lastIndexOf(']');
224
- if (start < 0 || end <= start) {
225
- log('[planner] headless LLM returned unparseable response', 'stderr');
226
- return null;
227
- }
228
- const parsed = JSON.parse(cleaned.slice(start, end + 1));
229
- if (!Array.isArray(parsed) || parsed.length === 0)
230
- return null;
231
- return parsed.map((node, i) => ({
232
- title: String(node.title ?? `Step ${i + 1}`).slice(0, 200),
233
- description: String(node.description ?? ''),
308
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(resultPath, "utf-8"));
309
+ const rawTasks = Array.isArray(parsed.tasks)
310
+ ? parsed.tasks
311
+ : [];
312
+ const tasks = rawTasks.map((node, i) => ({
313
+ title: sanitizeTitle(String(node.title ?? ""), `Step ${i + 1}`),
314
+ description: String(node.description ?? ""),
234
315
  dependencies: Array.isArray(node.dependencies)
235
- ? node.dependencies.filter((d) => Number.isInteger(d) && d >= 0 && d < parsed.length && d !== i)
316
+ ? node.dependencies.filter((d) => Number.isInteger(d) && d >= 0 && d < rawTasks.length && d !== i)
236
317
  : [],
237
318
  verification: Array.isArray(node.verification)
238
- ? node.verification.filter((v) => String(v).trim().length > 0).map(String)
319
+ ? node.verification.filter((v) => v.trim().length > 0)
239
320
  : [],
240
321
  }));
322
+ const ordered = Array.isArray(parsed.orderedTaskIds)
323
+ ? parsed.orderedTaskIds
324
+ .map(String)
325
+ .filter((id) => queueIds.includes(id))
326
+ : [];
327
+ const known = new Set(queueIds);
328
+ const dependencies = Array.isArray(parsed.dependencies)
329
+ ? parsed.dependencies.filter((e) => Array.isArray(e) &&
330
+ e.length === 2 &&
331
+ e[0] !== e[1] &&
332
+ known.has(e[0]) &&
333
+ known.has(e[1]))
334
+ : [];
335
+ return {
336
+ tasks: mode === "overview" ? [] : tasks,
337
+ orderedTaskIds: ordered.length ? ordered : queueIds,
338
+ dependencies,
339
+ planMarkdown: typeof parsed.planMarkdown === "string"
340
+ ? parsed.planMarkdown
341
+ : undefined,
342
+ acceptanceCriteria: typeof parsed.acceptanceCriteria === "string"
343
+ ? parsed.acceptanceCriteria
344
+ : undefined,
345
+ };
241
346
  }
242
- catch (err) {
243
- log(`[planner] headless LLM failed: ${err instanceof Error ? err.message : String(err)}`, 'stderr');
244
- return null;
347
+ catch {
348
+ log(`[planner] result file invalid: ${resultPath}`, "stderr");
349
+ return fallback;
245
350
  }
246
351
  }
247
352
  //# sourceMappingURL=planner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/cli/commands/planner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/cli/commands/planner.ts"],"names":[],"mappings":"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"}
@@ -139,7 +139,7 @@ function buildBrief(run, projectName) {
139
139
  lines.push(`- ${role}${d.required ? ' — REQUIRED' : ''}`);
140
140
  }
141
141
  if (spec.outputContract.manifest) {
142
- lines.push('- A source manifest — REQUIRED: map every output to its source URL(s) and local path.');
142
+ lines.push(`- Source manifest — REQUIRED: \`<Subject> — Sources (YYYY-MM-DD).md\` mapping every output to its source URL(s) and local path (table: Output | Type | Source URL(s) | Local path | Retrieved). State "No external sources" when the output is purely derived.`);
143
143
  }
144
144
  lines.push('');
145
145
  }
@@ -152,6 +152,7 @@ function buildBrief(run, projectName) {
152
152
  lines.push(`Name every DELIVERABLE \`<Subject> — <Artifact> (YYYY-MM-DD).<ext>\`, where Subject is ${baseName ? `\`${baseName}\`` : 'a short, specific label for this task'} (shorten it if the content is more specific). ` +
153
153
  `Example: \`${baseName ?? 'Abuja Web Dev Prospects'} — Leads (${today}).xlsx\`.`);
154
154
  lines.push('Never use a bare generic name (e.g. `leads.xlsx`, `summary.md`). Exception: render-handoff/spec files keep their EXACT name (`chart-data.csv`, `data.csv`, `outline.md`, `document.docx`) — only the final deliverable gets the descriptive name.');
155
+ lines.push('The source manifest is a DELIVERABLE: name it `<Subject> — Sources (YYYY-MM-DD).md` (artifact = `Sources`), never a bare `manifest.md`/`sources.md`.');
155
156
  lines.push('');
156
157
  // Allowed TeamShare MCP tools.
157
158
  if (spec?.requiredMcpTools?.length) {
@@ -229,7 +230,10 @@ function buildInstructions(run, folderBase) {
229
230
  parts.push(`Produce ${d.type === 'xlsx' ? 'an Excel workbook' : `a \`${d.name}\``} (${d.type})${d.required ? ' — required' : ''} under \`${folderBase}\`.`);
230
231
  }
231
232
  if (spec.outputContract.manifest) {
232
- parts.push(`Write \`manifest.md\` under \`${folderBase}\` mapping every output document to its source URL(s) and local path.`);
233
+ parts.push(`Write the SOURCE MANIFEST \`<subject> Sources (YYYY-MM-DD).md\` (a note via create_document) under \`${folderBase}\`. ` +
234
+ `It MUST map every output document above to its source URL(s) and local path, with a table: \`Output | Type | Source URL(s) | Local path | Retrieved\`. ` +
235
+ `Use numbered citations \`[n](url)\` that match the ones inside the deliverable, then a "Sources" list. ` +
236
+ `When the output is purely derived (no web research), state "No external sources" explicitly and record the input document as the provenance root.`);
233
237
  }
234
238
  return parts.join('\n') + common;
235
239
  }