pi-midcompact 0.5.3 → 0.7.0

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
@@ -17,7 +17,7 @@ The name `pi-midcompact` points to the other option: **mid-context compression**
17
17
 
18
18
  ## What it does
19
19
 
20
- At a natural checkpoint, `pi-midcompact` freezes the active session leaf as an anchor and opens a separate transaction. The Agent proposes ranges for completed low-value phases, preserves load-bearing messages verbatim, and prepares a draft for review. Nothing changes until you explicitly commit the plan.
20
+ At a natural checkpoint, `pi-midcompact` freezes the active session leaf as an anchor and opens a separate transaction. The Agent proposes ranges for completed low-value phases, preserves load-bearing messages verbatim, and prepares a plan for review. Nothing changes until you explicitly commit the plan.
21
21
 
22
22
  ### User-directed depth, Agent-designed plan
23
23
 
@@ -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 plan never becomes part of the committed working context.
33
33
 
34
34
  ```text
35
35
  Frozen anchor: raw session history
@@ -53,9 +53,9 @@ The raw session JSONL still contains:
53
53
  [original d1]──[decision to KEEP]──[original d2]──[latest work]
54
54
  ```
55
55
 
56
- ### A reviewed draft can reclaim meaningful context
56
+ ### A reviewed plan can reclaim meaningful context
57
57
 
58
- The earlier browser and TUI captures below illustrate a draft with **2 ranges** covering **42 of 73 atoms**, while the other 31 atoms remain verbatim. The current UI reports Pi-provided anchor usage separately from factual content chars and image counts; it does not derive projected token savings from local character estimates. Click either image to open it at full resolution.
58
+ The earlier browser and TUI captures below illustrate a plan with **2 ranges** covering **42 of 73 atoms**, while the other 31 atoms remain verbatim. The current UI reports Pi-provided anchor usage as the baseline and derives a **display-only** projection of post-commit usage from documented char-class assumptions (labeled `est.`, shown as a range, never used for gating); factual content chars and image counts stay alongside it. Click either image to open it at full resolution.
59
59
 
60
60
  <p align="center">
61
61
  <a href="./figures/review-webui.png">
@@ -94,7 +94,7 @@ pi-midcompact — mid-context compression, review, then human commit
94
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 | Plan → 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.
@@ -127,7 +127,7 @@ Run:
127
127
  /midcompact:start
128
128
  ```
129
129
 
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:
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 plan until the user hands off later. Save the initial plan, 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
133
  /midcompact:start Compress the early repository exploration, but keep user requirements verbatim.
@@ -168,7 +168,7 @@ Use Selection to create or change ranges and KEEP holes:
168
168
  /midcompact:select-webui
169
169
  ```
170
170
 
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.
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 plan; the Agent is prompted to read the existing plan first.
172
172
 
173
173
  ### 4. Commit the reviewed compression
174
174
 
@@ -216,12 +216,29 @@ Enter/Esc/q close
216
216
  | `/midcompact:select-webui` | Opens the local browser Selection workbench. |
217
217
  | `/midcompact:review` | Opens summary/topic review in the native TUI. |
218
218
  | `/midcompact:review-webui` | Opens summary/topic review in a local browser. |
219
- | `/midcompact:commit` | Commits the reviewed draft. Human only. |
219
+ | `/midcompact:commit` | Commits the reviewed plan. Human only. |
220
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. |
221
+ | `/midcompact:status` | Displays the current plan, 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
 
225
+ ## Web UI Development
226
+
227
+ From a source checkout, run the browser workbench against in-memory fixtures
228
+ without starting Pi:
229
+
230
+ ```bash
231
+ npm run dev:webui
232
+ npm run dev:webui -- --port=4180 --no-open
233
+ ```
234
+
235
+ The command opens a fixture router for `review-ready`, `review-pending`,
236
+ `selection-mixed`, `no-telemetry`, and `wide-content`. Each button opens an
237
+ isolated workbench with its own in-memory plan. Fixture pages survive browser
238
+ refresh and the page's Close action, reload HTML changes automatically, and
239
+ restart for imported TypeScript changes. Stop the router with `Ctrl+C`. Use
240
+ `dev/midcompact-debug-ui.ts` only when validating against an actual Pi session.
241
+
225
242
  ## Guarantees and Limits
226
243
 
227
244
  - **Original history is retained.** Compression changes what later model requests see, not the stored Pi messages.
@@ -233,4 +250,4 @@ The extension shows planning status in Pi's footer only while a transaction is a
233
250
  - **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.
234
251
  - **Provider and extension interoperability needs more real-session validation.** Unusual message shapes, third-party context-transform ordering, and long-lived exact message fingerprints have not been broadly exercised.
235
252
  - **Very long sessions are not stress-tested.** Large review snapshots and repeated block accumulation may eventually require consolidation.
