kijito-tools 0.2.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.
Files changed (104) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +6 -0
  3. package/README.md +220 -0
  4. package/bin/cli.js +34 -0
  5. package/install.sh +161 -0
  6. package/package.json +50 -0
  7. package/providers/_shared/wake-core.mjs +358 -0
  8. package/providers/claude/CLAUDE.md.snippet +31 -0
  9. package/providers/claude/install.sh +186 -0
  10. package/providers/claude/scripts/arm-session.sh +66 -0
  11. package/providers/claude/scripts/claude-armed.sh +101 -0
  12. package/providers/claude/scripts/heartbeat-watchdog.sh +209 -0
  13. package/providers/claude/scripts/inbox-selftest.sh +277 -0
  14. package/providers/claude/scripts/kijito-persona-lib.sh +94 -0
  15. package/providers/claude/scripts/kijito-qa-pass.sh +12 -0
  16. package/providers/claude/scripts/lifecycle-lib.sh +167 -0
  17. package/providers/claude/scripts/myctx.sh +46 -0
  18. package/providers/claude/scripts/self-clear.sh +134 -0
  19. package/providers/claude/scripts/session-autosend.sh +85 -0
  20. package/providers/claude/scripts/session-catchup-hint.sh +330 -0
  21. package/providers/claude/scripts/statusline-context.sh +67 -0
  22. package/providers/claude/skills/kijito-qa-memory/SKILL.md +110 -0
  23. package/providers/claude/skills/kijito-recall/SKILL.md +53 -0
  24. package/providers/claude/skills/kijito-start/SKILL.md +122 -0
  25. package/providers/claude/wiring/README.md +93 -0
  26. package/providers/claude/wiring/kijito-heartbeat@.service +21 -0
  27. package/providers/codex/README.md +75 -0
  28. package/providers/codex/codex-kijito-parity-plan.md +265 -0
  29. package/providers/codex/docs-codex-setup.md +64 -0
  30. package/providers/codex/install.mjs +184 -0
  31. package/providers/codex/n0-capability-probe-protocol.md +472 -0
  32. package/providers/codex/n0-harness/README.md +57 -0
  33. package/providers/codex/n0-harness/cli.mjs +58 -0
  34. package/providers/codex/n0-harness/evidence-manifest.mjs +77 -0
  35. package/providers/codex/n0-harness/fixture.mjs +279 -0
  36. package/providers/codex/n0-harness/lib.mjs +141 -0
  37. package/providers/codex/n0-harness/manifest.mjs +36 -0
  38. package/providers/codex/n0-harness/oracle.mjs +464 -0
  39. package/providers/codex/n0-harness/parser.mjs +200 -0
  40. package/providers/codex/n0-harness/prompt.mjs +43 -0
  41. package/providers/codex/n0-harness/snapshot.mjs +120 -0
  42. package/providers/codex/n0-harness/specimen.mjs +37 -0
  43. package/providers/codex/notify/kijito-notify-count.mjs +117 -0
  44. package/providers/codex/notify/kijito-notify-count.test.mjs +76 -0
  45. package/providers/codex/plans/gate4-battery-log.md +184 -0
  46. package/providers/codex/plans/gate4-battery-protocol.md +43 -0
  47. package/providers/codex/plans/hive-user-first-plan-QA.md +34 -0
  48. package/providers/codex/plans/hive-user-first-plan.md +247 -0
  49. package/providers/codex/release-manifest.json +53 -0
  50. package/providers/codex/same-chat-continuation-plan-gate.md +235 -0
  51. package/providers/codex/same-chat-continuation-plan.md +458 -0
  52. package/providers/codex/skills/kijito-qa-memory/SKILL.md +193 -0
  53. package/providers/codex/skills/kijito-qa-memory/agents/openai.yaml +4 -0
  54. package/providers/codex/skills/kijito-recall/SKILL.md +53 -0
  55. package/providers/codex/skills/kijito-start/SKILL.md +173 -0
  56. package/providers/codex/skills/kijito-start/agents/openai.yaml +4 -0
  57. package/providers/codex/test/n0-cli-refusal.test.mjs +31 -0
  58. package/providers/codex/test/n0-counterexample-matrix.test.mjs +118 -0
  59. package/providers/codex/test/n0-guard-census-core.mjs +1372 -0
  60. package/providers/codex/test/n0-guard-census.json +35479 -0
  61. package/providers/codex/test/n0-guard-census.mjs +31 -0
  62. package/providers/codex/test/n0-guard-census.test.mjs +374 -0
  63. package/providers/codex/test/n0-guard-counterexamples.mjs +1068 -0
  64. package/providers/codex/test/n0-guard-independent-projection.mjs +70 -0
  65. package/providers/codex/test/n0-guard-independent-projection.test.mjs +53 -0
  66. package/providers/codex/test/n0-guard-manifest-author.mjs +424 -0
  67. package/providers/codex/test/n0-guard-mutation-operators.test.mjs +244 -0
  68. package/providers/codex/test/n0-guard-mutation-runner.mjs +599 -0
  69. package/providers/codex/test/n0-guard-remainder-classes.test.mjs +314 -0
  70. package/providers/codex/test/n0-guard-sanitizer-pairs.test.mjs +68 -0
  71. package/providers/codex/test/n0-guard-shared-context-predicates.test.mjs +84 -0
  72. package/providers/codex/test/n0-harness.test.mjs +553 -0
  73. package/providers/codex/test/n0-notable-regressions.test.mjs +70 -0
  74. package/providers/codex/test/n0-subject-boundary.mjs +97 -0
  75. package/providers/codex/test/n0-subject-boundary.test.mjs +72 -0
  76. package/providers/codex/test/same-chat-plan-preflight.sh +167 -0
  77. package/providers/codex/tools/refresh-manifest.mjs +81 -0
  78. package/providers/codex/wake-helper/TRANSPORT-NOTES.md +25 -0
  79. package/providers/codex/wake-helper/integration.test.mjs +285 -0
  80. package/providers/codex/wake-helper/kijito-wake-helper.mjs +488 -0
  81. package/providers/codex/wake-helper/kijito-wake-helper.test.mjs +128 -0
  82. package/providers/codex/wake-helper/mock-daemon.mjs +64 -0
  83. package/providers/codex/wake-helper/status-probe.mjs +45 -0
  84. package/providers/codex/wake-helper/ws-uds.mjs +153 -0
  85. package/providers/monitor/.github/workflows/publish-npm.yml +38 -0
  86. package/providers/monitor/.github/workflows/publish-pypi.yml +30 -0
  87. package/providers/monitor/CHANGELOG.md +465 -0
  88. package/providers/monitor/IMPORT-PROVENANCE.md +68 -0
  89. package/providers/monitor/LICENSE +202 -0
  90. package/providers/monitor/NOTICE +7 -0
  91. package/providers/monitor/OPAQUE-OUTPUT-ENFORCEMENT.md +45 -0
  92. package/providers/monitor/README.md +571 -0
  93. package/providers/monitor/RELEASING.md +125 -0
  94. package/providers/monitor/arm-hive-monitor.sh +13 -0
  95. package/providers/monitor/bin/cli.js +43 -0
  96. package/providers/monitor/com.kijito.inbox-monitor.plist.template +59 -0
  97. package/providers/monitor/docs/DESIGN.md +984 -0
  98. package/providers/monitor/kijito-inbox-monitor@.service.template +95 -0
  99. package/providers/monitor/kijito_inbox_monitor.py +3666 -0
  100. package/providers/monitor/package.json +35 -0
  101. package/providers/monitor/pyproject.toml +42 -0
  102. package/providers/monitor/scripts/mutation-check.py +399 -0
  103. package/providers/monitor/scripts/prepublish-gate.sh +284 -0
  104. package/providers/monitor/test_kijito_monitor.py +5609 -0
