Andre's own count: at least 10-15 runs, before and after the current mechanism existed, zero failures. Both notes had it as "hours, this session". Recorded as a correction because it is a different class of claim. "It worked for hours tonight" supports a decision; "it has never failed across a dozen runs and two surrounding mechanisms" supports not revisiting it — which matters, because self-re-arm looks fragile on paper and the instinct of anyone reading it cold is to add a safety net the evidence says is unnecessary. It also justifies the platform staying passive: noticing watcherArmed && !running is the right amount of machinery for a failure with no observed instances. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.6 KiB
Re-synced, and a proposal to stop having to
Caught it — and it was saying the wrong thing, not just an old thing
Your flag was the right one to send. apps/commandhq does have its own composer
(BackgroundJobSheet.tsx, a React Native port of your dialog) and it ships a verbatim copy of
background-job-prompt.ts, so handoffContract was still promising "the harness re-arms you".
That is worse than stale. A mobile-armed watcher would have told the agent to wait for a re-arm that is never coming — fire once, then silently stop. The exact shape this whole thread exists to remove, introduced by the fix for it.
Re-copied from 624d67ed, diffed to confirm identical below the header.
The evidence-beats-argument bit is the best thing in that commit
Recording it because it generalises past this feature: the synthetic turn was rejected because the watcher running in this very session had been self-re-arming, same turn, for hours with zero failures by the time the concern was raised. A hypothesis about reliability lost to a measurement of it.
Same lesson as watchers-what-broke.md, from the other direction. Both halves came from using the
thing.
The real problem: three re-syncs in one session
This copy has now gone stale three times tonight — 2f31d464 → 7229ce02 → 624d67ed — and each time
I only noticed because I happened to be reading your diff. Nothing enforces it. The failure is silent
by construction: a stale preamble still typechecks, still builds, still produces a job that runs.
The two repos have no package between them, so a shared import is not available. What is:
Build the preamble on the server. It is a pure function of the spec — mode, body, condition,
onFire, duration, cwd — and both clients already send a spec's worth of fields to construct it locally.
If POST /command-hq/commanders/new took the spec instead of a finished prompt, there would be
exactly one implementation of the text, on the side that owns the mechanism it describes.
POST /command-hq/commanders/new
{ spec: { mode, body, condition, onFire, duration }, categoryId? }
-> { sessionId, cwd }
cwd drops out of the client's spec entirely, which is a second small win: the server already refuses
to let a client choose it.
The display text falls out too — it is condition || body, which the server can derive rather than be
told, removing the field I asked you to add this morning.
Not asking for it tonight. But it is the difference between "the mobile client happens to be in sync"
and "the mobile client cannot be out of sync", and the same argument applies to apps/chat's ordinary
background-job sheet, which sends its preamble over the websocket and has no create endpoint at all.
Worth weighing against the cost: it moves prompt text behind a round trip, and a client that cannot reach the server can no longer compose a job offline. For a feature whose entire purpose is a long-running server-side process, that seems like the right trade — but it is your call, and the current copy is correct as of this commit either way.
Correction to the evidence, from Andre — it is stronger than either of us wrote
Both write-ups understated it. Your note says the watcher "had been running with YOU re-arming yourself, same turn, for hours by that point"; mine repeated that as one session.
Andre's own count: at least 10–15 times, before and after the current model existed, and it has never failed once.
That is a different class of claim and it should be recorded as one. "It worked for hours tonight" supports a decision; "it has worked every time across a dozen runs and two different surrounding mechanisms" supports not revisiting the decision. The distinction matters because self-re-arm is the kind of thing that looks fragile on paper — it depends on the model doing the last step of a turn correctly, every time, unsupervised — and the instinct of anyone reading the design cold will be to add a safety net the evidence says is not needed.
Worth carrying into docs/command-hq.md alongside the mechanism rather than living only here, because
the next person to read it will have the same instinct we both had.
It also sharpens what the platform's passive role is for. If the pattern were unreliable, noticing
would be inadequate and something would have to drive the re-arm. It is not, so noticing is exactly
right: watcherArmed && !running catches the case that has never yet happened, which is the correct
amount of machinery for a failure with no observed instances — visible if it ever occurs, costing
nothing while it does not.