Commit graph

6 commits

Author SHA1 Message Date
9bbfe9facd docs(focus): record what shipped against the condition it was permitted under
The decision file was written before any code existed and said so in its
opening line. That line is now false, and the fix is not to delete the tense
but to name it: everything above "What shipped" is the record of what the
feature was ALLOWED to be, and the closing section reports what was built
against it.

Also records the one thing the decision could not have known, because it was
found by reading the consumer's parser rather than assuming it: paragraph mode
discards any block without tab=, so neither a '#' comment nor a bare key=value
in the header ever reaches the driver's records.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186vKCzuUEN5WcJB82kddzF
2026-08-02 20:02:44 +02:00
f9d2c927ab feat(board): give --plan a focus cutoff that reports what it held back
--focus "<prose>" narrows the day plan to repos whose STATE.md DECLARES a
matching topic marker. Measured on the real tree: 26 blocks to 6.

The filter alone was never the feature. --plan documents that it takes one
position (the order), hides nothing, and labels what it cannot rank rather
than dropping it, so a silent cutoff would break a property the format had
already written down. The same run prints the slugs the prose resolved to,
how many blocks it removed, the repos that MENTION a resolved slug with no
marker line - named, not counted - and how many STATE.md it searched. Each
surviving block carries the declaration it survived on.

Enumerated rather than counted because the decisive find behind this feature
was invisible to every string measurement until the held-back population was
listed. "nevner", never "dekker": this reports text found, and board.sh has
no grounds for a claim about relevance. The slug vocabulary comes from the
scanned STATE.md themselves, so the "no other file" invariant survives.

Emitted as key=value, not '#' comments: the consumer's parser runs in
paragraph mode and drops any block without tab=, so a comment would reach the
operator on the terminal path and vanish on the driver path - the one case
where the cutoff is applied unseen.

board-selftest 89 -> 113. The narrowing check is comparative, since every
presence-only assertion passes against a no-op filter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186vKCzuUEN5WcJB82kddzF
2026-08-02 19:58:25 +02:00
cb77f2889d docs(focus): record the condition --focus rests on, before it is built
A cross-repo exchange settled that --plan may grow a --focus filter only if
the same run reports the repos it held back. The decision constrains a future
feature, but it lived only in a private mailbox and a local-only STATE.md, so
nothing durable pointed at it.

The argument is an invariant, not a preference: --plan documents that it has
no cutoff and labels rather than drops, and --focus IS a cutoff. Measuring the
held-back population also turned up the find that carries the decision - a
heavy consumer of the subject, invisible to every strict-marker measurement in
the exchange, recovered only by enumerating what the filter would have hidden.

Other repos are unnamed by design: this mirror is public, and which repo
carries which malformed marker line is that repo's business.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01USD9q3Fr2unp58fe8YvapW
2026-08-02 18:42:45 +02:00
4080e22abd docs(ghostty): a ghost surface is detectable in one property read
The measurement identified realized surfaces by counting shell processes, which
is what was available while probing. morning-driver, building against this
document, found a cheaper and stronger test in the sdef: `working directory` is
readable on a terminal, and a surface with no shell process reports it EMPTY -
exactly the ghost signature the broken creation API produces.

That turns "has this surface been realized" from an inference into a
machine-checkable question, which is the guard anything driving Ghostty needs
before it types into a pane.

The same property answers one of the document's own open questions: it goes
empty when a shell exits and returns when the prompt is back, so "has this pane
returned to a prompt" can be polled rather than guessed at with a delay.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011eKRzhD1RqY2MxvDEkrJAM
2026-08-02 15:57:27 +02:00
5d9c76763d docs(board): measure what Ghostty 1.3.1 can actually be driven to do
The gate question before any day-plan design: can Ghostty be scripted to open
a tab with two vertical panes, each in its own directory, with a command
running in one? Measured against the installed 1.3.1 rather than reasoned
about, because this is undocumented platform behavior.