@@ -0,0 +1,458 @@
1
+ # Codex same-chat continuation plan
2
+
3
+ Status: **PLAN ONLY.**
4
+
5
+ **AUTHORITY:** Two consecutive Assay-CLEAN reviews of this exact plan digest open N0a/N0b only.
6
+ GREEN N0 then authorizes disposable test-persona probes of the current N1-N3 surfaces, but no
7
+ Codex-provider or Kijito-server implementation. If N1 rejects the current API, a separate
8
+ provider-neutral claim/operator-decision API plan owned by River must receive two consecutive
9
+ Assay-CLEAN reviews before any such API code is written. An installable Codex provider remains
10
+ forbidden until N0-N3 are GREEN and Jason explicitly accepts N3.
11
+
12
+ Owner: Codex provider lane. River owns repository integration and any production cutover. Assay owns
13
+ independent plan review. Jason owns residual-risk and measured-cost acceptance.
14
+
15
+ ## 1. Decision, evidence, and supersession
16
+
17
+ Reject the dedicated-thread notifier as an implementation of “mail wakes my Codex session and work
18
+ continues while I am away.” Live hive message 2630 proved the mismatch:
19
+
20
+ - Kijito stored 2630 at 18:25:50Z.
21
+ - The installed controller accepted a turn at 18:25:52Z on its dedicated thread
22
+ `019fab97-824b-7110-a2a4-27fea6c51d6a` and surfaced it at 18:26:05Z.
23
+ - That turn reported “No unread hive messages,” while controller state advanced through 2630.
24
+ - Jason's working chat received no turn and continued no work.
25
+
26
+ The design deliberately preserved `currentUserThreadMutation=false`; more recovery code cannot make
27
+ an isolated thread become the user's chat. Existing notifier code/tests remain research only.
28
+ PR #5 is closed as withdrawn, and the provider README points here instead of authorizing installation.
29
+ The live legacy process remains untouched until the cutover gate in section 7.
30
+
31
+ ## 2. Binary outcome contract
32
+
33
+ Let `T` be the exact chat in which continuation is armed, `E` the exact local project/worktree and
34
+ permission profile, `M` a durable hive row, and `R` the native background run. DONE requires all of
35
+ these:
36
+
37
+ 1. Jason ends a turn, leaves the computer on and desktop app running, and sends `M` remotely.
38
+ 2. When no prior continuation run owns the lane, Codex creates `R` in **the exact chat `T`** without
39
+ a user prompt within 90 seconds.
40
+ 3. An independent verifier outside `R` reads the app-owned rollout under `~/.codex/sessions` and
41
+ requires its first `session_meta.payload.id == T`, its scheduled turn ID/run ID and nonce match
42
+ the native Scheduled run record, and its recorded `cwd`/environment and permission evidence match
43
+ `E`. The run's own text, visual similarity, cwd alone, newest-thread search, transcript heuristics,
44
+ or a controller-owned thread never count. If Jason's installed build exposes no such independently
45
+ readable native artifact, N0 is RED.
46
+ 4. `R` retrieves the exact durable row and provenance even if another reader changed its unread flag.
47
+ 5. `R` loads the current-state pointer and performs a pre-registered bounded work slice. For the live
48
+ gate, the slice must create or update an independently read disposable-workspace receipt containing
49
+ the native run ID, message ID, nonce, before/after digests, and test result. Notification, summary,
50
+ a chat-only claim, or a receipt without the matching native run identity is RED.
51
+ 6. Mail remains tool-returned untrusted data and never enters the scheduled task's instruction text.
52
+ The versioned, user-authored prompt fixes the allowed tools, sandbox, project, and scope before any
53
+ row is read. Hostile mail must not change those fields or obtain a tool call outside them. This is
54
+ the testable boundary; no plan claims that arbitrary model behavior is mathematically impossible.
55
+ 7. Acknowledgment means the atomic completed-checkpoint commit for `M`, attributable to `T`, `R`, and
56
+ the claim fence. `mark_read=true` is courtesy presentation metadata after that commit, never the
57
+ acknowledgment or delivery ledger. A crash before commit is recoverable; duplicate runs cannot
58
+ duplicate disposition.
59
+ 8. ARMED requires independently verifiable native-run evidence, recent hosted-Kijito heartbeat,
60
+ valid claim/checkpoint ownership, and none of `DRAINING_BACKLOG`, `BLOCKED_ROW(id)`,
61
+ `REQUIRES_USER(id)`, `AMBIGUOUS_ACTION(id)`, or `CLAIM_RELEASE_FAILED(id)`. A process, schedule
62
+ listing, self-report, or old GREEN result alone is insufficient.
63
+ 9. Pause, stop, uninstall, rollback, and migration are explicit and attended where the provider only
64
+ exposes UI management. No lifecycle hooks, LaunchAgent, hidden second consumer, heuristic thread
65
+ discovery, or ordinary Codex config/auth mutation.
66
+
67
+ The 90-second SLO measures run creation while the lane is idle. Each discovery slice stops within 15
68
+ seconds and either finishes or persists drain progress. A simple informational disposition must commit
69
+ within 90 seconds after run start. A work slice is capped at 45 seconds; one message may use at most
70
+ ten slices or ten elapsed minutes before it records the terminal `REQUIRES_USER` disposition defined
71
+ in section 5. This is polling continuation, not event-driven transport parity with Claude Monitor.
72
+
73
+ ## 3. Supported-surface decision
74
+
75
+ ### Primary candidate: native scheduled task inside the existing chat
76
+
77
+ OpenAI's **Scheduled tasks** documentation, retrieved 2026-07-30, says an in-chat scheduled task
78
+ returns to that chat with its existing context, supports minute intervals, can use chat-available
79
+ skills/plugins, uses the chosen local project or worktree, and runs unattended with the default
80
+ sandbox. It also says Codex CLI and the IDE do not provide the Scheduled management interface; tasks
81
+ are created and managed through ChatGPT web/desktop and the **Scheduled** view. Documentation is not
82
+ a capability result. N0 must prove the exact installed behavior before code exists.
83
+
84
+ The candidate is a native in-chat **continuation heartbeat**:
85
+
86
+ - an attended ChatGPT/desktop procedure binds one task to `T` and `E` at a one-minute cadence;
87
+ - no-mail runs perform only bounded pointer/checkpoint/all-mail inbox reads and emit no user-visible
88
+ content if the product supports suppression;
89
+ - mail runs load Kijito state, handle rows in ID order, continue only already-authorized work in a
90
+ fenced slice, update memory as state changes, and commit completed dispositions;
91
+ - status describes scheduled polling honestly.
92
+
93
+ Official references (retrieved 2026-07-30):
94
+
95
+ - [Scheduled tasks](https://learn.chatgpt.com/docs/automations)
96
+ - [Codex App Server](https://learn.chatgpt.com/docs/app-server)
97
+
98
+ ### Conditional alternative: registered App Server thread
99
+
100
+ App Server supports `thread/resume` plus `turn/start` for a client-owned recorded ID. It is forbidden
101
+ for desktop-chat continuation unless a no-code probe proves the desktop host supplies the exact
102
+ current chat ID through a supported interface, explicitly leases it, displays client turns in the
103
+ same chat, queues collisions without `turn/steer`, and revokes the lease on handoff. No transcript
104
+ scan, mtime guess, private protocol, newest-thread selection, or separate `CODEX_HOME` is permitted.
105
+ Failure rejects this alternative; it never authorizes a heuristic.
106
+
107
+ ### Rejected
108
+
109
+ - dedicated background thread (disproved by 2630);
110
+ - lifecycle hooks (session failures and no supported chat ownership);
111
+ - bare shell tail (observes bytes but cannot invoke Codex);
112
+ - UI/accessibility scripting;
113
+ - newest/idle-thread guesses;
114
+ - inbox unread state as delivery state.
115
+
116
+ ## 4. Provider-agnostic architecture and security boundary
117
+
118
+ The shared package owns persona binding, inbox discovery/pagination, exact-row fetch, checkpoint and
119
+ claim state, post-disposition courtesy read marking, idempotency/crash reconciliation, untrusted-data
120
+ fencing, pointer loading, health evidence, and provider-neutral test vectors. It does **not** invoke
121
+ an agent or manage a provider UI.
122
+
123
+ | Provider | Invocation primitive | Latency | Same-session proof |
124
+ |---|---|---:|---|
125
+ | Claude Code | persistent Monitor in owning process | event-driven | process/session plus Monitor identity |
126
+ | Codex desktop | native task inside armed chat | ≤90 s idle | rollout `session_meta.id`, native run/turn ID, and Scheduled record equal `T` |
127
+ | Codex App Server | only after supported explicit registration | candidate | registered lease and returned ID equal `T` |
128
+ | Unknown | none | none | INACTIVE, never ARMED |
129
+
130
+ Drivers expose actual semantics; no universal “wake” label hides polling.
131
+
132
+ This design intentionally moves untrusted mail into Jason's working chat, whose already-selected
133
+ workspace-write profile has more capability than the withdrawn notifier's read-only dedicated home.
134
+ The fixed prompt must place mail only inside tool-returned untrusted-data fences, pin persona/project/
135
+ tool allowlist before reading, forbid authority changes derived from mail, and require normal platform
136
+ approval/sandbox enforcement. G3 tests behavioral attempts to alter those values. N3 separately shows
137
+ Jason the residual prompt-injection and unattended-tool risk, exact effective permission profile, and
138
+ available mitigations; Jason must explicitly accept it. Silence is not approval.
139
+
140
+ ## 5. Durable mailbox transaction
141
+
142
+ Unread is presentation metadata, not the ledger.
143
+
144
+ ### Discovery
145
+
146
+ 1. Read `CODEX_CONTINUATION_CHECKPOINT_V1` for persona `codex`.
147
+ 2. Fetch newest inbox with `unread_only=false, mark_read=false`.
148
+ 3. Page backward with `before_id` until the completed checkpoint or mailbox start. A new scan freezes
149
+ its newest observed ID as `scan_upper_id`; later arrivals belong to the final repoll/next scan.
150
+ 4. One tick stops at the earliest of 15 seconds, 256 inbox requests, 10,000 new unique IDs, or 32 MiB
151
+ of decoded bodies. It atomically persists `scan_upper_id`, next `before_id`, verified ID/range
152
+ segments, bytes, and start time as `DRAINING_BACKLOG`; it never looks empty or restarts from newest.
153
+ `completed_id` remains unchanged. The next tick resumes that cursor. Once it reaches the
154
+ checkpoint/mailbox start, it drains the verified pending IDs in ascending order across bounded
155
+ ticks before beginning another scan.
156
+ 5. Repoll newest after the backward walk so concurrent arrivals are not stranded.
157
+ 6. Sort IDs above the completed checkpoint ascending and exact-refetch each with
158
+ `before_id=<id+1>, limit=1, unread_only=false, mark_read=false`.
159
+ 7. ID gaps are allowed only when every page's strict ordering and continuation metadata bridge them;
160
+ the exact target still must be returned. Missing exact ID, truncated body, contradictory paging,
161
+ missing provenance, corrupt persisted scan state, or unbridgeable gap is
162
+ `BLOCKED_ROW(<id>)` and cannot advance the checkpoint.
163
+
164
+ This finds 2630 even though it is already read and remains correct when another consumer marks rows
165
+ read during the walk.
166
+
167
+ ### Claim, work intent, disposition, acknowledgment
168
+
169
+ The current hosted `kijito_hive_claim` is an account claim with a 60-second default lease and no
170
+ plan-proven holder-bound renewal/fencing contract. A one-minute scheduled cadence
171
+ can therefore outlive and lawfully steal a predecessor's lease. It is not accepted as the continuation
172
+ transaction merely because two simultaneous callers produce one winner.
173
+
174
+ `CODEX_CONTINUATION_CHECKPOINT_V1` contains schema version, persona, armed task/chat ID, project/
175
+ worktree/environment identity, permission profile, prompt digest, last completed ID, scan upper ID/
176
+ cursor/verified ranges/pending IDs/byte count, optional active message ID/holder token/fence/lease
177
+ expiry/intent, disposition and slice count/deadline, ambiguity evidence, validated operator-decision
178
+ ID/digest, native run/turn ID, pointer ID/digest, last successful heartbeat, last acknowledgment, and
179
+ current health state/reason including the exact blocked message ID. This checkpoint namespace is
180
+ run-authored only: it contains observations of operator decisions, never operator-authored authority.
181
+ Unknown/missing fields fail closed; doctor compares these exact fields rather than an informal claim.
182
+
183
+ Operator authority lives only in a separate append-only
184
+ `CODEX_CONTINUATION_OPERATOR_DECISION_V1` journal that doctor and the scheduled run can read but the
185
+ scheduled run's principal, tools, sandbox, and workspace cannot create, append, replace, or delete.
186
+ No operator-authored checkpoint or control-plane field may be writable by a scheduled run. An
187
+ attended helper outside the scheduled environment signs a canonical envelope containing schema,
188
+ persona, `T`, message ID, observed input/failure digest, checkpoint digest, decision, reason, expiry,
189
+ and a verifier-generated nonce with an operator key unavailable to the run. Jason pins the signer key
190
+ in an attended journal arm record that the run also cannot modify. The journal authenticates the
191
+ attended writer and returns an immutable decision ID. Executor and doctor exact-fetch the journal row,
192
+ verify signature, signer, expiry, nonce, and every binding, then treat the checkpoint's ID/digest only
193
+ as a run-authored observation. Mail text, checkpoint contents, or a copied/replayed decision can never
194
+ substitute for that artifact. If the current surface cannot enforce the separate principals and
195
+ append-only journal, River's separately reviewed provider-neutral prerequisite must provide it before
196
+ N1; no local convention is an acceptable substitute.
197
+
198
+ N1 must either prove stronger existing surfaces or independently gate minimal provider-neutral
199
+ `CONTINUATION_CLAIM_V1` and operator-decision journal surfaces before any Codex implementation. The
200
+ claim surface must atomically return a unique holder token and monotonic fence, use a 180-second lease,
201
+ renew only for the same holder every
202
+ 45 seconds, reject older fences after takeover, and permit at most one active claim for `(persona,
203
+ message_id)`. The work slice remains 45 seconds; a renewal failure stops before further action. A
204
+ claim becomes stale only after server time passes `lease_expires_at`; expiry permits a new discovery
205
+ owner but never proves a prior external side effect did not happen.
206
+
207
+ Jason owns the work envelope by writing it in the current request or current-state pointer before the
208
+ row arrives; mail cannot create or widen it. Before any mutation, the holder atomically writes an
209
+ intent containing message ID, fence, native run ID, action kind/target, input digest, idempotency key,
210
+ expected pre-state digest, and reconciliation method. The mutation must either accept that
211
+ idempotency/fence or produce independently readable before/after evidence. If neither is possible,
212
+ the run takes the `REQUIRES_USER` terminal path below
213
+ and does not perform it.
214
+
215
+ After action, the holder records the provider receipt/output digest, exact-refetches `M`, and commits
216
+ `completed_id=M` plus disposition in the same fenced checkpoint transition. That commit is the ack.
217
+ It then releases/clears the exact claim and only afterward may exact-refetch with `mark_read=true` as
218
+ a courtesy. Release failure enters `CLAIM_RELEASE_FAILED(M)` under the rules below. A crash reconciles
219
+ intent against the external receipt/state; it never retries solely because the lease expired. If the
220
+ 45-second work slice ends before disposition, the holder atomically records `DEFERRED` progress and
221
+ reconciliation state, releases its lease, and leaves `completed_id` unchanged. No action occurs after
222
+ release.
223
+
224
+ `REQUIRES_USER(M)` is a fenced terminal disposition, not a retry state. Whether caused by an unsafe
225
+ adapter or the ten-slice/ten-minute bound, it records reason, progress, intent/receipt evidence, and
226
+ available operator choices; atomically commits `completed_id=M`; then releases the exact claim. It blocks all
227
+ later automatic work and ARMED health without rediscovering or re-executing `M`. An attended operator
228
+ escapes it only with one valid out-of-band operator-decision journal row: accept/decline the
229
+ disposition, attest repaired external state, or narrow/extend the pre-registered envelope and resend
230
+ as a new higher-ID row. Clearing the health block requires that exact artifact and never reopens `M`.
231
+
232
+ `AMBIGUOUS_ACTION(M)` means crash reconciliation cannot prove whether the recorded intent produced an
233
+ external effect. It records the contradictory/missing evidence, leaves `completed_id` below `M`,
234
+ releases the exact claim, and blocks discovery, later work, and ARMED health without attempting the
235
+ effect again. An attended operator must supply independently readable evidence that lets the fenced
236
+ checkpoint, under a fresh higher holder/fence for `M`, either commit `M` once or exact-quarantine `M`
237
+ with a valid exact-bound operator-decision artifact; only then may the block clear. Quarantine and
238
+ `REQUIRES_USER` release their exact claim after their fenced commit.
239
+
240
+ Any release failure enters `CLAIM_RELEASE_FAILED(M)`. It preserves the already-chosen
241
+ `completed_id` effect, performs only idempotent release/server-absence checks, and remains doctor-RED.
242
+ It clears automatically only when server time proves the lease expired or the exact holder is absent;
243
+ an attended operator may exact-release the verified holder. Neither recovery repeats disposition or
244
+ external action. Clearing this release substate restores any underlying `REQUIRES_USER`, ambiguity,
245
+ or deferred/committed checkpoint state and forces doctor to re-evaluate every ARMED requirement.
246
+
247
+ ## 6. Health and attended lifecycle
248
+
249
+ There is no assumed programmatic Scheduled management API.
250
+
251
+ - **Arm:** Jason or an attended operator creates/enables the in-chat task through ChatGPT/desktop,
252
+ selects `T`, local project/worktree, model, cadence, and permission profile, then records the native
253
+ task/run evidence discovered by N0. Re-arm for the same identity is a documented idempotent UI
254
+ procedure; another chat requires cutover first.
255
+ - **Doctor:** a read-only verifier outside the scheduled run reads the recorded rollout/run artifact,
256
+ checkpoint/claim state, operator-decision journal, and hosted heartbeat. For a one-minute cadence,
257
+ “recent” means server age at most 135 seconds (two cadences plus 15 seconds measured skew); excess
258
+ skew is RED. It reports ARMED only while successful native runs continue within two cadences and
259
+ every identity field matches. It reports `DRAINING_BACKLOG`,
260
+ `BLOCKED_ROW(id)`, `REQUIRES_USER(id)`, `AMBIGUOUS_ACTION(id)`, `CLAIM_RELEASE_FAILED(id)`,
261
+ `LEGACY_CONSUMER`, `STALE`, or `INACTIVE` explicitly.
262
+ It never claims that a UI task exists/enabled from self-report alone.
263
+ - **Blocked-row escape:** automatic skipping is forbidden. An attended operator may repair/resend the
264
+ row or exact-quarantine one ID with reason and a valid exact-bound operator-decision artifact.
265
+ Quarantine writes a durable tombstone/disposition, preserves body digest/provenance where available,
266
+ advances only that exact ID under the claim fence, and releases the exact claim. The validated
267
+ journal decision is the recovery confirmation; successful commit/release clears that exact block.
268
+ Release failure follows the path above.
269
+ - **Pause/uninstall:** the attended operator disables or deletes the exact task in **Scheduled** and
270
+ verifies no run for two cadences. Uninstall then removes only manifest-owned checkpoint artifacts
271
+ after identity/ownership verification. No hooks, LaunchAgents, ordinary auth/config edits, or UI
272
+ scripting are used.
273
+
274
+ N0b must probe the complete attended create, inspect, pause, resume, and delete path plus quotas,
275
+ expiry, cadence limits, locked/background behavior, and recent-run evidence. If the installed product
276
+ cannot expose enough evidence for doctor, the candidate is RED rather than papered over by a command.
277
+ If the Scheduled record is UI-only, its attended capture is setup evidence; mechanized doctor uses
278
+ the immutable rollout plus hosted heartbeat and lets ARMED expire within two missed cadences. It does
279
+ not pretend to read an unsupported management API.
280
+
281
+ ## 7. Legacy cutover ownership and rollback
282
+
283
+ ARMED is unreachable while PID 38082 or any legacy notifier can consume persona `codex`. Planning and
284
+ N0-N3 do not touch it.
285
+
286
+ After two Assay-CLEAN plan reviews, N0-N3, implementation gates, and Jason's explicit authorization,
287
+ River owns the attended cutover:
288
+
289
+ 1. Pause the new native task and snapshot its empty/non-disposition state.
290
+ 2. Stop the legacy controller; freeze and verify its last durable row/checkpoint and consumer lock.
291
+ 3. Prove for two old poll windows that no legacy or second consumer can advance the stream.
292
+ 4. Import/reconcile the checkpoint under the new fenced schema, verify exact IDs/digests, then enable
293
+ the native task and run one isolated canary.
294
+ 5. On failure before a native disposition, disable the native task, remove its uncommitted claim, and
295
+ restart the legacy process from the verified snapshot. After any native intent/disposition,
296
+ automatic rollback is forbidden; River reconciles the exact row/action before choosing one owner.
297
+
298
+ The rollback never runs two consumers concurrently and never treats `mark_read` as the cursor.
299
+
300
+ ## 8. Pre-implementation gates
301
+
302
+ **AUTHORITY:** Two consecutive Assay-CLEAN reviews of this exact plan digest open N0a/N0b only.
303
+ GREEN N0 then authorizes disposable test-persona probes of the current N1-N3 surfaces, but no
304
+ Codex-provider or Kijito-server implementation. If N1 rejects the current API, a separate
305
+ provider-neutral claim/operator-decision API plan owned by River must receive two consecutive
306
+ Assay-CLEAN reviews before any such API code is written. An installable Codex provider remains
307
+ forbidden until N0-N3 are GREEN and Jason explicitly accepts N3.
308
+
309
+ Disposable probes use a dedicated test persona, never persona `codex`, except N0a's explicitly
310
+ read-only `mark_read=false` capability peek.
311
+
312
+ ### N0a — native same-chat, collision, and unattended capability
313
+
314
+ Before task creation, the outside verifier snapshots the app-owned rollout set, generates a 128-bit
315
+ nonce, and Jason submits that nonce in one attended marker turn in the target chat. Exactly one rollout
316
+ created/advanced after the snapshot must contain that marker turn and a first
317
+ `session_meta.payload.id`; that ID becomes pinned `T`. Zero/multiple matches, run-generated nonce,
318
+ newest/mtime selection, or visual/transcript similarity is RED. Marker evidence acquires `T` only and
319
+ never proves a background run's identity.
320
+
321
+ With a disposable schedule and no Kijito controller code, record `T` and `E`; create a one-minute
322
+ task inside `T` that returns a second verifier-generated 128-bit nonce pre-registered with task ID and
323
+ prompt digest before scheduling, and performs a read-only proof of `E`. An independent
324
+ verifier outside the run must read the app-owned rollout plus Scheduled run record and match `T`,
325
+ turn/run ID, nonce, cwd/project/worktree, model, sandbox, approval and permission profile. Repeat:
326
+
327
+ - after a completed manual turn;
328
+ - while a manual turn is still active, proving the scheduled input queues and never uses steering;
329
+ - with two disposable in-chat tasks synchronized to one minute boundary while the first waits on a
330
+ disposable 75-second barrier, forcing overlap and proving only one run acts while the other records
331
+ a collision without steering or disposition; this synthetic overlap probe is exempt from the
332
+ 45-second production work-slice cap;
333
+ - while the app is backgrounded and Jason has been inactive for ten minutes;
334
+ - once while the screen is locked, with computer awake and app running.
335
+
336
+ In a second disposable run, invoke installed `kijito-start` far enough to reach hosted Kijito, read the
337
+ current pointer ID, and perform a `mark_read=false` inbox peek. Prove the scheduled run has the exact
338
+ skill/plugin/MCP availability required. Manual prompting, a lookalike chat, self-reported identity,
339
+ wrong environment/profile, steering, unavailable tools, a different brain, unread mutation, hidden
340
+ API, or UI automation is RED.
341
+
342
+ ### N0b — attended task-management and health evidence
343
+
344
+ Through documented ChatGPT/desktop controls, create, inspect, pause, resume, and delete the disposable
345
+ task. Independently capture which stable IDs/run records/rollout artifacts are readable, cadence and
346
+ quota/rate/expiry limits, and what happens after app exit, sleep, lock, project removal, and permission
347
+ change. Measure server/host clock skew and require it not exceed 15 seconds. Prove doctor derives its
348
+ state only from those artifacts plus hosted heartbeat and turns RED within two cadences after
349
+ pause/delete/drift. If management requires unsupported automation or doctor
350
+ cannot distinguish enabled from stale/disabled, N0b is RED.
351
+
352
+ ### N1 — fenced checkpoint transaction
353
+
354
+ Test the exact chosen API, not a mock. This synthetic lease-duration probe is exempt from the 45-second
355
+ production work-slice limit. Two concurrent claimers yield one holder token/fence. Keep one
356
+ holder alive past 60 seconds and two schedule cadences; a contender cannot steal it. Stop renewal and
357
+ prove takeover only after the 180-second server deadline with a larger fence. The old holder then
358
+ cannot write intent, renew, commit, or acknowledge. Crash before intent, after intent, after external
359
+ effect, and after commit; each reconciles without duplicate side effect. A non-idempotent adapter
360
+ without intent+receipt reconciliation is refused. If this requires either new surface, its API,
361
+ threat model, tests, and independent review are a separate provider-neutral prerequisite.
362
+ Force both causes of `REQUIRES_USER`, an irresolvable receipt into `AMBIGUOUS_ACTION`, and release
363
+ failure after success/terminal/quarantine commits. Assert each state's checkpoint and `completed_id`
364
+ effect, doctor/ARMED block, no-repeat behavior, and automatic or attended escape.
365
+ Attempt scheduled-run writes to every operator journal/control-plane field and require structural
366
+ denial. Inject forged, copied, expired, replayed, wrong-chat/message/body/checkpoint, and valid
367
+ operator-decision artifacts; only the exact live journal row may authorize one escape.
368
+
369
+ ### N2 — exact durable-row retrieval and blocked recovery
370
+
371
+ Synthetic account-owned mail proves unread, already-read, older-window, ID-gap, and content-budget
372
+ rows are found; another consumer marks rows read during every paging phase; arrival during paging is
373
+ caught by final repoll; exact fetch returns the intended ID; oversized/truncated/missing/provenance-bad
374
+ content blocks discovery and makes doctor RED; no later row advances. Corrupt derived scan state
375
+ blocks at `completed_id+1`; a valid operator-decision artifact may discard only scan cursor/ranges/
376
+ pending/byte fields and force a full newest-to-completed rescan while leaving `completed_id`
377
+ unchanged. Repair and operator-quarantine each recover only the exact blocked ID; checkpoint ack and courtesy `mark_read` affect only the intended
378
+ row. Exercise the 15-second/request/ID/byte bounds, require persisted `DRAINING_BACKLOG`, resume from
379
+ the saved cursor across ticks, and drain the entire backlog once without false empty or duplicate work.
380
+
381
+ ### N3 — measured cost, compaction, interference, and risk acceptance
382
+
383
+ Run 30 idle minutes and 30 active-mail minutes in the disposable workspace, followed by one forced
384
+ native compaction and a six-hour unattended soak. Record run count, exposed tokens/rate-limit change,
385
+ wall time, failures, completed-disposition latency, manual-turn collisions, visible no-mail artifacts,
386
+ rollout/transcript byte growth, context-window growth, compaction behavior, and locked/background runs.
387
+
388
+ Default RED thresholds, fixed before measurement: any wrong-chat/steered/overlapping disposition;
389
+ any no-mail user-visible message; more than 2 KiB rollout growth per idle run; more than 5% context
390
+ growth in 30 idle minutes; more than 30,000 exposed tokens in 30 idle minutes; any missed idle run
391
+ beyond 90 seconds while computer/app are available; any simple disposition beyond 90 seconds after
392
+ run start; any compaction that loses pointer/claim state; or any permission/tool drift. A threshold
393
+ may change only in a new plan digest before the run, never after seeing results.
394
+
395
+ Jason receives the measured daily projection, visible-noise/context cost, exact permission profile,
396
+ prompt-injection residual risk, polling semantics, and mitigations. The disclosure states that any
397
+ single inbound row can terminally halt the lane—through invalid/provenance-bad content or the work
398
+ bound—until Jason supplies an out-of-band attended decision. These bounds are not runtime-adjustable;
399
+ changing them requires a new reviewed plan digest before measurement. He must explicitly accept all
400
+ of this before implementation. Silence is not approval.
401
+
402
+ ## 9. Future implementation gates
403
+
404
+ These specify QA; they are not implementation permission.
405
+
406
+ - **G1 protocol:** property tests for paging/bounds, exact fetch, fenced lease renewal/takeover, stale
407
+ writer rejection, intent/effect/commit crash reconciliation, operator-journal signature/replay/write
408
+ partition, ordering, duplicates, hostile content, bad provenance, clock skew, blocked health, and
409
+ migration fence. Each high-value property has a
410
+ mutation failing at its unique named assertion.
411
+ - **G2 same chat:** no-mail read-only; normal/already-read mail handled once in `T`; native rollout
412
+ identity independently verified; manual-turn input queues without steer; overlaps suppress; sleep/
413
+ restart drains backlog; compaction reloads pointer; no authorized work yields explicit disposition.
414
+ - **G3 security:** injection, role impersonation, exfiltration, scope expansion, destructive requests,
415
+ sender spoofing, oversized text, and malformed Unicode/JSON cannot change prompt/instruction role,
416
+ tool allowlist, sandbox, project, chat target, claim fence, intent, operator-decision ID/digest, or
417
+ ack order. No operator-authored checkpoint/control-plane field is writable by the scheduled run;
418
+ this write partition is a property test over the schema, not a field enumeration.
419
+ - **G4 lifecycle:** attended idempotent arm, wrong-chat refusal, pause/resume, ownership-bound uninstall,
420
+ app-down/disabled/outage/blocked health, stale-claim recovery, cutover/rollback, hard double-consumer
421
+ fence, and zero hooks/LaunchAgents.
422
+ - **G5 live golden:** A performs the registered disposable file/test mutation in exact `T`; B repeats
423
+ after app restart or sleep/wake; C repeats after forced compaction; disabled schedule leaves D
424
+ durable and health not ARMED, then re-enable handles D once. Each has independently matched native
425
+ run identity, external receipt, exact disposition, fenced checkpoint ack, and SLO. Summary-only is
426
+ RED.
427
+
428
+ ## 10. Plan QA and independent gate
429
+
430
+ Author preflight is presence-only lint and never counts toward the two-review bar. On one digest it
431
+ must:
432
+
433
+ 1. trace every outcome clause and every accumulated independent load-bearing finding to a named N/G
434
+ assertion;
435
+ 2. require named rejection text for dedicated/lookalike thread, self-reported identity, manual prompt,
436
+ chat-only “work,” unread-only lookup, expired lease, stale writer, poison row under ARMED, second
437
+ consumer, hostile authority text, disabled task, and summary-only turn;
438
+ 3. emit unique lint markers. It constructs no specimen and is not semantic review evidence.
439
+
440
+ For every runtime state or production execution bound added by a revision, the author lint record must
441
+ explicitly trace five properties: doctor enumeration, outcome 8 ARMED effect, checkpoint fields, a
442
+ named N/G probe, and the `completed_id` effect plus automatic/attended escape. Missing any one is RED
443
+ before freeze.
444
+
445
+ After preflight, commit/push the plan-and-supersession-fence branch and send Assay the exact returned
446
+ commit SHA plus plan digest. A load-bearing finding changes the digest and resets the Assay count. The
447
+ AUTHORITY statement in the status and section 8 is the complete post-review boundary.
448
+
449
+ ## 11. Non-goals and exit
450
+
451
+ No use of the withdrawn controller's upgrade/migration path; section 7 alone governs checkpoint
452
+ cutover. No instant/event-driven claim for polling; no universal transport;
453
+ no autonomy outside an explicitly armed chat and existing authority; no mail-as-command authority;
454
+ no merge/publish/production change during plan approval.
455
+
456
+ Planning ends when this document passes author preflight, its gate artifact is committed, the branch
457
+ is pushed, Assay records two consecutive CLEAN reviews on the exact digest, memory points to the
458
+ verdict/next gate, and production remains untouched.
@@ -0,0 +1,193 @@
1
+ ---
2
+ name: kijito-qa-memory
3
+ description: Curate and verify Codex memories in the hosted Kijito brain before native compaction, handoff, or session completion. Create missing durable memories, correct false ones, fade obsolete ones, update the current-state pointer, require two consecutive context-free cold boots, and request compaction only after recording the one-use pass.
4
+ ---
5
+
6
+ # Kijito QA Memory
7
+
8
+ Memory QA is creation, correction, handoff preload, and proof. Run the phases in
9
+ order. A compaction handoff is not valid until Phase 4 passes twice.
10
+
11
+ ## 1. Create missing memory first
12
+
13
+ Enumerate every durable decision, finding, state change, user preference,
14
+ failure mode, reusable command, and gate result learned since the last QA pass.
15
+ For each candidate, recall before writing and create one atomic memory only when
16
+ it is missing. Pass `persona="codex"` and `project="Codex"` on every write.
17
+ Use honest basis, confidence, and importance.
18
+
19
+ Ask both questions explicitly, and answer both before leaving this phase:
20
+
21
+ 1. Existence: “What did this session learn that is not written yet?”
22
+ 2. Adequacy: “Is any memory I wrote a list of the cases I happened to hit
23
+ rather than the property that decides new ones?” A memory can be present,
24
+ accurate, and still be a rule with an expiry date: it fails silently on the
25
+ first case its author did not foresee. Restate it as the property.
26
+
27
+ The existence question is the one that gets asked and the adequacy question is
28
+ the one that gets skipped. Repeat until both answers are nothing.
29
+
30
+ ## 2. Correct and prune
31
+
32
+ Recall each topic touched:
33
+
34
+ - Use `kijito_correct` for wrong or superseded claims.
35
+ - Use `kijito_fade` for obsolete-but-still-true claims.
36
+ - Verify operational facts against current code, configuration, or live state.
37
+ - Do not treat account-wide recall as persona-private.
38
+
39
+ `kijito_correct` rots every inbound `[[id]]` citation pointing at the memory it
40
+ retires, and nothing warns you. It links forward, from the retired record to the
41
+ fix; nothing traverses backward. So a live memory citing the old id now points at
42
+ a record the server itself believes is false, and the more disciplined you are
43
+ the more of this rot you generate — correcting well is what causes it. After each
44
+ correction, find the inbound citers and re-point them at the live id with
45
+ `kijito_update` and `structural=true`, which preserves the operational-staleness
46
+ clock because bracketed digits carry no meaning.
47
+
48
+ Liveness reads differently per tool (re-measured 2026-09-11): `kijito_get` renders a definitive
49
+ `Status:` line (`retired (believed-false — corrected; …)` on a corrected record — trust it);
50
+ `kijito_recall` / `kijito_startup` / `kijito_browse` render no Status, so there judge by
51
+ `importance` (retired ≈ 0.1) / `confidence` (retired ≈ 0.05). An earlier version of this file said
52
+ Status reads `active` on believed-false records — no longer true.
53
+
54
+ After creation, correction, and pruning are complete, run `kijito_dream` now if
55
+ the curation batch warrants it. Dreaming can mutate themes and edges, so it
56
+ must finish before the final pointer update and before either cold boot. Do not
57
+ dream again after the pointer is preloaded.
58
+
59
+ ## 3. Preload the pointer
60
+
61
+ Update the stable current-state pointer in place. Open with:
62
+
63
+ `RESUME NOW [CODEX_CURRENT_STATE_POINTER_V1]: <one exact next action>`
64
+
65
+ Include the single active task, done versus remaining work, current adversarial
66
+ gate count, exact next steps, DONE-WHEN, and linked anchor IDs. If the work is
67
+ actually complete, remove `RESUME NOW` and mark it complete. Keep the literal
68
+ sentinel out of every live support memory so exact recall remains pointer-only;
69
+ retired version-history snapshots are the audit-only exception.
70
+
71
+ ## 4. Prove two clean cold boots
72
+
73
+ Before spawning either boot, obtain the exact `pointer-digest.mjs` command and
74
+ the exact `qa-gate.mjs record` command emitted by the active hook. If either
75
+ command is unavailable, stop: do not invent a plugin path and do not claim a
76
+ pass. Replace only `REPLACE_WITH_POINTER_ID` in the digest command at this
77
+ stage. Keep the record command unused until Phase 5. Establish a single-writer
78
+ pointer lease: no other seat may mutate the current-state pointer from the
79
+ first boot's before-read digest through the final record action. If that
80
+ discipline cannot be confirmed, keep compaction blocked.
81
+
82
+ Spawn a fresh context-free agent with no conversation fork. Give it only:
83
+
84
+ > Run this exact pointer-digest command immediately before reading Kijito:
85
+ > `<EXACT HOOK-EMITTED POINTER-DIGEST COMMAND>`. Record its pointer ID and
86
+ > lowercase digest. Then connect to Kijito as persona `codex`, project `Codex`.
87
+ > Call `kijito_startup`, then call
88
+ > `kijito_recall(query="CODEX_CURRENT_STATE_POINTER_V1 RESUME NOW", scope="project", project="Codex", full=true)`.
89
+ > Require one unambiguous top current-state result whose ID equals the pointer
90
+ > ID embedded in the supplied digest command; otherwise fail immediately.
91
+ > Scan every returned live memory and fail if any body other than the selected
92
+ > pointer contains the literal sentinel.
93
+ > Then read that pointer and every live, load-bearing linked
94
+ > memory. A server-generated predecessor marked `Source: version_history` is retired audit history regardless of importance.
95
+ > A predecessor identified only by a `version_of`/`derived:version_of` edge is retired audit history when its importance is at or below `0.1`.
96
+ > A matching predecessor is never a candidate current instruction: note that it exists, but do not follow or compare any
97
+ > `RESUME NOW` directive in its body.
98
+ > If archive status is ambiguous, fail the boot. Using only Kijito between the
99
+ > two digest commands, report the active task, exact next step, done versus
100
+ > remaining, DONE-WHEN, and every ambiguity or contradiction. Do not re-check
101
+ > defects the pointer already names as fixed — those are the ones most likely
102
+ > handled; hunt instead for siblings of those classes in places nobody has looked
103
+ > yet. Do not inspect files or guess. Immediately after reading and evaluating the pointer, run the
104
+ > same exact pointer-digest command again. Require the before-read and after-read pointer IDs and digests to be identical.
105
+ > Report the
106
+ > recall-selected ID and digest as one verified pair, but never the pointer
107
+ > body. These two invocations of the exact digest command are your only
108
+ > non-Kijito actions.
109
+
110
+ Compare its result to ground truth.
111
+
112
+ Severity gate. Only a finding that would cause a cold agent to take a WRONG
113
+ ACTION resets the count. An ambiguity, a cosmetic inconsistency, or a “could be
114
+ clearer” is recorded in the handoff as known-open and does not reset. Ask of each
115
+ finding: would an agent acting on this do the wrong thing?
116
+
117
+ Remediate by CLASS, never by instance. Before repairing anything, name the class
118
+ the finding belongs to, sweep every sibling location that could hold the same
119
+ class — the other memories, the pointer, the linked anchors — and fix them
120
+ together in one pass. Repairing only the instance the verifier named makes each
121
+ round surface one more member of the same class, so the loop runs in
122
+ O(instances) instead of O(classes), and it looks like diligence the entire way.
123
+
124
+ Hard cap: three rounds. “Any finding resets the count” plus an adversarial
125
+ verifier reading a rich pointer means findings are always available, so this loop
126
+ is non-terminating by construction: termination would otherwise depend on the
127
+ reviewer running out of things to say. A stated gap costs one sentence and fixing
128
+ it costs a whole round, which is why the loop conflates disclosed with fixed. At
129
+ the cap, stop, write every residual into the handoff, and mark the pass complete.
130
+ A residual you have disclosed is not a residual you have hidden. A stronger model
131
+ converging in one pass is not the fix — that makes the stopping condition depend
132
+ on the agent's judgement, which is a piece of advice, not a guard.
133
+
134
+ Require two consecutive clean passes.
135
+ Each boot must prove its own before-read digest equals its after-read digest,
136
+ and both clean boot reports must name the same pointer ID and digest. A missing,
137
+ malformed, or different digest is a failed boot and restarts both.
138
+
139
+ ## 5. Record the one-use pass and request native compaction
140
+
141
+ Only after Phase 4 is 2/2 green, run the same exact hook-emitted
142
+ `pointer-digest.mjs` command once more, immediately before recording. Require
143
+ its pointer ID and digest to equal both cold-boot reports. If it differs or
144
+ fails, the pointer changed and both boots restart.
145
+
146
+ Then replace `REPLACE_WITH_POINTER_ID` and
147
+ `REPLACE_WITH_POINTER_DIGEST` in the exact hook-emitted `qa-gate.mjs record`
148
+ command with those verified values. Make no pointer edit after either clean
149
+ boot or this final digest check, and do not permit another seat to edit it
150
+ during the final-check-to-record window. Run the record command as the final
151
+ memory-QA action. The token attests that specific pointer revision plus the
152
+ session and transcript; it is private, fresh for 30 minutes, and consumed by
153
+ one compaction.
154
+
155
+ The successful record command emits a machine-readable
156
+ `kijito.compaction.ready` signal with a cryptographic per-compaction nonce.
157
+ Immediately request native Codex compaction through the adapter that already
158
+ owns the active thread:
159
+
160
+ - An app-server host calls `thread/compact/start` for that exact thread.
161
+ - A Codex CLI supervisor may submit the literal `/compact` command to its
162
+ explicitly pinned pane.
163
+
164
+ The request is not authorization: `PreCompact` independently validates and
165
+ atomically promotes the pass into the one-use nonce-bound re-entry ticket.
166
+ `PostCompact` alone claims that ticket and owns Kijito re-entry;
167
+ `SessionStart(compact)` is a no-op. Do not call `thread/resume`, create a
168
+ replacement app-server connection, guess a thread or pane, inject arbitrary
169
+ keystrokes, or substitute `/clear`. If the current host exposes no safe
170
+ preemptive trigger, report that autonomous recycle is unavailable on that
171
+ adapter; never wait for forced automatic compaction or claim that compaction
172
+ occurred.
173
+
174
+ The pass cryptographically binds the exact pointer content only. The cold boots
175
+ also provide best-effort resumability verification of linked and recall-reached
176
+ memory as it existed during their bracketed reads, but the token does not
177
+ cryptographically cover that unbounded graph surface or later changes to it.
178
+ Normal runtime is single-writer-of-own-handoff; the advisory pointer lease
179
+ prevents concurrent development seats from creating a false gate during QA
180
+ without pretending to be a graph-wide lock.
181
+
182
+ `PreCompact` deliberately performs no network request. It format-validates and
183
+ reports the attested revision but does not refetch the hosted pointer. The
184
+ workflow ordering above—not a runtime network comparison—prevents a stale
185
+ attestation from being used after an in-place pointer edit.
186
+
187
+ If no exact hook command is available, report that the pre-compaction token
188
+ could not be recorded and keep compaction blocked.
189
+
190
+ After the record action, report counts created/corrected/faded, the pointer ID,
191
+ the two cold-boot verdicts, whether the one-use pass was recorded, its readiness
192
+ nonce, and whether native compaction was requested. Do not call `kijito_dream`
193
+ or any other graph-mutating tool after recording.