pi-midcompact 0.5.1 → 0.5.2

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.
package/README.md CHANGED
@@ -29,7 +29,7 @@ That is planning guidance, not an enforced token target: semantic importance win
29
29
 
30
30
  ### A selective projection, prepared on a temporary branch
31
31
 
32
- `/midcompact start` freezes the current session leaf as an **anchor**. Planning happens on a disposable child branch, so the discussion used to create and edit the draft never becomes part of the committed working context.
32
+ `/midcompact:start` freezes the current session leaf as an **anchor**. Planning happens on a disposable child branch, so the discussion used to create and edit the draft never becomes part of the committed working context.
33
33
 
34
34
  ```text
35
35
  Frozen anchor: raw session history
@@ -42,7 +42,7 @@ Planning is isolated on a temporary branch:
42
42
  ... [latest work] ──┬── [transaction] ── [draft v1] ── [draft v2] ◀ review / edit
43
43
  │ (abandoned at commit)
44
44
  └── [midcompact-state] ◀ committed leaf
45
- (reviewed selection metadata, not a model message; written only by /midcompact commit)
45
+ (reviewed selection metadata, not a model message; written only by /midcompact:commit)
46
46
 
47
47
  Later model requests see a selective projection:
48
48
 
@@ -91,10 +91,10 @@ pi-midcompact — mid-context compression, review, then human commit
91
91
 
92
92
  | | Pi `/compact` | `pi-midcompact` |
93
93
  | --- | --- | --- |
94
- | Starts | Automatically near the context limit, or with `/compact` | At an explicit natural checkpoint with `/midcompact start` |
94
+ | Starts | Automatically near the context limit, or with `/compact` | At an explicit natural checkpoint with `/midcompact:start` |
95
95
  | Selects | One older contiguous prefix; keeps a recent token-budgeted tail | One or more reviewed ranges, including non-contiguous ranges and `KEEP` holes |
96
96
  | Planning | Optional one-shot instruction to focus the generated summary | User states scope and retention depth; the Agent discusses trade-offs and drafts selective ranges and summaries |
97
- | Decision gate | Generates a compaction checkpoint directly | Draft → TUI or browser review → explicit human `/midcompact commit` |
97
+ | Decision gate | Generates a compaction checkpoint directly | Draft → TUI or browser review → explicit human `/midcompact:commit` |
98
98
  | Best fit | Automatic context maintenance and overflow recovery | Deliberate cleanup of completed phases while retaining specific decisions verbatim |
99
99
 
100
100
  `pi-midcompact` does not disable or replace Pi's automatic compaction; it gives you a separate, human-reviewed way to make selective reductions. See [Pi's compaction documentation](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/compaction.md) for the built-in mechanism.
@@ -124,13 +124,13 @@ Start a transaction at a natural breakpoint: the current work is complete enough
124
124
  Run:
125
125
 
126
126
  ```text
127
- /midcompact start
127
+ /midcompact:start
128
128
  ```
129
129
 
130
130
  Pi opens a three-way chooser before creating transaction state: **Agent direct**, **User manual**, or **Drop**. Agent direct is the first and default-highlighted option, matching the previous fast path. The chooser is the standard `select` dialog, identical in interactive and RPC mode; RPC carries it as an extension UI `select` message with a bounded timeout, so an unresponsive client cancels instead of blocking. print/JSON modes have no dialog and default to **Agent direct**. Agent direct starts the existing inventory-first Agent workflow. User manual sends the same transaction guidance with a final “acknowledge only” instruction; after the Agent replies briefly, the Selection workbench opens (browser-based outside interactive mode). It does not start planning or mutate the DraftPlan until the user hands off later. Save the initial DraftPlan, close the UI, then tell the Agent to continue when you are ready. You can include an initial focus in the same command:
131
131
 
132
132
  ```text
133
- /midcompact start Compress the early repository exploration, but keep user requirements verbatim.
133
+ /midcompact:start Compress the early repository exploration, but keep user requirements verbatim.
134
134
  ```
135
135
 
136
136
  ### 2. Discuss what to compress with the Agent
@@ -150,7 +150,7 @@ The Agent locates relevant parts of the frozen conversation, proposes one or mor
150
150
  Run:
151
151
 
152
152
  ```text
