@ordewell/core 0.4.11 → 0.4.13

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.
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The planner's single approval seam. Every capability that reaches beyond the
3
+ * default read-only, in-workspace envelope — a path outside the workspace root,
4
+ * a shell command outside the auto-allowed set, a URL fetch — routes through
5
+ * one `request()` so the policy has exactly one owner (the same "one repair
6
+ * owner" shape as PlanRepair).
7
+ *
8
+ * Surfaces supply the human channel. VS Code answers with a modal; the web
9
+ * server currently has no prompt UI, so it denies unless the scope was
10
+ * pre-approved through config. Denial is always a visible, actionable tool
11
+ * result — never a silent success.
12
+ */
13
+ type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
14
+ interface ApprovalRequest {
15
+ kind: ApprovalKind;
16
+ /** The concrete thing being asked about: an absolute path, a command line, a URL. */
17
+ subject: string;
18
+ /**
19
+ * What a grant covers. Approving remembers this, not `subject`, so reading a
20
+ * second file from an already-approved directory does not prompt again.
21
+ */
22
+ scope: string;
23
+ /** One-line context for the prompt. */
24
+ detail?: string;
25
+ }
26
+ interface IApproval {
27
+ request(req: ApprovalRequest): Promise<boolean>;
28
+ }
29
+ /** Denies everything. The safe default when a surface wires no approval channel. */
30
+ declare const DENY_ALL: IApproval;
31
+
32
+ /**
33
+ * Decides whether one out-of-envelope capability may run, and remembers the
34
+ * answer for the rest of the session.
35
+ *
36
+ * Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
37
+ * subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
38
+ * approving `az group list` grants `az group`. Without that, a planner doing
39
+ * real research would prompt on every single call and the feature would be
40
+ * unusable.
41
+ *
42
+ * `mode` is the policy floor:
43
+ * ask consult the human channel; no channel means deny (headless, web)
44
+ * allow grant everything the tier system did not already refuse
45
+ * deny grant nothing beyond `preApproved`
46
+ *
47
+ * Note the ordering: `preApproved` is honored under every mode including
48
+ * `deny`, because it is an explicit operator decision rather than a default.
49
+ */
50
+ type ApprovalMode = 'ask' | 'allow' | 'deny';
51
+ interface ApprovalPolicyOptions {
52
+ mode?: ApprovalMode;
53
+ /** Scopes granted up front from config. A trailing `*` matches by prefix. */
54
+ preApproved?: string[];
55
+ /** The human channel. Absent means there is nobody to ask. */
56
+ ask?: (req: ApprovalRequest) => Promise<boolean>;
57
+ /** Called whenever a decision is reached, for surfacing in a UI or a log. */
58
+ onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
59
+ }
60
+ type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
61
+ declare class ApprovalPolicy implements IApproval {
62
+ private readonly mode;
63
+ private readonly preApproved;
64
+ private readonly asker?;
65
+ private readonly onDecision?;
66
+ private readonly granted;
67
+ private readonly refused;
68
+ /** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
69
+ private readonly inFlight;
70
+ private generation;
71
+ constructor(opts?: ApprovalPolicyOptions);
72
+ request(req: ApprovalRequest): Promise<boolean>;
73
+ /** Scopes the user has granted this session — for display and for persistence. */
74
+ grantedScopes(): string[];
75
+ /** Drop every session-scoped decision. Called on session reset. */
76
+ reset(): void;
77
+ }
78
+
79
+ export { type ApprovalKind as A, DENY_ALL as D, type IApproval as I, type ApprovalMode as a, ApprovalPolicy as b, type ApprovalPolicyOptions as c, type ApprovalRequest as d, type ApprovalSource as e };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The planner's single approval seam. Every capability that reaches beyond the
3
+ * default read-only, in-workspace envelope — a path outside the workspace root,
4
+ * a shell command outside the auto-allowed set, a URL fetch — routes through
5
+ * one `request()` so the policy has exactly one owner (the same "one repair
6
+ * owner" shape as PlanRepair).
7
+ *
8
+ * Surfaces supply the human channel. VS Code answers with a modal; the web
9
+ * server currently has no prompt UI, so it denies unless the scope was
10
+ * pre-approved through config. Denial is always a visible, actionable tool
11
+ * result — never a silent success.
12
+ */
13
+ type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
14
+ interface ApprovalRequest {
15
+ kind: ApprovalKind;
16
+ /** The concrete thing being asked about: an absolute path, a command line, a URL. */
17
+ subject: string;
18
+ /**
19
+ * What a grant covers. Approving remembers this, not `subject`, so reading a
20
+ * second file from an already-approved directory does not prompt again.
21
+ */
22
+ scope: string;
23
+ /** One-line context for the prompt. */
24
+ detail?: string;
25
+ }
26
+ interface IApproval {
27
+ request(req: ApprovalRequest): Promise<boolean>;
28
+ }
29
+ /** Denies everything. The safe default when a surface wires no approval channel. */
30
+ declare const DENY_ALL: IApproval;
31
+
32
+ /**
33
+ * Decides whether one out-of-envelope capability may run, and remembers the
34
+ * answer for the rest of the session.
35
+ *
36
+ * Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
37
+ * subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
38
+ * approving `az group list` grants `az group`. Without that, a planner doing
39
+ * real research would prompt on every single call and the feature would be
40
+ * unusable.
41
+ *
42
+ * `mode` is the policy floor:
43
+ * ask consult the human channel; no channel means deny (headless, web)
44
+ * allow grant everything the tier system did not already refuse
45
+ * deny grant nothing beyond `preApproved`
46
+ *
47
+ * Note the ordering: `preApproved` is honored under every mode including
48
+ * `deny`, because it is an explicit operator decision rather than a default.
49
+ */
50
+ type ApprovalMode = 'ask' | 'allow' | 'deny';
51
+ interface ApprovalPolicyOptions {
52
+ mode?: ApprovalMode;
53
+ /** Scopes granted up front from config. A trailing `*` matches by prefix. */
54
+ preApproved?: string[];
55
+ /** The human channel. Absent means there is nobody to ask. */
56
+ ask?: (req: ApprovalRequest) => Promise<boolean>;
57
+ /** Called whenever a decision is reached, for surfacing in a UI or a log. */
58
+ onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
59
+ }
60
+ type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
61
+ declare class ApprovalPolicy implements IApproval {
62
+ private readonly mode;
63
+ private readonly preApproved;
64
+ private readonly asker?;
65
+ private readonly onDecision?;
66
+ private readonly granted;
67
+ private readonly refused;
68
+ /** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
69
+ private readonly inFlight;
70
+ private generation;
71
+ constructor(opts?: ApprovalPolicyOptions);
72
+ request(req: ApprovalRequest): Promise<boolean>;
73
+ /** Scopes the user has granted this session — for display and for persistence. */
74
+ grantedScopes(): string[];
75
+ /** Drop every session-scoped decision. Called on session reset. */
76
+ reset(): void;
77
+ }
78
+
79
+ export { type ApprovalKind as A, DENY_ALL as D, type IApproval as I, type ApprovalMode as a, ApprovalPolicy as b, type ApprovalPolicyOptions as c, type ApprovalRequest as d, type ApprovalSource as e };
@@ -1,36 +1,6 @@
1
+ import { I as IApproval, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.mjs';
1
2
  import { h as RunnerId } from './Task-cGrfYRXK.mjs';
2
3
 
3
- /**
4
- * The planner's single approval seam. Every capability that reaches beyond the
5
- * default read-only, in-workspace envelope — a path outside the workspace root,
6
- * a shell command outside the auto-allowed set, a URL fetch — routes through
7
- * one `request()` so the policy has exactly one owner (the same "one repair
8
- * owner" shape as PlanRepair).
9
- *
10
- * Surfaces supply the human channel. VS Code answers with a modal; the web
11
- * server currently has no prompt UI, so it denies unless the scope was
12
- * pre-approved through config. Denial is always a visible, actionable tool
13
- * result — never a silent success.
14
- */
15
- type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
16
- interface ApprovalRequest {
17
- kind: ApprovalKind;
18
- /** The concrete thing being asked about: an absolute path, a command line, a URL. */
19
- subject: string;
20
- /**
21
- * What a grant covers. Approving remembers this, not `subject`, so reading a
22
- * second file from an already-approved directory does not prompt again.
23
- */
24
- scope: string;
25
- /** One-line context for the prompt. */
26
- detail?: string;
27
- }
28
- interface IApproval {
29
- request(req: ApprovalRequest): Promise<boolean>;
30
- }
31
- /** Denies everything. The safe default when a surface wires no approval channel. */
32
- declare const DENY_ALL: IApproval;
33
-
34
4
  interface ToolOutcome {
35
5
  success: boolean;
36
6
  output: string;
@@ -104,53 +74,6 @@ interface IFileSystem {
104
74
  setApproval?(approval: IApproval): void;
105
75
  }
106
76
 
107
- /**
108
- * Decides whether one out-of-envelope capability may run, and remembers the
109
- * answer for the rest of the session.
110
- *
111
- * Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
112
- * subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
113
- * approving `az group list` grants `az group`. Without that, a planner doing
114
- * real research would prompt on every single call and the feature would be
115
- * unusable.
116
- *
117
- * `mode` is the policy floor:
118
- * ask consult the human channel; no channel means deny (headless, web)
119
- * allow grant everything the tier system did not already refuse
120
- * deny grant nothing beyond `preApproved`
121
- *
122
- * Note the ordering: `preApproved` is honored under every mode including
123
- * `deny`, because it is an explicit operator decision rather than a default.
124
- */
125
- type ApprovalMode = 'ask' | 'allow' | 'deny';
126
- interface ApprovalPolicyOptions {
127
- mode?: ApprovalMode;
128
- /** Scopes granted up front from config. A trailing `*` matches by prefix. */
129
- preApproved?: string[];
130
- /** The human channel. Absent means there is nobody to ask. */
131
- ask?: (req: ApprovalRequest) => Promise<boolean>;
132
- /** Called whenever a decision is reached, for surfacing in a UI or a log. */
133
- onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
134
- }
135
- type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
136
- declare class ApprovalPolicy implements IApproval {
137
- private readonly mode;
138
- private readonly preApproved;
139
- private readonly asker?;
140
- private readonly onDecision?;
141
- private readonly granted;
142
- private readonly refused;
143
- /** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
144
- private readonly inFlight;
145
- private generation;
146
- constructor(opts?: ApprovalPolicyOptions);
147
- request(req: ApprovalRequest): Promise<boolean>;
148
- /** Scopes the user has granted this session — for display and for persistence. */
149
- grantedScopes(): string[];
150
- /** Drop every session-scoped decision. Called on session reset. */
151
- reset(): void;
152
- }
153
-
154
77
  interface CatalogModel {
155
78
  id: string;
156
79
  name: string;
@@ -535,6 +458,12 @@ interface ITerminalSession {
535
458
  kill(): void;
536
459
  getOutput(): string;
537
460
  write(text: string): void;
461
+ /**
462
+ * Optional transport-level control channel: PTY resize requests for a session
463
+ * whose runner renders a TUI. Absent on transports without a resizable PTY
464
+ * (a plain piped subprocess); surfaces must feature-detect before calling.
465
+ */
466
+ writeControl?(text: string): void;
538
467
  }
539
468
 
540
469
  interface ITerminalRunner {
@@ -564,4 +493,4 @@ interface ITerminalRunner {
564
493
  activeCount: number;
565
494
  }
566
495
 
567
- export { type AiProvider as A, type ProviderModelsResult as B, type CatalogModel as C, DENY_ALL as D, type ResolveContext as E, type FetchAllProviderModelsOptions as F, GREP_DEFAULT_HEAD_LIMIT as G, type RunnerInvocation as H, type IApproval as I, type RunnerPluginManifest as J, RunnerRegistry as K, collectProviderCredentials as L, ModelCatalog as M, enabledRunners as N, ORCHESTRATOR_SHORTCUTS as O, type PluginCloneFn as P, fetchAllProviderModels as Q, type ReadFileOpts as R, SEARCH_EXCLUSIONS as S, type ToolOutcome as T, isReservedRunnerName as U, knownModelId as V, resolveModelShortcut as W, resolveProvider as X, toOrchestratorOptions as Y, type AllProviderModels as a, type ApprovalKind as b, type ApprovalMode as c, ApprovalPolicy as d, type ApprovalPolicyOptions as e, type ApprovalRequest as f, type ApprovalSource as g, type DiscoveryCommand as h, type FindSymbolOptions as i, type GlobOptions as j, type GrepOptions as k, type GrepOutputMode as l, type IConfig as m, type IFileSystem as n, type IPluginStore as o, type ITerminalRunner as p, type ITerminalSession as q, type ModelShortcut as r, type OrchestratorOption as s, type PluginEntry as t, type PluginFeatures as u, type PluginMode as v, type PluginModelDiscovery as w, type PluginRunnerDef as x, type ProviderCredentialSource as y, type ProviderModelLists as z };
496
+ export { type AiProvider as A, isReservedRunnerName as B, type CatalogModel as C, type DiscoveryCommand as D, knownModelId as E, type FetchAllProviderModelsOptions as F, GREP_DEFAULT_HEAD_LIMIT as G, resolveModelShortcut as H, type IConfig as I, resolveProvider as J, toOrchestratorOptions as K, ModelCatalog as M, ORCHESTRATOR_SHORTCUTS as O, type PluginCloneFn as P, type ReadFileOpts as R, SEARCH_EXCLUSIONS as S, type ToolOutcome as T, type AllProviderModels as a, type FindSymbolOptions as b, type GlobOptions as c, type GrepOptions as d, type GrepOutputMode as e, type IFileSystem as f, type IPluginStore as g, type ITerminalRunner as h, type ITerminalSession as i, type ModelShortcut as j, type OrchestratorOption as k, type PluginEntry as l, type PluginFeatures as m, type PluginMode as n, type PluginModelDiscovery as o, type PluginRunnerDef as p, type ProviderCredentialSource as q, type ProviderModelLists as r, type ProviderModelsResult as s, type ResolveContext as t, type RunnerInvocation as u, type RunnerPluginManifest as v, RunnerRegistry as w, collectProviderCredentials as x, enabledRunners as y, fetchAllProviderModels as z };
@@ -1,36 +1,6 @@
1
+ import { I as IApproval, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.js';
1
2
  import { h as RunnerId } from './Task-cGrfYRXK.js';
2
3
 
3
- /**
4
- * The planner's single approval seam. Every capability that reaches beyond the
5
- * default read-only, in-workspace envelope — a path outside the workspace root,
6
- * a shell command outside the auto-allowed set, a URL fetch — routes through
7
- * one `request()` so the policy has exactly one owner (the same "one repair
8
- * owner" shape as PlanRepair).
9
- *
10
- * Surfaces supply the human channel. VS Code answers with a modal; the web
11
- * server currently has no prompt UI, so it denies unless the scope was
12
- * pre-approved through config. Denial is always a visible, actionable tool
13
- * result — never a silent success.
14
- */
15
- type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
16
- interface ApprovalRequest {
17
- kind: ApprovalKind;
18
- /** The concrete thing being asked about: an absolute path, a command line, a URL. */
19
- subject: string;
20
- /**
21
- * What a grant covers. Approving remembers this, not `subject`, so reading a
22
- * second file from an already-approved directory does not prompt again.
23
- */
24
- scope: string;
25
- /** One-line context for the prompt. */
26
- detail?: string;
27
- }
28
- interface IApproval {
29
- request(req: ApprovalRequest): Promise<boolean>;
30
- }
31
- /** Denies everything. The safe default when a surface wires no approval channel. */
32
- declare const DENY_ALL: IApproval;
33
-
34
4
  interface ToolOutcome {
35
5
  success: boolean;
36
6
  output: string;
@@ -104,53 +74,6 @@ interface IFileSystem {
104
74
  setApproval?(approval: IApproval): void;
105
75
  }
106
76
 
107
- /**
108
- * Decides whether one out-of-envelope capability may run, and remembers the
109
- * answer for the rest of the session.
110
- *
111
- * Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
112
- * subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
113
- * approving `az group list` grants `az group`. Without that, a planner doing
114
- * real research would prompt on every single call and the feature would be
115
- * unusable.
116
- *
117
- * `mode` is the policy floor:
118
- * ask consult the human channel; no channel means deny (headless, web)
119
- * allow grant everything the tier system did not already refuse
120
- * deny grant nothing beyond `preApproved`
121
- *
122
- * Note the ordering: `preApproved` is honored under every mode including
123
- * `deny`, because it is an explicit operator decision rather than a default.
124
- */
125
- type ApprovalMode = 'ask' | 'allow' | 'deny';
126
- interface ApprovalPolicyOptions {
127
- mode?: ApprovalMode;
128
- /** Scopes granted up front from config. A trailing `*` matches by prefix. */
129
- preApproved?: string[];
130
- /** The human channel. Absent means there is nobody to ask. */
131
- ask?: (req: ApprovalRequest) => Promise<boolean>;
132
- /** Called whenever a decision is reached, for surfacing in a UI or a log. */
133
- onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
134
- }
135
- type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
136
- declare class ApprovalPolicy implements IApproval {
137
- private readonly mode;
138
- private readonly preApproved;
139
- private readonly asker?;
140
- private readonly onDecision?;
141
- private readonly granted;
142
- private readonly refused;
143
- /** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
144
- private readonly inFlight;
145
- private generation;
146
- constructor(opts?: ApprovalPolicyOptions);
147
- request(req: ApprovalRequest): Promise<boolean>;
148
- /** Scopes the user has granted this session — for display and for persistence. */
149
- grantedScopes(): string[];
150
- /** Drop every session-scoped decision. Called on session reset. */
151
- reset(): void;
152
- }
153
-
154
77
  interface CatalogModel {
155
78
  id: string;
156
79
  name: string;
@@ -535,6 +458,12 @@ interface ITerminalSession {
535
458
  kill(): void;
536
459
  getOutput(): string;
537
460
  write(text: string): void;
461
+ /**
462
+ * Optional transport-level control channel: PTY resize requests for a session
463
+ * whose runner renders a TUI. Absent on transports without a resizable PTY
464
+ * (a plain piped subprocess); surfaces must feature-detect before calling.
465
+ */
466
+ writeControl?(text: string): void;
538
467
  }
539
468
 
540
469
  interface ITerminalRunner {
@@ -564,4 +493,4 @@ interface ITerminalRunner {
564
493
  activeCount: number;
565
494
  }
566
495
 
567
- export { type AiProvider as A, type ProviderModelsResult as B, type CatalogModel as C, DENY_ALL as D, type ResolveContext as E, type FetchAllProviderModelsOptions as F, GREP_DEFAULT_HEAD_LIMIT as G, type RunnerInvocation as H, type IApproval as I, type RunnerPluginManifest as J, RunnerRegistry as K, collectProviderCredentials as L, ModelCatalog as M, enabledRunners as N, ORCHESTRATOR_SHORTCUTS as O, type PluginCloneFn as P, fetchAllProviderModels as Q, type ReadFileOpts as R, SEARCH_EXCLUSIONS as S, type ToolOutcome as T, isReservedRunnerName as U, knownModelId as V, resolveModelShortcut as W, resolveProvider as X, toOrchestratorOptions as Y, type AllProviderModels as a, type ApprovalKind as b, type ApprovalMode as c, ApprovalPolicy as d, type ApprovalPolicyOptions as e, type ApprovalRequest as f, type ApprovalSource as g, type DiscoveryCommand as h, type FindSymbolOptions as i, type GlobOptions as j, type GrepOptions as k, type GrepOutputMode as l, type IConfig as m, type IFileSystem as n, type IPluginStore as o, type ITerminalRunner as p, type ITerminalSession as q, type ModelShortcut as r, type OrchestratorOption as s, type PluginEntry as t, type PluginFeatures as u, type PluginMode as v, type PluginModelDiscovery as w, type PluginRunnerDef as x, type ProviderCredentialSource as y, type ProviderModelLists as z };
496
+ export { type AiProvider as A, isReservedRunnerName as B, type CatalogModel as C, type DiscoveryCommand as D, knownModelId as E, type FetchAllProviderModelsOptions as F, GREP_DEFAULT_HEAD_LIMIT as G, resolveModelShortcut as H, type IConfig as I, resolveProvider as J, toOrchestratorOptions as K, ModelCatalog as M, ORCHESTRATOR_SHORTCUTS as O, type PluginCloneFn as P, type ReadFileOpts as R, SEARCH_EXCLUSIONS as S, type ToolOutcome as T, type AllProviderModels as a, type FindSymbolOptions as b, type GlobOptions as c, type GrepOptions as d, type GrepOutputMode as e, type IFileSystem as f, type IPluginStore as g, type ITerminalRunner as h, type ITerminalSession as i, type ModelShortcut as j, type OrchestratorOption as k, type PluginEntry as l, type PluginFeatures as m, type PluginMode as n, type PluginModelDiscovery as o, type PluginRunnerDef as p, type ProviderCredentialSource as q, type ProviderModelLists as r, type ProviderModelsResult as s, type ResolveContext as t, type RunnerInvocation as u, type RunnerPluginManifest as v, RunnerRegistry as w, collectProviderCredentials as x, enabledRunners as y, fetchAllProviderModels as z };
@@ -841,6 +841,59 @@ function classifyOutcome(success, output) {
841
841
  return "success";
842
842
  }
843
843
 
844
+ // src/services/SessionMessage.ts
845
+ function serializeTask(t) {
846
+ return {
847
+ id: t.id,
848
+ order: t.order,
849
+ title: t.title,
850
+ type: t.type,
851
+ description: t.description,
852
+ dependencies: t.dependencies || [],
853
+ assignedRunner: t.assignedRunner,
854
+ assignedModel: t.assignedModel || null,
855
+ taskMode: t.taskMode || "build",
856
+ prompt: t.prompt || null,
857
+ subtasks: (t.subtasks || []).map(serializeTask),
858
+ userSteps: t.userSteps || void 0,
859
+ thinkingEffort: t.thinkingEffort || void 0,
860
+ autonomy: t.autonomy || void 0,
861
+ sliceType: t.sliceType || void 0,
862
+ userStoriesCovered: t.userStoriesCovered || void 0
863
+ };
864
+ }
865
+ function serializeTaskStatus(t, idleSince = null) {
866
+ return {
867
+ id: t.id,
868
+ status: t.status,
869
+ verdict: t.verdict ? { outcome: t.verdict.outcome, reason: t.verdict.reason, checks: t.verdict.checks || [] } : null,
870
+ idleSince
871
+ };
872
+ }
873
+ function serializePlan(plan) {
874
+ return {
875
+ tasks: plan.tasks.map(serializeTask),
876
+ runners: plan.runners,
877
+ generatedAt: plan.generatedAt,
878
+ conversationHistory: plan.conversationHistory,
879
+ prdMarkdown: plan.prdMarkdown,
880
+ queuedMessages: plan.queuedMessages
881
+ };
882
+ }
883
+ function executionSummary(tasks) {
884
+ return {
885
+ total: tasks.length,
886
+ completed: tasks.filter((t) => t.status === "completed").length,
887
+ failed: tasks.filter((t) => t.status === "failed").length
888
+ };
889
+ }
890
+ var CHECKPOINT_TRUNCATE_LENGTH = 120;
891
+ function truncateCheckpointSummary(summary) {
892
+ const firstLine = summary.split("\n")[0].trim();
893
+ if (firstLine.length <= CHECKPOINT_TRUNCATE_LENGTH) return firstLine;
894
+ return firstLine.slice(0, CHECKPOINT_TRUNCATE_LENGTH - 1) + "\u2026";
895
+ }
896
+
844
897
  export {
845
898
  effectiveAllowlist,
846
899
  filterModelsForPrompt,
@@ -857,6 +910,12 @@ export {
857
910
  canSplitTask,
858
911
  applyTaskOps,
859
912
  summarizeToolCall,
860
- classifyOutcome
913
+ classifyOutcome,
914
+ serializeTask,
915
+ serializeTaskStatus,
916
+ serializePlan,
917
+ executionSummary,
918
+ CHECKPOINT_TRUNCATE_LENGTH,
919
+ truncateCheckpointSummary
861
920
  };
862
- //# sourceMappingURL=chunk-DNNZGH3I.mjs.map
921
+ //# sourceMappingURL=chunk-YTJ7EOV6.mjs.map