Repository navigation
v6.1.0
The world outside a run. 6.1 lets an unattended run wait on what happens outside its own checkout,
and tells the truth about where its work stands. A wait can watch a job on another machine
(unit:<host>/<unit>), a date can stand beside a live ref as its backstop, a plan can raise its own
wait count, and the operator's own acts — a command to run, a click path to follow — form one queue
whose entries come due when their trigger lands. A run is settled only once its branch has landed on
the trunk, a manual gate is a person's alone, a session can no longer press its own console, and the
Issues desk reads a repository's whole issue list, each issue with its category, severity and plan
status. The free tree stays MIT. Nothing a 6.0 plan says stops working — what moved under people's
feet is below.
Migration
- A manual gate is a person's. A gate the plan marks
manualis never delegated to a session,
whatever thegatesrow says.gate-status.mdgains aDoorcolumn, and--gate-statushonours a
manual approval only when a person's door — the console's Gate card or a person's own terminal —
wrote it, so a row written before 6.1, which names no door, no longer clears its gate: approve it
again. - A run is settled only once it has landed. A run that owns a branch reads
finishedonly when
every repository'spe/<slug>, the root's included, is held byorigin/<trunk>; until then it parks
unlandedwith one merge errand, where 6.0 called it finished. Underlanding: holdnothing moves
the branch onto the trunk by itself. - A session cannot press its own console. A supervised session's HTTP client (
curl,wget,
http,xh) against a console's approval, policy, run-settings, gate or person's-step routes, and
its writes into the console's state or config directories, are denied before they run
(console-forge). A phase that must press one names that press's CLI form in the plan's
permission.destructiverow. - A §Verification line runs without
CI=1. The console no longer sets it, so a suite that changed
its behaviour onCIruns as it does in the session; non-interactivity comes fromNO_COLOR,
TERM=dumband a closed stdin, and aCIthe console itself was started with passes through. - A session's turn ends after its own agents. While a background subagent or monitor the session
launched still runs, the Stop hook refuses apartialorcompleteexit (twice at most) and names
the two ways out: wait for it in one bounded foreground call, or stop it and record what it was doing. - A new advisory lint, F39
setup-deps-missing, names a §Verification line that runs a package
script or a.venv/bin/*binary in a repository the phase's- **Setup:**installs nothing for.
Add the install to Setup; the lint never changes the exit code. - Update the console's scripts and the plugin together, as at 6.0: a 6.0.0
phase-outcome.shhas
no--actor--due-whenand knows nounit:ref, and a 6.0.0phase-graph.shhas no
--wait-countor--verify-inarm. - For readers of the vocabularies: a person's turn has a seventeenth kind,
operator-act, and a
ninth state,upcoming, first in the path; a run has a new halt kind,unlanded.
Added
- A wait on another machine's job (control-tower phase 121, #181). A new watch scheme,
unit:<host>/<unit>, asks a systemd unit on another machine whether it is still running — over ONE
shared ssh connection per host (ControlMaster, its socket under the console's state directory),
every 5 minutes — and lands the moment the unit leavesactivating/active, recording itsResult=
and exit time in the wait history. The host's address, user, key and port come fromhosts.<name>in
the machine profile~/.config/phase-console/fleet.json; a host not named there is refused, and none
of those details is written into a run record — ssh's own failure is told in fixed words of its class,
never its text. The master socket lives with the instance's state, or, where that path would overrun a
Unix socket's 104 bytes, in a private directory of the user's own under the system's temporary one.
phase-outcome.shrefuses a malformedunit:ref. - A date beside a live ref is a backstop (#181).
waiting-external --watch <ref> --watch date:<iso>
wakes the phase the moment the ref lands; the date only bounds the wait, and if it passes first the
phase is resumed told that the ref has NOT landed and what it last read (phase.waitingcarries
backstop). The script says which ref is the backstop when it records the declaration. - A plan raises its own wait count (#40).
**Wait count:** <n>in §Session budget, or
- **Wait count:** <n>on a phase (1–99), lifts the four declared waits a phase may spend;
phase-graph.sh --wait-count [N]reads it,wait-budget.sh [--phase N] --count <n>writes it. A park
on a spent count or a spent time budget whose watch ref still polls now reads as a WAIT on that ref —
the runwaitingon it, looked at again every six hours — never an errand to re-check it by hand. A
date:is a clock, not such a ref, and a ref the watch clock has refused for good no longer counts:
either way the park is a person's again, with itsbudgetserrand. The session contract states the
raised count and where it came from. - The operator's acts, as one queue (#182). A seventeenth human-step kind,
operator-act— an act
only the operator does, a command to run or a click path to follow — and a ninth state,upcoming,
first in the path: a step declared with a due-when ref is shown under Coming up, unannounced and
unreminded, its window not started, until that ref lands; then it is due with ONE notification,
NOW: <command>, and its proof landing clears it and resumes the phase that needed it. A session
declares one withphase-outcome.sh … needs-human --act --due-when <ref>; a plan with adue: <ref>
field on its- **Human step:**bullet, in a phase or under## Operator errands(the plan's own,
phase 0). Adue:that fits no scheme's shape fails the F37 lint by name. While an act is coming up
its park summons nobody — no needs-you push, no errand row — and a due-when ref the console refuses
makes it due at once, the refusal named; a frozen console asks no due-when ref at all. The approve page
and the Tower list Coming up after what is due, each row with its command to copy. New journal line
phase.human-step-due, loghuman-steps.due. - The Issues desk (control-tower phase 118). Repo ▸ Issues reads a repository's WHOLE issue list:
onegh issue list --state allwith a cap of 2,000 (ISSUE_LIST_CAP, asked one over sotruncatedis
measured, never assumed), withauthor,createdAtandclosedAtnow among the fields and still no
field that returns a body. Each issue carries what the desk reads off it, derived once in
viewer/shared/issues-model.js(categoryOf,severityOf,planStateOf,triageOf) and drawn
through the status family: its category (bug·enhancement·documentation·question·
other), its severity (aseverity:label, or none) and where it stands in a plan — needs a plan
(awaiting-plan), planned in<slug>phase N (plan:<slug>, with the phase a local plan'sFixes:
line names), deferred (plan:<slug>-deferred), fixed (closed, with a plan label). Every column sorts
and the sort is in the URL beside the new Category, Severity and Plan status filters. The repository
picker takes any GitHubowner/namean operator adds (prefs.issueRepos, at most 12), read and
refreshed like the estate and marked "outside this console". The palette's entry is "The Issues
desk", and the Plans page links "Plan from issues" to it. - The issue rubric's words (control-tower phase 114).
viewer/shared/issues-model.jsowns the
three issue types (bug·enhancement·documentation), the four severities worst-first with their
one-line meanings (critical — data loss, a security or permission bypass, an unapproved production
change, or every lane blocked; high — a run halts or parks, or reaches a wrong verdict, with no in-run
workaround; medium — time or money wasted, a workaround exists; low — cosmetic, wording, noise), the
lifecycle labelsawaiting-planandfrom-sessionwith theseverity:prefix, and the suggestion
words;scripts/issues.envis their bash twin, held word for word bygates-vocab.test.ts. - The docs say what 6.1 adds, in English and Persian (control-tower phase 122). The help sheet's
Halts section gains A job on another machine (theunit:watch and itshosts.<name>profile
entry) and its watch card the date backstop and the raised wait count; Your turn gains Acts that come
due later (operator-act, Coming up,due:,--act --due-when); Getting around's Repo card says
what the Issues desk reads off each issue; When stuck ▸ Parked explains a run that is done but not on
its trunk (unlanded). README and USAGE carry a 6.1 paragraph each and their Persian twins the same,
viewer/README.mdand its twin state the 6.1 wait rules, anddocs/loop.md's scheme table gains
unit:.
Fixed
- A temp-file save under
docs/no longer makes the console forget every plan (#244). An editor's or
an agent's atomic write reached the plan store as a change that named no plan, so the console forgot
every plan and read them all again, and hung while every board was derived anew. The watcher now drops
temp-file and atomic-save artifacts before they become a change, and a change forgets only the plans it
moved or named. - A plan card's repository tag keeps its width on a phone (control-tower phase 118, #203). At 360 px
a range estimate and the time filled the card's meta row, and the tag — the one part allowed to shrink —
gave way to zero pixels. The row now wraps the time onto a line of its own first, and the tag never
draws narrower than three characters. The e2e register gains a probe class,squeezed, for text a
layout gave a line's height and no width; without the fix it names the tag (span "app" ×2on the
Plans stop at phone-360), ande2e/baseline.jsonstays[]. - No test reaches the login keychain, and the suite's slow and flaky fixtures are mended
(control-tower phase 116, #200, #169).auto-recovery.test.tsRCV-10/ACC-3.2 registered a spare token
account on a realService, so every suite run wrote a token into the operator's macOS login keychain
and deleted it again — and went red whenever that keychain was locked.realExec
(server/accounts/credentials.ts) now refuses every keychain write, replace and delete in any test
process (NODE_TEST_CONTEXT,VITEST, a--testargv, orPHASE_CONSOLE_KEYCHAIN=0, which
test/state-sandbox.tssets for a file run with plainnode, andtest/spawn-console.tsfor every
console a test or the browser tour spawns — the tour's since phase 123) before
a child starts, with the fix in the sentence, andkeychainStorelets that sentence through rather than
"unlock the login keychain". A lookup still runs: a realServicejudges the machine login by its item.
Production carries none of these markers;testProcessinshared/instances.mjsis the one reading of
"a test process" for both belts.git-browse.test.ts's fixturegitis hermetic — no global or system
config,gc.auto=0andmaintenance.auto=falseas command-line config, the inheritedGIT_*
environment dropped — and a fixture command that fails reports.git/HEAD, the refs and the reflog
tail. G-DIFF builds its overflowing stat from 5 500 deep paths in onegit fast-import(5 s under load,
where it took 102 s). The runner suite'ssleepstub was never a Runner option, so RF-3 and two
connectivity tests waited out real 60 s backoffs; the harness now installs it, and the two boarding-pause
tests press inside the slow gate's window rather than 300 ms after the start. UP-3 pins the doctor's
Claude Code rows in the order phase 108 gave them (hooks, presence, skill),plan-fields.ts
accounts for--verify-in, and the eight files that boot a console wait about 60 s for it, not 5–10 s.
Phase 117 mended the two the release gate still met: BL-3 expects the suite's own priority plus the
baseline's nice, clamped at the kernel's floor, rather than an absolute niceness, so a suite started
niced passes; and PR-3 registers the free tree's one default slot rather than a second console its
one-slot registry refuses. - One
psper process in flight, so a busy console cannot run out of descriptors (control-tower
phase 123). The process probe's single-flight started a newpsbefore it looked for the one already
out, so it deduplicated the bookkeeping and not the subprocess: every ask on a stale sample spawned
anotherps. A presence backlog applied on a busy loop asked about 3,500 times about a few live pids,
eachpsheld three pipe descriptors until the loop could reap it, and once the process had about
10,240 open — macOS'sOPEN_MAX— every later spawn in it failedEBADF,gitandbashincluded.
That wassessions-presence.test.ts's cascade under whole-suite load (phase 116 met it twice in three
runs). A probe already out is now the refresh, and the awaited ask joins it. - A session cannot press its own console (control-tower phase 129, #218). A supervised session runs as
the operator's own OS user, and the console's write guard is a capability flag, its header and a
same-origin test — so onecurlcould answer the session's own permission card, strike a deny rule,
raise its run tobypass, approve a manual gate or prove a person's step. A new hook guard,
console-forge, denies such a call before it runs, on every profile and besidegate-forge: an HTTP
client the shell would run (curl,wget,http,xh) against a console's address with a mutating
method and a path inviewer/shared/door-model.js'sAUTHORITY_ROUTES(the approval cards, the
policy, a run's settings, the gate route,/api/write, a person's step's check and dismiss), the CLI
twins (phase-console run approve|deny), a wrapper whose text carries a console address and a fenced
path, and a write into the console's state or config directories by the file tools or a shell
redirection. A run's own checkout and a session's memory, which can live under the state directory,
stay writable; reads,/hooks/*, a session's message token, the skill's scripts and the operational
verbs pass; a press the plan'spermission.destructiverow names for the running phase passes. The
refusal names the declaration to make instead, and is journalledphase.tool-denied {rule: 'console-forge', verb}. AndPOST /api/write {action: 'gate-approve'}no longer takes a gate's door
from its body: an approval there goes through the gate route's own person test, so a manual gate is
refused to a script whatever door it claims. - Settled means landed (control-tower phase 112, #184). A run that owns a branch now reports
finished
with nothing outstanding only when every repository's run branch — each mirror mount, the root's
included — is held byorigin/<trunk>. The proof is tree containment asked in each repository:
git merge-tree --write-tree <trunk> <tip>writing<trunk>^{tree}, nevergit cherry; the local trunk
only for a repository with no remote copy (run.landing-proof). Anything else parks the rununlanded
— a new run-level halt kind — with one errand ("pe/x conflicts with main in a.md, b.md"), whose card
opens a merge errand tree; the read path never settles it tofinished, and Recover & continue proves it
again. Before, a hub run settledkeepand readfinished {outstanding: []}with its last two phases'
docs on an unpushed root branch that conflicted withmainin six files. Underlanding: holdevery
brief now says nothing moves the branch onto the trunk by itself. And untracked files never pin a mirror
mount at the prune: they move to the run'sstale-mounts/and the mount goes; a mount kept for tracked
edits is named in arun.errandwith its paths. - A squash-landed branch is re-seated (control-tower phase 112, #183). Once a release squash-merges
pe/<slug>and the trunk holds all its content (the same merge-tree proof), the console moves the branch
ontoorigin/<trunk>in the run's own checkout (run.branch-reseated, with the old tip and the proof).
It does this before its own verification of the phase and at every boundary, only on a clean mount, and
never under another lane. A mount a session detached on the trunk is re-seated rather than switched back
to the pre-squash tip. A dirty one'sisolation-refusednames that remedy instead of only "switch it
back or remove it". And a session'sgit switch --detach/git checkout <commit>inside its run's own
checkout is refused before it runs (run-tree-detach). Before, a release'stask drift:*lines could go
green only by detaching the mirror, and the next boarding was refused. - Retention leaves live trees alone (control-tower phase 112, #171). A tree whose run is live, or
whose mtime moved in the last ten minutes, keeps its last known size and is never scanned. At most one
duruns console-wide. Adupast its 30 s ceiling is ended through the signals ladder (SIGCONT,
SIGTERM to its group, SIGKILL after 2 s) and its tree is not asked again for six hours. Nothing is
measured while the one-minute load exceeds twice the cores. The runner's git probe no longer measures the
run it is driving. Before, threedu -skof one live mirror ran at once at load 279 on 14 cores, and
1,419 of 1,419 scans of a 14-repository mirror hit the ceiling without an answer. - Spend is corroborated at each model's own rates (control-tower phase 109, #202). The price table
had one row,opus, found by a family substring, so every Opus 5.5 session was priced at Opus 5's
rates and journalled a falsephase.cost-mismatchreadingunder(347 on one machine) — and a
doubled booking on the default model read as agreement. Opus 5.5 now has its own row ($4 input, $8
one-hour cache write, $0.20 cache read, $20 output per MTok) beside Opus 5's, matched by the whole
model id; a version with no measured row, or an alias that names none, is not priced and not
corroborated. P85's tokens price to $14.2217, the CLI's own figure. A model whose fresh sessions sit
at one ratio all day is announced once, asphase.cost-drift, and a session off that ratio is still
a finding. - A wrap-up keeps its lane (control-tower phase 109, #192). A phase that hands off
partialat the
console's wrap-up with its own work uncommitted in a shared tree now re-boards before any sibling
whose scope meets its own — ranked right after a person's re-board, and with its scope held for it
in the very pass that released its lane (phase.lane-kept). Before, the lane's teardown woke the
loop while the attempt was still settling, and a graph-ready sibling was admitted one second later
over the red WIP (ai-builder-v7 P13 past P7, on a console with #128's fix). - A session ends when its agents do (control-tower phase 109, #188). While a background subagent or
monitor the session launched still runs, the Stop hook refuses apartialorcompleteexit (twice
at most), with the two ways out: wait for it in one bounded foreground call, orTaskStopit and
record what it was doing under Outstanding. The 0.6× wrap-up notice names the live agents. One still
killed by the CLI's ten-minute ceiling after the handoff is named in the next attempt's brief — its
description, its last words and the paths it wrote after the handoff (phase.agents-killed). - A live lane keeps its handle (control-tower phase 109, #170). The input of a session that ended
its turn to wait on its own background subagent stays open, so a steer, an ask, a peer's message and
the wrap-up notice reach it; the turn after the agent reports closes it, bounded by the idle closer
and the CLI's background ceiling. A refused message now names the session's real state — "phase 6's
session (pid 7529) is running, but its input closed at 07:12:04Z (…)", or that it was adopted from
the run record with no pipe — never "no session is running". Every close is journalled with its
cause (phase.input-closed) and the lane view carriesinput: {open: false, closedAt, cause}. - A
/clearends the session it replaced, and a released lock holds nothing (control-tower phase
108, #172). ASessionStartfor a new session id in a process that other records name now ends
those records at once: the registry reads themended, superseded by the new id
(endedBy: successorwhen no end was reported), their waits closed, their messaging sockets
dropped and asupersededline on their event logs. A terminal a person/cleared therefore no
longer stands in the queue as the holder of the scope it used to work in. Only records last seen
within two seconds of the new start are ended, never another process's, and a/resumeof the old
id in the same process revives it. While that process runs, a lock it took is still never treated
as debris. Areleasein a session's own transcript now cancels its earlier lock calls for that
phase, and a claim whose lock has gone holds nothing after 60 s, so a released lock's scope no
longer lingers on the record. - Hold evidence counts only the tree (control-tower phase 108, #180). Writes under
~/.claude/**, another Claude config directory,~/.claude.jsonor the session's own config
directory are no longer evidence of touching the tree. A baregit -C <root> …no longer claims
the whole root, though a git verb in a repository under the root still holds it. The queue card
shows, under the terminal it waits on, what the hold rests on (held because it edited …), newest
first. - Every account reports presence (control-tower phase 108, #194). A session spawned under a
profile account runs with that profile'sCLAUDE_CONFIG_DIR, whosesettings.jsoncarried no
presence hook, so the registry never saw it and its lock could not be tied to a session. Each
profile workspace'ssettings.jsonnow carries this console's four presence entries and never the
login's other hooks: a person's own hooks are kept, a stale entry is refreshed, and a file that
does not parse is left alone and logged (accounts.workspace.presence-installed,
…presence-failed). A phase session on a profile now appears in the registry with its plan, phase
and run.phase-console doctorgains a non-blockingpresencerow over every pooled account's
config directory, whether the console is up or not. - The pre-session baseline is quick, visible and never a verdict (control-tower phase 105, #190,
#193, #173). A session no longer waits for its phase's baseline: what must be measured runs BESIDE
it in a clean checkout of the boarding head, niced and held by the machine-load guard, and the
session hears the result as a next-turn note; the verdict waits for a baseline still running and
compares against it as before. A red baseline line is run once and recordedred once (not retried)— the one recorded retry is the verdict's alone. A line any plan of the console measured
on the same tree, command, environment digest and directory in the last day is reused, named with
its source run and age. A phase in its baseline or itsSetup:is a lane on every surface
(baseline 9/10 · <line>with its clock), the header names it (running — P8 baseline 9/10, never
phase ?), and a read that does not know the run is live no longer paints itinterrupted: the
command's process is recorded on the run, and a lane whose lock its console keeps refreshing keeps
the runrunning. - A §Verification line runs in the session's environment, and ends (control-tower phase 106,
#195, #191, #185, #168, #196). The console no longer setsCI=1on the lines it runs — suites
read it as "this is the CI infrastructure", and a line green in the session was red every time the
console ran it; non-interactivity comes fromNO_COLOR,TERM=dumband a closed stdin, and a
CIthe console itself was started with passes through untouched. A red line keeps its failing
tests and the end of its output for a baseline as for a verdict — on the record, in the ledger,
in the session's baseline note and in the phase drawer. A clean export of a repository that is a
superproject's submodule now stands at its own path with the sibling repositories and the root's
files linked around it, so a line reading a sibling (../frontend) reads it; untracked files no phase
wrote, the phase's ownSetup:outputs and dependency directories no longer send a verdict to an
export at all; and a sibling an export cannot provide isenvironment, never red. A line that
fails within seconds because itsnode_modulesor.venvis not installed isenvironmenttoo,
with its tail, and the session is told to install the dependencies — and a new advisory lint,
F39setup-deps-missing, names a §Verification line that runs a package script or a
.venv/bin/*binary in a repository the phase'sSetup:installs nothing for, before any run
meets it.phase-graph.sh <slug> --verify-in Nreads a phase'sVerify in:. When a line's leader exits
while a process it left behind still holds its output, the line settles on the leader's exit code
after a two-second grace, the stragglers named and stopped; at its timeout the signal ladder now
reaches the whole process group even when the leader is gone, and a process that left the group
can no longer hold a line open.phase-outcome.sh … verifiedkeys a proof where the console judges
the line (PE_VERIFY_DIR, which the runner now gives every phase session, withPE_RUN_ROOT):
--inis resolved against the run root, never the shell's cwd, and a proof the verdict could only
refuse is refused when it is recorded, naming both trees. - A manual gate is a person's, and a cross-plan gate clears (control-tower phase 107, #174,
#167). A gate the plan marksmanualis never delegated to a session, whatever thegatesrow
says: the runner holds it, the boot prompt tells the session to stop and declare
needs-human --needs gates, and the inbox always raises it.gate-approve.shnow names its DOOR
from its own environment, never from--by—console(a person's press in the console),
terminal(a person's own shell),sessionorscript— refuses a manual gate from a session, a
script or anai-*approver, and records the door in a newDoorcolumn ofgate-status.md;
--gate-statusignores a manual approval a person's door did not write, the door-less row a
session once wrote for itself included, and says why. The console approves a manual gate only for
a person's press — the Gate card from a browser, a phone's signed Approve, a supervisor-chat act a
person confirmed — and logs anything else asgate.approve-refused. A session's own tools cannot
borrow a person's door either: settingPE_GATE_DOOR, or writing a plan'sgate-status.mdwith the
file tools, is denied before it runs (gate-forge), and a--noteor--bycarrying escapes can no
longer write a row of its own (the cells reach awk verbatim). Aplan <slug>:<phases>gate
reads the other plan's verified set whatever its separators, soplan other:10,11clears once the
other plan has verified 10 and 11 — it could clear only when exactly one phase was verified. - The approval judge reads a shell line as a shell does (control-tower phase 107, #189, #186,
#205). Permission rules match only the words a line would run: a quoted here-doc's body, an
interpreter's-c/-epayload and a quoted argument are data and match no rule, while a$( … ),
a backtick, a<( … ), a group, a compound, a shell's-cpayload, aneval's words and an
unquoted here-doc's substitutions are commands — and what the judge cannot read it matches raw as
well, so the deny wall is never weaker than before. A handoff written by apython3 - <<'EOF'whose
text mentionsgit pushno longer raises a person's card. A push the plan's
permission.destructiverow names is answered from the row beside read-only company — a read-only
$( … ), a$?,rc=$?— and the same push in a shape the row cannot answer as it stands (a
git add/git commitbeside it, a$( … )that writes, a branch the shell computes, a bare
git push, a push inside a here-doc or aneval) is refused at once, naming the bare form to re-run
alone, rather than left an hour on a card (phase.approval-reshaped); a card an automatic actor
settles under that answer no longer parks the run. A row's exceptions are read for the RUNNING
phase: "with these allow rows: Phases 4/17/22 —gh pr create,gh pr merge --squash --delete-branch…" grants those commands in phases 4, 17 and 22, announced as any manifest grant,
and another phase's card says which phases the row allows. The row answers the publishing act
alone: a command beside it that the run would ask about on its own is never carried past the ask
list (the call is answered at once with the bare form), a form the row names with options is that
form (--adminbeside--squash --delete-branchis a card), and a push goes to a remote the
checkout names, never a URL or a path. What runs is what the row answered: a publishing command with
an environment in front (GIT_SSH_COMMAND=…,GH_HOST=…,env) or git's own options before its
verb (-c …) is a person's card, a push goes toorigin, and a line that also assigns, changes its
shell (export,alias,source…) or defines a function is answered with the bare form. The
reader also follows bash on here-doc delimiters (<<E"OF",<<END!), an unclosed here-doc,$[ … ]
arithmetic, ANSI-C quoting ($'git' push) andcoproc. A here-doc OWNER that is a shell in a quoted
or escaped spelling —"sh" <<EOF,b\ash <<EOF,s""h <<EOF— now reads its body as CODE as bash
does, so agit pushthe shell runs there meets the wall; deciding by a raw-text regex alone had
called that body data and let the push through. - An orphan is a session the live console did not launch (control-tower phase 110, #175). Each
session's record now names the console that launched it — its pid and the instant it booted — and a
run is parkedorphaned-sessiononly when that console is gone (the pid exited, or a later boot
holds it), never because the record went quiet or a reader did not know the run was live. The hourly
sizing census read every run file as if nothing were live, and parked the runs its own console was
driving — on disk, once an hour, with no journal line. Every run-file read now says which runs are
live, a real orphan park is journalled (run.orphaned), and a start beside a session this console
launched is refused, naming its pid and phase, instead of parking it. - A heal acts on the run as it is now (control-tower phase 110, #178). A healer pass re-reads the
run after classifying — the slow part — and again before it climbs or launches anything, and drops
itself (run.heal-dropped) when the run is live again, a phase holds a newer attempt than it read,
or the stop was resolved meanwhile. What a pass records is merged onto the record as it stands, never
its whole copy saved back; a dropped pass writes nothing, and converge keeps no fingerprint for it
(run.convergecarriesstale: true). An operator's Retry had boarded attempt 3 while a heal read
attempt 2 for five minutes and then saved that copy over the live run. - A parked run whose plan gains ready work comes back (control-tower phase 110, #176). Resume
continues a parked, halted or interrupted run through the one start door with its own settings — it
refused every one ("No pause … Continue brings it back") — and an automatic press never lifts a halt
only a person may, a person's stop or a person's dismissal. A dismissal records who made it and what
the board read ready then: a script's is worded as a script's ("dismissed by a script, not a
person"), and converge relaunches the run once work turns ready after it, while a person's still
pins the run and now names the ready work it holds back. A hub run sat parked for 6.6 hours with a
ready phase behind a watchdog's dismissal recorded as the operator's. - An API safeguard false positive is not the model declining the task (control-tower phase 111,
#177). The banner "safeguards flagged this message … This sometimes happens with safe, normal
conversations" classifies assafeguard-flag, read off the API-error channel or a stop that was a
refusal or an API error — never off a successful session quoting it. The phase is boarded FRESH with
the resume brief (resuming would re-send the flagged message), then fresh again — or on the next
model under aladdermodel policy — and only the third flag asks a person: "the API's safeguards
flagged the session (a false positive is likely); two fresh sessions were tried — report request
req_…".phase.safeguard-flagcarries the classifier, the request id and the message id. A twenty-hour
run had parked on "the model declined the task". - The in-turn clock guard judges a wait by its subject (control-tower phase 111, #179, #206). A loop
on nothing but the clock is the session's own job, whatever its line runs afterdone, and a URL the
summary's cap cut before its host was whole names no remote host — P34's fixture window had been
checkpointed at minute five as somebody else's clock. An external-clock wait is now nudged first and
parked only if the call is still open five minutes after a nudge the session received; a park on a
clock loop is bounded by the loop's own target instant; the phase lifecycle names the watchdog as the
actor (stop.kind: watchdog), neverdeclared; and a person's Continue on a run waiting on parks
cuts a watchdog window short, and a declared one whose ref has landed — asked at the press — or says
why not when the relaunch could only park it again (phase.wait-cut). It had answeredrunningand
the run parked again 72 s later. Time a call spends held on a person's approval card is credited back
to its wait, a window closes when its call returns once the session is in another wait, and while the
session's own background tasks run an external wait takes the own-job rungs, so a checkpoint no longer
ends them (two release preflights had died with one) — and a park that does end them names them. - A CI run GitHub never started is not a red CI (control-tower phase 111, #166). When a watched run
endscompleted: failurewith every failed job unstarted — no runner, no step — under the "job was not
started … spending limit" annotation, the probe readsnot-run (billing): the wait stays open, ONE
errand names the repository's Actions budget and its consumed amount when the token can read them,
and the Tower draws one "CI refused (billing)" line per repository, however many phases wait behind
it. When the budget is read again with room, the ref lands and the phase resumes with "re-run the
failed jobs (gh run rerun <id> --repo <repo> --failed)", watching the same ref, which follows the
run's newest attempt. Four sessions of one plan had been sent to fix a CI that never ran. - A keychain proof is a watch verb (control-tower phase 111, #201).
security find-generic-password
andfind-internet-passwordare commands the judge accepts — attributes only:-wand-g, which
print the secret, and every othersecuritysubcommand stay refused, each with its reason. The plan's
own E5.1 proof and the human-steps fixture's declare as written, with no wrapper script. - Recheck on a declared external wall asks the wall (control-tower phase 111, #204). The card's
recommended verb ran the three done-checks, which a phase waiting on the outside world can only fail,
and re-judged the wallfailed/no-handoff. It now probes the declaration's watch refs through the
watch clock: a landed one resumes the phase's own session exactly as the scheduler's landing does, and
otherwise onerun.recheckline names each ref and what it read, the wall left as it was.