153
- /midcompact review
153
+ /midcompact:review
154
154
  ```
155
155
 
156
156
  In interactive mode, the native TUI displays the frozen conversation as a linear timeline. Each item is marked either `KEEP` or as belonging to a proposed range. Review the range boundaries and the summary that will replace each range.
@@ -158,14 +158,14 @@ In interactive mode, the native TUI displays the frozen conversation as a linear
158
158
  For RPC, print, or other no-TUI modes, use the editable local browser interface instead:
159
159
 
160
160
  ```text
161
- /midcompact review-webui
161
+ /midcompact:review-webui
162
162
  ```
163
163
 
164
164
  Use Selection to create or change ranges and KEEP holes:
165
165
 
166
166
  ```text
167
- /midcompact select
168
- /midcompact select-webui
167
+ /midcompact:select
168
+ /midcompact:select-webui
169
169
  ```
170
170
 
171
171
  Use the TUI or local browser Review surface to edit summaries/topics and reject ranges. Review deliberately does not create or resize ranges; reopen Selection for boundary changes. To continue with Agent after a user-created plan, send a normal message asking it to continue the current midcompact draft; the Agent is prompted to read the existing plan first.
@@ -175,7 +175,7 @@ Use the TUI or local browser Review surface to edit summaries/topics and reject
175
175
  When the plan is correct, run:
176
176
 
177
177
  ```text
178
- /midcompact commit
178
+ /midcompact:commit
179
179
  ```
180
180
 
181
181
  This is deliberately a human command. The Agent cannot commit compression itself.
@@ -187,14 +187,14 @@ Pi returns to the anchor, discards the temporary planning branch, stores the rev
187
187
  Keep working normally after committing. If you decide not to compress, run:
188
188
 
189
189
  ```text
190
- /midcompact abort
190
+ /midcompact:abort
191
191
  ```
192
192
 
193
193
  This returns to the anchor and discards the transaction without changing the active context.
194
194
 
195
195
  ## Native TUI Controls
196
196
 
197
- Inside `/midcompact review`:
197
+ Inside `/midcompact:review`:
198
198
 
199
199
  ```text
200
200
  n/p or Left/Right select a proposed range
@@ -211,14 +211,14 @@ Enter/Esc/q close
211
211
 
212
212
  | Command | Result |
213
213
  | --- | --- |
214
- | `/midcompact start [instructions]` | Opens Agent direct / User manual / Drop, then starts a transaction at the current session-tree leaf. |
215
- | `/midcompact select` | Opens the native TUI Selection workbench for range and KEEP editing. |
216
- | `/midcompact select-webui` | Opens the local browser Selection workbench. |
217
- | `/midcompact review` | Opens summary/topic review in the native TUI. |
218
- | `/midcompact review-webui` | Opens summary/topic review in a local browser. |
219
- | `/midcompact commit` | Commits the reviewed draft. Human only. |
220
- | `/midcompact abort` | Abandons the transaction and returns to the anchor. |
221
- | `/midcompact status` | Displays the current draft, or the committed compression state on this branch. |
214
+ | `/midcompact:start [instructions]` | Opens Agent direct / User manual / Drop, then starts a transaction at the current session-tree leaf. |
215
+ | `/midcompact:select` | Opens the native TUI Selection workbench for range and KEEP editing. |
216
+ | `/midcompact:select-webui` | Opens the local browser Selection workbench. |
217
+ | `/midcompact:review` | Opens summary/topic review in the native TUI. |
218
+ | `/midcompact:review-webui` | Opens summary/topic review in a local browser. |
219
+ | `/midcompact:commit` | Commits the reviewed draft. Human only. |
220
+ | `/midcompact:abort` | Abandons the transaction and returns to the anchor. |
221
+ | `/midcompact:status` | Displays the current draft, or the committed compression state on this branch. |
222
222
 
223
223
  The extension shows planning status in Pi's footer only while a transaction is active. It disappears after commit or abort.
224
224
 
@@ -227,7 +227,7 @@ The extension shows planning status in Pi's footer only while a transaction is a
227
227
  - **Original history is retained.** Compression changes what later model requests see, not the stored Pi messages.
228
228
  - **Fail-open projection.** If an exact reviewed sequence no longer resolves, the extension sends the raw history unchanged rather than removing uncertain content.
229
229
  - **State is branch-local.** Navigating with `/tree` to a point before a committed state restores raw history; returning to its descendant restores the projection.
