-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimplementation-notes.html
More file actions
246 lines (246 loc) · 26.6 KB
/
Copy pathimplementation-notes.html
File metadata and controls
246 lines (246 loc) · 26.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pi Context Implementation Notes</title>
<style>
:root { color-scheme: light dark; font-family: system-ui, sans-serif; line-height: 1.5; }
body { max-width: 72rem; margin: 0 auto; padding: 2rem; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #8888; padding: .6rem; text-align: left; vertical-align: top; }
th { background: #8882; }
code { background: #8882; padding: .1rem .25rem; border-radius: .2rem; }
</style>
</head>
<body>
<h1>Pi Context Implementation Notes</h1>
<table>
<thead><tr><th>Provenance</th><th>Decision</th><th>Rationale and constraint</th></tr></thead>
<tbody>
<tr>
<td>user-decided</td>
<td>Migrate the complete canonical ACM architecture and behavior from <code>omp-context</code> to <code>pi-context</code>, preferring public Pi interfaces where available.</td>
<td>The Pi implementation must preserve observable ACM contracts without mechanically copying OMP-private types or seams.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Gate Live Agent Sync only on the runtime capabilities it uses; do not inspect or report the Pi host version.</td>
<td>If the required <code>AgentSession</code> lifecycle and mutable message-state capabilities are present, synchronization runs. Missing or failed capabilities fall back to the persistent context rebuild and reload recovery path. Version and compatibility labels are intentionally omitted because timeline output enters model context.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Associate live <code>AgentSession</code> instances with <code>SessionManager</code> identity through one idempotent, weakly referenced adapter.</td>
<td>The adapter probes the <code>getContextUsage()</code> lifecycle seam and each captured session's <code>sessionManager</code>, <code>agent.state</code>, and replaceable <code>messages</code> state. It rebuilds messages from the active SessionManager leaf and never owns tree mutations.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Keep persistent tree mutation in Host Bridge and live-state replacement in a separate compatibility boundary.</td>
<td><code>appendLabelChange()</code> and <code>branchWithSummary()</code> are public runtime capabilities, while <code>buildSessionContext()</code> is a public <code>@earendil-works/pi-coding-agent</code> package export. Extension tool context exposes only a readonly manager type, so Host Bridge performs guarded mutation access and centralizes package-level context reconstruction; the adapter only synchronizes the matching live session after callers schedule it.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Schedule live synchronization only after a structurally verified travel and apply it from the matching <code>tool_execution_end</code> event.</td>
<td>The travel tool remains synchronous and truthful about its branch result. Deferring message replacement until the matching tool execution ends preserves the in-flight call/result protocol while preventing failed, indeterminate, or unrelated tool executions from modifying live state.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Preserve a verified traveled branch when live message replacement fails, and surface reload guidance without attempting tree rollback.</td>
<td>The persistent SessionManager branch and context-event rebuild remain authoritative. A post-travel live-sync failure clears only the matching pending tool operation, records a terminal diagnostic, and emits a warning; rolling back a valid travel would be more destructive than leaving native accounting stale until reload.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Treat each scheduled synchronization as replaceable per <code>SessionManager</code>, and make the resulting persisted branch the only resume authority.</td>
<td>A later travel supersedes stale pending work only for the same manager. Off-path restoration rebuilds from the newly selected leaf, while process resume opens the persisted tree into a new manager/session association instead of retaining any previous-process <code>AgentSession</code> object.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Scope live synchronization strictly to each <code>SessionManager</code>/<code>AgentSession</code> identity pair, including parent/subagent and duplicate extension registrations.</td>
<td>The process-wide adapter owns weak session associations and one atomic <code>{ toolCallId, preferredLeafId }</code> pending ticket per manager. Duplicate extension runtimes therefore cannot consume each other's tool completion, lifecycle cleanup addresses one manager only, and no working-directory, model, session-file, or global-current-session matching is used.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Use strict Pi TypeBox schemas rather than recreating the OMP runtime-injected Zod seam.</td>
<td>Pi exposes TypeBox through <code>@earendil-works/pi-ai</code>. The timeline schema keeps the single-view contract, including omitted <code>view</code> as active mode, without accepting legacy competing booleans.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Make capability observation non-throwing and publish installation state only through a successfully installed wrapper.</td>
<td>Frozen/read-only host prototypes and throwing session getters are capability failures, not extension-fatal errors. The wrapper carries the process-wide installation marker, observation never prevents the original lifecycle method from running, and current session capabilities are re-probed when synchronization is scheduled and applied.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Verify message replacement by checking that live state retains the rebuilt message sequence, not the caller's array identity.</td>
<td>Live validation against Pi 0.80.6 exposed that the documented <code>Agent.state.messages</code> setter deliberately stores <code>nextMessages.slice()</code>. Reference identity therefore reports a false failure after a successful replacement. Element-by-element sequence identity accepts the host's top-level defensive copy while still detecting thrown or silently ignored replacement when the rebuilt branch differs.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Retire prototype-only synchronization code only after the production capability matrix proves equivalent behavior.</td>
<td>The final fixture combines a shrinking travel, a valid in-flight <code>acm_travel</code> call/result pair, provider-context rebuild, archive recovery, and native compaction accounting. Additional fixtures cover unsupported capability, replacement failure, repeated travel, off-path restoration, persistence/resume, lifecycle cleanup, and multi-session/parent-subagent isolation. No prototype runner or duplicated adapter remains.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Keep the independently improved Pi-only <code>/context</code> TUI and route its compaction-aware message reconstruction through Host Bridge.</td>
<td>The remote implementation depended on a helper removed by the modular ACM migration. Reusing <code>buildSessionMessages()</code> preserves its calibrated token breakdown and <code>Other</code> accounting while keeping SessionManager reconstruction capability access at the repository's single host seam.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Implement semantic rebase as agent-level use of the existing Pi <code>acm_travel</code> contract, with cold start as the hard safety gate.</td>
<td>The underlying Pi tree mutation is identical to local travel. The runtime therefore reports only factual active/projected summary depth and travel deltas; candidate safety remains a semantic judgment performed from earliest to latest, with root treated as a candidate rather than a default.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Keep Pi-native TypeBox schemas, lifecycle seams, <code>/context</code> TUI, and capability-probed adapter while synchronizing the shared ACM guidance and evidence model.</td>
<td>The corresponding behavior is adapted to Pi architecture instead of copying OMP-specific package APIs, injected Zod, or host contracts. The extension now always registers its canonical prompt hook because this repository has no integrated-consumer bypass.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Refine rebase without weakening checkpoint, local-fold, failed-direction, or task-end behavior.</td>
<td>The always-on CORE retains every normal transition and a complete local-fold example. Rebase adds a structural-reset criterion alongside cold start rather than replacing the existing fold gate.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Improve checkpoint invocation predictability by front-loading a task-start preflight and making the checkpoint tool description trigger-first.</td>
<td>The prompt follows the user-provided <code>writing-great-skills</code> principles: <code>preflight</code> is the leading word, the first action is explicit, and completion is checkable from the checkpoint tool result.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Prioritize reliable model behavior and complete operational contracts over the previous 6,000-character CORE and 300-character checkpoint-description budgets.</td>
<td>The limits are now loose anti-sprawl guards rather than optimization targets. Vocabulary precision, transition timing, checkpoint naming and target semantics, and preflight failure handling may use the space needed for predictable execution.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Define managed work concretely and make non-ACM tool use an explicit preflight trigger.</td>
<td>Investigation, planning, delegation, non-ACM tools, file or external side effects, and multi-step reasoning require a completed checkpoint first; only a text-only direct reply requiring none of them stays outside the managed-chain workflow. When finished work is still active, its rebase/fold transition runs first so the new checkpoint lands on the branch that will carry the new goal.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Use one advanced reference at a time and reroute when the observable condition changes.</td>
<td>This preserves progressive disclosure without trapping archive recovery inside the wrong playbook after a failure. Recovery references now distinguish backup-label rollback from indeterminate branch mutation and use factual refresh/live-sync lifecycle states.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Send ACM context-usage reminders through Pi's hidden custom-message channel at 30%, 50%, and 70% usage tiers.</td>
<td>The reminder must identify itself as ACM-generated and remain invisible in the Pi TUI while participating in model context. The 30% tier is a light opportunity cue, 50% asks the agent to actively look for a safe travel boundary, and 70% is the final and strongest reminder for that context cycle.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Keep reminders advisory: prefer low active-context usage, but never force summary, fold, rebase, or travel.</td>
<td>The agent evaluates whether current task requirements permit a complete and recoverable handoff. Correctness, task continuity, required working state, and recoverability take priority; native compaction remains acceptable for genuinely long tasks.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Track the highest reminder tier per context cycle; ordinary usage drops do not rearm tiers, while successful ACM travel and native Pi compaction start a new cycle.</td>
<td>Within a cycle only a newly reached higher tier produces a reminder, and a single observation that skips tiers emits only the highest one. A new cycle treats its first authoritative post-transition usage as a no-reminder baseline.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Arm reminders from the <code>context</code> lifecycle, deliver at <code>tool_result</code> with <code>steer</code>, and use normal-stop <code>agent_end</code> with <code>followUp</code> as the no-tool fallback.</td>
<td>This follows Pi's public Channel 2 transport without modifying tool output. After travel or compaction, immediate <code>getContextUsage()</code> may still reflect pre-transition native accounting, so baseline establishment waits for the next real assistant prompt usage captured at <code>turn_end</code>.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Persist the first authoritative post-transition baseline as an <code>acm:context-usage-state</code> custom entry, then restore reminder-cycle state from baseline entries plus delivered reminder messages.</td>
<td>A delivered reminder alone cannot distinguish “baseline not established” from “baseline established below 30%,” and reload must also preserve a baseline already at 30% or 50%. Pi's public <code>appendEntry()</code> channel keeps the baseline marker on the active branch without adding it to LLM context; reconstruction scans only after the latest ACM travel branch summary or native compaction boundary.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Classify ACM reminders against a working budget capped at 400K tokens while preserving hard-window usage as a separate metric.</td>
<td><code>workingBudgetTokens = min(contextWindow, 400000)</code>: models at or below 400K retain their actual-window 30% / 50% / 70% behavior, while larger windows use 400K and therefore trigger at 120K / 200K / 280K active tokens. Existing persisted levels remain compatible; reminder details, baseline state, and the timeline dashboard expose both hard usage and ACM pressure rather than redefining <code>usagePercent</code>.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Give all three ACM tools explicit <code>promptSnippet</code>, <code>promptGuidelines</code>, self-owned shells, and custom call/result rendering.</td>
<td>The tools must be easier for the model to discover and use correctly while presenting checkpoint placement, timeline evidence, and travel outcomes more clearly in Pi's TUI.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Keep prompt metadata trigger-first and render compact evidence by default, with full raw tool output available only in the expanded view.</td>
<td>Each flat guideline names its tool as required by Pi. Renderers reuse row components, distinguish success from error or indeterminate outcomes, and remain presentation-only: the LLM-facing <code>content</code>, structured <code>details</code>, and mutation behavior are unchanged.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Neutralize terminal control characters in dynamic ACM tool-renderer text without changing LLM-facing tool results.</td>
<td>Pi 0.80.6 custom <code>Text</code> components preserve embedded C0/C1 controls, while the default tool renderer strips them. Session snippets, host errors, and streaming arguments can therefore carry cursor-control or terminal-title sequences into the ACM self-owned shells. Shared presentation sanitization now normalizes carriage returns and removes unsafe controls before dynamic values enter <code>Text</code>; tabs, line breaks, structured <code>details</code>, and tool <code>content</code> remain unchanged.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Reserve <code>root</code> case-insensitively across checkpoint and backup aliases, while keeping it exclusively as the structural first-root target.</td>
<td>Target resolution treats every letter-case variant of <code>root</code> as the structural keyword. Allowing the same spelling as a label creates an alias that can be written but never addressed, so validation now rejects it both at tool entry points and at the Host Bridge mutation boundary.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Contain every guarded SessionManager observation inside typed Host Bridge/coordinator outcomes and report backup-label presence as <code>present</code>, <code>absent</code>, or <code>unknown</code>.</td>
<td>Host getters and post-mutation reads can fail after a mutation may have landed. Pre-mutation failures remain <code>not_applied</code>; unverifiable post-mutation state is <code>indeterminate</code>. Recovery presence replays the complete global label journal so alias reassignment is honored, and user-facing guidance falls back to the backup history node rather than claiming an unverified alias remains.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Keep npm as the reproducible root installer and Bun as the test/build runtime, with host-fixture dependency resolution isolated behind its own frozen Bun lock.</td>
<td>Pi 0.80.6 clones git packages and runs <code>npm install --omit=dev</code>, so the root <code>package-lock.json</code> is part of the production installation contract rather than disposable development state. Root <code>bun test</code> excludes <code>test/host-fixture/**</code>; the complete gate runs every root test and then lets the fixture install, build, and test against its exact Pi version independently. CI pins both toolchains and starts from <code>npm ci</code> so stale locks and residue-dependent passes fail.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Require <code>acm_travel</code> to execute alone in its assistant tool batch, force sequential dispatch, and reject a detected mixed batch before any session mutation.</td>
<td>Pi 0.80.6 persists the assistant tool-call message before dispatch but emits <code>tool_execution_end</code> before persisting each tool result. A successful travel replaces the live/session branch at that event, so sibling results from the removed assistant message can become orphaned and be sanitized away even though their external side effects already occurred. Sequential dispatch makes ordering deterministic; the runtime guard remains the safety boundary for both call orders, while canonical guidance prevents avoidable retries.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Keep <code>/context</code> attribution aligned with Pi's provider-visible payload and native message estimator.</td>
<td><code>getAllTools()</code> includes source metadata and prompt guidelines that are not part of the provider tool schema; guidelines already contribute through the effective system prompt. The panel therefore estimates only <code>name</code>, <code>description</code>, and <code>parameters</code>, reports zero tool-schema tokens when no tools are active, and splits assistant text/thinking/tool calls with the same character weights as Pi 0.80.6 <code>estimateTokens()</code>. Downward-only calibration and an explicit <code>Other</code> remainder preserve the official total without inventing attribution.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Treat an equivalent branch summary as applied only when the active leaf changes during the current host mutation attempt.</td>
<td>Summary-content equality alone cannot attribute a mutation: the active leaf may already contain the requested handoff before <code>branchWithSummary()</code> throws or performs no work. Host Bridge now classifies an unchanged equivalent leaf as <code>not_applied</code> while preserving any host error, accepts a changed exact-summary leaf as observed application even if the host return is malformed or throws afterward, and retains <code>indeterminate</code> for failed post-mutation observation.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Treat <code>/context</code> as a TUI-only diagnostic surface, contain host/UI failures, and verify its public contract through the exact Pi <code>0.80.6</code> runner.</td>
<td>Pi exposes <code>mode</code> specifically to guard terminal-only custom components, while non-TUI hosts may provide a silent <code>ui.custom()</code>. The command now rejects unavailable or non-finite usage, sanitizes host-derived warning text, reports a custom-UI no-op, and keeps failures from escaping normal command execution. The host fixture loads the built extension through the exact <code>ExtensionRunner</code> and renders it with exact <code>pi-tui</code>, so registration, command context, and component compatibility remain regression-tested.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Canonicalize guidance source and generated-output line endings to LF, and enforce LF text checkouts through <code>.gitattributes</code>.</td>
<td>Windows Git checkouts can convert repository text to CRLF. Without normalization, <code>JSON.stringify()</code> preserves CRLF inside generated runtime strings and the strict generated-guidance check reports a false stale artifact before tests run. The generator now normalizes source and comparison input, while the repository attribute keeps normal working trees deterministic across operating systems.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Replace the mandatory ACM preflight, transition table, and gate checklists with compression-as-intelligence doctrine, recognition cues, and default agent autonomy. Supersedes the earlier preflight and transition-table decisions.</td>
<td>Scripted workflows made weak models copy rituals and strong models route around the tools. The CORE now teaches judgment: the working set carries settled knowledge, honest uncertainty, the hot set, and pointers; compression is continuous while folding is batched between the sediment and thrash failure modes. Fold moments are recognition patterns ("the weighing, not the fold, is what the moment asks for"), never required transitions, and travel is autonomous unless the user explicitly holds it.</td>
</tr>
<tr>
<td>user-decided</td>
<td>Split canonical guidance into <code>CORE.md</code> (道 and 度: judgment and cadence) and <code>TOOL-CONTRACTS.md</code> (术: tool descriptions, prompt metadata, result cues, recovery text), both compiled by one generator.</td>
<td>Tool descriptions and result cues sit at the invocation moment and survive long contexts, so mechanics belong there; the always-on CORE stays small enough to hold attention. Prompt snippets and guidelines now come from the generated module so no runtime string can drift from the canonical source.</td>
</tr>
<tr>
<td>user-decided</td>
<td>State a lean-working-set preference — about one third of the working budget as a comfortable cruise — and present rehydrate and fork as first-class moves.</td>
<td>The preference aligns the doctrine with the 30% reminder tier while remaining subordinate to correctness, task continuity, and cold start. Rehydrate (save, travel to the archive, return with the extract) and fork (save, explore, fold forward or travel back) make travel bidirectional rather than only a retreat.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Remove suffix-driven cue branching from the runtime; checkpoint and travel each emit one canonical cue.</td>
<td>Selecting cues by <code>-done</code> suffixes made label spelling a hidden state machine, contradicting the contract that names are recovery cues rather than workflow states. The single cues describe the observable outcome and the next judgment without inferring task phase from names.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Advance the exact supported Pi host from <code>0.80.6</code> to <code>0.80.7</code> across dev, peer, and host-fixture pins.</td>
<td>The user's live Pi installation runs <code>0.80.7</code>, so the verified contract must match the actual runtime. The full fixture matrix — <code>ExtensionRunner</code> registration, <code>/context</code> rendering, adapter capability probing, travel/live-sync ordering, and lifecycle isolation — passes unchanged on <code>0.80.7</code>; <code>navigateTree()</code> remains command-context-only and cannot carry an agent-authored handoff, so the Host Bridge <code>branchWithSummary()</code> path and the capability-probed adapter remain the correct seams.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Treat manual <code>/tree</code> navigation as a first-class context transition: reset volatile ACM runtime state on <code>session_tree</code>, shape plain summarize requests through <code>session_before_tree</code> into the seven-slot handoff, and count every active-branch summary or compaction as a reminder-cycle boundary on restore.</td>
<td>Manual navigation bypasses <code>acm_travel</code>, so stale refresh targets, live-sync tickets, and reminder baselines could otherwise survive onto the newly selected branch, and native summaries spoke a different vocabulary than travel handoffs. User-authored summarization instructions always win; the extension only replaces the default prompt when the user asked for a plain summary. Restore-boundary detection now matches live behavior, which resets the cycle on travel, compaction, and manual navigation alike.</td>
</tr>
<tr>
<td>agent-resolved</td>
<td>Make every prompt surface name its concrete next move: the checkpoint cue teaches the checkpoint→travel chain, each reminder tier carries one tool step, and the handoff contract states line-per-slot shape with an immediately executable <code>NEXT</code>.</td>
<td>Weaker models act on named tools, not abstract advice: "weigh a fold" gives no callable action, while "acm_travel targeting this point folds that process" does. The additions stay advisory — no tier or cue mandates a call — so stronger models keep full judgment while the action gradient still points the same direction at every capability level.</td>
</tr>
</tbody>
</table>
<h2>Open decisions</h2>
<p>None. The capability and recovery verification matrix passes against the repository host fixture. If Pi later exposes an official tool-context interface that atomically navigates the session tree and synchronizes live agent messages, replace and remove the capability-probed AgentSession adapter rather than maintaining both paths.</p>
</body>
</html>