Version. 0.1
Date. 2026-08-20
Status. H0's work streams are closed. This is the state of the runtime, not a plan. Every criterion below is stated as true or false of the running system, per loomworks-standing-note-we-do-not-build-for-demonstration-v0_1.
Engine. main at 22bec5d. Alembic head 0114. Suite 3909 passed, 68 skipped, 0 failed; ruff clean; mypy 536 errors, all covered by the 336-entry baseline, baseline file unchanged across the whole of H0.
| Stream | CR | Engine |
|---|---|---|
| W7 — the system actor kind | CR-2026-226 (+ amendment v0_1) | 1b850d5, fresh-chain fix b606309 |
| W1 — sessions for native agents | CR-2026-227 v0_1→v0_6 | items 1–3 720aa06 (merge 2ff25e3); items 4–12 53eccd7 (merge 2010d75); item 10 39733d9 (merge d275df6); Q5 0c1bf80 (merge 5c0eeea) |
| W2 — grantability at the front | CR-2026-229 v0_1 | merge f786b83 |
| W4 — presence and the silent session | CR-2026-230 v0_1 | merge bb2c806 |
| Own-key ungated path | CR-2026-228 v0_1 | merge e951e60 |
| Closing (invariant intent comments) | — | merge 22bec5d |
Migrations added: 0112 (actor_kind widening), 0113 (agent_identities, seeded), 0114 (agent_sessions). All apply, downgrade and re-apply cleanly on dev and test databases.
Not opened, by direction: W3 (envelope), W5 (workspace), W6 (session events as boundary records), and the per-binding session minting scoping item.
test_h0_end_to_end_traversal — passing. All seven steps against the runtime in one test: mint → work → warn → stop → freeze → unfreeze → walk. The walk asserts one identity, four sessions, four distinct ends (abandoned, signed_out, killed, live).
It traverses the shaping path, because shaping is where the identity model is complete. The render path cannot be traversed: it mints no sessions. That is a property of the runtime, recorded in §4 and in two standing notes — not a choice about what is easier to run.
> Every agent action at the named chokepoints carries (agent UUID, session id); an unlabeled agent action is impossible, not just unusual.
True on the shaping path. An agent action reaches the spend chokepoint carrying its agent UUID and its session id, and cannot proceed without both — UnlabelledAgentActionError raises before the model is called. Every path through gated_room_complete is gated; the own-key hole in O1's coverage is closed for all callers.
False of the runtime. Cause: the render path presents no agent to the chokepoint at all. A render specialist acts under a per-binding identity from render_specialist_binding (migration 0045), mints no session, consults no grantability check, and passes no agent_actor_id.
Why it is not a patch. Two identity grains do not line up — sessions mint per role, specialists hold identity per binding — and the SEED ruling, correct on the evidence available, does not reach actors created at runtime when an operator declares a render type. loomworks-scoping-per-binding-session-minting-v0_1.
> Freezing an identity refuses its next session request and ends its live session — demonstrated end to end, with the human-only, confirm-step unfreeze.
The mechanism is true and tested end to end. freeze_agent_identity sets status='frozen', ends every live session of that identity, and reloads the roster so the next check_grantability refuses — instant, machine-permitted, cascading. unfreeze_agent_identity requires a human actor and a non-empty rationale; a machine cannot reach past it under any condition.
The scope clause is part of the sentence, not a caveat: it holds on the shaping path. Freezing the rendering identity returns successfully and stops nothing, because no render specialist consults that identity. A control that reports success without acting — the sharpest form of §3's acceptance-1 falsehood, and the reason loomworks-standing-note-h0-tightening-guarantee-and-its-scope-v0_1 exists.
> "Which agents are running right now" is one query; a killed-without-signout agent produces exactly one silent-session event after grace.
Second half — true. A session unheard for 3 missed beats (30s) is alarmed once and ended as abandoned. Deduplication is per identity over 5 minutes, so a crash-restart-crash agent produces one alarm per window rather than one every thirty seconds. A suppressed alarm still ends its session.
**First half — it is one query, and it does not answer the question. get_live_sessions returns agents that hold sessions. A running render specialist holds none and is therefore invisible to it.** So the query truthfully answers "which session-governed agents are running" and is read as answering "which agents are running." Same cause as acceptance 1.
Known limitation, stated: the dedupe ledger is process-local, so N scheduler processes could emit up to N alarms per window. The sweep itself is concurrency-safe — sessions end with a conditional UPDATE — so the failure mode is duplicate noise, never a missed alarm or a double-ended session.
> A session's full story (grant → actions with verdicts → sign-out) reads as one thread from the record; the same agent's story across sessions reads by its UUID. Independent records, one identity.
Second half — true, and it was not true before H0. Agent identities are seeded and resolved, so a UUID is stable across process restarts. Two sessions of one role read as one identity, two threads. Before H0 the render dispatch agent minted a fresh UUID per process and the seed-induction agent per request, so this was unachievable at any grain.
First half — false. No action carries the session id into the record. The session id travels to the spend chokepoint at runtime and is discarded there; nothing persists it. AgentDecision.session_id exists as a field and nothing populates it — the one construction site (agents/retrieval.py:136) does not pass it.
So a session's story in the record is grant → sign-out, with no actions in between. The mint, the end and the reason are durable; the work is not linked to them. Writing actions into the session's thread is W6's scope (session events on the record), which was not opened.
This is the least visible of the four falsehoods and worth stating plainly: the labelling invariant makes an unlabelled agent action impossible at the gate, but the label is not written down. Enforcement is real; the audit trail it implies is not yet there.
5 (zero stored agent credentials; zero unnamed cross-run agent state). The first half is true and structural: agent_identities has no column capable of holding a secret, contributors forbids an agent bearer token by constraint (ck_contributors_token_presence), and no credential is created anywhere in agents/ — asserted by test. The second half depends on the W5 inventory, which was not opened.
6 (every W6 event has its FORAY call site; the traversal runs clean). The traversal runs clean (§2). Six call sites are registered at standard priority — agent_session_minted, agent_session_closed, agent_session_refused, agent_session_silent, agent_identity_minted, agent_identity_frozen — with the emitter still a no-op by design (O7). W6 itself was not opened.
One cause produces three of them. Acceptance 1, the substance of 3, and acceptance 2's scope clause are the same fact seen from three sides: the render path is ungoverned by sessions. It mints none, so it labels nothing, appears in no live-session query, and is unreachable by freeze.
rendering identity has no effect on render work.The fourth is independent. Acceptance 4's first half fails for a different reason: the session id is enforced but not persisted. Its cause is that writing session events into the record is W6, which was not opened. Nothing about the render path affects it, and closing the render path would not close it.
These are as much the output as the code.
Change requests — loomworks-record/change-requests/
cr-2026-226-w7-system-actor-kind-v0_1.md + -amendment-v0_1.mdcr-2026-227-w1-agent-sessions-v0_1.md … -v0_6.md (six versions, all siblings)cr-2026-228-own-key-ungated-path-v0_1.mdcr-2026-229-w2-grantability-v0_1.mdcr-2026-230-w4-presence-v0_1.mdloomworks-cr-brief-h0-native-habitat-v0_1.md (the work order)
Standing notes — loomworks-record/standing-notes/
loomworks-standing-note-runtime-direction-v0_1.md — the O1–O10 screen every CR carriesloomworks-standing-note-we-do-not-build-for-demonstration-v0_1.md — the vocabulary correctionloomworks-standing-note-h0-tightening-guarantee-and-its-scope-v0_1.md — the guarantee with its scope clauseloomworks-standing-note-a-test-that-pins-a-literal-cannot-follow-a-ruling-v0_1.mdloomworks-standing-note-migrations-and-the-code-that-runs-at-another-time-v0_1.mdloomworks-scoping-per-binding-session-minting-v0_1.md — open scoping work
Investigation — loomworks-record/investigations/
loomworks-boundaries-arc-cc-investigation-findings-v0_1.md and -v0_2.md (siblings)
Boundaries side — boundaries-record/
decisions/boundaries-dr-01-amendment-agent-identity-v0_1.md (+ .html) — the agent_identity termdecisions/boundaries-seed-ratification-list-v0_1.md — SR-1 (per-engagement freeze), SR-2 (the completeness pattern)arc/briefs/loomworks-boundaries-note-freeze-blast-radius-v0_1.md and -v0_2.md (siblings)arc/briefs/loomworks-boundaries-step5-report-inputs-v0_1.md — six instances of the build-surfaces-what-review-cannot patternarc/briefs/loomworks-handoff-step-4-v0_1.md — the work order that opened the lane2026-09-09 is defended for H0 complete and traversable end to end. It is a forcing function, not an event. As of 2026-08-20 the four narrowed work streams and the own-key CR are closed, and what stands between the runtime and its acceptance criteria is stated in §4 rather than scheduled here.