236
- - **Browser workbenches are local.** `select-webui` and `review-webui` bind to loopback and mutate the same branch-local DraftPlan as the native TUI surfaces.
253
+ - **Browser workbenches are local.** `select-webui` and `review-webui` bind to loopback and mutate the same branch-local plan as the native TUI surfaces.
package/README.zh-CN.md CHANGED
@@ -55,7 +55,7 @@ Pi 内置的 `/compact` 可理解为**前缀压缩**(prefix compaction):
55
55
 
56
56
  ### 实际压缩效果
57
57
 
58
- 下面的早期浏览器和 TUI 截图展示了一份包含 **2 个区段**、覆盖 **73 个 atom 中 42 个**的草案,其余 31 个 atom 保留原文。当前 UI 会把 Pi 提供的锚点 usage 与扩展统计的 content chars、图片数量分开显示,不再根据本地字符估算推导预计 token 节省量。点击图片可查看原图。
58
+ 下面的早期浏览器和 TUI 截图展示了一份包含 **2 个区段**、覆盖 **73 个 atom 中 42 个**的草案,其余 31 个 atom 保留原文。当前 UI Pi 上报的锚点 usage 为基线,并根据文档化的字符分类假设推导**仅供展示**的 commit 后占用预计(标注 `est.`、以区间呈现、绝不参与门禁);事实性的 content chars 与图片数量仍然并列展示。点击图片可查看原图。
59
59
 
60
60
  <p align="center">
61
61
  <a href="./figures/review-webui.png">
@@ -222,6 +222,21 @@ Enter/Esc/q 关闭
222
222
 
223
223
  扩展只在事务进行期间在 Pi 页脚显示规划状态;提交或放弃后会自动清除。
224
224
 
225
+ ## Web UI 开发
226
+
227
+ 在源码 checkout 中,无需启动 Pi 即可用内存 fixture 运行浏览器工作台:
228
+
229
+ ```bash
230
+ npm run dev:webui
231
+ npm run dev:webui -- --port=4180 --no-open
232
+ ```
233
+
234
+ 命令会打开一个 fixture router,其中包含 `review-ready`、`review-pending`、
235
+ `selection-mixed`、`no-telemetry` 和 `wide-content`。每个按钮都会打开一套独立的
236
+ 工作台和内存草案。刷新浏览器或点击 Close 不会终止 fixture;HTML 修改会自动刷新
237
+ 页面,导入的 TypeScript 修改会触发进程重启。用 `Ctrl+C` 停止 router。只有在验证
238
+ 真实 Pi 会话集成时,才需要使用 `dev/midcompact-debug-ui.ts`。
239
+
225
240
  ## 保证与限制
226
241
 
227
242
  - **保留原始历史。** 压缩只改变后续模型请求看到的内容,不改写存储的 Pi 消息。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-midcompact",
3
- "version": "0.5.3",
3
+ "version": "0.7.0",
4
4
  "description": "Branch-aware mid-context compression for the Pi coding agent",
5
5
  "author": "frostime",
6
6
  "repository": {
@@ -32,7 +32,8 @@
32
32
  ],
33
33
  "scripts": {
34
34
  "typecheck": "tsc -p tsconfig.json --noEmit",
35
- "test": "rm -rf .test-dist && tsc -p tsconfig.test.json && node test/install-mocks.mjs && node --test test/schema-contract.test.mjs test/core.test.mjs test/runtime-start.test.mjs test/runtime-agent.test.mjs test/runtime-user.test.mjs test/runtime-transaction.test.mjs test/runtime-lock.test.mjs",
35
+ "dev:webui": "tsx watch dev/review-webui-preview.ts",
36
+ "test": "rm -rf .test-dist && tsc -p tsconfig.test.json && node test/install-mocks.mjs && node --test test/schema-contract.test.mjs test/core.test.mjs test/runtime-start.test.mjs test/runtime-agent.test.mjs test/runtime-user.test.mjs test/runtime-transaction.test.mjs test/runtime-lock.test.mjs && node test/review-webui-dom.test.mjs",
36
37
  "typecheck:contract": "tsc -p tsconfig.test.json --noEmit",
37
38
  "pack:check": "npm pack --dry-run"
38
39
  },
@@ -45,6 +46,7 @@
45
46
  "@earendil-works/pi-ai": "^0.84.1",
46
47
  "@earendil-works/pi-coding-agent": "^0.84.1",
47
48
  "typescript": "^5.9.3",
49
+ "tsx": "^4.23.13",
48
50
  "@earendil-works/pi-tui": "^0.84.1"
49
51
  },
