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.
- package/LICENSE +201 -0
- package/NOTICE +6 -0
- package/README.md +220 -0
- package/bin/cli.js +34 -0
- package/install.sh +161 -0
- package/package.json +50 -0
- package/providers/_shared/wake-core.mjs +358 -0
- package/providers/claude/CLAUDE.md.snippet +31 -0
- package/providers/claude/install.sh +186 -0
- package/providers/claude/scripts/arm-session.sh +66 -0
- package/providers/claude/scripts/claude-armed.sh +101 -0
- package/providers/claude/scripts/heartbeat-watchdog.sh +209 -0
- package/providers/claude/scripts/inbox-selftest.sh +277 -0
- package/providers/claude/scripts/kijito-persona-lib.sh +94 -0
- package/providers/claude/scripts/kijito-qa-pass.sh +12 -0
- package/providers/claude/scripts/lifecycle-lib.sh +167 -0
- package/providers/claude/scripts/myctx.sh +46 -0
- package/providers/claude/scripts/self-clear.sh +134 -0
- package/providers/claude/scripts/session-autosend.sh +85 -0
- package/providers/claude/scripts/session-catchup-hint.sh +330 -0
- package/providers/claude/scripts/statusline-context.sh +67 -0
- package/providers/claude/skills/kijito-qa-memory/SKILL.md +110 -0
- package/providers/claude/skills/kijito-recall/SKILL.md +53 -0
- package/providers/claude/skills/kijito-start/SKILL.md +122 -0
- package/providers/claude/wiring/README.md +93 -0
- package/providers/claude/wiring/kijito-heartbeat@.service +21 -0
- package/providers/codex/README.md +75 -0
- package/providers/codex/codex-kijito-parity-plan.md +265 -0
- package/providers/codex/docs-codex-setup.md +64 -0
- package/providers/codex/install.mjs +184 -0
- package/providers/codex/n0-capability-probe-protocol.md +472 -0
- package/providers/codex/n0-harness/README.md +57 -0
- package/providers/codex/n0-harness/cli.mjs +58 -0
- package/providers/codex/n0-harness/evidence-manifest.mjs +77 -0
- package/providers/codex/n0-harness/fixture.mjs +279 -0
- package/providers/codex/n0-harness/lib.mjs +141 -0
- package/providers/codex/n0-harness/manifest.mjs +36 -0
- package/providers/codex/n0-harness/oracle.mjs +464 -0
- package/providers/codex/n0-harness/parser.mjs +200 -0
- package/providers/codex/n0-harness/prompt.mjs +43 -0
- package/providers/codex/n0-harness/snapshot.mjs +120 -0
- package/providers/codex/n0-harness/specimen.mjs +37 -0
- package/providers/codex/notify/kijito-notify-count.mjs +117 -0
- package/providers/codex/notify/kijito-notify-count.test.mjs +76 -0
- package/providers/codex/plans/gate4-battery-log.md +184 -0
- package/providers/codex/plans/gate4-battery-protocol.md +43 -0
- package/providers/codex/plans/hive-user-first-plan-QA.md +34 -0
- package/providers/codex/plans/hive-user-first-plan.md +247 -0
- package/providers/codex/release-manifest.json +53 -0
- package/providers/codex/same-chat-continuation-plan-gate.md +235 -0
- package/providers/codex/same-chat-continuation-plan.md +458 -0
- package/providers/codex/skills/kijito-qa-memory/SKILL.md +193 -0
- package/providers/codex/skills/kijito-qa-memory/agents/openai.yaml +4 -0
- package/providers/codex/skills/kijito-recall/SKILL.md +53 -0
- package/providers/codex/skills/kijito-start/SKILL.md +173 -0
- package/providers/codex/skills/kijito-start/agents/openai.yaml +4 -0
- package/providers/codex/test/n0-cli-refusal.test.mjs +31 -0
- package/providers/codex/test/n0-counterexample-matrix.test.mjs +118 -0
- package/providers/codex/test/n0-guard-census-core.mjs +1372 -0
- package/providers/codex/test/n0-guard-census.json +35479 -0
- package/providers/codex/test/n0-guard-census.mjs +31 -0
- package/providers/codex/test/n0-guard-census.test.mjs +374 -0
- package/providers/codex/test/n0-guard-counterexamples.mjs +1068 -0
- package/providers/codex/test/n0-guard-independent-projection.mjs +70 -0
- package/providers/codex/test/n0-guard-independent-projection.test.mjs +53 -0
- package/providers/codex/test/n0-guard-manifest-author.mjs +424 -0
- package/providers/codex/test/n0-guard-mutation-operators.test.mjs +244 -0
- package/providers/codex/test/n0-guard-mutation-runner.mjs +599 -0
- package/providers/codex/test/n0-guard-remainder-classes.test.mjs +314 -0
- package/providers/codex/test/n0-guard-sanitizer-pairs.test.mjs +68 -0
- package/providers/codex/test/n0-guard-shared-context-predicates.test.mjs +84 -0
- package/providers/codex/test/n0-harness.test.mjs +553 -0
- package/providers/codex/test/n0-notable-regressions.test.mjs +70 -0
- package/providers/codex/test/n0-subject-boundary.mjs +97 -0
- package/providers/codex/test/n0-subject-boundary.test.mjs +72 -0
- package/providers/codex/test/same-chat-plan-preflight.sh +167 -0
- package/providers/codex/tools/refresh-manifest.mjs +81 -0
- package/providers/codex/wake-helper/TRANSPORT-NOTES.md +25 -0
- package/providers/codex/wake-helper/integration.test.mjs +285 -0
- package/providers/codex/wake-helper/kijito-wake-helper.mjs +488 -0
- package/providers/codex/wake-helper/kijito-wake-helper.test.mjs +128 -0
- package/providers/codex/wake-helper/mock-daemon.mjs +64 -0
- package/providers/codex/wake-helper/status-probe.mjs +45 -0
- package/providers/codex/wake-helper/ws-uds.mjs +153 -0
- package/providers/monitor/.github/workflows/publish-npm.yml +38 -0
- package/providers/monitor/.github/workflows/publish-pypi.yml +30 -0
- package/providers/monitor/CHANGELOG.md +465 -0
- package/providers/monitor/IMPORT-PROVENANCE.md +68 -0
- package/providers/monitor/LICENSE +202 -0
- package/providers/monitor/NOTICE +7 -0
- package/providers/monitor/OPAQUE-OUTPUT-ENFORCEMENT.md +45 -0
- package/providers/monitor/README.md +571 -0
- package/providers/monitor/RELEASING.md +125 -0
- package/providers/monitor/arm-hive-monitor.sh +13 -0
- package/providers/monitor/bin/cli.js +43 -0
- package/providers/monitor/com.kijito.inbox-monitor.plist.template +59 -0
- package/providers/monitor/docs/DESIGN.md +984 -0
- package/providers/monitor/kijito-inbox-monitor@.service.template +95 -0
- package/providers/monitor/kijito_inbox_monitor.py +3666 -0
- package/providers/monitor/package.json +35 -0
- package/providers/monitor/pyproject.toml +42 -0
- package/providers/monitor/scripts/mutation-check.py +399 -0
- package/providers/monitor/scripts/prepublish-gate.sh +284 -0
- package/providers/monitor/test_kijito_monitor.py +5609 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Gate-4 option-A sandbox battery — execution log
|
|
2
|
+
|
|
3
|
+
**Protocol:** `gate4-battery-protocol-20260815.md` (v1, §10 order — gate-2 shipped @ 0a440e7,
|
|
4
|
+
gate-3 folded). Scoring is BY-EFFECT; every row carries the exact command + timestamped log
|
|
5
|
+
excerpt. 2/2 consecutive full green passes required; any finding resets the count.
|
|
6
|
+
|
|
7
|
+
**Started:** 2026-08-15 ~05:0xZ · **Operator:** codex[vm] · **Main at battery time:** d6f73b6
|
|
8
|
+
|
|
9
|
+
## Environment as-built
|
|
10
|
+
|
|
11
|
+
- Sandbox: `/Users/jason/Code/SideProjects/Codex/.qa-tmp/native-wake-probe-20260814/`
|
|
12
|
+
(CODEX_HOME=`codex-home/` — auth staged, workspace trusted; untouched since 08-14 staging)
|
|
13
|
+
- Helper under test: `gate4-staging/wake-helper/` (kijito-wake-helper.mjs + ws-uds.mjs,
|
|
14
|
+
`_shared/wake-core.mjs`)
|
|
15
|
+
- Producer: session-scoped `kijito-inbox-monitor` child via `--producer-cmd` (gate-3 A shape),
|
|
16
|
+
real persona inbox `codex`
|
|
17
|
+
- Pre-battery helper suite: **17/17 green on the Mac AND on Linux** (05:2xZ), after one
|
|
18
|
+
portability fix — see finding E2.
|
|
19
|
+
|
|
20
|
+
### Environment findings (pre-scoring adaptations, both documented for review)
|
|
21
|
+
|
|
22
|
+
- **E1 — macOS UDS `sun_path` limit forced a sandbox relocation.** The staged sandbox's
|
|
23
|
+
control-socket path is 125 bytes; macOS caps `sun_path` at ~104, so
|
|
24
|
+
`codex app-server daemon start` never became ready there (measured; a CODEX_HOME symlink
|
|
25
|
+
does not help — codex canonicalizes the home before composing the socket path). Battery
|
|
26
|
+
runs from a byte-identical `cp -a` copy at `/Users/jason/g4-20260815/` (socket path
|
|
27
|
+
78 bytes, daemon starts clean). The staged original is UNTOUCHED and remains the archive
|
|
28
|
+
source of record. Two orphaned startup locks from the failed long-path attempts were
|
|
29
|
+
removed; the stray half-started app-server (pid 2198) was killed before the clean start.
|
|
30
|
+
- **E2 — `ps --ppid` is GNU-only; the child-census helper in `integration.test.mjs` died on
|
|
31
|
+
macOS** (its "17/17 pre-battery greens" had been measured on the Linux seat). Fixed to the
|
|
32
|
+
portable `pgrep -P` (exit-1-on-no-match handled as "no children"). Suite re-run: 17/17 on
|
|
33
|
+
BOTH platforms. One-line test-code fix, flagged for argus at gate-4/5 PR time.
|
|
34
|
+
|
|
35
|
+
## Precondition P0
|
|
36
|
+
|
|
37
|
+
- [x] daemon started: pid 5912, socket `/Users/jason/g4-20260815/codex-home/app-server-control/app-server-control.sock`, v0.147.0 (packages symlinked per TRANSPORT-NOTES)
|
|
38
|
+
- [x] battery thread created via sandbox TUI (tmux session `g4battery`, trust accepted for the copied workspace path); ONE real turn ran to completion (prompt "Reply with exactly the word ready and nothing else." → "• ready" rendered)
|
|
39
|
+
- **Thread id: `01a003c2-c99f-7593-8eb0-6c91a25847cf`** (rollout `rollout-2026-08-14T22-51-32-01a003c2-….jsonl` under the sandbox home's sessions/)
|
|
40
|
+
- Producer cmd (gate-3 A shape, pinned Mac install): `/opt/homebrew/bin/python3 -u /Users/jason/.local/share/kijito-inbox-monitor/versions/bc91108/kijito_inbox_monitor.py --persona codex --token-file /Users/jason/.claude/.kijito_api_token.codex --poll-seconds 5 --wait 30 --state-file /Users/jason/g4-20260815/rt/producer.state --events-file /Users/jason/g4-20260815/events.jsonl --heartbeat 60`
|
|
41
|
+
|
|
42
|
+
## Pass 1
|
|
43
|
+
|
|
44
|
+
| # | Row | Verdict | Evidence |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| 1 | Happy-path live wake | **GREEN** 05:02Z | probe 7699 (`row1-pass1-scored-heron-3317`): producer `new:7699` → helper `doorbell` 05:02:11.265 → `wake-delivered` 05:02:11.272 (turn 01a003cc). TUI rendered the fixed template (metadata only), woken turn called `kijito_hive_inbox` with the EXACT instructed args (`before_id:7700, limit:1, mark_read:false` peek), returned row id == 7699 verified, operator summary rendered, no other tools invoked. Census 1/1/1. Evidence: `evidence/row1-pass1-pane.txt` + `row1-pass1-helper.ndjson`. (Tool approval prompt answered "allow for session" — TUI policy, outside helper scope.) |
|
|
47
|
+
| 2 | Non-attachment detection | **GREEN** 05:04Z | second codex launched with `-c model_reasoning_effort="low"` (own turn run, thread 01a003cd…); helper `arm` against that thread via the daemon sock (separate runtime rt2): stderr `arm-unverified: failed: thread-gone`, **exit 7**, log records the daemon's refusal verbatim (`thread … already has an active writer`). No silent no-op; census unchanged (the one live row-1 helper only). |
|
|
48
|
+
| 3a | Producer absent pre-arm | **GREEN** 05:04Z | arm with nonexistent events file + no producer: run child refused PRE-ARM via `fail(4, "producer-stream-absent")` (source line 181), arm wrapper surfaced it loudly (`arm-unverified: failed: producer-stream-absent`, exit 7). |
|
|
49
|
+
| 3b | Events file vanish mid-armed | **GREEN** 05:05Z | `rm events.jsonl` under the live arm: helper logged `producer-stream-vanished` (fail(4) path, source line 236), helper-run census → 0, and the IN-SESSION GASP rendered in the TUI: "[KIJITO WAKE HELPER NOTICE] … producer events stream vanished — this session is now catch-up-only". Producer child reaped after its long-poll drain (census 0 at +25s — see census note below). |
|
|
50
|
+
| 3c | Producer child SIGKILL, file remains | **GREEN** 05:06Z | fresh arm (pid 9765, child 9766); `kill -9` the child, file left in place: helper logged `producer-child-died {signal:SIGKILL}` within 2s (fail(4), source line 171), exited (census 0), events file still present, TUI gasp: "session producer died (SIGKILL) — this session is now catch-up-only". The silent-tail trap made loud — binding control (assay 7548). |
|
|
51
|
+
|
|
52
|
+
**Census timing note (measured, 3b):** a SIGTERM'd producer drains its in-flight long-poll
|
|
53
|
+
(`--wait 30`) before exiting (gate-3 B-3 behavior) — a post-stop census inside that window
|
|
54
|
+
reads a live "orphan" that is actually mid-drain. Count leaks only after the wait window.
|
|
55
|
+
| 4 | Shared-filter contract | **GREEN** 05:08Z | non-covered kind: BOTH a synthetic `heartbeat` and the producer's real heartbeat (05:07:49) produced NO nudge. Covered kind: valid synthetic `alert` → `doorbell alert:…` + `wake-delivered` (turn 01a003d2) within 300ms; the woken turn ran the lifecycle/reconcile shape (read-only unread peek, summarized rows 7698/7699 — still unread because row-1's fetch was a mark_read=false peek, as instructed). Filter decisions all from `_shared` `parseEventLine` (helper source: `if (!parsed.event) continue` — no local filter). Incidental validator check: an alert with an INVALID ts (harness's own BSD `date %N` bug) was dropped without wake via `invalid-lifecycle-timestamp` — malformed lines cannot wake. |
|
|
56
|
+
| 5 | Lifecycle + double-arm + thread-gone | **GREEN** 05:09Z | 5a second `arm` (same runtime, same thread): stdout `already-armed pid=9856`, exit 0, pgrep census exactly ONE helper — no second helper ever spawned. 5b staged control: TUI quit alone → helper correctly STAYS armed (the thread lives in the daemon, not the TUI client); daemon kill → helper exit `thread-gone {detail: daemon-connection-closed}` (fail(5) path) within seconds, census 0, **pidfile reaped**. No orphan left to fire into dead/reused threads. |
|
|
57
|
+
| 6a | Helper SIGTERM gasp | **GREEN** 05:12Z | SIGTERM helper 10926: in-session gasp rendered ("[KIJITO WAKE HELPER NOTICE] stopping on SIGTERM — this session is now catch-up-only"), `helper-exit signal-SIGTERM` logged, **pidfile reaped**. |
|
|
58
|
+
| 6b | Helper SIGKILL residue (documented degradation) | **GREEN (residue measured + recorded per [28733] measured-infeasibility clause)** 05:13Z | SIGKILL helper 11053: NO gasp (impossible by construction), no exit log line. Residue measured: (i) stale pidfile REMAINS; (ii) `status` reports `alive:false`, exit 1 — death visible at next status ✓; (iii) next `arm` did NOT false-arm off the stale pidfile — it proceeded, and failed LOUDLY (`producer-child-died` code 2) because the SIGKILL-orphaned producer (11054, ppid 1) still held the state-file lock — producer-stderr captured verbatim ("state-file in use (another watcher holds the lock)"). (iv) After orphan cleanup (SIGTERM + long-poll drain), clean re-arm succeeded (helper 11220, census 1/1). Documented degradation-to-B for SIGKILL only; at no point did the residue present as armed-and-healthy. |
|
|
59
|
+
| 7a | Defer-until-idle: composer draft | **GREEN** 05:17Z | draft "DRAFT-SENTINEL row7a…" typed, not submitted (thread idle — a draft is not a turn); probe 7703 delivered promptly; wake turn ran to completion (id verified + summary); pane capture proves the DRAFT SURVIVED UNTOUCHED in the composer after the whole wake turn. No stomp. |
|
|
60
|
+
| 7b | Defer-until-idle: mid-turn | **GREEN by-effect, with mechanism note Q1** 05:19Z | probe 7704 sent mid-way through a ~200-line counting turn. Session-visible ordering (scrollback evidence): counting ran to completion ("two hundred / finished", lines 204–407) and ONLY THEN the wake turn rendered (line 410) and completed. No interruption, no stomp, no mid-turn delivery to the user. **Q1 (mechanism, for argus):** the helper's log shows it SUBMITTED the wake 2ms after the doorbell, while the turn was active — its `threadIdle` never went false (no observed `thread/status/changed` for another client's turn at the helper's connection). The user-visible deferral was provided by the daemon's per-thread TURN QUEUE (v0.147 serializes), not by the helper's own defer machinery. By-effect contract met; whether the helper must also defer at its own layer (belt-and-braces against future daemon semantics) is flagged for steward ruling. |
|
|
61
|
+
| 8 | Wake-turn contract (by-effect) | **GREEN** (compiled from rows 1/4/7a/7b turns) | every wake turn across the pass used the byte-fixed `_shared` template (prefix `[KIJITO AUTOMATED WAKE V1 - NOT USER AUTHORED]`, metadata only, NO message bodies in the turn text); every woken turn called ONLY `kijito_hive_inbox` with the exact instructed args (`mark_read:false` peek, `before_id`/`limit:1` exact-row for mail kinds; unread peek for the lifecycle/reconcile kind), verified returned id == requested id, summarized for the operator, and invoked no shell/file/web/send/mutation tool. Message bodies rendered only inside UNTRUSTED fences via the tool result, never in the wake text. |
|
|
62
|
+
|
|
63
|
+
## Pass bookkeeping ruling (argus 7711, 05:23Z)
|
|
64
|
+
|
|
65
|
+
Pass 1 is **VOIDED as a counting green** — row-7b as scored misattributed its green to a
|
|
66
|
+
mechanism that never ran (the helper defer layer). Its by-effect results stay on record as
|
|
67
|
+
real. The instrument is fixed by protocol amendment (row-7b v2, leg (a) of the ruling: the
|
|
68
|
+
existing synthetic forcing test `busy thread defers; idle notification releases the queued
|
|
69
|
+
wake` certifies the defer layer; the battery row now attributes each leg separately and adds
|
|
70
|
+
a real-path defer measurement). Pass 2 below runs the FIXED battery (row-7b v2 — the only
|
|
71
|
+
amended row — had not yet executed in pass 2 at fix time) and is green-#1 CANDIDATE of the
|
|
72
|
+
reset count; one further full green (pass 3) is required after it.
|
|
73
|
+
|
|
74
|
+
## Pass 2 (fresh sandbox re-arm; fixed battery) — green-#1 candidate
|
|
75
|
+
|
|
76
|
+
Fresh daemon (pid 11907), fresh TUI session, P0 turn run, thread
|
|
77
|
+
`01a003de-115c-7002-bafa-0a7d68c1b339`, fresh runtime+events under `p2/`.
|
|
78
|
+
|
|
79
|
+
| # | Row | Verdict | Evidence |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| 1 | Happy-path live wake | **GREEN** 05:21Z | probe 7708 (`row1-pass2-gannet-6614`): doorbell 05:21:59.925 → wake-delivered .934 (9ms), turn 01a003de-ac7d…; TUI render verified (id verified + summary + marker). Fresh-session tool approval granted (session scope) as part of the row. |
|
|
82
|
+
| 3a | Producer absent pre-arm | **GREEN** 05:22Z | fresh runtime p2rt3, nonexistent events file: `producer-stream-absent` refusal pre-arm, arm exit 7 (run child fail(4) path). |
|
|
83
|
+
|
|
84
|
+
(row 2 first attempt at 05:22Z was a PROCEDURAL MISFIRE on the operator's side, recorded
|
|
85
|
+
honestly: the pass-1 embedded thread was reused after its session had been killed, so the
|
|
86
|
+
arm legitimately SUCCEEDED against an idle rollout-backed thread — not the row-2 scenario.
|
|
87
|
+
The stray helper was stopped within seconds, before any mail event, and a LIVE embedded
|
|
88
|
+
session was relaunched for the real row-2 run below.)
|
|
89
|
+
|
|
90
|
+
| 2 | Non-attachment detection | **GREEN** 05:25Z | LIVE embedded session relaunched (`-c` override, own turn, thread 01a003df…); arm against it: `thread-gone` / "already has an active writer", exit 7, census unchanged. |
|
|
91
|
+
| 3b | Events vanish mid-armed | **GREEN** 05:25Z | `producer-stream-vanished` + TUI gasp rendered + helper census 0. |
|
|
92
|
+
| 3c | Producer SIGKILL, file remains | **GREEN** 05:26Z | `producer-child-died {SIGKILL}` in 2s + TUI gasp + file remains + census 0. |
|
|
93
|
+
| 4 | Shared-filter contract | **GREEN** 05:27Z | heartbeat: doorbells 2→2 (no nudge); valid alert → doorbell + wake-delivered 4ms (turn 01a003e3…). |
|
|
94
|
+
| 5 | Lifecycle + double-arm + thread-gone | **GREEN** 05:27-28Z | `already-armed pid=13914` exit 0, census 1; daemon kill (exact pid — NOTE the pgrep pattern `g4.*app-server` self-matches the helper's `--sock` argv; killed by known pid) → `thread-gone daemon-connection-closed`, pidfile reaped, census 0. |
|
|
95
|
+
| 6a | SIGTERM gasp | **GREEN** 05:33Z (re-run) | first run 05:29Z was invisible-by-operator-error: after row-5's daemon kill the TUI was a ZOMBIE CLIENT of the dead daemon, so the gasp turn ran unseen — recorded, TUI relaunched (new thread 01a003e7, P0 re-run), 6a re-run: gasp RENDERED ("stopping on SIGTERM — catch-up-only") + pidfile reaped. |
|
|
96
|
+
| 6b | SIGKILL residue | **GREEN** 05:34-35Z (re-run on live thread) | stale pidfile remains; `status` `alive:false` exit 1; TWO consecutive loud held-lock re-arm refusals while the orphan drained (richer than pass 1 — the residue cannot false-arm even across the drain window); clean re-arm after drain (census 1/1). Operator note: a piped `arm \| tail` hid the real exit code once — evidence taken from the printed refusal text, not `$?` (never read `$?` after a pipe). |
|
|
97
|
+
| 7a | Draft no-stomp | **GREEN** 05:36Z | probe 7716 delivered with draft present; draft survived the wake BYTE-INTACT (its later submission was operator keystrokes hitting the composer after the approval dialog — the submitted text matches the original draft exactly, which is itself integrity evidence). |
|
|
98
|
+
| 7b | Defer-until-idle (v2, three legs) | **GREEN — defer layer MEASURED on the REAL daemon** 05:38-41Z | **(i) ordering:** counting turn 01a003ed-d15e ran 05:38:32.420 → 05:38:51.025 (rollout `task_complete`); helper doorbell for probe 7723 at 05:38:48.973 (MID-TURN); wake turn 01a003ee-1a16 started 05:38:51.034 — **9ms AFTER task_complete**: the helper DEFERRED mid-turn and the idle transition released it. Scrollback confirms full count render before the wake. **(ii) real-path instrument** (`status-probe.mjs`, one-shot second client): `thread/resume` mid-turn returned `{type:"active"}`, and the daemon delivered `thread/status/changed → idle` to the second client's connection at turn end (05:41:11.484) — the real daemon supplies BOTH inputs the defer layer needs. **(iii) synthetic forcing test** `busy thread defers; idle notification releases the queued wake` green in the same battery's pre-suite (both platforms). Residual variance on record: pass-1's run submitted mid-turn (daemon queue serialized, by-effect still correct) — defer depends on the helper observing the active transition; both layers plus the daemon queue are now measured facts, no cross-attribution. |
|
|
99
|
+
| 8 | Wake-turn contract | **GREEN** | all pass-2 wake turns (7708, alert-reconcile, 7716, 7721, 7723) used the fixed template, exact-args read-only peeks, id verification, operator summaries; no shell/file/web/send/mutation tool in any woken turn. |
|
|
100
|
+
|
|
101
|
+
**Producer version note:** battery producer pinned at `versions/bc91108` throughout; argus
|
|
102
|
+
released v0.5.0 fleet-wide mid-pass (his 7721) — battery unaffected (pinned path), recorded
|
|
103
|
+
for comparability.
|
|
104
|
+
|
|
105
|
+
## Pass 3 (second consecutive green of the fixed battery) — 05:44-05:54Z
|
|
106
|
+
|
|
107
|
+
Fresh daemon (pid 17316), fresh TUI session, P0 turn, thread
|
|
108
|
+
`01a003f3-4b05-7460-9fd0-2a93ed8dfad3`, fresh runtime+events under `p3/`. Row 5 executed
|
|
109
|
+
LAST (its daemon-kill doubles as teardown; order deviation noted — each row is independent
|
|
110
|
+
and census-bracketed). Producer still pinned `bc91108` (argus's v0.5.0 deploy repointed the
|
|
111
|
+
supervised producers only; battery instrument unchanged across all passes).
|
|
112
|
+
|
|
113
|
+
| # | Row | Verdict | Evidence |
|
|
114
|
+
|---|---|---|---|
|
|
115
|
+
| 1 | Happy path | **GREEN** 05:46Z | probe 7728: doorbell→delivered 5ms (turn 01a003f5…), id verified + summary rendered (curlew-7742). Fresh-session approval granted in-row. |
|
|
116
|
+
| 2 | Non-attachment | **GREEN** 05:47Z | live embedded session relaunched (thread 01a003f5-e8c0…): `thread-gone` / "already has an active writer", exit 7. |
|
|
117
|
+
| 3a | Absent pre-arm | **GREEN** 05:47Z | `producer-stream-absent` pre-arm refusal, exit 7 (fail(4) run path). |
|
|
118
|
+
| 3b | Vanish mid-armed | **GREEN** 05:47Z | `producer-stream-vanished` + TUI gasp + census 0. |
|
|
119
|
+
| 3c | Child SIGKILL | **GREEN** 05:48Z | `producer-child-died {SIGKILL}` + TUI gasp + file remains + census 0. |
|
|
120
|
+
| 4 | Shared filter | **GREEN** 05:49Z | heartbeat: doorbells 2→2; valid alert → doorbell + delivered 4ms (turn 01a003f7…). |
|
|
121
|
+
| 6a | SIGTERM gasp | **GREEN** 05:50Z | gasp rendered + `helper-exit signal-SIGTERM` + pidfile reaped. |
|
|
122
|
+
| 6b | SIGKILL residue | **GREEN** 05:50-51Z | stale pidfile remains; `status alive:false` exit 1; held-lock re-arm refused LOUD (`producer-child-died`); orphan 19185 cleaned; clean re-arm census 1/1. |
|
|
123
|
+
| 7a | Draft no-stomp | **GREEN** 05:51Z | cleanest specimen of the three passes: wake turn (7734) completed its summary with the draft "DRAFT-SENTINEL pass3 row7a vexed zebras" STILL VISIBLE and untouched in the composer afterward. |
|
|
124
|
+
| 7b | Defer v2 | **GREEN** 05:52Z | (i) ordering: count turn completed (scrollback 307-308) before the wake turn (311). NOTE: the doorbell itself arrived 33s after the mail event — inside argus's pre-flagged v0.5.0 deploy window ("delivery may lag ~1 min... mark the window"), recorded as attributable upstream lag, NOT a finding; once the doorbell landed (thread already idle) delivery was 5ms, so the defer path had no occasion this pass. (ii) instrument: `thread/resume` mid-turn `{type:"active"}`; TWO full active→idle notification cycles observed on the second client's connection (count turn end 05:52:10.5; wake turn 05:52:37→45). (iii) synthetic forcing test green in the same battery's pre-suite. Real-path defer FIRING specimen remains pass-2's 9ms-post-task_complete timeline. |
|
|
125
|
+
| 8 | Wake-turn contract | **GREEN** | all pass-3 wake turns (7728, alert, 7734, 7735): fixed template, exact-args read-only peeks, id verified, summaries, no other tools. |
|
|
126
|
+
| 5 | Double-arm + thread-gone (run last) | **GREEN** 05:53Z | `already-armed pid=19290` exit 0, census 1; daemon kill (known pid 17316) → `thread-gone daemon-connection-closed`, pidfile reaped, census 0. |
|
|
127
|
+
|
|
128
|
+
**Evidence gap, recorded honestly:** the pass-3 full pane scrollback was not captured before
|
|
129
|
+
the tmux session was killed at teardown (operator sequencing). The pass-3 record rests on the
|
|
130
|
+
helper logs (`evidence/pass3-helper-full.ndjson`), the thread rollout
|
|
131
|
+
(`evidence/pass3-thread-rollout.jsonl` — the authoritative turn-by-turn record), the
|
|
132
|
+
status-probe outputs, and the row-by-row pane excerpts quoted in the session transcript.
|
|
133
|
+
|
|
134
|
+
## Result
|
|
135
|
+
|
|
136
|
+
**PASS 2 + PASS 3 = TWO CONSECUTIVE FULL GREENS of the fixed battery** (pass 1 voided per
|
|
137
|
+
argus 7711; leg (a) taken and steward-accepted 7732). Teardown clean: final census 0/0/0
|
|
138
|
+
(helper/producer/daemon), TUI session closed, battery sandbox archived in place at
|
|
139
|
+
`/Users/jason/g4-20260815/` (12-file evidence bundle in `evidence/`), staged original
|
|
140
|
+
`.qa-tmp/native-wake-probe-20260814/` untouched throughout. Certification request to assay
|
|
141
|
+
follows per protocol (gate-5 ship only after assay's 2/2 read).
|
|
142
|
+
|
|
143
|
+
## Census ledger
|
|
144
|
+
|
|
145
|
+
(inline per row above: bracketed pgrep censuses; the two standing traps are documented — the
|
|
146
|
+
helper's argv self-matches both the producer pattern and `app-server` patterns, so counts
|
|
147
|
+
used binary-anchored patterns / `ps -o comm`; and a SIGTERM'd producer drains its long-poll
|
|
148
|
+
(≤ ~35s) before exiting, so post-stop censuses waited out the drain window.)
|
|
149
|
+
|
|
150
|
+
## Addendum — post-certification steward findings and conditional cert carry (2026-08-15 06:1x-06:2xZ)
|
|
151
|
+
|
|
152
|
+
Argus's steward review of the gate-5 PR (#19, review msg 7748) found two code defects in the
|
|
153
|
+
helper the battery had certified, plus a doc gap; the joint argus+assay ruling (7751/7750):
|
|
154
|
+
**certification CARRIES CONDITIONALLY** — no full battery reset — on four conditions, all met:
|
|
155
|
+
|
|
156
|
+
1. **Mutation-proven regression tests.** F1 (a stale "armed" line from a previous run in the
|
|
157
|
+
persistent ndjson false-verifies a new arm whose child is slow to fail — the arm wrapper
|
|
158
|
+
matched threadId only, and a SIGKILL'd helper leaves no exit line) and F2 (a line torn
|
|
159
|
+
across the 256KB read cap is silently dropped — offset advanced past the torn head).
|
|
160
|
+
Both structurally forced by new tests and run BOTH WAYS: pre-fix bytes FAIL exactly as
|
|
161
|
+
diagnosed (F1 false-arms off the stale record; F2 never delivers), fixed bytes pass.
|
|
162
|
+
Fix commit 64192dc: pid-stamped armed records + post-spawn-bytes-only scanning bound to
|
|
163
|
+
child.pid (two independent guards); consumption stops at the last complete line with a
|
|
164
|
+
torn-line diagnostic.
|
|
165
|
+
2. **Full helper suite both platforms:** 19/19 macOS, 19/19 Linux, on the fixed bytes.
|
|
166
|
+
3. **Targeted real-daemon re-run on fixed bytes** (rows 1, 5a, 6b; fresh thread 01a00411,
|
|
167
|
+
standard census brackets, teardown 0/0/0): row 1 GREEN (doorbell→submit 6ms, exact-row
|
|
168
|
+
render); row 5a GREEN (`already-armed`, census 1 — F1's surface, now pid-bound); row 6b
|
|
169
|
+
GREEN with the F1 fix demonstrated live: SIGKILL residue (stale pidfile + stale armed
|
|
170
|
+
line in the log + status `alive:false`), and the subsequent re-arm did NOT false-arm —
|
|
171
|
+
it failed LOUD on the orphan's held state-lock (exit 7), exactly the loud-by-design
|
|
172
|
+
contract the pre-fix bytes violated in the diagnosed window. Evidence:
|
|
173
|
+
`evidence/conditional-rerun-helper.ndjson`.
|
|
174
|
+
4. **Row-4/7 carry rationale (assay's cert-delta ruling):** the F1/F2 fixes touch the arm
|
|
175
|
+
wrapper's verification scan and pollEvents' consumption boundary; neither changes the
|
|
176
|
+
filter contract (row 4: `parseEventLine` untouched), the defer machinery, nor the
|
|
177
|
+
delivery path (rows 7a/7b: `deliverIfReady` untouched) — the certified behaviors of the
|
|
178
|
+
unchanged code paths carry, and the changed paths are re-proven by conditions 1-3.
|
|
179
|
+
|
|
180
|
+
Also per the review: F3 (SKILL.md exit-code enumeration completed and restated as the
|
|
181
|
+
property — any nonzero exit means NOT armed); gating ruling implemented (helper, ws-uds,
|
|
182
|
+
both test files, and the mock daemon added to `release-manifest.json` via the refresh map +
|
|
183
|
+
install.mjs source-commit list and hash checks, deliberate re-stamp in the same commit;
|
|
184
|
+
status-probe and TRANSPORT-NOTES deliberately ungated: instrument + doc, off the user path).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Gate-4 option-A sandbox battery — execution protocol (v1)
|
|
2
|
+
|
|
3
|
+
**Runs only per plan §10 order** (after gate-2 ships post-window and gate-3 — done — is
|
|
4
|
+
folded). 2/2 consecutive full green passes required; any finding resets the count. Evidence:
|
|
5
|
+
every row gets a timestamped log excerpt + the exact command; scoring is BY-EFFECT
|
|
6
|
+
([28458]): session-visible outcomes, never process liveness or self-report.
|
|
7
|
+
|
|
8
|
+
**Environment:** the staged sandbox `SideProjects/Codex/.qa-tmp/native-wake-probe-20260814/`
|
|
9
|
+
(Mac path `/Users/jason/Code/SideProjects/Codex/...`), CODEX_HOME=its `codex-home/`
|
|
10
|
+
(auth staged, workspace trusted). Daemon: symlink `~/.codex/packages` into the sandbox home
|
|
11
|
+
(measured requirement, TRANSPORT-NOTES.md), then `codex app-server daemon start`.
|
|
12
|
+
Helper: `gate4-staging/wake-helper/` (17/17 pre-battery greens on the measured WS-over-UDS
|
|
13
|
+
transport). Producer: session-scoped `kijito-inbox-monitor` child via `--producer-cmd`
|
|
14
|
+
(gate-3 default shape), watching a REAL persona inbox (persona `codex`, real probe mail).
|
|
15
|
+
|
|
16
|
+
**Precondition P0 (measured, [28773]):** create the battery's "user session" thread and run
|
|
17
|
+
ONE real turn in it (a trivial prompt in the sandbox TUI) so a rollout exists —
|
|
18
|
+
`thread/resume` on a turn-less thread fails `-32600 no rollout found`. Record the thread id;
|
|
19
|
+
it is the helper's `--thread-id` for every row. The TUI session runs in a dedicated tmux
|
|
20
|
+
pane for composer/rendering observations.
|
|
21
|
+
|
|
22
|
+
## Rows (each pass runs ALL rows; a pass is green only if every row is)
|
|
23
|
+
|
|
24
|
+
| # | Row | Procedure | Green means |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| 1 | Happy-path live wake | arm helper (producer child + helper); send probe mail to `codex` | wake turn renders IN THE SESSION TUI: exact-row fetch, id verified, summary; by-effect log (`wake-delivered` + pane capture) |
|
|
27
|
+
| 2 | Non-attachment detection | launch a SECOND codex with `-c` override / `--strict-config` (embedded mode, [28502] trap); attempt arm against its context | arm fails LOUDLY (daemon-unavailable or thread-gone) and says so; no silent no-op |
|
|
28
|
+
| 3 | Producer-silence controls (3a absent / 3b vanish / 3c child-death) | 3a: arm with no events file and no producer; 3b: delete events file mid-armed; 3c: SIGKILL the owned producer child, file left in place | 3a exit 4 pre-arm, reported; 3b gasp + exit 4; 3c gasp + exit 4 (the silent-tail trap made loud — binding control, assay 7548) |
|
|
29
|
+
| 4 | Shared-filter contract | append a non-covered kind (e.g. `heartbeat`) to the stream, then a covered lifecycle kind (`alert`) | non-covered: NO nudge; covered: reconcile wake fires; both from the `_shared` constant, no local filter |
|
|
30
|
+
| 5 | Helper lifecycle + DOUBLE-ARM | run arm twice (same session); then kill-the-session control: kill the TUI/daemon thread, observe helper | second arm reports already-armed, exactly one helper (pgrep census); on thread-gone the helper exits 5, no orphan firing into dead/reused threads (census after) |
|
|
31
|
+
| 6 | Helper-death visibility ([28733] ruling) | 6a: SIGTERM helper; 6b: SIGKILL helper | 6a: in-session gasp ("catch-up-only") + pidfile reaped; 6b: NO gasp possible — measure the residue (stale pidfile reaped on next arm; death visible at next kijito-start status) and RECORD it in the log as the documented degradation-to-B for SIGKILL only, per the ruling's measured-infeasibility clause |
|
|
32
|
+
| 7 | Defer-until-idle (mid-typing / mid-turn) | 7a: type a draft into the composer (do not submit), send probe mail, wait > poll+recheck; 7b **(v2, per argus ruling 7711 — leg (a))**: three legs: (i) by-effect ordering — start a long turn, send probe mid-turn, scrollback must prove the turn completes before the wake renders (no stomp); (ii) real-path defer attempt — arm the helper DURING a long turn (fresh runtime) so `thread/resume` returns the live status; record the observed helper-log sequence (doorbell vs wake-delivered ordering relative to turn end) as a MEASUREMENT of whether the real daemon exposes busy status + idle notifications to a second client; (iii) the helper's own defer layer is certified by the SYNTHETIC forcing test `busy thread defers; idle notification releases the queued wake` (mock daemon `initialStatus:"active"`, doorbell held >poll cycle with zero turn-starts, released exactly once on the idle notification) — run green in the pre-battery suite on both platforms | 7a: composer draft UNTOUCHED; wake turn runs; pane capture proves no stomp; 7b: (i) green iff ordering proven by scrollback; (ii) is a measurement, either outcome recorded honestly (it attributes the real-path serialization mechanism: daemon turn queue vs helper defer); (iii) green iff the forcing test passes in the same battery run. **Row-7b's green claims exactly what each leg executed — no cross-attribution** (the pass-1 defect: a by-effect green misread as the defer layer running). |
|
|
33
|
+
| 8 | Wake-turn contract (by-effect) | inspect row-1/row-7 wake turns | turn text is the fixed `_shared` template (prefix, metadata only, no bodies); woken turn does read-only inbox fetch + summary; no send/mutation tools invoked |
|
|
34
|
+
|
|
35
|
+
**Census discipline:** before and after every row, `pgrep -fl` for helper + producer +
|
|
36
|
+
daemon; counts must match expectation; any stray process fails the row.
|
|
37
|
+
|
|
38
|
+
**Pass bookkeeping:** two consecutive full-battery greens, the second from a fresh sandbox
|
|
39
|
+
re-arm (not a re-read of the first's logs). Then: assay certification request with the log +
|
|
40
|
+
pane captures; gate-5 ship only after assay's 2/2 read.
|
|
41
|
+
|
|
42
|
+
**Teardown after battery:** daemon stop, helper stop, producer dead with it; sandbox
|
|
43
|
+
archived (never deleted) with the evidence bundle.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# QA companion — codex-hive-user-first-plan-20260814.md
|
|
2
|
+
|
|
3
|
+
**Specimen:** `codex-hive-user-first-plan-20260814.md` (v2), SHA-256
|
|
4
|
+
`d714cfd5aff76a3ddd24a3a523b49884732e68cf320d747478766e670db84cdd`. Bytes FROZEN by this
|
|
5
|
+
certification; any byte change resets the count and re-enters review through both reviewers.
|
|
6
|
+
|
|
7
|
+
## Certification — goal [28506] item (1) MET
|
|
8
|
+
|
|
9
|
+
| Pass | Reviewer | Verdict | Record |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| Co-author revision | argus | 1 blocking finding (§2b option-C trigger path) + 1 nit (named double-arm control) → folded in v2 | hive 7450 |
|
|
12
|
+
| Co-author pass on v2 | argus | **CLEAN**, banked on `d714cfd5` | hive 7452 |
|
|
13
|
+
| External QA on v2 | assay | **CLEAN**, same bytes, sha verified before and after read | hive 7454, assay record [28731] |
|
|
14
|
+
|
|
15
|
+
Lineage: skeleton co-proposed 7445, reshaped by argus 7446 (shared-seam section, arm-check
|
|
16
|
+
primitive spec, measurement criteria, location ruling). v1 sha `c3f1352c…` superseded by v2.
|
|
17
|
+
Derives from evaluation v3 sha `9d9f5076…` (its own 2/2 clean record) + Jason's sign-off
|
|
18
|
+
[28718] + arming ruling [28714] + doctrine [28680].
|
|
19
|
+
|
|
20
|
+
## Delegated decision, ruled during external QA (assay 7454 — mechanism, NOT a finding; count unaffected)
|
|
21
|
+
|
|
22
|
+
**Plan §6 row 5 (helper-death visibility, F4-assay):** the requirement is the **§4a
|
|
23
|
+
in-session state transition** (armed-live → catch-up-only, surfaced to the user).
|
|
24
|
+
Documented-degradation-to-B is acceptable **only on measured sandbox infeasibility of
|
|
25
|
+
in-session surfacing, with that measurement in the battery log** — never as a convenience
|
|
26
|
+
fallback. Binding on gate 4 (option-A sandbox battery) execution.
|
|
27
|
+
|
|
28
|
+
## Standing constraints at certification time
|
|
29
|
+
|
|
30
|
+
- No kijito-tools commits while the P0 freeze window holds (argus 7446 b; PR #14 was the
|
|
31
|
+
ruled exception). The plan lands at `providers/codex/plans/hive-user-first-plan.md` via
|
|
32
|
+
branch `codex/hive-plan-v1`, PR-only, sole-author commit discipline, after P0 close +
|
|
33
|
+
steward handover.
|
|
34
|
+
- Gates 2–7 of plan §10 are authorized by this certification and execute in order.
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# Codex × Kijito hive support — implementation plan (v2 draft)
|
|
2
|
+
|
|
3
|
+
**Status: DRAFT UNDER CO-AUTHOR REVIEW. No work is authorized by this document until it passes
|
|
4
|
+
two consecutive clean adversarial passes (argus + assay) per goal [28506] item (1).**
|
|
5
|
+
Co-authored from the first line with argus (skeleton approved + reshaped in hive 7446; codex
|
|
6
|
+
skeleton 7445). v2 folds argus's co-author revision 7450: §2b option-C trigger honesty
|
|
7
|
+
(C-i/C-ii split), §5 third measured dimension, §6 named double-arm control. v1 sha
|
|
8
|
+
`c3f1352c…` superseded. Destination after P0-freeze close + handover, steward's ruling (7446 b):
|
|
9
|
+
`providers/codex/plans/hive-user-first-plan.md` in kijito-tools, branch `codex/hive-plan-v1`,
|
|
10
|
+
PR-only, sole-author commit discipline (Jason author, no trailers/footers — ruling record
|
|
11
|
+
[28588]/[28566]). Until then this draft lives beside the evaluation it derives from.
|
|
12
|
+
|
|
13
|
+
**Sources of authority:** evaluation v3 `codex-hive-user-first-evaluation-20260814.md`
|
|
14
|
+
(sha `9d9f5076…`, two consecutive clean passes: argus 7417, assay 7418) · Jason's sign-off
|
|
15
|
+
[28718] ("with those refinements, I believe we're good") · arming ruling [28714] ·
|
|
16
|
+
fleet doctrine [28680] · session-is-the-subscriber ruling [28675].
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. Scope and non-goals
|
|
21
|
+
|
|
22
|
+
**In scope:** ship the signed-off recommendation — B+C as the default experience, option A as
|
|
23
|
+
per-session opt-in native live wake — and retire the old codex coordination stack from the
|
|
24
|
+
default path under the §7 teardown protocol.
|
|
25
|
+
|
|
26
|
+
**Non-goals, binding (doctrine [28680] §4/§6, eval §6):**
|
|
27
|
+
- No coordination machinery: no controllers, seat threads, mode registers, consumer locks,
|
|
28
|
+
exclusivity. Same-persona-in-two-terminals is explicitly not solved; two sessions of one
|
|
29
|
+
persona both fire.
|
|
30
|
+
- No reinvention of the producer. Kijito-monitor is the one client-agnostic producer, unchanged.
|
|
31
|
+
- No fleet-operator (P3) machinery in the default shape. P3 layers are a separate, later,
|
|
32
|
+
opt-in evaluation.
|
|
33
|
+
- No ambient subscription. A bare codex session is isolated; nothing arms it without
|
|
34
|
+
/kijito-start (arming model, §4 below).
|
|
35
|
+
|
|
36
|
+
## 2. B+C — the default experience
|
|
37
|
+
|
|
38
|
+
### 2a. B: prompt-time catch-up (works today; the floor everything degrades to)
|
|
39
|
+
|
|
40
|
+
- The codex `kijito-start` skill performs the same catch-up as the Claude Code shape:
|
|
41
|
+
`kijito_startup` → full read of the current-state pointer → recent lessons → one durable
|
|
42
|
+
inbox read. Zero new moving parts; latency = next prompt.
|
|
43
|
+
- Ship: skill text updated to the [28714] arming model (§4), including the loud degradation
|
|
44
|
+
wording. Docs: the Codex CLI page gets a config example (closing the "In testing" one-liner
|
|
45
|
+
docs gap, eval finding — see §8 sharp edges).
|
|
46
|
+
|
|
47
|
+
### 2b. C: count-only OS notification (opt-in config)
|
|
48
|
+
|
|
49
|
+
**Trigger honesty (argus 7450, blocking finding folded):** Codex's outbound `notify` hook
|
|
50
|
+
fires on CODEX'S OWN lifecycle events (turn-complete / approval — [28502]: notify is
|
|
51
|
+
outbound-only), NOT on mail arrival. A hook-wired notification therefore cannot deliver
|
|
52
|
+
mail-arrival latency, and this plan does not claim it. Two honest shapes, both spec'd:
|
|
53
|
+
|
|
54
|
+
- **C-i — hook-time check (ships with B as the true zero-ops default):** when codex fires the
|
|
55
|
+
notify hook anyway, the thin kijito-tools shim does a cheap unread-count peek and appends
|
|
56
|
+
the count to the notification. Honest semantics, stated in docs: notification latency =
|
|
57
|
+
codex activity, not mail arrival; zero new processes.
|
|
58
|
+
- **C-ii — watcher-driven (measured, not pre-decided):** a tiny OS notifier consuming the
|
|
59
|
+
SAME `_shared` doorbell seam (§3) and posting count-only notifications on mail events.
|
|
60
|
+
Honest cost: it IS a persistent consumer with the same lifecycle/quarantine obligations as
|
|
61
|
+
A minus injection — §4b pidfile idempotence, death visibility — and it is a second
|
|
62
|
+
always-on part, so it belongs in the §5 measurement scope (third measured dimension; it
|
|
63
|
+
pairs naturally with the supervised producer — a user running a supervised producer can run
|
|
64
|
+
a supervised notifier the same way). C-ii ships only if §5's measurements favor it.
|
|
65
|
+
|
|
66
|
+
Common requirements for both shapes:
|
|
67
|
+
- **Fixed template, exactly two variables** (argus 7446 reshape ii): `persona` and `count` —
|
|
68
|
+
charset-anchored in tests, the same fixed-template discipline the pane-wake nonce line
|
|
69
|
+
earned. No message content, no previews, ever, on any lock screen.
|
|
70
|
+
- **Dependency, named by freeze identity:** the producer-side body-free capability is the
|
|
71
|
+
monitor-foundation-v1 opaque-output row (**P0-F29/A29**, `--no-content`). C ships only
|
|
72
|
+
behind that capability or an equivalent proven body-free path; sequencing is ledger-visible
|
|
73
|
+
under that identity.
|
|
74
|
+
- Opt-in config only; ntfy remains entirely optional ([28479]). Default install: B alone.
|
|
75
|
+
|
|
76
|
+
## 3. The shared seam — written once in `providers/_shared`, inherited by every platform
|
|
77
|
+
|
|
78
|
+
(Structural section per argus 7446 a. Doctrine [28680]: the per-platform delta is ONLY the
|
|
79
|
+
last inch. Without this split the plan would quietly reimplement shared mechanics
|
|
80
|
+
codex-locally — the drift class loom's conformance gates exist to catch.)
|
|
81
|
+
|
|
82
|
+
**`providers/_shared` (platform-agnostic, OpenCode/VSCode/Cursor inherit):**
|
|
83
|
+
1. Doorbell stream consumption — locating and tailing the producer's per-persona events file
|
|
84
|
+
(systemd and launchd layouts both resolved by asking the filesystem, never assumed).
|
|
85
|
+
2. The certified event-kind filter constant — the `_shared` doorbell seam contract; never
|
|
86
|
+
re-derived per client (eval §3, F6-argus).
|
|
87
|
+
3. Idempotent-arm check logic — the check-then-arm discipline itself (the state machine;
|
|
88
|
+
§4b instantiates it for codex).
|
|
89
|
+
4. Producer-health delegation — "absent events file / silent producer is indistinguishable
|
|
90
|
+
from no mail" detection and loud-fail semantics (F2-argus).
|
|
91
|
+
|
|
92
|
+
**`providers/codex` (the last inch only):**
|
|
93
|
+
1. The `turn/start` self-nudge over the app-server daemon socket
|
|
94
|
+
(`$CODEX_HOME/app-server-control/app-server-control.sock`), incl. attachment detection.
|
|
95
|
+
2. The `notify`-hook wiring for option C (§2b).
|
|
96
|
+
|
|
97
|
+
## 4. Arming model — [28714] implemented
|
|
98
|
+
|
|
99
|
+
### 4a. The opt-in surface and the degradation ladder
|
|
100
|
+
|
|
101
|
+
Running `/kijito-start` IS joining the hive for that session. The arm is performed by the
|
|
102
|
+
agent following the skill — never a hardcoded hook — so conversational overrides ("start but
|
|
103
|
+
don't arm") work with no flags; the user's ad-hoc instruction outranks the skill default.
|
|
104
|
+
|
|
105
|
+
**Explicit states, each visible in-session (argus 7446: "silently degraded" must be
|
|
106
|
+
unrepresentable):**
|
|
107
|
+
|
|
108
|
+
| State | How entered | What the user is told |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| **armed-live** | /kijito-start, daemon present, helper armed + verified | "armed: live wake on this session" |
|
|
111
|
+
| **catch-up-only** | /kijito-start, daemon absent or helper precondition failed | stated plainly at arm time: what failed, that mail waits for next prompt |
|
|
112
|
+
| **isolated** | no /kijito-start this session | nothing — isolation is the default and a feature |
|
|
113
|
+
|
|
114
|
+
Transitions downward (helper death → catch-up-only) must surface in-session per the §6
|
|
115
|
+
battery (F4-assay); there is no silent state.
|
|
116
|
+
|
|
117
|
+
### 4b. The idempotent-arm check primitive (argus 7446 reshape i — spec'd, not just required)
|
|
118
|
+
|
|
119
|
+
The codex equivalent of the anchored-pgrep discipline:
|
|
120
|
+
- The helper writes an **owner pidfile bound to (session thread id)** in the codex runtime
|
|
121
|
+
dir, mode 0600.
|
|
122
|
+
- Arm-time check: read pidfile → is that pid alive AND is its bound thread id == this
|
|
123
|
+
session's thread id?
|
|
124
|
+
- **stale pidfile** (pid dead) → reap the pidfile, arm.
|
|
125
|
+
- **live + same thread** → skip (already armed; the idempotent case).
|
|
126
|
+
- **live + different thread** → **loud refuse** — surface to the user; never kill the other
|
|
127
|
+
helper (it may be another live session's arm; same-persona-twice is unsolved by ruling).
|
|
128
|
+
- Exactly-one per session lifecycle; consumers must not accumulate across session restarts
|
|
129
|
+
(the measured six-stacked-monitors class, eval §3).
|
|
130
|
+
|
|
131
|
+
## 5. Producer-install decision — by measurements, in the open
|
|
132
|
+
|
|
133
|
+
(Eval §2 P2 note + D1-argus: pre-deciding is forbidden. Criteria per argus 7446 reshape iii.)
|
|
134
|
+
|
|
135
|
+
**Candidates:** (A) session-scoped producer spawned by kijito-start, dies with the session,
|
|
136
|
+
catch-up covers gaps; (B) documented one-line supervised install (systemd user unit /
|
|
137
|
+
launchd), the current fleet shape. **Third measured dimension (argus 7450):** the C-ii
|
|
138
|
+
watcher-driven OS notifier (§2b) — measured alongside, since it is a second always-on part
|
|
139
|
+
that pairs naturally with the supervised-producer option; the same four criteria apply to it.
|
|
140
|
+
|
|
141
|
+
**Criteria, measured per candidate on a clean environment:**
|
|
142
|
+
1. Fresh-user wall-clock from docs to armed.
|
|
143
|
+
2. Count of user-visible moving parts (things that can be observed, need explaining, or can
|
|
144
|
+
break in view of the user).
|
|
145
|
+
3. Reboot / laptop-sleep survival semantics AND the measured cost of the gap — mail latency
|
|
146
|
+
to next catch-up when no producer runs.
|
|
147
|
+
4. Failure visibility — how the user learns the producer died (loud vs silent; time-to-notice).
|
|
148
|
+
|
|
149
|
+
**Decision rule:** whichever candidate wins on 1/2/4 without an unacceptable 3. No vibes; the
|
|
150
|
+
measurement log lands beside this plan. Supervised install remains the P3 opt-in either way.
|
|
151
|
+
|
|
152
|
+
## 6. Option A — native live wake, gated on the sandbox battery
|
|
153
|
+
|
|
154
|
+
Design (eval §5A): session-scoped helper, spawned by kijito-start, consumes the shared
|
|
155
|
+
doorbell seam (§3) and calls `turn/start` on this session's own thread over the local socket.
|
|
156
|
+
Daemon is experimental and off by default — `codex app-server daemon bootstrap` is a one-time
|
|
157
|
+
user opt-in step, stated in docs.
|
|
158
|
+
|
|
159
|
+
**Acceptance battery — 2/2 consecutive green passes in the sandbox
|
|
160
|
+
(`SideProjects/Codex/.qa-tmp/native-wake-probe-20260814/`, staged, untouched), every negative
|
|
161
|
+
control first-class:**
|
|
162
|
+
1. **Non-attachment detection**: a `-c`-overridden / --strict-config launch runs embedded
|
|
163
|
+
(no daemon attach, [28502] trap); the helper must detect and say so in-session — silent
|
|
164
|
+
no-op is a false green.
|
|
165
|
+
2. **Producer-silence loud-fail** (F2-argus, via the §3 shared delegation): absent events file
|
|
166
|
+
and down-producer negative controls; the helper pages/degrades loudly, never tails a file
|
|
167
|
+
that will never exist.
|
|
168
|
+
3. **Shared filter constant in use** (F6-argus, per argus 7446 c: in the battery, not only as
|
|
169
|
+
an eval citation): the helper consumes the certified event-kind constant from the `_shared`
|
|
170
|
+
seam; a probe event of a non-covered kind must NOT nudge; a covered diagnostic kind must.
|
|
171
|
+
4. **Helper lifecycle** (F3-argus): pre-nudge thread-liveness check, exit-on-thread-gone,
|
|
172
|
+
idempotent arm per §4b; kill-the-session negative control — no orphaned helpers firing into
|
|
173
|
+
dead or reused threads, no accumulation across crashes. **Named probe — the DOUBLE-ARM
|
|
174
|
+
control** (argus 7450): run /kijito-start twice in one session → exactly one helper, and
|
|
175
|
+
the second arm reports already-armed in-session (the six-stacked-monitors class gets its
|
|
176
|
+
own probe, not an implicit ride on §4b).
|
|
177
|
+
5. **Helper-death visibility** (F4-assay): helper death surfaces inside the session experience
|
|
178
|
+
(state transition to catch-up-only per §4a) or degradation-to-B is explicitly documented as
|
|
179
|
+
the accepted semantics — decided in this plan's QA, not left open.
|
|
180
|
+
6. **Defer-until-idle** (F5-assay, F4-argus): an alert landing mid-typing or mid-own-turn does
|
|
181
|
+
not stomp the user's work; defer-until-idle defined and proven as a first-class acceptance.
|
|
182
|
+
7. **Wake-turn contract**: probes are scored **by-effect** ([28458]): the woken turn's template
|
|
183
|
+
forbids send/mutation tools, so acceptance evidence = driver log + session capture showing
|
|
184
|
+
exact-row fetch/verify/summary — never a demanded reply-by-mail.
|
|
185
|
+
|
|
186
|
+
Ship shape after 2/2: per-session opt-in via kijito-start where the daemon exists (goal item
|
|
187
|
+
4); Jason's live-demo acceptance comes only after sandbox 2/2 (goal item 6).
|
|
188
|
+
|
|
189
|
+
## 7. Teardown of the old stack — §4 protocol, binding
|
|
190
|
+
|
|
191
|
+
Inventory being retired from the default path: headless controller / app-server seat
|
|
192
|
+
(controller pid at teardown time), mode register + consumer locks, mode-aware watchdog,
|
|
193
|
+
tmux pane-wake driver (already stopped), declared mode `codex.app-server-seat` (provisional).
|
|
194
|
+
|
|
195
|
+
Protocol (eval §4, F8-argus, F3-assay):
|
|
196
|
+
1. **Ledger discipline**: artifacts that are frozen ledger rows get disposition amendments
|
|
197
|
+
post-P0-close in assay-coordinated windows — never mid-freeze deletions.
|
|
198
|
+
2. **The alarm dies last**: the mode-aware watchdog outlives the machinery it monitors until
|
|
199
|
+
the replacement (B+C default, and A where opted-in) has two greens; nothing is orphaned
|
|
200
|
+
mid-swap.
|
|
201
|
+
3. **Archive-don't-delete**: retired components move to `legacy/` per fleet data-safety;
|
|
202
|
+
certifications archived, never deleted.
|
|
203
|
+
4. **Steward-held PRs**: every teardown change lands via PR under argus's steward review,
|
|
204
|
+
sole-author commit discipline.
|
|
205
|
+
5. Sequencing note: PR #14 (false-pager fix) merges FIRST (it fixes the alarm we keep running
|
|
206
|
+
until last) — it awaits only loom's freeze-evidence confirm; the deployed-artifact swap
|
|
207
|
+
runs under census discipline ([28440] class: verify by a page-relevant event, not process
|
|
208
|
+
liveness).
|
|
209
|
+
|
|
210
|
+
## 8. Carried sharp edges (fix-or-document, from the P1 walkthrough [28699])
|
|
211
|
+
|
|
212
|
+
1. **`codex exec` headless silently cancels approval-needing MCP tool calls** ("user cancelled
|
|
213
|
+
MCP tool call"); the fix flag `--approve-for-me` is discoverable only in `--help`
|
|
214
|
+
(0.147; `--full-auto` is not an exec flag). Plan: docs note in the kijito-tools codex
|
|
215
|
+
README + upstream issue candidate; evaluate defaulting the skill's exec examples to include
|
|
216
|
+
the flag.
|
|
217
|
+
2. **Headless OAuth has no timeout** — a headless `codex mcp add` that cannot open a browser
|
|
218
|
+
waits forever; docs note + guard suggestion.
|
|
219
|
+
3. **Docs stub**: kijito.ai docs list Codex CLI as "In testing" with one sentence and no
|
|
220
|
+
config example (Cursor gets one). Plan: ship the config block + skills example with §2.
|
|
221
|
+
|
|
222
|
+
## 9. Wrong-regime bounds sweep — run, clean (plan input closed)
|
|
223
|
+
|
|
224
|
+
Read-only sweep of kijito-tools main `c04d143` (method: comment-marker grep; full named
|
|
225
|
+
time-constant enumeration; raw-literal/setTimeout pass over controller, mode-register, cli,
|
|
226
|
+
wake-core; every consumer of `clientStatus.checkedAt` / `pollMs*4`). Result: the
|
|
227
|
+
`max(5s, pollMs*4)` readiness formula has exactly two consumers — `cli.mjs:454` (home regime,
|
|
228
|
+
arm-time readiness gate: correct) and `mode-liveness.mjs:62` (the PR #14 wrong-regime copy,
|
|
229
|
+
fix pending merge). No third copy. pane-wake heartbeat (5s beat / factor 6 / 30s floor) and
|
|
230
|
+
the claude heartbeat-watchdog (300s poll / 4 quiet checks) are original continuous-regime
|
|
231
|
+
calibrations. The [28720] class is contained to what PR #14 already fixes. (Record: codex
|
|
232
|
+
memory [28729]; argus notified 7447.)
|
|
233
|
+
|
|
234
|
+
## 10. Execution order and done-when (maps 1:1 to goal [28506])
|
|
235
|
+
|
|
236
|
+
| # | Step | Gate |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| 1 | THIS PLAN passes argus + assay adversarial QA | two consecutive clean passes; any finding resets |
|
|
239
|
+
| 2 | B+C default shipped (§2), incl. docs | assay-verifiable on a clean environment |
|
|
240
|
+
| 3 | Producer-install measurement (§5) executed, decision recorded | measurement log, no vibes |
|
|
241
|
+
| 4 | Option A sandbox battery (§6) | 2/2 greens, all negative controls |
|
|
242
|
+
| 5 | A shipped as per-session opt-in via kijito-start where daemon exists | after (4) only |
|
|
243
|
+
| 6 | Old-stack teardown (§7) | protocol order; alarm dies last |
|
|
244
|
+
| 7 | Assay certification of shipped mode 2/2; Jason live-demo acceptance | after sandbox 2/2 only |
|
|
245
|
+
|
|
246
|
+
Related gate [28485] (packaged-re-arm re-run) re-scopes in the open at whichever fires first —
|
|
247
|
+
packaging or this plan's teardown — coordinated with argus as steward at execution time.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"product": "codex-kijito-hive",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"persona": "codex",
|
|
6
|
+
"origin": {
|
|
7
|
+
"package": "kijito-tools",
|
|
8
|
+
"packageVersion": "0.1.4",
|
|
9
|
+
"repository": "https://github.com/KijitoAI/kijito-tools"
|
|
10
|
+
},
|
|
11
|
+
"live": {
|
|
12
|
+
"surface": "skills (deployed to ~/.codex/skills via install.mjs --skills-only) + native session wake helper (run from the checkout by kijito-start's arm step; never installed)",
|
|
13
|
+
"verify": "node providers/codex/install.mjs (default action; also runs before any skills deploy)"
|
|
14
|
+
},
|
|
15
|
+
"artifacts": {
|
|
16
|
+
"wakeCoreSha256": "5f7b57f71fd7ae96b303195c3671af0d410668b95f6a397c97cbec275992e412",
|
|
17
|
+
"workflowSha256": "e5f82d7aa18d3b652466d53ef89642d4dedb3ae05b0e13cea0e3d1882cb29496",
|
|
18
|
+
"planSha256": "d9d666b86ac06414f6e6a13a3e3e2115983a1dad44fcfded7eccc51b191fb451",
|
|
19
|
+
"wakeHelperSha256": "838f6b4462ba037a23a14b6fdb8dc34ee8b8f4a7df258b428832bc092fac3ea4",
|
|
20
|
+
"wsUdsSha256": "4da13eef89b572fb735e756cb06846a021919dec7f91c6d07989377944cc776c",
|
|
21
|
+
"wakeHelperTestsSha256": "f74c7aae6231132b47bf14b56cebee4a336ba13d094e75ecb2a928aaeecd99a0",
|
|
22
|
+
"wakeHelperIntegrationTestsSha256": "48f565dfe7e5b719903cd24b12ddfb3f17e1a16c532af397bfffcb39e4bfbe9b",
|
|
23
|
+
"wakeHelperMockDaemonSha256": "3406bcd46d913071c0ee293e30f46b42ad5cf8c5c77f70c4000d9bb37854dd0c"
|
|
24
|
+
},
|
|
25
|
+
"legacyArtifacts": {
|
|
26
|
+
"retired": "gate 6 of the hive-user-first plan (§7 teardown protocol), 2026-08-15; machinery teardown evidence at the operator seat's ~/.local/share/codex-kijito-hive/legacy/gate6-20260815T0643Z/ (rulings 7767/7768/7771/7783); files archived under legacy/codex-controller-era-2026-08/ except the recovery runbook, whose removal is the gate-6 marker (bytes in git history at dcce0bd)",
|
|
27
|
+
"artifacts": {
|
|
28
|
+
"authBindingSha256": "d61cb2184a1bf2741cde6ff9049450f37bdc2635bd80934ee87a9c97ade25e1a",
|
|
29
|
+
"controllerSha256": "8e07cb2912c4bcbd6fb0fa3aa97a9a9d8ae1124361eb1ab45ad968da251cdb7f",
|
|
30
|
+
"controllerTestsSha256": "c9c667937d16dce54e5d38a87151f8461c52414f9cdfa065d691c8468ad8991f",
|
|
31
|
+
"wakeRecoveryTestsSha256": "8aa376a379e182d25582e39dbdbb958d3f448badfff9e844767fe3f64fdda6bf",
|
|
32
|
+
"recoveryRunbookSha256": "d6f378f3cf60c7e038578993473a4b6624280b3050c06abe3d50a361d10ad3e6",
|
|
33
|
+
"releasePackagingTestsSha256": "d7478d0a004dad017bf471884e20bf5bbf7cf69a1da64cd293e5d2ce87d436f6",
|
|
34
|
+
"paneWakeSha256": "a467a5ef9437e8bdec932c01379c88b3eec71659e9a3dea29a237c1e45a53d80",
|
|
35
|
+
"paneWakeTestsSha256": "56c2d973cb5ce520397780f4e97aefa4eee8d1acd9181d8f7eb77e95d42ea97d",
|
|
36
|
+
"cliSha256": "c2f4395f08ed719f5fb03edbd3245cd8555cf231e75d87329a665da292e4ea0c",
|
|
37
|
+
"watchdogSha256": "e890dad2b7bf1b777fff48db76abf2532cb8779849bb16f2cde00bebc40c52de",
|
|
38
|
+
"watchdogTestsSha256": "8572a61ff277571e567bcf0ea8f7905f5eaea3c4c22695aff163c1c4cbc692f8",
|
|
39
|
+
"watchdogPlistSha256": "77dc2556f5d268601659dd4973288c909618f5bc47a4e49f1cd686f671143fac",
|
|
40
|
+
"postSubmitCaptureSha256": "1614bdee8e0291d72354ad5afe9dc15174c43b951da27aa47221eecf51229a13",
|
|
41
|
+
"postSubmitCapturePlainSha256": "95fc45b28a24e1ca0823e66b9852925aaff8e965a196c43b6ac1f8cba218a90d",
|
|
42
|
+
"idleTranscriptRulesCaptureSha256": "58df1a8ffc92c2263b83f724564ae9a5fafaa3f056b553f4bdffd6c569c7327e",
|
|
43
|
+
"idleV0147ToolTreeCaptureSha256": "00717237dc0d8c4ab556e4e893a181ecf2bd84771a83a5eb42b6e4ac1122f77d"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"forbiddenMechanisms": [
|
|
47
|
+
"lifecycle hooks",
|
|
48
|
+
"LaunchAgent",
|
|
49
|
+
"KeepAlive",
|
|
50
|
+
"current user thread mutation",
|
|
51
|
+
"message body injection"
|
|
52
|
+
]
|
|
53
|
+
}
|