@ordewell/core 0.4.10 → 0.4.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.
Files changed (43) hide show
  1. package/dist/{ITerminalRunner-CbE6gKLI.d.ts → ITerminalRunner-BTaKZ659.d.mts} +2 -2
  2. package/dist/{ITerminalRunner-1NAv8wCC.d.mts → ITerminalRunner-DVwORcV9.d.ts} +2 -2
  3. package/dist/{ModeResolver-F5wnlSz1.d.mts → ModeResolver-CCKYqdZC.d.mts} +1 -1
  4. package/dist/{ModeResolver-Dx5gzNPC.d.ts → ModeResolver-CzZd-i6T.d.ts} +1 -1
  5. package/dist/{Task-1NwmUImI.d.mts → Task-cGrfYRXK.d.mts} +8 -1
  6. package/dist/{Task-1NwmUImI.d.ts → Task-cGrfYRXK.d.ts} +8 -1
  7. package/dist/{chunk-YI4ZDZEE.mjs → chunk-DNNZGH3I.mjs} +2 -2
  8. package/dist/chunk-HPNUFBIT.mjs +19 -0
  9. package/dist/chunk-HPNUFBIT.mjs.map +1 -0
  10. package/dist/{chunk-IO6PEEN6.mjs → chunk-N6HTBUKG.mjs} +11 -1
  11. package/dist/chunk-N6HTBUKG.mjs.map +1 -0
  12. package/dist/{chunk-TUGJXD4G.mjs → chunk-UEJ3SZQ7.mjs} +2 -2
  13. package/dist/index.d.mts +124 -73
  14. package/dist/index.d.ts +124 -73
  15. package/dist/index.js +611 -433
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +590 -442
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/order-labels.d.mts +17 -0
  20. package/dist/order-labels.d.ts +17 -0
  21. package/dist/order-labels.js +44 -0
  22. package/dist/order-labels.js.map +1 -0
  23. package/dist/order-labels.mjs +9 -0
  24. package/dist/order-labels.mjs.map +1 -0
  25. package/dist/{parsing-BqbJySeo.d.mts → parsing-BT-dvFcu.d.mts} +2 -2
  26. package/dist/{parsing-X0Gvuz-q.d.ts → parsing-D87zKtTe.d.ts} +2 -2
  27. package/dist/parsing.d.mts +3 -3
  28. package/dist/parsing.d.ts +3 -3
  29. package/dist/parsing.js.map +1 -1
  30. package/dist/parsing.mjs +3 -2
  31. package/dist/{plan-utils-B5rVXNVI.d.mts → plan-utils-BHLbBym3.d.mts} +2 -2
  32. package/dist/{plan-utils-DtsfHnn_.d.ts → plan-utils-akoB6YCL.d.ts} +2 -2
  33. package/dist/plan-utils.d.mts +3 -3
  34. package/dist/plan-utils.d.ts +3 -3
  35. package/dist/plan-utils.mjs +3 -2
  36. package/dist/testing.d.mts +2 -2
  37. package/dist/testing.d.ts +2 -2
  38. package/package.json +12 -2
  39. package/skills/grilling/SKILL.md +31 -0
  40. package/skills/to-spec/SKILL.md +64 -0
  41. package/dist/chunk-IO6PEEN6.mjs.map +0 -1
  42. /package/dist/{chunk-YI4ZDZEE.mjs.map → chunk-DNNZGH3I.mjs.map} +0 -0
  43. /package/dist/{chunk-TUGJXD4G.mjs.map → chunk-UEJ3SZQ7.mjs.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { h as RunnerId } from './Task-1NwmUImI.js';
1
+ import { h as RunnerId } from './Task-cGrfYRXK.mjs';
2
2
 
3
3
  /**
4
4
  * The planner's single approval seam. Every capability that reaches beyond the
@@ -474,7 +474,7 @@ interface RunnerInvocation {
474
474
  * testable without real I/O.
475
475
  */
476
476
  interface IPluginStore {
477
- /** Path to the user plugins directory (~/.config/ordewell/plugins/). */
477
+ /** Path to the user plugins directory (~/.ordewell/plugins/). */
478
478
  getUserPluginsDir(): string;
479
479
  /** List subdirectory names inside the user plugins directory. */
480
480
  listUserPluginDirs(): string[];
@@ -1,4 +1,4 @@
1
- import { h as RunnerId } from './Task-1NwmUImI.mjs';
1
+ import { h as RunnerId } from './Task-cGrfYRXK.js';
2
2
 
3
3
  /**
4
4
  * The planner's single approval seam. Every capability that reaches beyond the
@@ -474,7 +474,7 @@ interface RunnerInvocation {
474
474
  * testable without real I/O.
475
475
  */
476
476
  interface IPluginStore {
477
- /** Path to the user plugins directory (~/.config/ordewell/plugins/). */
477
+ /** Path to the user plugins directory (~/.ordewell/plugins/). */
478
478
  getUserPluginsDir(): string;
479
479
  /** List subdirectory names inside the user plugins directory. */
480
480
  listUserPluginDirs(): string[];
@@ -1,4 +1,4 @@
1
- import { h as RunnerId } from './Task-1NwmUImI.mjs';
1
+ import { h as RunnerId } from './Task-cGrfYRXK.mjs';
2
2
 
3
3
  interface RunnerModeInfo {
4
4
  id: string;
@@ -1,4 +1,4 @@
1
- import { h as RunnerId } from './Task-1NwmUImI.js';
1
+ import { h as RunnerId } from './Task-cGrfYRXK.js';
2
2
 
3
3
  interface RunnerModeInfo {
4
4
  id: string;
@@ -235,9 +235,16 @@ type PlanState = {
235
235
  };
236
236
  declare function migratePlanState(raw: unknown): PlanState;
237
237
  declare function migrateLegacyPlan(legacy: LegacyPlanState): PlanState;
238
+
238
239
  declare function createTask(overrides?: Partial<Task>): Task;
239
240
  declare function createEmptyPlan(): LegacyPlanState;
240
241
  declare function flattenTasks(tasks: Task[]): Task[];
242
+ /** A flattened task with the parent it hangs under, null for a top-level task. */
243
+ interface TaskWithParent {
244
+ task: Task;
245
+ parent: Task | null;
246
+ }
247
+ declare function flattenTasksWithParents(tasks: Task[]): TaskWithParent[];
241
248
  declare function migrateTask(task: Record<string, unknown>): Task;
242
249
  declare function addTaskToPlan(tasks: Task[], partial: Partial<Task>): Task[];
243
250
  declare function removeTaskFromPlan(tasks: Task[], taskId: string): Task[];
@@ -261,4 +268,4 @@ interface ValidationContext {
261
268
  type ValidationCheck = (ctx: ValidationContext) => ValidationResult;
262
269
  declare function warningsText(w: PlanModificationWarnings): string | null;
263
270
 
264
- export { type ActiveTaskSession as A, flattenTasks as B, type ConversationMessage as C, type DiscoveredMode as D, migrateLegacyPlan as E, migratePlanState as F, migrateTask as G, removeTaskFromPlan as H, renumberTasks as I, updateTaskInPlan as J, validateModifiedPlan as K, type LegacyPlanState as L, type Message as M, warningsText as N, type PlanModificationWarnings as P, type QueuedMessage as Q, type ResearchLogEntry as R, type StreamEvent as S, type Task as T, type UserPromptEntry as U, type ValidationCheck as V, type DiscoveredModel as a, type PlanState as b, type PlanStatus as c, type ResearchProgress as d, type ResearchStep as e, type ResearchStepOutcome as f, type ResearchToolType as g, type RunnerId as h, type StreamStepEvent as i, type StreamThinkingEvent as j, type TaskMode as k, type TaskModelAssignment as l, type TaskOutputSummary as m, type TaskSnapshot as n, type TaskStatus as o, type TaskType as p, type ThinkingBlock as q, type UserStep as r, type ValidationContext as s, type ValidationResult as t, type Verdict as u, type VerificationCheck as v, addTaskToPlan as w, createEmptyPlan as x, createTask as y, emptyWarnings as z };
271
+ export { type ActiveTaskSession as A, emptyWarnings as B, type ConversationMessage as C, type DiscoveredMode as D, flattenTasks as E, flattenTasksWithParents as F, migrateLegacyPlan as G, migratePlanState as H, migrateTask as I, removeTaskFromPlan as J, renumberTasks as K, type LegacyPlanState as L, type Message as M, updateTaskInPlan as N, validateModifiedPlan as O, type PlanModificationWarnings as P, type QueuedMessage as Q, type ResearchLogEntry as R, type StreamEvent as S, type Task as T, type UserPromptEntry as U, type ValidationCheck as V, warningsText as W, type DiscoveredModel as a, type PlanState as b, type PlanStatus as c, type ResearchProgress as d, type ResearchStep as e, type ResearchStepOutcome as f, type ResearchToolType as g, type RunnerId as h, type StreamStepEvent as i, type StreamThinkingEvent as j, type TaskMode as k, type TaskModelAssignment as l, type TaskOutputSummary as m, type TaskSnapshot as n, type TaskStatus as o, type TaskType as p, type TaskWithParent as q, type ThinkingBlock as r, type UserStep as s, type ValidationContext as t, type ValidationResult as u, type Verdict as v, type VerificationCheck as w, addTaskToPlan as x, createEmptyPlan as y, createTask as z };
@@ -235,9 +235,16 @@ type PlanState = {
235
235
  };
236
236
  declare function migratePlanState(raw: unknown): PlanState;
237
237
  declare function migrateLegacyPlan(legacy: LegacyPlanState): PlanState;
238
+
238
239
  declare function createTask(overrides?: Partial<Task>): Task;
239
240
  declare function createEmptyPlan(): LegacyPlanState;
240
241
  declare function flattenTasks(tasks: Task[]): Task[];
242
+ /** A flattened task with the parent it hangs under, null for a top-level task. */
243
+ interface TaskWithParent {
244
+ task: Task;
245
+ parent: Task | null;
246
+ }
247
+ declare function flattenTasksWithParents(tasks: Task[]): TaskWithParent[];
241
248
  declare function migrateTask(task: Record<string, unknown>): Task;
242
249
  declare function addTaskToPlan(tasks: Task[], partial: Partial<Task>): Task[];
243
250
  declare function removeTaskFromPlan(tasks: Task[], taskId: string): Task[];
@@ -261,4 +268,4 @@ interface ValidationContext {
261
268
  type ValidationCheck = (ctx: ValidationContext) => ValidationResult;
262
269
  declare function warningsText(w: PlanModificationWarnings): string | null;
263
270
 
264
- export { type ActiveTaskSession as A, flattenTasks as B, type ConversationMessage as C, type DiscoveredMode as D, migrateLegacyPlan as E, migratePlanState as F, migrateTask as G, removeTaskFromPlan as H, renumberTasks as I, updateTaskInPlan as J, validateModifiedPlan as K, type LegacyPlanState as L, type Message as M, warningsText as N, type PlanModificationWarnings as P, type QueuedMessage as Q, type ResearchLogEntry as R, type StreamEvent as S, type Task as T, type UserPromptEntry as U, type ValidationCheck as V, type DiscoveredModel as a, type PlanState as b, type PlanStatus as c, type ResearchProgress as d, type ResearchStep as e, type ResearchStepOutcome as f, type ResearchToolType as g, type RunnerId as h, type StreamStepEvent as i, type StreamThinkingEvent as j, type TaskMode as k, type TaskModelAssignment as l, type TaskOutputSummary as m, type TaskSnapshot as n, type TaskStatus as o, type TaskType as p, type ThinkingBlock as q, type UserStep as r, type ValidationContext as s, type ValidationResult as t, type Verdict as u, type VerificationCheck as v, addTaskToPlan as w, createEmptyPlan as x, createTask as y, emptyWarnings as z };
271
+ export { type ActiveTaskSession as A, emptyWarnings as B, type ConversationMessage as C, type DiscoveredMode as D, flattenTasks as E, flattenTasksWithParents as F, migrateLegacyPlan as G, migratePlanState as H, migrateTask as I, removeTaskFromPlan as J, renumberTasks as K, type LegacyPlanState as L, type Message as M, updateTaskInPlan as N, validateModifiedPlan as O, type PlanModificationWarnings as P, type QueuedMessage as Q, type ResearchLogEntry as R, type StreamEvent as S, type Task as T, type UserPromptEntry as U, type ValidationCheck as V, warningsText as W, type DiscoveredModel as a, type PlanState as b, type PlanStatus as c, type ResearchProgress as d, type ResearchStep as e, type ResearchStepOutcome as f, type ResearchToolType as g, type RunnerId as h, type StreamStepEvent as i, type StreamThinkingEvent as j, type TaskMode as k, type TaskModelAssignment as l, type TaskOutputSummary as m, type TaskSnapshot as n, type TaskStatus as o, type TaskType as p, type TaskWithParent as q, type ThinkingBlock as r, type UserStep as s, type ValidationContext as t, type ValidationResult as u, type Verdict as v, type VerificationCheck as w, addTaskToPlan as x, createEmptyPlan as y, createTask as z };
@@ -10,7 +10,7 @@ import {
10
10
  renumberTasks,
11
11
  stripTrailingCommas,
12
12
  updateTaskInPlan
13
- } from "./chunk-IO6PEEN6.mjs";
13
+ } from "./chunk-N6HTBUKG.mjs";
14
14
 
15
15
  // src/services/ModelAllowlistResolver.ts
16
16
  function effectiveAllowlist(allowlist, runner, modelsByRunner) {
@@ -859,4 +859,4 @@ export {
859
859
  summarizeToolCall,
860
860
  classifyOutcome
861
861
  };
862
- //# sourceMappingURL=chunk-YI4ZDZEE.mjs.map
862
+ //# sourceMappingURL=chunk-DNNZGH3I.mjs.map
@@ -0,0 +1,19 @@
1
+ // src/order-labels.ts
2
+ function taskOrderLabel(task, parent) {
3
+ return parent ? `${parent.order}.${task.order}` : String(task.order);
4
+ }
5
+ function resolveOrderLabel(tasks, label) {
6
+ const parts = label.split(".");
7
+ if (parts.length > 2 || parts.some((p) => !/^\d+$/.test(p))) return void 0;
8
+ const [topOrder, childOrder] = parts.map(Number);
9
+ const top = tasks.find((t) => t.order === topOrder);
10
+ if (!top) return void 0;
11
+ if (childOrder === void 0) return top;
12
+ return top.subtasks.find((s) => s.order === childOrder);
13
+ }
14
+
15
+ export {
16
+ taskOrderLabel,
17
+ resolveOrderLabel
18
+ };
19
+ //# sourceMappingURL=chunk-HPNUFBIT.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/order-labels.ts"],"sourcesContent":["import type { Task } from './models/Task';\n\n/**\n * Parent-scoped dotted order label for a task, e.g. \"2.1\" for the first subtask\n * of task 2. Kept in its own module (no Node imports) so a browser-bundled\n * surface — the VS Code webview — can import it via `@ordewell/core/order-labels`\n * without dragging the rest of core in.\n */\nexport function taskOrderLabel(task: { order: number }, parent?: { order: number }): string {\n return parent ? `${parent.order}.${task.order}` : String(task.order);\n}\n\n/** Resolve a dotted label to a task in a plan's top-level task list. */\nexport function resolveOrderLabel(tasks: Task[], label: string): Task | undefined {\n const parts = label.split('.');\n if (parts.length > 2 || parts.some((p) => !/^\\d+$/.test(p))) return undefined;\n const [topOrder, childOrder] = parts.map(Number);\n const top = tasks.find((t) => t.order === topOrder);\n if (!top) return undefined;\n if (childOrder === undefined) return top;\n return top.subtasks.find((s) => s.order === childOrder);\n}"],"mappings":";AAQO,SAAS,eAAe,MAAyB,QAAoC;AAC1F,SAAO,SAAS,GAAG,OAAO,KAAK,IAAI,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK;AACrE;AAGO,SAAS,kBAAkB,OAAe,OAAiC;AAChF,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,MAAI,MAAM,SAAS,KAAK,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,EAAG,QAAO;AACpE,QAAM,CAAC,UAAU,UAAU,IAAI,MAAM,IAAI,MAAM;AAC/C,QAAM,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,QAAQ;AAClD,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,eAAe,OAAW,QAAO;AACrC,SAAO,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,UAAU;AACxD;","names":[]}
@@ -184,6 +184,15 @@ function createEmptyPlan() {
184
184
  function flattenTasks(tasks) {
185
185
  return tasks.flatMap((t) => [t, ...flattenTasks(t.subtasks ?? [])]);
186
186
  }
187
+ function flattenTasksWithParents(tasks) {
188
+ const rows = [];
189
+ const walk = (t, parent) => {
190
+ rows.push({ task: t, parent });
191
+ for (const sub of t.subtasks ?? []) walk(sub, t);
192
+ };
193
+ for (const t of tasks) walk(t, null);
194
+ return rows;
195
+ }
187
196
  function migrateTask(task) {
188
197
  if (!task.assignedModel) {
189
198
  task.assignedModel = void 0;
@@ -444,6 +453,7 @@ export {
444
453
  createTask,
445
454
  createEmptyPlan,
446
455
  flattenTasks,
456
+ flattenTasksWithParents,
447
457
  migrateTask,
448
458
  addTaskToPlan,
449
459
  removeTaskFromPlan,
@@ -462,4 +472,4 @@ export {
462
472
  stripTrailingCommas,
463
473
  escapeControlCharsInStrings
464
474
  };
465
- //# sourceMappingURL=chunk-IO6PEEN6.mjs.map
475
+ //# sourceMappingURL=chunk-N6HTBUKG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/models/Task.ts","../src/services/JsonExtractor.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid';\n\nexport interface UserStep {\n order: number;\n instruction: string;\n completed: boolean;\n}\n\n/** One deterministic signal gathered while verifying a completed task. */\nexport interface VerificationCheck {\n name: 'exit_code' | 'completion_marker' | 'manual';\n passed: boolean;\n /** A check that did not apply. Skipped checks don't affect the verdict. */\n skipped: boolean;\n detail: string;\n}\n\n/** Evidence-based verdict for a completed task. Single end-to-end outcome produced by verification. */\nexport interface Verdict {\n outcome: 'pass' | 'fail';\n reason: string;\n checks: VerificationCheck[];\n decidedAt: string;\n}\n\nexport interface TaskOutputSummary {\n reviewReason: string;\n logTail: string;\n capturedAt: string;\n}\n\nexport type TaskType = 'ai' | 'user';\nexport type TaskStatus = 'pending' | 'approved' | 'in_progress' | 'completed' | 'failed' | 'blocked' | 'awaiting_user';\nexport type TaskMode = string;\n\nexport interface TaskModelAssignment {\n modelId: string;\n modelLabel: string;\n thinkingEffort?: string;\n /**\n * All variant ids the model offered when this assignment was made. Carried\n * on the assignment because runners need it at spawn time (opencode's TUI\n * only honors an assigned variant when the others are config-disabled) and\n * the discovery catalog isn't available there.\n */\n availableVariants?: string[];\n}\n\nexport type RunnerId = string;\n\nexport interface Task {\n id: string;\n order: number;\n title: string;\n description: string;\n type: TaskType;\n status: TaskStatus;\n dependencies: string[];\n prompt?: string;\n userSteps?: UserStep[];\n subtasks: Task[];\n verdict?: Verdict;\n outputSummary?: TaskOutputSummary;\n assignedModel?: TaskModelAssignment;\n assignedRunner: RunnerId;\n thinkingEffort?: string;\n taskMode?: TaskMode;\n completionMarker: string;\n autonomy?: 'AFK' | 'HITL';\n sliceType?: 'HITL' | 'AFK';\n userStoriesCovered?: string[];\n}\n\nexport interface DiscoveredMode {\n id: string;\n label: string;\n description: string;\n}\n\nexport type ResearchToolType =\n | 'read_file' | 'read_files' | 'glob' | 'grep' | 'find_symbol' | 'list_dir'\n | 'bash' | 'fetch' | 'web_search' | 'spawn_research_agent'\n /**\n * A tool belonging to a harness planner's own toolbox (ADR-0009) that has no\n * Ordewell equivalent — Edit, WebFetch, TodoWrite, whatever a coding agent\n * ships next. The real name travels in `toolLabel` rather than being\n * relabelled as a tool it is not; the union stays closed so the\n * exhaustiveness checks in every surface's icon/label switch survive.\n */\n | 'agent_tool';\n\n/**\n * What happened when a research tool call ran, for honest per-surface\n * rendering. The broadcast seam carries this on every `research_step_done` so\n * surfaces do not have to pattern-match refusal text to tell a refused `rm`\n * from a successful `rm` — the old render path flipped a `✓` for both.\n */\nexport type ResearchStepOutcome = 'success' | 'failure' | 'refused' | 'denied' | 'not_executed';\n\nexport interface ResearchStep {\n id: string;\n tool: ResearchToolType;\n /** The tool's own name when it came from a harness planner — always set for `agent_tool`. */\n toolLabel?: string;\n args: string;\n result: string;\n success: boolean;\n outcome: ResearchStepOutcome;\n /** The model's tool_call id, so a surface can match `tool_result` to the\n * pending `tool_call` it announced — robust under parallel same-tool rounds. */\n toolCallId?: string;\n timestamp: string;\n thinkingText?: string;\n}\n\nexport interface UserPromptEntry {\n id: string;\n type: 'user_prompt' | 'system';\n content: string;\n timestamp: string;\n}\n\nexport type ResearchLogEntry = ResearchStep | UserPromptEntry;\n\nexport interface ResearchProgress {\n type: 'thinking' | 'tool_call' | 'tool_result' | 'plan_token' | 'interrupted';\n text?: string;\n tool?: string;\n /** Harness planners (ADR-0009): the agent's own name for a tool Ordewell has no member for. */\n toolLabel?: string;\n toolArgs?: string;\n toolResult?: string;\n planToken?: string;\n step?: ResearchStep;\n /** The model's tool_call id, threaded on tool_call and tool_result so a\n * surface can match the result to its pending call — robust under parallel\n * same-tool rounds where LIFO-by-name matching mislabels summaries. */\n toolCallId?: string;\n /** Present when this event originates from (or reports on) one spawned research subagent (issue #34). */\n subagentId?: string;\n}\n\nexport interface ThinkingBlock {\n id: string;\n text: string;\n}\n\nexport interface StreamThinkingEvent {\n type: 'thinking';\n block: ThinkingBlock;\n}\n\nexport interface StreamStepEvent {\n type: 'step';\n step: ResearchStep;\n}\n\nexport type StreamEvent = StreamThinkingEvent | StreamStepEvent;\n\nexport interface DiscoveredModel {\n modelId: string;\n modelLabel: string;\n runnerProvider?: string;\n /**\n * Human-facing provider name as the runner itself reports it (e.g.\n * \"OpenCode Zen\" for `runnerProvider: 'opencode'`). Populated from the\n * runner's own provider catalog when available; when absent the UI derives a\n * label from `runnerProvider` by title-casing.\n */\n runnerProviderLabel?: string;\n /**\n * The runner whose catalog listed this model. Stamped once, at the single\n * `ModelDiscovery.discover` choke point, so a flat cross-runner list can\n * still say where each entry came from — `runnerProvider` alone cannot:\n * OpenCode reports most of its catalog as `openrouter`, which names the\n * serving backend, not the agent Ordewell would spawn.\n */\n runnerId?: string;\n /** The runner's display name (`OpenCode`), from its manifest. */\n runnerLabel?: string;\n variants: { id: string; label: string }[];\n}\n\nexport type PlanStatus = 'draft' | 'approved' | 'rejected' | 'running' | 'completed';\n\n/**\n * One entry of the planner's persisted dialogue (ADR-0002). The single source\n * of truth for both UI redisplay and conversational context. Tool-call results\n * are NOT stored here — they live in the AI service's tool-use history;\n * `researchLog` remains the persisted tool trace for the UI.\n */\nexport interface ConversationMessage {\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n /**\n * Timeline marker: 'plan_generated' records the point in the dialogue where\n * the plan was committed (the UI anchors the plan card there on restore);\n * 'system' is a host-injected notice. Absent for ordinary chat turns, so\n * sessions saved before markers existed degrade gracefully.\n */\n kind?: 'plan_generated' | 'system';\n}\n\nexport interface QueuedMessage {\n id: string;\n text: string;\n timestamp: string;\n}\n\nexport interface PlanModificationWarnings {\n deletedCompleted: string[];\n changedCompleted: string[];\n deletedInProgress: string[];\n modifiedInProgress: string[];\n brokenDependencies: string[];\n}\n\nexport function emptyWarnings(): PlanModificationWarnings {\n return { deletedCompleted: [], changedCompleted: [], deletedInProgress: [], modifiedInProgress: [], brokenDependencies: [] };\n}\n\nexport interface LegacyPlanState {\n tasks: Task[];\n generatedAt: string;\n status: PlanStatus;\n runners: RunnerId[];\n lastUpdated: string;\n researchLog?: ResearchLogEntry[];\n /** The planner dialogue — user messages and assistant messages, in order (ADR-0002). */\n conversationHistory?: ConversationMessage[];\n /** Full markdown PRD once written by the planner (PRD mode), also saved to .scratch/<slug>/PRD.md. */\n prdMarkdown?: string;\n /** Follow-ups queued while tasks execute — applied as plan modifications between batches. */\n queuedMessages?: QueuedMessage[];\n}\n\nexport interface Message {\n id: string;\n role: 'user' | 'planner' | 'system';\n content: string;\n timestamp: number;\n}\n\nexport interface TaskSnapshot extends Task {\n completedAt: number;\n verdict?: Verdict;\n retryCount: number;\n finalized: boolean;\n}\n\nexport type PlanState =\n | {\n phase: 'planning';\n history: Message[];\n message: string;\n pendingTasks: Task[];\n }\n | {\n phase: 'executing';\n history: Message[];\n message: string;\n executionLog: TaskSnapshot[];\n pendingTasks: Task[];\n goal: string;\n runners: string[];\n status: PlanStatus;\n };\n\nfunction hasPhase(raw: unknown): raw is PlanState {\n return typeof raw === 'object' && raw !== null && 'phase' in raw;\n}\n\nfunction hasTasks(raw: unknown): raw is LegacyPlanState {\n return typeof raw === 'object' && raw !== null && 'tasks' in raw && Array.isArray((raw as Record<string, unknown>).tasks);\n}\n\nfunction migrateHistory(raw: LegacyPlanState): Message[] {\n const messages: Message[] = [];\n\n if (raw.researchLog) {\n for (const entry of raw.researchLog) {\n if ('type' in entry && entry.type === 'user_prompt') {\n messages.push({\n id: entry.id,\n role: 'user',\n content: (entry as UserPromptEntry).content,\n timestamp: new Date(entry.timestamp).getTime(),\n });\n } else {\n const step = entry as ResearchStep;\n messages.push({\n id: step.id,\n role: 'system',\n content: JSON.stringify({ tool: step.tool, args: step.args, result: step.result }),\n timestamp: new Date(step.timestamp).getTime(),\n });\n }\n }\n }\n\n if (raw.queuedMessages) {\n for (const qm of raw.queuedMessages) {\n messages.push({\n id: qm.id,\n role: 'system',\n content: qm.text,\n timestamp: new Date(qm.timestamp).getTime(),\n });\n }\n }\n\n return messages;\n}\n\nexport function migratePlanState(raw: unknown): PlanState {\n if (hasPhase(raw)) return raw;\n\n if (!hasTasks(raw)) {\n return {\n phase: 'planning',\n history: [],\n message: '',\n pendingTasks: [],\n };\n }\n\n const hasExecution = raw.tasks.some(\n (t) => t.status === 'completed' || t.status === 'failed',\n );\n\n const messages = migrateHistory(raw);\n\n if (hasExecution) {\n const executionLog: TaskSnapshot[] = raw.tasks\n .filter((t) => t.status === 'completed' || t.status === 'failed')\n .map((t) => ({\n ...t,\n completedAt: new Date(raw.lastUpdated).getTime(),\n verdict: t.verdict,\n retryCount: 0,\n finalized: true,\n }));\n\n const pendingTasks = raw.tasks.filter(\n (t) => t.status !== 'completed' && t.status !== 'failed' && t.status !== 'blocked',\n );\n\n return {\n phase: 'executing',\n history: messages,\n message: '',\n executionLog,\n pendingTasks,\n goal: '',\n runners: raw.runners,\n status: raw.status,\n };\n }\n\n return {\n phase: 'planning',\n history: messages,\n message: '',\n pendingTasks: raw.tasks,\n };\n}\n\nexport function migrateLegacyPlan(legacy: LegacyPlanState): PlanState {\n const messages: Message[] = [];\n\n if (legacy.researchLog) {\n for (const entry of legacy.researchLog) {\n if ('type' in entry && entry.type === 'user_prompt') {\n messages.push({\n id: entry.id,\n role: 'user',\n content: (entry as UserPromptEntry).content,\n timestamp: new Date(entry.timestamp).getTime(),\n });\n } else {\n const step = entry as ResearchStep;\n messages.push({\n id: step.id,\n role: 'system',\n content: JSON.stringify({ tool: step.tool, args: step.args, result: step.result }),\n timestamp: new Date(step.timestamp).getTime(),\n });\n }\n }\n }\n\n if (legacy.queuedMessages) {\n for (const qm of legacy.queuedMessages) {\n messages.push({\n id: qm.id,\n role: 'system',\n content: qm.text,\n timestamp: new Date(qm.timestamp).getTime(),\n });\n }\n }\n\n const isPlanning = legacy.status === 'draft' || legacy.status === 'approved' || legacy.status === 'rejected';\n\n if (isPlanning) {\n return {\n phase: 'planning',\n history: messages,\n message: 'Plan generation',\n pendingTasks: legacy.tasks.filter((t) => t.status === 'pending' || t.status === ('draft' as never)),\n };\n }\n\n const nonCompletedTasks = legacy.tasks.filter(\n (t) => t.status !== 'completed' && t.status !== 'failed' && t.status !== 'blocked'\n );\n\n const completedSnapshot: TaskSnapshot[] = legacy.tasks\n .filter((t) => t.status === 'completed' || t.status === 'failed')\n .map((t) => ({\n ...t,\n completedAt: new Date(legacy.lastUpdated).getTime(),\n verdict: t.verdict,\n retryCount: 0,\n finalized: true,\n }));\n\n return {\n phase: 'executing',\n history: messages,\n message: 'Plan migration',\n executionLog: completedSnapshot,\n pendingTasks: nonCompletedTasks,\n goal: 'Plan migration',\n runners: legacy.runners,\n status: legacy.status,\n };\n}\n\nexport { taskOrderLabel, resolveOrderLabel } from '../order-labels';\n\nexport function createTask(overrides: Partial<Task> = {}): Task {\n return {\n id: overrides.id ?? uuidv4(),\n order: overrides.order ?? 0,\n title: overrides.title ?? '',\n description: overrides.description ?? '',\n type: overrides.type ?? 'ai',\n status: overrides.status ?? 'pending',\n dependencies: overrides.dependencies ?? [],\n prompt: overrides.prompt,\n userSteps: overrides.userSteps,\n subtasks: overrides.subtasks ?? [],\n verdict: overrides.verdict,\n outputSummary: overrides.outputSummary,\n assignedModel: overrides.assignedModel,\n assignedRunner: overrides.assignedRunner ?? 'claude-code',\n thinkingEffort: overrides.thinkingEffort,\n taskMode: overrides.taskMode ?? 'build',\n completionMarker: overrides.completionMarker ?? uuidv4(),\n autonomy: overrides.autonomy,\n sliceType: overrides.sliceType,\n userStoriesCovered: overrides.userStoriesCovered,\n };\n}\n\nexport function createEmptyPlan(): LegacyPlanState {\n return {\n tasks: [],\n generatedAt: new Date().toISOString(),\n status: 'draft',\n runners: ['claude-code'],\n lastUpdated: new Date().toISOString(),\n };\n}\n\nexport function flattenTasks(tasks: Task[]): Task[] {\n return tasks.flatMap((t) => [t, ...flattenTasks(t.subtasks ?? [])]);\n}\n\n/** A flattened task with the parent it hangs under, null for a top-level task. */\nexport interface TaskWithParent {\n task: Task;\n parent: Task | null;\n}\n\nexport function flattenTasksWithParents(tasks: Task[]): TaskWithParent[] {\n const rows: TaskWithParent[] = [];\n const walk = (t: Task, parent: Task | null) => {\n rows.push({ task: t, parent });\n for (const sub of t.subtasks ?? []) walk(sub, t);\n };\n for (const t of tasks) walk(t, null);\n return rows;\n}\n\nexport function migrateTask(task: Record<string, unknown>): Task {\n if (!task.assignedModel) {\n task.assignedModel = undefined;\n }\n if (!task.assignedRunner) {\n task.assignedRunner = 'claude-code';\n }\n if (!task.thinkingEffort) {\n task.thinkingEffort = undefined;\n }\n if (!task.completionMarker) {\n task.completionMarker = uuidv4();\n }\n if (task.verdict && task.verification) {\n delete task.verification;\n }\n if (!task.autonomy) {\n task.autonomy = undefined;\n }\n if (!task.sliceType) {\n task.sliceType = undefined;\n }\n if (!task.userStoriesCovered) {\n task.userStoriesCovered = undefined;\n }\n return task as unknown as Task;\n}\n\nexport function addTaskToPlan(tasks: Task[], partial: Partial<Task>): Task[] {\n const maxOrder = tasks.reduce((max, t) => Math.max(max, t.order), 0);\n const newTask = createTask({\n ...partial,\n order: partial.order ?? maxOrder + 1,\n status: 'pending',\n });\n return renumberTasks([...tasks, newTask]);\n}\n\nexport function removeTaskFromPlan(tasks: Task[], taskId: string): Task[] {\n const result = tasks\n .filter((t) => t.id !== taskId)\n .map((t) => ({\n ...t,\n dependencies: t.dependencies.filter((depId) => depId !== taskId),\n subtasks: removeTaskFromPlan(t.subtasks, taskId),\n }));\n return renumberTasks(result);\n}\n\nexport function updateTaskInPlan(tasks: Task[], taskId: string, changes: Partial<Task>): Task[] {\n return renumberTasks(\n tasks.map((t) => {\n if (t.id === taskId) return { ...t, ...changes, id: t.id };\n return { ...t, subtasks: updateTaskInPlan(t.subtasks, taskId, changes) };\n })\n );\n}\n\nexport function renumberTasks(tasks: Task[]): Task[] {\n return tasks.map((t, i) => ({\n ...t,\n order: i + 1,\n subtasks: renumberTasks(t.subtasks),\n }));\n}\n\nexport function validateModifiedPlan(original: Task[], modified: Task[]): PlanModificationWarnings {\n const allOriginal = flattenTasks(original);\n const allModified = flattenTasks(modified);\n const warnings = emptyWarnings();\n const originalMap = new Map(allOriginal.map((t) => [t.id, t]));\n const modifiedIds = new Set(allModified.map((t) => t.id));\n\n for (const ot of originalMap.values()) {\n if (ot.status === 'completed' && !modifiedIds.has(ot.id)) {\n warnings.deletedCompleted.push(ot.title);\n } else if (ot.status === 'in_progress' && !modifiedIds.has(ot.id)) {\n warnings.deletedInProgress.push(ot.title);\n }\n }\n\n for (const mt of allModified) {\n const orig = originalMap.get(mt.id);\n if (orig) {\n if (orig.status === 'completed' && mt.status !== 'completed') {\n warnings.changedCompleted.push(orig.title);\n }\n if (orig.status === 'in_progress' && (mt.status !== 'in_progress' || mt.prompt !== orig.prompt)) {\n warnings.modifiedInProgress.push(orig.title);\n }\n if (orig.status === 'failed' && mt.status === 'pending') {\n for (const dt of allModified) {\n if (dt.dependencies.includes(mt.id) && dt.status === 'blocked') {\n dt.status = 'pending';\n }\n }\n }\n }\n }\n\n for (const t of allModified) {\n for (const depId of t.dependencies) {\n if (!modifiedIds.has(depId)) {\n warnings.brokenDependencies.push(`${t.title} → ${depId}`);\n }\n }\n }\n\n return warnings;\n}\n\nexport interface ActiveTaskSession {\n id: string;\n taskId: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport interface ValidationContext {\n executionLog: TaskSnapshot[];\n oldPending: Task[];\n newPending: Task[];\n activeSessions: Map<string, ActiveTaskSession>;\n}\n\nexport type ValidationCheck = (ctx: ValidationContext) => ValidationResult;\n\nexport function warningsText(w: PlanModificationWarnings): string | null {\n const lines: string[] = [];\n if (w.deletedCompleted.length) lines.push(`Completed tasks deleted: ${w.deletedCompleted.join(', ')}`);\n if (w.changedCompleted.length) lines.push(`Completed tasks modified: ${w.changedCompleted.join(', ')}`);\n if (w.deletedInProgress.length) lines.push(`In-progress tasks deleted: ${w.deletedInProgress.join(', ')}`);\n if (w.modifiedInProgress.length) lines.push(`In-progress tasks modified: ${w.modifiedInProgress.join(', ')}`);\n if (w.brokenDependencies.length) lines.push(`Broken dependencies: ${w.brokenDependencies.join(', ')}`);\n return lines.length > 0 ? lines.join('\\n') : null;\n}\n","/** The envelope key a full plan reply is keyed by: `{\"tasks\":[...]}`. */\nexport const PLAN_ENVELOPE_KEY = 'tasks';\n/** The envelope key a targeted-edits reply is keyed by: `{\"taskOps\":[...]}`. */\nexport const TASK_OPS_ENVELOPE_KEY = 'taskOps';\n/** The envelope key a read-only detail request is keyed by: `{\"taskQuery\":{...}}`. */\nexport const TASK_QUERY_ENVELOPE_KEY = 'taskQuery';\n\n/** Thrown when an LLM plan response cannot be parsed into a valid plan. Carries the raw text so callers can log it or retry. */\nexport class PlanParseError extends Error {\n readonly raw: string;\n /**\n * True when the reply was cut off mid-object (output-token limit) rather\n * than malformed — the two need different repairs: a truncated emission will\n * be cut at the same point again unless the retry frees context or asks for\n * terser output.\n */\n readonly truncated: boolean;\n /**\n * True when the JSON parsed fine and a *shape* rule rejected it. The generic\n * \"could not be parsed as JSON\" corrective is a lie for these, so the model\n * re-sends the same object; a semantic rejection must be repaired by naming\n * the rule it broke.\n */\n readonly semantic: boolean;\n constructor(message: string, raw: string, opts?: { truncated?: boolean; semantic?: boolean }) {\n super(message);\n this.name = 'PlanParseError';\n this.raw = raw;\n this.truncated = opts?.truncated ?? false;\n this.semantic = opts?.semantic ?? false;\n }\n}\n/**\n * Strip the noise reasoning models wrap around their answer: markdown code\n * fences and `<think>…</think>` chain-of-thought blocks (which routinely contain\n * stray braces that would otherwise derail brace-balancing). Reasoning captured\n * out-of-band by the service never reaches here, but a model that inlines its\n * thinking in the content channel still must not corrupt parsing.\n */\nexport function stripModelNoise(raw: string): string {\n return raw\n .replace(/<think>[\\s\\S]*?<\\/think>/gi, '')\n .replace(/```json\\s*/gi, '')\n .replace(/```\\s*/g, '')\n .trim();\n}\n\n/**\n * Scan from `start` (which must point at a `{`) for the matching balanced close,\n * ignoring braces inside strings. Returns the object substring and whether it was\n * balanced; an unbalanced result means the input was truncated mid-object.\n */\nfunction balancedObjectAt(text: string, start: number): { json: string; balanced: boolean } {\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === '{') depth++;\n else if (ch === '}') {\n depth--;\n if (depth === 0) return { json: text.slice(start, i + 1), balanced: true };\n }\n }\n return { json: text.slice(start), balanced: false };\n}\n\n/**\n * Scan an LLM response for every balanced `{…}` object carrying a `\"<key>\":`\n * entry. Strips fences and `<think>` blocks first. A matching object is\n * skipped over wholesale, so its nested braces don't produce fragment\n * candidates; non-matching objects are descended into, so a match wrapped in\n * an unrelated outer object is still found. `fallback` preserves the legacy\n * behavior for callers with no keyed match: the first balanced object, else\n * the stripped text so a JSON.parse error still surfaces.\n */\nexport function extractObjectsWithKey(raw: string, key: string): {\n matches: string[];\n fallback: { json: string; balanced: boolean };\n sawBrace: boolean;\n /** An object ran to EOF unclosed — the classic signature of truncated output. */\n sawUnbalanced: boolean;\n} {\n const stripped = stripModelNoise(raw);\n const keyRe = new RegExp(`\"${key}\"\\\\s*:`);\n\n const matches: string[] = [];\n let firstObject: string | null = null;\n let sawBrace = false;\n let sawUnbalanced = false;\n let inString = false;\n let escaped = false;\n for (let i = 0; i < stripped.length; i++) {\n const ch = stripped[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') { inString = true; continue; }\n if (ch !== '{') continue;\n\n sawBrace = true;\n const obj = balancedObjectAt(stripped, i);\n // A stray brace in a reasoning preamble produces an unbalanced candidate,\n // which we skip so it can't swallow the real object that follows.\n if (obj.balanced && keyRe.test(obj.json)) {\n matches.push(obj.json);\n i += obj.json.length - 1;\n continue;\n }\n if (!obj.balanced) sawUnbalanced = true;\n if (!firstObject && obj.balanced) firstObject = obj.json;\n }\n\n return {\n matches,\n fallback: firstObject !== null ? { json: firstObject, balanced: true } : { json: stripped, balanced: false },\n sawBrace,\n sawUnbalanced,\n };\n}\n\n/**\n * Pull the JSON object out of an LLM response and report whether it was balanced.\n * Strips fences and `<think>` blocks, then walks every top-level `{…}` and\n * returns the FIRST one that contains a `\"tasks\"` key — so a brace appearing\n * earlier in reasoning (or an unrelated preamble object) can't make us parse the\n * wrong thing. Falls back to the first balanced object and, failing that, the\n * first `{` onwards so a genuine `JSON.parse` error still surfaces.\n */\nexport function extractObjectWithBalance(raw: string): { json: string; balanced: boolean; sawBrace: boolean } {\n const { matches, fallback, sawBrace } = extractObjectsWithKey(raw, PLAN_ENVELOPE_KEY);\n if (matches.length > 0) return { json: matches[0], balanced: true, sawBrace };\n return { ...fallback, sawBrace };\n}\n\n/**\n * Pull the JSON object out of an LLM response. Strips markdown code fences and\n * `<think>` blocks, prefers the object containing a `tasks` key, and tolerates a\n * prose preamble and trailing prose. Returns the fence-stripped text unchanged\n * if no `{` is present so the caller's JSON.parse produces a clear failure.\n */\nexport function extractJsonObject(raw: string): string {\n return extractObjectWithBalance(raw).json;\n}\n\n/** Drop trailing commas before a closing `}` or `]` — a common model quirk. */\nexport function stripTrailingCommas(json: string): string {\n return json.replace(/,(\\s*[}\\]])/g, '$1');\n}\n\n/**\n * Escape raw control characters that appear INSIDE string literals — budget\n * models routinely emit multi-line `prompt` strings with literal newlines,\n * which strict JSON.parse rejects (\"bad control character\"). Characters\n * outside strings (formatting whitespace) are left untouched.\n */\nexport function escapeControlCharsInStrings(json: string): string {\n let out = '';\n let inString = false;\n let escaped = false;\n for (const ch of json) {\n if (inString) {\n if (escaped) { out += ch; escaped = false; continue; }\n if (ch === '\\\\') { out += ch; escaped = true; continue; }\n if (ch === '\"') { out += ch; inString = false; continue; }\n if (ch === '\\n') { out += '\\\\n'; continue; }\n if (ch === '\\r') { out += '\\\\r'; continue; }\n if (ch === '\\t') { out += '\\\\t'; continue; }\n out += ch;\n continue;\n }\n if (ch === '\"') inString = true;\n out += ch;\n }\n return out;\n}\n"],"mappings":"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","names":[]}
@@ -6,7 +6,7 @@ import {
6
6
  extractObjectsWithKey,
7
7
  stripModelNoise,
8
8
  stripTrailingCommas
9
- } from "./chunk-IO6PEEN6.mjs";
9
+ } from "./chunk-N6HTBUKG.mjs";
10
10
 
11
11
  // src/services/ModeResolver.ts
12
12
  function runnerModesFrom(registry, runners) {
@@ -395,4 +395,4 @@ export {
395
395
  validatePlanModification,
396
396
  parsePartialPlan
397
397
  };
398
- //# sourceMappingURL=chunk-TUGJXD4G.mjs.map
398
+ //# sourceMappingURL=chunk-UEJ3SZQ7.mjs.map