50
52
  "pi": {
@@ -1,134 +1,101 @@
1
1
  ---
2
2
  name: midcompact
3
- description: Use when a midcompact runtime prompt starts or hands off a compression-planning transaction, or when current work needs details from an active committed midcompact block. Guides user-aligned candidate discovery, effort-scaled inspect/locate/plan work, replacement-summary writing, and recall.
3
+ description: "Use when runtime starts or hands off midcompact planning, or current work needs originals from a committed block. Guides selective compression, local summaries, and recall."
4
4
  ---
5
5
 
6
6
  # Midcompact
7
7
 
8
- ## Route the activation
9
-
10
- This skill handles two independent tasks: planning compression and recalling committed content. Choose the route before calling the tool.
11
-
12
- | Signal | Immediate duty | First action |
13
- |--------|----------------|--------------|
14
- | Runtime prompt says `FINAL STATE: USER MANUAL` | Let the user create the initial DraftPlan | Reply exactly `OK`; call no midcompact tool |
15
- | Runtime prompt says `FINAL STATE: AGENT DIRECT` | Start from the new empty draft | `request={action:"inspect"}` |
16
- | A handoff reports a persisted DraftPlan and the user asks to continue | Read the shared selection and determine what help the user wants | `request={action:"plan", op:"show"}` |
17
- | The user or a projected summary needs detail from a committed block | Retrieve that history only | Follow **Recall workflow** |
18
-
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
-
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
-
23
- ## Plan compression
8
+ The frozen **anchor** contains **atoms**, the smallest selectable units (ref `a0001`); tool calls and their results stay together. Agent and user share one **plan** of contiguous **ranges** with replacement summaries (id `d1`). **Measure** compares candidates without changing the plan. Human commit turns each range into a **block** (`c0001`), replacing its originals in future context. **Recall** retrieves those originals.
24
9
 
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`.
26
-
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.
28
-
29
- Apply one invariant:
30
-
31
- > Every fact that can still affect future work must remain with sufficient fidelity, either outside the selected ranges or in their replacement summaries.
32
-
33
- ### Planning workflow
34
-
35
- #### 1. Read the entry state and user intent
10
+ ## Route the activation
36
11
 
37
- For a fresh Agent-direct transaction, begin with `request={action:"inspect"}`. For a handed-off DraftPlan, begin with `request={action:"plan", op:"show"}`; inspect the anchor only if the requested work needs broader context.
12
+ | Signal | Immediate action |
13
+ |---|---|
14
+ | Runtime says `FINAL STATE: USER MANUAL` | Reply exactly `OK`; call no midcompact tool. |
15
+ | Runtime says `FINAL STATE: AGENT DIRECT` | Call `request={action:"inspect"}`. |
16
+ | Handoff reports a persisted plan and user asks to continue | Call `request={action:"plan_show"}` before other midcompact actions. |
17
+ | Current work needs originals from a committed block | Follow **Recall**; do not enter planning. |
38
18
 
39
- Establish the user's desired scope, fidelity, and planning effort from their words, current selection, `User focus: ...`, and surrounding interaction. Treat answers collected through question, questionnaire, or similar tools as user-originated input even when represented as tool results.
19
+ Runtime instructions are authoritative. User-manual acknowledgement also forbids questions. Otherwise, complete the required first action before establishing direction.
40
20
 
41
- A manual selection records what the user selected, not whether they mean "only this" or "help me refine it." Follow a clear intent directly. If different interpretations would materially change the work, ask briefly whether to limit work to the selection or inspect and suggest changes. Do not force clarification when the user has already expressed a preference or delegated the judgment.
21
+ Read `references/tool-interface.md` when composing calls or handling protection/truncation. Use the schema for fields and defaults.
42
22
 
43
- Match effort to the requested fidelity. A quick or approximate request calls for bounded planning; a precision-sensitive request may justify deeper work after alignment.
23
+ ## Establish the compression direction
44
24
 
45
- #### 2. Form a bounded semantic view
25
+ If the user has not expressed a compression preference, ask before selecting ranges or investigating deeply:
46
26
 
47
- `inspect` returns factual structure with bounded user landmarks, grouped by user message. Use it for structure and volume, not to invent semantics. Ground candidates in visible conversation or a few targeted `locate` calls, and stop paging after the potentially relevant region. When exact candidate spans are known and their relative volume could change the choice, use read-only `inspect` spans to compare them without mutating the DraftPlan.
27
+ > Do you want light cleanup or substantial room for what comes next? What should I focus on, and what must stay verbatim? You can give a target usage or delegate the choice.
48
28
 
49
- Segment by completed work phase, not message count. User-originated input and concluding Agent responses are useful landmarks for intent and outcome, but are not automatically KEEP. Intermediate tool exchanges may also contain decisions or evidence absent from the final response.
29
+ Honor existing preferences; otherwise accept qualitative goals or delegation. Clarify ambiguous handoffs: refine the selection or work only within it? Respect explicit scope limits.
50
30
 
51
- | Often able to yield to a summary | Often load-bearing |
52
- |-----------------------------------|--------------------|
53
- | Repetitive or superseded exploration | Current intent and active constraints |
54
- | Tool output absorbed into a conclusion | Exact errors, evidence, or wording whose form matters |
55
- | A completed subtask's intermediate process | Decisions and rationale still governing the work |
56
- | A rejected attempt's mechanics | Its still-relevant failure reason |
31
+ Match compression and investigation effort to that direction. Compare factual character/image measurements; do not promise exact post-commit token savings. If meeting a target requires sacrificing important information, explain the tradeoff.
57
32
 
58
- Use little or no `locate` during this reconnaissance. If a phase cannot yet be described faithfully, omit it from the proposal or mark it as needing confirmation rather than exploring the anchor broadly.
33
+ ## Select worthwhile ranges
59
34
 
60
- #### 3. Present semantic options and align
35
+ Keep originals unless replacement serves the agreed goal; full-history coverage is not success.
61
36
 
62
- Before deep `locate` work or substantial DraftPlan mutation, establish the user's compression preference through explicit instruction, a reliable implication, or concise clarification.
37
+ Use `inspect` for structure and volume, not to infer unseen content. Ground candidates in visible conversation or targeted `locate_ref`/`locate_search` calls. Investigate only what could change selection; omit uncertain candidates or ask if investigation exceeds the agreed effort. Use `measure` when relative sizes affect the choice.
63
38
 
64
- Describe each proposal in recognizable conversation terms:
39
+ Weigh bulk removed against original detail lost and what retained context already carries. Technical eligibility alone does not justify compression.
65
40
 
66
- > From `<semantic start>` to `<semantic end>`, `<replace the whole phase / keep the endpoints and compress the work between>`; preserve `<load-bearing information>` in the summary.
41
+ ### Common patterns
67
42
 
68
- Use short recognizable excerpts when available and clear paraphrases otherwise. State whether the endpoint messages remain verbatim, what intermediate work disappears, and what the summary carries. Do not identify a user-facing range primarily by atom refs, DraftPlan ids, or arbitrary item numbers.
43
+ These are examples, not fixed rules about message roles or age.
69
44
 
70
- When treatments involve a meaningful tradeoff, present concise alternatives and recommend one. A clear quick request may need only one proportionate proposal. Add factual content or image measurements only when they help the choice, and do not convert them into unsupported token-savings claims.
45
+ - **Long execution between user messages.** Replace repetitive search, reading, editing, and testing when only results matter. Retain useful request/conclusion text and summarize key findings absent from it; tool output is not automatically noise.
46
+ - **Multi-turn discussion.** Summarize superseded proposals, repeated clarification, and detours. Keep failure reasons that explain decisions or prevent repeated mistakes; age alone does not make discussion obsolete.
71
47
 
72
- #### 4. Resolve boundaries and build the DraftPlan
48
+ One range reduces repetition in coherent discussion but may flatten distinctions. Semantic ranges allow different detail levels and KEEP holes, but risk duplication or broken causal links. Choose by content, not turn count; split around important originals.
73
49
 
74
- After the intended treatment is clear, use `request={action:"locate"}` for targeted content and boundary checks. An atom is the smallest selectable unit; a tool call and its matching results form one indivisible `tool_exchange` atom. Keep source text outside a range when exact wording or provenance matters and a summary cannot preserve it equivalently.
50
+ ### Preserve important user expression
75
51
 
76
- Choose boundaries from the information that must survive, not from a fixed category. A range may replace a whole semantic phase, including its initiating and concluding messages. It may instead retain a load-bearing user instruction and concluding Agent response while replacing only the execution between them. It may split around important material to leave KEEP holes. These are reasoning patterns, not rules tied to start mode, message age, or one prescribed kind of work.
52
+ Keep important user goals, constraints, preferences, corrections, authorizations, and refusals verbatim by default. Summaries can alter their scope or force. Ask for explicit agreement before summarizing them; general permission for aggressive compression is insufficient.
77
53
 
78
- Build or refine the shared DraftPlan with `plan add`, `update`, `remove`, and `show`. A handed-off selection may be preserved or revised as the user's intent permits. Use separate ranges for non-contiguous phases; fill pending summaries before commit. If deeper inspection would materially change the agreed treatment, surface the change instead of silently applying it.
54
+ Ask Question, questionnaire, and similar tool results may contain user expression. Judge by the speaker, not entry type. Retain the whole indivisible tool-exchange atom containing an important answer; split around it.
79
55
 
80
- Read `references/tool-interface.md` before retrying a rejected operation or when exact parameters, protected-atom causes, or measurements matter.
56
+ Routine acknowledgements can be candidates; task completion alone does not invalidate important statements.
81
57
 
82
- #### 5. Write replacement summaries
58
+ ### Propose and stop
83
59
 
84
- A replacement summary is successor context for a future Agent, not a transcript or a prompt to perform compression. State the resulting knowledge and working state directly.
60
+ Use conversation landmarks to explain replacements, originals kept, and summary contents. Offer alternatives for meaningful tradeoffs, not every delegated choice.
85
61
 
86
- Preserve, when applicable:
62
+ Stop when the goal is reasonably served or further compression is not worth the loss, not when all eligible content is covered. Re-align if findings materially change the treatment.
87
63
 
88
- - user intent and active constraints;
89
- - decisions, conclusions, and necessary rationale;
90
- - relevant files, symbols, interfaces, commands, or configuration;
91
- - completed changes and validation results;
92
- - rejected approaches only when their failure reason still matters;
93
- - unresolved issues and any established next step or continuation state.
64
+ ## Write a local replacement
94
65
 
95
- Remove repetitive exploration, superseded hypotheses, raw output captured by a conclusion, and chronology with no remaining consequence. Do not turn uncertainty into fact, invent a next action, or use references that only make sense inside the removed text. If retained endpoint messages already carry part of the intended context, do not duplicate them mechanically; use the summary to preserve what would otherwise be lost.
66
+ Summaries belong between retained earlier and later context, not as compression instructions or standalone handoffs.
96
67
 
97
- Organize by future utility rather than original chronology. When useful, use this compact frame without forcing empty fields:
68
+ Preserve necessary causes, consequential actions and findings, and resulting knowledge. Name important files, symbols, commands, or artifacts with their roles. Distinguish proposals from changes and assumptions from observed results. Length follows information needs, not a fixed ratio.
98
69
 
99
- ```text
100
- Goal and constraints:
101
- Established state and decisions:
102
- Artifacts and validation:
103
- Open issues and established next state:
104
- ```
70
+ Preserve consequential process, not activity logs. Replace vague “files changed, tests passed” with specific evidence: “Compared caller and parser, found ignored boundary arguments, added rejection, and verified an invalid-argument test.” Include relevant paths and results from the source.
105
71
 
106
- Length follows the information that must survive, not a target ratio. Final test: could a fresh Agent continue correctly from this summary plus retained context, without repeating work or violating a prior decision?
72
+ ### Fit the retained surroundings
107
73
 
108
- #### 6. Verify and hand off
74
+ Read enough surrounding context to avoid duplication and preserve what it depends on from this range. Resolve dangling references without inventing facts. Recall is recovery, not a substitute for sufficient summaries.
109
75
 
110
- Call `request={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.
76
+ A range's end is a historical boundary, not automatically the present state:
111
77
 
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.
78
+ - Do not turn an old unfinished task into a current TODO. Omit it if later retained context resolves it and its earlier status adds nothing.
79
+ - If the earlier status explains later events, describe it as historical. Do not attribute a later result to work within this range.
80
+ - Include current open issues and established next steps only when the range reaches the current working frontier and continuation needs them. Never invent a next action.
113
81
 
114
- ## Recall compressed content
82
+ If later retained turns test and reject approach A, “Next: validate A” is stale. Preserve why A was proposed if needed to explain the rejection; leave later outcomes where they belong.
115
83
 
116
- Recall works with or without an active planning transaction. It reads committed blocks active on the current branch without changing projection or DraftPlan.
84
+ ## Build, check, and hand off
117
85
 
118
- ### Recall workflow
86
+ Resolve boundaries with targeted lookups; split around protected atoms. Use `plan_add`, `plan_update`, and `plan_remove`. Updates change summary/topic; boundaries require remove + add. Fill pending summaries before handoff.
119
87
 
120
- #### 1. Find the block
88
+ Call `plan_show`; use `plan_read` when a stored summary needs full review. Check both:
121
89
 
122
- If its id is unknown, call `request={action:"recall", pattern:"..."}` to search active topics and summaries. A projected summary also states its block id and exact recall call.
90
+ - **Selection:** Does each range serve the user's direction? Are important originals and intended KEEP holes retained? Has unnecessary full-history coverage crept in?
91
+ - **Replacement:** Mentally remove the originals. Do summaries plus retained context explain the necessary causes, actions, evidence, and outcomes without gaps, vague claims, stale instructions, or state conflicts?
123
92
 
124
- #### 2. Retrieve the detail
93
+ Report replacements, retained originals, and stopping rationale. Boundaries: `/midcompact:select` or `/midcompact:select-webui`. Summaries: `/midcompact:review` or `/midcompact:review-webui`. Prefer browser variants when TUI is unavailable or unwanted. Only the user runs `/midcompact:commit`.
125
94
 
126
- Call `request={action:"recall", ref:"c0001"}`. If the readable, structure-flattened result ends with a truncation marker, retry with `detail="full"`. Retrieve only what the current task needs; do not start or change a plan merely to recall history.
95
+ ## Recall
127
96
 
128
- ## Tool conventions
97
+ Recall reads active committed blocks without changing a plan and needs no transaction. If the id is unknown, use `request={action:"recall_list",pattern:"..."}` to search ids, topics, and summaries, not originals. Projected summaries carry block ids and recall calls.
129
98
 
130
- - `g0001` labels an inventory group; use its `a...` span as internal landmarks.
131
- - `a0001` is a transaction-local atom ref; `d1` is a DraftPlan range id; `c0001` is an active committed-block id.
132
- - Protected atoms cannot enter a range. Split around them.
99
+ Use `request={action:"recall_read",block:"c0001"}`; retry truncation with `detail:"full"`. If still truncated, read `references/tool-interface.md`. Retrieve only needed content.
133
100
 
134
- These refs are planning handles, not the primary way to explain compression to the user. Read `references/tool-interface.md` for exact defaults and limits, rejected operations, protected-atom causes, measurements, repeated compression, or recall truncation.
101
+ `a...` refs are transaction-local; `d...` identifies a plan range; `c...` a committed block. Inventory `g...` labels are display-only; use listed atom refs for calls.
@@ -1,87 +1,69 @@
1
- # Midcompact Tool Interface
1
+ # Tool Call Patterns
2
2
 
3
- Read this reference when exact call requirements, limits, rejection behavior, repeated compression, or recall truncation matters. The main workflow remains in `../SKILL.md`.
3
+ Use the schema for fields/defaults. Follow only the steps needed. Example refs and summaries must be replaced with verified content.
4
4
 
5
- ## Parameter grouping
5
+ ## Survey where context space goes
6
6
 
7
- The parameters are one object with a single `request` field; `request` is a discriminated union where each branch binds one `action` value to exactly that action's fields and is closed (`additionalProperties: false`). A call that mixes actions (for example `locate` fields on `plan`) is rejected by the schema itself; 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.
7
+ Start a fresh Agent-direct transaction with:
8
8
 
9
- ## Inspect
10
-
11
- Without `spans`, `request.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.
12
-
13
- - `page_size`: default 20 groups, maximum 50.
14
- - `cursor`: opaque value returned by the previous page.
15
- - Results include group refs, atom spans, content chars, image facts, protected/compressible counts, and Pi-reported anchor usage.
16
-
17
- Stop paging after the candidate regions are covered.
18
-
19
- To compare explicit candidates without mutating the DraftPlan, pass one or more possibly overlapping spans:
20
-
21
- ```text
22
- midcompact(request={action:"inspect", spans=[
23
- {"start":"a0006","end":"a0014"},
24
- {"start":"a0006","end":"a0020"}
25
- ]})
9
+ ```json
10
+ {"request":{"action":"inspect"}}
26
11
  ```
27
12
 
28
- Span inspection reports bounded endpoint landmarks, atom/message and role counts, tool exchanges and calls, factual content share, images, and protected/compressible counts. It has a 12,000-character total output budget and reports how many requested spans fit. It does not report per-span tokens: Pi supplies usage for the whole anchor, not token attribution by range. Do not combine `spans` with `page_size` or `cursor`.
29
-
30
- ## Locate
13
+ Read overall Pi token usage and chronological groups: user landmarks, endpoints, characters, images, protection counts. This paginated volume distribution is not a per-group token curve. Large groups invite investigation, not automatic compression.
31
14
 
32
- `request.action="locate"` returns atoms from the frozen anchor. Supply either:
15
+ Continue with the returned `cursor` only where relevant. Use listed `a...` refs, not display-only `g...` labels. Landmarks are not full content; combine the overview with user preferences before selection.
33
16
 
34
- - `ref`: one direct atom lookup; or
35
- - at least one real filter: `pattern`, `tool_name`, or `source` other than `any`.
17
+ ## Find evidence and check boundaries
36
18
 
37
- With no lookup or filter it returns no matches rather than an error. Filtered searches return at most three brief candidates; when more match, the result reports the total and asks for a more specific pattern or additional filter. `direction` is `oldest` by default or `newest`; `limit` may request one to three results.
19
+ For a recent bash result containing a known phrase:
38
20
 
39
- Brief direct lookups preserve both ends of an atom landmark. Pattern searches show a bounded excerpt around the match rather than the atom prefix. `detail="full"` is allowed only with one direct `ref` and preserves both ends with an explicit middle-omission marker when the 12,000-character atom limit is exceeded.
21
+ ```json
22
+ {"request":{"action":"locate_search","source":"tool_result","tool_name":"bash","pattern":"timeout","direction":"newest"}}
23
+ ```
40
24
 
41
- A `g...` inventory ref is not a locate ref; use the group's `a...` start/end landmarks.
25
+ Filters combine with AND. Use a returned atom ref to inspect the match:
42
26
 
43
- ## Plan
27
+ ```json
28
+ {"request":{"action":"locate_ref","ref":"a0007","detail":"full"}}
29
+ ```
44
30
 
45
- `request.action="plan"` uses `op="show"` by default. Agent and user mutate the same DraftPlan.
31
+ Known refs need no search. Excerpts are incomplete; `full` can omit the middle. Check markers before drawing conclusions. Narrow excessive matches with filters. Recover unknown refs using `inspect` or `locate_search`; `measure` needs known refs.
46
32
 
47
- | op | Required fields |
48
- |----|-----------------|
49
- | `show` | none; optional `draft_id` for one range |
50
- | `add` | `start`, `end`; optional `summary`, `topic` |
51
- | `update` | `draft_id` and at least one of `summary`, `topic` |
52
- | `remove` | `draft_id` |
33
+ ## Compare candidates without changing the plan
53
34
 
54
- Default show lists each range with bounded `from`, `to`, and `summary` landmarks plus factual metrics. Use `op="show", detail="full", draft_id="d1"` for one stored summary and endpoint previews under a 40,000-character total budget; full detail without `draft_id` is rejected. Show is read-only and does not persist a duplicate DraftPlan entry.
35
+ ```json
36
+ {"request":{"action":"measure","candidates":[{"start":"a0006","end":"a0014"},{"start":"a0006","end":"a0020"}]}}
37
+ ```
55
38
 
56
- Add/update return the changed range in brief form; remove returns its id and compact draft totals. Mutation responses omit the Pi-awareness header and unchanged ranges. Use explicit show when complete awareness is needed.
39
+ Candidates may overlap without changing the plan. Compare landmarks, content share, images, and protection, not assumed token savings. If fewer candidates are reported than requested, measure the remainder separately.
57
40
 
58
- An omitted or empty `summary` creates a pending range. Review can open it, but commit requires at least one range and a non-empty summary for every range. Changing boundaries requires removing the old range and adding the replacement.
41
+ ## Keep important originals between ranges
59
42
 
60
- ### Add rejection conditions
43
+ If an important user answer occupies `a0010`, locate it and verify boundaries, then add separate ranges on its two sides:
61
44
 
62
- | Condition | Response |
63
- |-----------|----------|
64
- | The range crosses a protected atom | Split the range around that atom |
65
- | The range overlaps an existing draft range | Remove or replace the existing range first |
66
- | `start` occurs after `end` | Correct the positional order |
67
- | An atom ref is unknown | Re-run inspect/locate against the current transaction snapshot |
45
+ ```json
46
+ {"request":{"action":"plan_add","start":"a0006","end":"a0009","summary":"<replacement for the earlier work>"}}
47
+ {"request":{"action":"plan_add","start":"a0011","end":"a0014","summary":"<replacement for the later work>"}}
48
+ ```
68
49
 
69
- An atom is protected when its tool protocol is incomplete or orphaned, it represents an existing compressed block, its message kind is unsupported, or it lacks the persistent session entry needed to anchor compression.
50
+ Question-tool answers are user expression. Keep the whole tool-exchange atom containing an important answer; do not split a call from its results. Unlike measurement candidates, plan ranges cannot overlap or contain protected atoms.
70
51
 
71
- ## Telemetry
52
+ ## Refine an existing plan
72
53
 
73
- Explicit `plan show` includes Pi-reported anchor usage when available and factual draft measurements: original/replacement content chars, image count, and decoded payload bytes. Mutation results omit awareness and report only compact totals plus the changed range where one remains. Local character or image measurements are not converted into token savings or projected-token percentages. Use measurements to compare the proposal with user-directed depth, not as an optimization target.
54
+ Start with `plan_show`. Use `plan_read` with its returned `range_id` when the stored summary or endpoints need full review. Change summary/topic with `plan_update`.
74
55
 
75
- ## Repeated compression
56
+ For new boundaries, first read and retain the existing summary/topic and verify the replacement endpoints. Then `plan_remove` the old range and `plan_add` its replacement. Do not assume the new id is unchanged. Check the resulting plan; mutation replies show the changed item and compact totals, not all ranges. Fill pending summaries before handoff; only the user commits.
76
57
 
77
- Committed blocks appear as protected atoms in later transaction snapshots and cannot be compressed again. A later transaction may compress newly accumulated raw history around those blocks. Re-run inspect/locate because atom refs are transaction-local.
58
+ ## Work around protected content
78
59
 
79
- ## Recall
60
+ Split around protected atoms. Causes include incomplete tool exchanges, unsupported message kinds, missing persistent entries, and existing committed blocks. Later transactions can compress remaining raw history around those blocks, not recompress the blocks themselves. Obtain current atom refs from `inspect`; refs are transaction-local.
80
61
 
81
- `request.action="recall"` works independently of a planning transaction and reads committed blocks active on the current branch.
62
+ ## Retrieve committed evidence
82
63
 
83
- - Without `ref`, `pattern` searches block topics and summaries; `limit` defaults to 8 and has a maximum of 20.
84
- - With `ref="c0001"`, the tool renders that block's stored messages.
85
- - `detail="full"` raises the rendering cap when the normal result is truncated.
64
+ ```json
65
+ {"request":{"action":"recall_list","pattern":"timeout"}}
66
+ {"request":{"action":"recall_read","block":"c0001"}}
67
+ ```
86
68
 
87
- Recall has no paging. The truncation marker is `[truncated; refine the recall request or inspect the source session for more]`. If `detail="full"` still truncates before the needed detail, report that recall cannot expose the omitted content; do not infer it.
69
+ Use the actual block id returned by the list; skip listing when known. Listing searches ids/topics/summaries, not originals. Recall needs no transaction. If truncated, retry the same block with `detail:"full"`. There is no paging: if still truncated, report that recall cannot expose the omitted evidence. Do not infer it or start another transaction as a recovery workaround. Inspecting the source session requires a separate available means; this tool offers none.
package/src/SPEC.md CHANGED
@@ -32,7 +32,12 @@ package.json → `pi.extensions`).
32
32
  then appends state, abort appends nothing. Both refuse to run while the
33
33
  Agent holds the planning lock.
34
34
  - `anchorUsage` is informational only — Pi-reported awareness, never an
35
- optimization target (same rule as `projectedTokens` / estimates).
35
+ optimization target. The web workbench may additionally render a
36
+ **display-level** post-commit projection derived from the documented
37
+ char-class assumption table in `content-metrics` (`TOKEN_ESTIMATE`): always
38
+ labeled `est.`, shown as a propagated band, and never feeding commit
39
+ gating, range validation, or any decision (same rule as `projectedTokens`
40
+ / `approxTokens`).
36
41
  - Atom refs are transaction-local: re-run inspect/locate in a later
37
42
  transaction; group refs (`g...`) are never locate refs.
38
43
 
@@ -66,21 +71,44 @@ package.json → `pi.extensions`).
66
71
  ## External contracts (reference, don't duplicate)