Yes, but not through the documented API. new window / new tab / split return
correctly shaped objects that never spawn a shell - nine probe windows, shell
count flat at 29 - and every call that needs the process fails with "Terminal
surface model is not available". That is issue #12730, a 1.3.1 regression
closed as not planned, and 1.3.1 is the newest release. surface configuration
is collateral: all four of its useful properties ride that path.

What does work is perform action on an ALREADY REALIZED surface. new_tab and
new_split produce live shells (29 -> 31), and input text + send key drives
them - two panes cd'd to different repos reported distinct directories and
distinct PIDs. The working directory becomes a typed cd, so the broken path is
not needed at all.

Three constraints fell out of the measurement and are recorded because each
was found by breaking something: pane targeting must diff tab ids, since
last tab of w is not the new tab and a probe that trusted position typed into
a tab it did not create; new tabs inherit the anchor's directory; and
count of terminals is not a pane count.

Recommends splitting the work - the plan here as a third rendering of the
board scan, the Ghostty driver in a separate repo. The argument is the
measurement: a preview API that breaks in 1.4, whose documented path is
already broken, with a blast radius reaching into other repos' live sessions,
does not belong behind the mailbox.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GfDGWyyhnM26J4p93GSk2L
2026-08-02 06:15:47 +02:00
1d62b073f8 fix(engine)!: identity is derived, never invented
Four defects that all reduce to the same thing: the engine trusted a name it
had no business trusting.

_broadcast is now a reserved namespace, not a repo. coord-send guarded
retraction with a sender check, but that guard only covered the door it was
nailed to: `coord-done --repo _broadcast <file>` walked in the side entrance
and archived a broadcast out of the queue - a full unauthenticated retract of
an announcement for every repo that had not read it yet. The rule reserves the
whole `_` prefix rather than one literal, so a later `_seen` or `_config`
cannot reopen the hole, and it is enforced in every CLI: a rule held in three
of four places is not a rule.

The pwd fallback is gone. It existed so the CLI would work anywhere, but
"anywhere" includes every global surface: a session in ~/repos is not a repo,
and basename(pwd) silently handed it the identity "repos". That is not
hypothetical - mail was delivered under exactly that name. git toplevel or an
explicit --from/--repo are now the only two sources. The write paths refuse
and say so; the read path declines silently, because the hook runs it at every
session start and must never fail a session.

Two checkouts with the same directory name still share one mailbox - re-keying
identity would break every existing mailbox and the readable `--to <repo>`
addressing. Instead the first git-derived read records the claiming path in
<repo>/.origin, and a read from elsewhere is warned about in the injection. A
warning, not a refusal: the same repo moved or re-cloned is the ordinary case.
The warning goes in the injection because the hook discards stderr, and a
warning nobody can see is not a warning. The collision is live in this tree:
claude-code-100x is nested inside a repo of the same name.

Broadcast delivery is recorded only after the injection is written. Marking
inside the read loop left a window where the seen set said "delivered" while
the operator saw nothing, and the hook runs under `timeout: 10`, so the window
was reachable. A lost broadcast is unrecoverable by design - the seen set is
delivery history and retraction deliberately leaves it alone - so the failure
mode has to be redelivery, never loss.

The hook stops resolving identity altogether. It was the fourth copy of the
rule and the only one that runs in production, so passing --repo bypassed the
engine's guards exactly where they mattered and suppressed the collision check
along with them. It is now the pure wrapper the boundary rule always claimed
it was, pinned by two behavioral tests rather than by reading the source.

Selftest 93 -> 116; three node tests cover the hook.

BREAKING CHANGE: coord-send and coord-done exit 2 outside a git repo instead
of naming themselves after the working directory. Pass --from/--repo to choose
an identity explicitly. Repo names beginning with _ are refused everywhere.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U6EixQo6hpoRCVtiAXdnFs
2026-07-25 20:34:43 +02:00