Commit Graph
9 Commits
Author SHA1 Message Date
pastilhasandClaude Fable 5 bd9d26199f the ephemeral pane is open when it exists, not when an effect says so
Refresh on /files/...?view=x.m4a came back with the query string intact and no
viewer, and then double-clicking the file did nothing at all. Two symptoms, one
cause, and the second is what made it read as a click bug.

WorkspaceView gave the pane defaultSize={0} and opened it from an effect calling
panel.resize(), so open/closed was expressed twice — the markup said closed and
the effect was meant to correct it. A correction step can be missed, and this one
was: on a deep link isEphemeralOpen is true on the first render, but
workspace.isLoaded is false until /dashboards answers and the early return means
nothing is rendered, so the effect ran against a null ref and returned. Its deps
were [isEphemeralOpen, defaultBaseSize] — one already true, the other a constant
— so it never ran again. URL open, pane at zero width.

Then the inert double-click follows for free: ?view= already held that name, so
setSearchParams changed nothing, so there was no transition for the effect to
react to. The URL being already correct is exactly why the click had nothing to
say.

Now the pane is rendered conditionally with id + order — the same pair
WorkspaceRenderer already uses — and both panels take declarative sizes. There is
no moment where markup and intent disagree, and a deep link is right on first
paint rather than corrected after it. The try/catch that guarded resizing an
unlaid-out group goes with it; nothing calls resize now.

ephemeral-pane.test.tsx asserts the SIZE the group computes, not that the element
exists — a pane at zero width satisfies any is-it-in-the-document check, which is
the failure being guarded against. Five of its six tests fail against the old
implementation, including the load-order one. Full suite: 1316 pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 21:11:15 +00:00
pastilhasandClaude Opus 5 530e5880e1 todo: what tonight's deploy work left behind, and two items it closed
Closed:

- fleet/an-orchestrator-that-acts-on-every-server-at — built, and as none of the three shapes it
  proposed. Not a script, not a screen, not a chat capability: an agent handed a written procedure and a
  server list it has to read rather than one baked into it. All three verified facts in the item earned
  their place; two things it did not anticipate are now new items.
- fleet/a-way-to-mark-a-commit-this-one-ships-so-a — built as a TAG, which the item explicitly ruled out.
  The owner reversed it, and the argument that changed his mind is recorded: a codeword can be written by
  accident, because every document about deploying contains it, so the trigger needs rules about where in
  a subject line it sits and a rule like that is one somebody eventually gets wrong.

Opened, all from tonight and all with the evidence attached:

- a deploy verifies pm2 and not that the app serves anything — the commander raised this against itself
- the commander cannot finish its own host, so one machine is always a build behind
- the watcher loop is rewritten by an agent every arming, so its correctness is re-rolled each time
- plugins:update restarts every sidecar, so a report naming only officer understates what moved
- an agent spawned by a background job is invisible in the UI while being perfectly readable
- AskUserQuestion can fail to parse its own call
- a commander opened from /chat loses its commander controls, because isCommander comes from the screen
  rather than the session

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 20:27:00 +00:00
pastilhasandClaude Fable 5 44f6c6d6ac todo: group the url and query-string items into one theme
files-app becomes url-state: the file browser is where the work happened, but where
selection lives and who clears a query string are framework questions. The panel
framework's version of the same question moves in beside them, extracted from the
deep-read item, which keeps it as one of its three questions.

Item ids changed with the theme. Done now deliberately — no board reads them yet, and
this is the last cheap moment to move one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 16:40:39 +00:00
pastilhasandClaude Opus 5 ff7358188d sub-agents: a spawn cannot take the last of a window
The failure this prevents is specific — a sub-agent burns the end of a limit window and the session the
owner is actually sitting in dies mid-turn, because the credits went somewhere nobody was watching. So
it is a condition on spawning rather than a refinement: an endpoint that can start unattended work
without checking is wrong from its first call, and the symptom lands on someone else's conversation.

Wired into POST /command-hq/commanders/new, which — this is the finding — already IS the spawn
mechanism the sub-agents item was asking for. It starts a turn with ws: null, waits only for
session:claude, and returns the transcript id, with command_hq_sessions naming, listing and costing it.
So "commander or something lighter" answers itself: a commander costs nothing extra and a lighter thing
would need its own registry to be visible at all. What is still missing is only the agent-callable
surface.

Refuses rather than queues or downgrades. Queueing means holding work against a window Officer does not
control, and the reset it would wait for is a claim about a shared pool — every claude on the machine
spends these, including terminals and pipelines. A refusal naming the window, the percentage and the
reset is something a caller can act on now.

The floor is 15% and the reasoning is in the file: the interactive failure is not "cannot start a chat",
it is "a turn already in flight is cut off", and a turn costs a fraction of a window.

Fails OPEN, deliberately. The numbers come from an external endpoint with a credential Officer does not
own, so a blip or a signed-out CLI must not stop every spawn on the machine with an error about usage
that has nothing to do with usage. The problem is reported so a caller can say "started, but unchecked".

Seven tests on the pure rule — tightest window decides rather than the average, no limits allowed rather
than blocked, exactly-at-the-ceiling refuses. Verified against the live account, where it correctly
refuses right now at Session 90%.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 06:42:27 +00:00
pastilhasandClaude Fable 5 4c26e13535 todo: OPM — officer's processes on a manager of their own
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 06:05:57 +00:00
pastilhasandClaude Fable 5 645c8e36eb todo: urgent — per-feature server routing, due tomorrow for reclip
Adds priority/due to the item format and an Urgent section to the generated index.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 06:03:51 +00:00
pastilhasandClaude Fable 5 47f3fbaf76 todo: centralise custom components, with per-theme overrides
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 05:58:42 +00:00
pastilhasandClaude Fable 5 a34ef422f4 todo: turn timer in chat, and a sub-agent spawn endpoint bounded by usage limits
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 05:44:47 +00:00
pastilhasandClaude Fable 5 6071ded175 todo: one file per item, grouped by theme, with a generated index
TODO.md had reached 1050 lines and 72 open items across 28 sections, read mostly
on a phone. It is now a directory: todo/<theme>/<item>.md, one card per file, with
frontmatter carrying id, status, created date and order, and the prose body copied
across verbatim. TODO.md becomes a generated index (bun run todo:index).

Dates: where an item's prose stated one it is used; otherwise its old section's;
otherwise 2026-08-20, floored at the day before the split rather than invented.
date_source records which.

Shaped for a two-way Kanban board, filed as todo/tooling — a card is a file, id is
the identity, frontmatter is the machine's half and the body is the owner's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 05:42:39 +00:00