67
72
 
68
73
  - Tool: one `midcompact` tool whose parameters are `{ request: <union> }` —
69
- a root `type: "object"` wrapping a discriminated union on `action`
70
- (inspect/locate/plan/recall); each branch is closed
71
- (`additionalProperties: false`), so cross-action parameters are
72
- schema-rejected. The `request` wrapper exists because some providers
73
- (e.g. DeepSeek) reject a root-level `anyOf` before the model sees the
74
- schema.
74
+ a root `type: "object"` wrapping a union of 11 single-purpose actions
75
+ (inspect/measure/locate_ref/locate_search/plan_show/plan_read/plan_add/
76
+ plan_update/plan_remove/recall_list/recall_read); each branch is closed
77
+ (`additionalProperties: false`), so extra fields are rejected (schema where
78
+ enforced, runtime backstop everywhere — a silently ignored field is a bug).
79
+ Former second-level discriminators (plan `op`, locate ref-vs-filter, recall
80
+ list-vs-render, inspect inventory-vs-spans) are flattened into branches so
81
+ field legality is schema-visible. The `request` wrapper exists because some
82
+ providers (e.g. DeepSeek) reject a root-level `anyOf` before the model sees
83
+ the schema.
75
84
  Details: `skills/midcompact/references/tool-interface.md`.