230
- - **Human review is required.** The Agent can propose a plan but cannot execute `/midcompact commit`.
230
+ - **Human review is required.** The Agent can propose a plan but cannot execute `/midcompact:commit`.
231
231
  - **Tool protocol is protected.** Unknown, incomplete, or orphaned tool exchanges are not compressible.
232
232
  - **Repeated transactions work.** Later transactions can compress newly accumulated raw context; existing summaries remain protected.
233
233
  - **Native Pi `/compact` interaction needs more real-session validation.** Avoid relying on mixed automatic/native compaction behavior for critical work until it has been exercised in your environment.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-midcompact",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Branch-aware mid-context compression for the Pi coding agent",
5
5
  "author": "frostime",
6
6
  "repository": {
@@ -18,9 +18,11 @@ This skill handles two independent tasks: planning compression and recalling com
18
18
 
19
19
  The state-specific runtime prompt is authoritative. Recall does not enter planning or mutate the DraftPlan. During the User-manual acknowledgement turn, the no-tool instruction overrides every other route.
20
20
 
21
+ The tool groups parameters by `action`: each action accepts only its own fields, and fields from other actions are rejected. Read `references/tool-interface.md` before adding workload-specific parameters, and treat the action-specific field lists there as exhaustive.
22
+
21
23
  ## Plan compression
22
24
 
23
- Selected ranges become summaries in future model context; content outside them stays verbatim. Originals remain stored, but recall is a recovery path, not a substitute for a sufficient summary. Agent and user edit one DraftPlan; the user retains final control through review and `/midcompact commit`.
25
+ Selected ranges become summaries in future model context; content outside them stays verbatim. Originals remain stored, but recall is a recovery path, not a substitute for a sufficient summary. Agent and user edit one DraftPlan; the user retains final control through review and `/midcompact:commit`.
24
26
 
25
27
  The start mode controls how the first draft is created. It does not determine whether a user selection is final, how much initiative the Agent should take, or how deeply the history should be investigated.
26
28
 
@@ -107,7 +109,7 @@ Length follows the information that must survive, not a target ratio. Final test
107
109
 
108
110
  Call `action="plan", op="show"`. Check that the intended semantic phases are covered, KEEP holes remain outside ranges, every range has a summary, and the summaries conserve the future working state.
109
111
 
110
- Describe the completed proposal with the same recognizable landmarks used during alignment. Direct the user to `/midcompact select` or `/midcompact select-webui` for boundaries and KEEP holes, and to `/midcompact review` or `/midcompact review-webui` for summary inspection or rejection. Use browser variants when the TUI is unavailable or preferred. Ask the user to run `/midcompact commit` when ready; never commit for them.
112
+ Describe the completed proposal with the same recognizable landmarks used during alignment. Direct the user to `/midcompact:select` or `/midcompact:select-webui` for boundaries and KEEP holes, and to `/midcompact:review` or `/midcompact:review-webui` for summary inspection or rejection. Use browser variants when the TUI is unavailable or preferred. Ask the user to run `/midcompact:commit` when ready; never commit for them.
111
113
 
112
114
  ## Recall compressed content
113
115
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  Read this reference when exact call requirements, limits, rejection behavior, repeated compression, or recall truncation matters. The main workflow remains in `../SKILL.md`.
4
4
 
5
+ ## Parameter grouping
6
+
7
+ The tool schema is a discriminated union on `action`: selecting an action admits exactly the fields documented in that action's section, and no fields from other actions. A call that mixes actions (for example `locate` fields on `plan`) is invalid; do not repair it by dropping fields, re-issue the call with only the selected action's parameters. Shared field names (`ref`, `pattern`, `limit`, `detail`) are defined independently per action with the meaning documented in that section.
8
+
5
9
  ## Inspect
6
10
 
7
11
  Without `spans`, `action="inspect"` inventories the frozen anchor. It returns factual structure and bounded user landmarks, not full message bodies, assistant/tool previews, summaries, or image base64.
package/src/index.ts CHANGED
@@ -6,8 +6,6 @@ import {
6
6
  type ExtensionContext,
7
7
  type SessionEntry,
8
8
  } from "@earendil-works/pi-coding-agent";
9
- import type { AutocompleteItem } from "@earendil-works/pi-tui";
10
-
11
9
  import { buildAtoms, formatLocatedAtom, isProtectedAtom, locateAtomMatches } from "./atoms.js";
12
10
  import { buildInventory, formatInventory, formatSpanInspection } from "./inventory.js";
13
11
  import { messageText } from "./messages.js";
@@ -69,8 +67,20 @@ const TOOL_DESCRIPTION =
69
67
  const STATUS_KEY = "midcompact";
70
68
  const START_PROMPT_PREFIX = "A mid-compaction transaction is active on a frozen anchor snapshot.";
71
69
 
72
- const Params = Type.Object({
73
- action: StringEnum(["inspect", "locate", "plan", "recall"] as const),
70
+ // The tool is a discriminated union: `action` selects the only parameter
71
+ // group that applies. The schema exposes just that group's fields, so a call
72
+ // cannot mix parameters from different actions, and cross-action misuse
73
+ // becomes a compile-time error in the handler types rather than a runtime rule.
74
+ const InspectParams = Type.Object({
75
+ action: Type.Literal("inspect"),
76
+ // inventory pagination or explicit candidate-span measurement
77
+ spans: Type.Optional(Type.Array(Type.Object({ start: Type.String(), end: Type.String() }))),
78
+ page_size: Type.Optional(Type.Number()),
79
+ cursor: Type.Optional(Type.String()),
80
+ });
81
+
82
+ const LocateParams = Type.Object({
83
+ action: Type.Literal("locate"),
74
84
  ref: Type.Optional(Type.String()),
75
85
  pattern: Type.Optional(Type.String()),
76
86
  source: Type.Optional(StringEnum(["any", "user", "assistant", "tool_call", "tool_result"] as const)),
@@ -78,19 +88,34 @@ const Params = Type.Object({
78
88
  direction: Type.Optional(StringEnum(["oldest", "newest"] as const)),
79
89
  limit: Type.Optional(Type.Number()),
80
90
  detail: Type.Optional(StringEnum(["brief", "full"] as const)),
91
+ });
92
+
93
+ const PlanParams = Type.Object({
94
+ action: Type.Literal("plan"),
81
95
  op: Type.Optional(StringEnum(["show", "add", "update", "remove"] as const)),
82
96
  start: Type.Optional(Type.String()),
83
97
  end: Type.Optional(Type.String()),
84
98
  draft_id: Type.Optional(Type.String()),
85
99
  topic: Type.Optional(Type.String()),
86
100
  summary: Type.Optional(Type.String()),
87
- // inspect inventory pagination or explicit candidate-span measurement
88
- page_size: Type.Optional(Type.Number()),
89
- cursor: Type.Optional(Type.String()),
90
- spans: Type.Optional(Type.Array(Type.Object({ start: Type.String(), end: Type.String() }))),
101
+ detail: Type.Optional(StringEnum(["brief", "full"] as const)),
91
102
  });
92
103
 
104
+ const RecallParams = Type.Object({
105
+ action: Type.Literal("recall"),
106
+ ref: Type.Optional(Type.String()),
107
+ pattern: Type.Optional(Type.String()),
108
+ limit: Type.Optional(Type.Number()),
109
+ detail: Type.Optional(StringEnum(["brief", "full"] as const)),
110
+ });
111
+
112
+ const Params = Type.Union([InspectParams, LocateParams, PlanParams, RecallParams]);
113
+
93
114
  type ParamsType = Static<typeof Params>;
115
+ type InspectParamsType = Static<typeof InspectParams>;
116
+ type LocateParamsType = Static<typeof LocateParams>;
117
+ type PlanParamsType = Static<typeof PlanParams>;
118
+ type RecallParamsType = Static<typeof RecallParams>;
94
119
 
95
120
  type RuntimeSnapshot = { atoms: Atom[]; anchorState?: CompressionState };
96
121
 
@@ -172,48 +197,63 @@ export default function (pi: ExtensionAPI) {
172
197
  return { messages: projectMessages(event.messages as MessageLike[], activeState) as typeof event.messages };
173
198
  });
174
199
 
175
- pi.registerCommand("midcompact", {
176
- description: "Start, select, review, commit, inspect, or abort a branch-isolated mid-context compression transaction",
177
- getArgumentCompletions(prefix: string): AutocompleteItem[] | null {
178
- const query = prefix.trimStart().toLowerCase();
179
- if (/\s/.test(query)) return null;
180
- const items: AutocompleteItem[] = [
181
- { value: "start", label: "start — Start a new midcompact transaction at the current anchor" },
182
- { value: "abort", label: "abort — Abort the active transaction and return to anchor" },
183
- { value: "commit", label: "commit — Commit the current draft to the branch state" },
184
- { value: "review", label: "review — Open interactive TUI to inspect and edit the draft" },
185
- { value: "review-webui", label: "review-webui — Open a local web page to inspect and edit the draft (works without TUI)" },
186
- { value: "select", label: "select — Open the TUI Selection surface to edit range boundaries" },
187
- { value: "select-webui", label: "select-webui — Open Selection in a local browser" },
188
- { value: "status", label: "status — Show current transaction and draft status" },
189
- ];
190
- const filtered = items.filter((item) => item.value.startsWith(query));
191
- return filtered.length > 0 ? filtered : null;
192
- },
200
+ // One command per operation; the `midcompact:` prefix follows the same
201
+ // naming convention as Pi's own `skill:<name>` commands. The former
202
+ // composite `/midcompact <subcommand>` command is gone.
203
+ pi.registerCommand("midcompact:start", {
204
+ description: "Start a new midcompact transaction at the current anchor. Optional trailing text becomes the initial focus.",
193
205
  handler: async (args: string, ctx: ExtensionCommandContext) => {
194
206
  await ctx.waitForIdle();
195
- const rawArgs = args.trim();
196
- const lower = rawArgs.toLowerCase();
197
-
198
- if (lower === "abort") return abortTransaction(ctx);
199
- if (lower === "commit") return commitTransaction(ctx);
200
- if (lower === "review") return reviewTransaction(ctx, "tui");
201
- if (lower === "review-webui") return reviewTransaction(ctx, "web");
202
- if (lower === "select") return openSelectionUi(ctx, "auto");
203
- if (lower === "select-webui") return openSelectionUi(ctx, "web");
204
- if (lower === "status") return showStatus(ctx);
205
-
206
- // start [instructions...]
207
- const startMatch = rawArgs.match(/^start\b\s*(.*)$/i);
208
- if (startMatch) {
209
- const instructions = (startMatch[1] ?? "").trim();
210
- return startTransaction(ctx, instructions || undefined);
211
- }
212
-
213
- ctx.ui.notify(
214
- "Usage: /midcompact start [instructions] | /midcompact select[-webui] | /midcompact review[-webui] | /midcompact commit | /midcompact status | /midcompact abort",
215
- "warning",
216
- );
207
+ return startTransaction(ctx, args.trim() || undefined);
208
+ },
209
+ });
210
+ pi.registerCommand("midcompact:abort", {
211
+ description: "Abort the active transaction and return to the anchor",
212
+ handler: async (_args: string, ctx: ExtensionCommandContext) => {
213
+ await ctx.waitForIdle();
214
+ return abortTransaction(ctx);
215
+ },
216
+ });
217
+ pi.registerCommand("midcompact:commit", {
218
+ description: "Commit the current draft to the branch state",
219
+ handler: async (_args: string, ctx: ExtensionCommandContext) => {
220
+ await ctx.waitForIdle();
221
+ return commitTransaction(ctx);
222
+ },
223
+ });
224
+ pi.registerCommand("midcompact:review", {
225
+ description: "Open the interactive TUI review to inspect and edit the draft",
226
+ handler: async (_args: string, ctx: ExtensionCommandContext) => {
227
+ await ctx.waitForIdle();
228
+ return reviewTransaction(ctx, "tui");
229
+ },
230
+ });
231
+ pi.registerCommand("midcompact:review-webui", {
232
+ description: "Open a local web page to inspect and edit the draft (works without TUI)",
233
+ handler: async (_args: string, ctx: ExtensionCommandContext) => {
234
+ await ctx.waitForIdle();
235
+ return reviewTransaction(ctx, "web");
236
+ },
237
+ });
238
+ pi.registerCommand("midcompact:select", {
239
+ description: "Open the TUI Selection surface to edit range boundaries",
240
+ handler: async (_args: string, ctx: ExtensionCommandContext) => {
241
+ await ctx.waitForIdle();
242
+ return openSelectionUi(ctx, "auto");
243
+ },
244
+ });
245
+ pi.registerCommand("midcompact:select-webui", {
246
+ description: "Open Selection in a local browser",
247
+ handler: async (_args: string, ctx: ExtensionCommandContext) => {
248
+ await ctx.waitForIdle();
249
+ return openSelectionUi(ctx, "web");
250
+ },
251
+ });
252
+ pi.registerCommand("midcompact:status", {
253
+ description: "Show current transaction and draft status",
254
+ handler: async (_args: string, ctx: ExtensionCommandContext) => {
255
+ await ctx.waitForIdle();
256
+ return showStatus(ctx);
217
257
  },
218
258
  });
219
259
 
@@ -473,7 +513,7 @@ export default function (pi: ExtensionAPI) {
473
513
 
474
514
  if (ctx.mode !== "tui") {
475
515
  ctx.ui.notify(
476
- "Interactive TUI review is only available in interactive (tui) mode. Use /midcompact review-webui to open a local web page instead.",
516
+ "Interactive TUI review is only available in interactive (tui) mode. Use /midcompact:review-webui to open a local web page instead.",
477
517
  "warning",
478
518
  );
479
519
  return;
@@ -538,7 +578,7 @@ export default function (pi: ExtensionAPI) {
538
578
  if (params.action === "recall") return toolResult(handleRecall(params, ctx));
539
579
  const restored = restoreTransaction(ctx.sessionManager.getBranch() as SessionEntry[]);
540
580
  const currentTx = withCompatDefaults(restored.transaction ?? transaction);
541
- if (!currentTx) return toolResult("No active midcompact transaction. Ask the user to run `/midcompact start` first.");
581
+ if (!currentTx) return toolResult("No active midcompact transaction. Ask the user to run `/midcompact:start` first.");
542
582
  transaction = currentTx;
543
583
  draft = restored.draft ? { ...restored.draft, ranges: restored.draft.ranges.map(coerceDraftRange) } : (draft ?? emptyDraft(currentTx.id));
544
584
  if (!requireAgentAccess(ctx)) {
@@ -569,7 +609,7 @@ export default function (pi: ExtensionAPI) {
569
609
  },
570
610
  });
571
611
 
572
- function handleInspect(params: ParamsType, atoms: Atom[], tx: TransactionState): string {
612
+ function handleInspect(params: InspectParamsType, atoms: Atom[], tx: TransactionState): string {
573
613
  if (params.spans) {
574
614
  if (params.page_size !== undefined || params.cursor !== undefined) {
575
615
  throw new Error("inspect spans cannot be combined with inventory pagination.");
@@ -580,7 +620,7 @@ export default function (pi: ExtensionAPI) {
580
620
  return formatInventory(page);
581
621
  }
582
622
 
583
- function handleRecall(params: ParamsType, ctx: ExtensionContext): string {
623
+ function handleRecall(params: RecallParamsType, ctx: ExtensionContext): string {
584
624
  const sm = ctx.sessionManager;
585
625
  const branchState = restoreCompressionState(sm.getBranch() as SessionEntry[]) ?? activeState;
586
626
  if (!branchState?.blocks.length) return "No compressed blocks are active on this branch.";
@@ -616,7 +656,7 @@ export default function (pi: ExtensionAPI) {
616
656
 
617
657
  // ---- Pure handlers ----
618
658
 
619
- function handleLocate(params: ParamsType, atoms: Atom[]): string {
659
+ function handleLocate(params: LocateParamsType, atoms: Atom[]): string {
620
660
  const hasFilter = Boolean(params.pattern || params.tool_name || (params.source && params.source !== "any"));
621
661
  if (params.ref && hasFilter) {
622
662
  throw new Error("locate accepts either one direct ref or search filters, not both.");
@@ -648,7 +688,7 @@ type PlanHandleResult =
648
688
  | { op: "show"; draft: DraftPlan }
649
689
  | { op: "add" | "update" | "remove"; draft: DraftPlan; changedId: string };
650
690
 
651
- function handlePlan(params: ParamsType, current: DraftPlan, atoms: Atom[]): PlanHandleResult {
691
+ function handlePlan(params: PlanParamsType, current: DraftPlan, atoms: Atom[]): PlanHandleResult {
652
692
  const op = params.op ?? "show";
653
693
  if (op === "show") return { op, draft: current };
654
694
  if (op === "remove") {
package/src/types.ts CHANGED
@@ -178,7 +178,7 @@ export interface TransactionState {
178
178
  startedAt: string;
179
179
  /** Initial routing chosen at start: Agent-first prompt or User-first UI. */
180
180
  startMode?: StartMode;
181
- /** Frozen awareness captured when /midcompact starts; informational, never a target. */
181
+ /** Frozen awareness captured when /midcompact:start runs; informational, never a target. */
182
182
  anchorUsage?: ContextUsageSnapshot;
183
183
  }
184
184