76
85
  - Commands: `midcompact:start|abort|commit|review|review-webui|select|select-webui|status`;
77
86
  no composite `/midcompact`; native naming convention `name:sub` (Pi's
78
87
  `skill:<name>`).
79
88
  - The tool never starts a transaction and never commits; both are command-
80
89
  or user-gated. Recall is the only action valid without a transaction.
90
+ - Web workbench (`review-webui.html` + `review-webui.ts`): the state payload
91
+ carries per-atom char-class counts (`narrowChars`/`wideChars`), per-range
92
+ replacement char-class counts (including the actual wrapper), and the
93
+ assumption table (`est`), so the page renders the projection band and can
94
+ update estimates while a summary is edited; `GET /api/atom/:ref` serves the
95
+ frozen atom's full text for the original-text drawer (read-only, snapshot-local).
96
+ `startReviewWebUiServer` owns the Pi-independent loopback HTTP contract;
97
+ `showReviewWebUi` adapts it to Pi notification, browser launch, and page-bound
98
+ lifetime. Development may opt into a persistent server without changing the
99
+ production defaults.
100
+ User-facing copy says "can't compress" for protected atoms; "protected"
101
+ stays the agent/tool-side term.
102
+ Page invariants that broke once and must hold: the `<!--MIDCOMPACT_STATE-->`
103
+ script tag is the server's template injection point (renaming it breaks
104
+ state loading); `selectionRefs` initialization depends on helpers defined
105
+ later in the page script (order is load-bearing, TDZ); `gbody` visibility
106
+ is driven by the render-time `hidden` attribute, so collapse handlers must
107
+ sync that attribute, not just a class.
81
108
 
82
109
  ## Change rules
83
110
 
111
+ - Model-facing copy (schema descriptions, prompts, errors, notices, skill docs) follows `.dev/docs/agent-vocabulary.md`; a new action, field, or concept is registered there **before** implementation.
84
112
  - Adding a tool action → new request branch + handler type + tool-interface
85
113
  section + SKILL.md routing; adding parameters to an action → its branch
86
114
  only (the union stays nested under `request`).