Skip to content
This repository was archived by the owner on Jul 24, 2026. It is now read-only.

feat(ding): --root flag + unset-root WARN (pin the state root against pty-restart env drop) - #85

Merged
myobie merged 1 commit into
mainfrom
feat/ding-root-flag
Jul 13, 2026
Merged

feat(ding): --root flag + unset-root WARN (pin the state root against pty-restart env drop)#85
myobie merged 1 commit into
mainfrom
feat/ding-root-flag

Conversation

@myobie

@myobie myobie commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

What

st ding gains --root PATH (alias --st-root): an explicit state-root override that wins over $ST_ROOT and the install default. Plus a startup WARN when $ST_ROOT is unset and more than one state root exists on disk.

Why (the incident this closes)

A fleet of ding daemons was launched without $ST_ROOT set, so they fell back to the install default ~/.local/state/smalltalk — but the live network runs on ~/.local/state/convoy. Where the old root had stranded messages, the daemon re-poked them forever ("phantom pokes") while never delivering the agent's real (convoy-root) inbox. The [id:] discriminator (#84) is what finally made these visible.

Crucially, pty restart reuses the stored command but can drop/replace env, so a daemon relying only on $ST_ROOT silently reverts to the default root on every restart — env alone isn't durable. The fix must live where a restart can't drop it: the command line.

The change

  • --root PATH / --st-root PATHconst root = rootArg ?? ctx.stRoot. Put it in the launch command and it survives pty restart.
  • Startup WARN: if the root was neither passed nor set via $ST_ROOT (fell back to default) and plausibleStateRoots() finds >1 root under ~/.local/state/, emit one loud stderr line naming them. This one warning would have turned a 3-round diagnosis into an instant one.

Division of labor (with convoy-claude)

  • This PR (smalltalk): the flag + WARN.
  • convoy (follow-up): writePtyToml's dingCommand emits --root <net> so every sidecar pins its root; + the fleet re-launch of the 13 daemons still on unset-root. convoy is waiting on this flag to wire that.

Back-compat

Fully additive. Existing st ding invocations are unchanged; single-root setups never warn.

Blast radius

  • src/commands/ding.tscmdDingCli arg parse + root resolution + --help; new read-only plausibleStateRoots() helper.
  • tests/unit/ding.test.ts — 6 new tests (flag parse, --st-root alias, override reaches identity check, WARN fires on ambiguity, WARN suppressed by --root and by $ST_ROOT).
  • CHANGELOG.md.

Verification

  • vitest run tests/unit/ding.test.ts101 passed (95 + 6 new).
  • tsc -p tsconfig.build.json --noEmit → clean.
  • Drove the real st ding from source: --help shows the flag; --root /custom/root reaches mkdir '/custom/root/<id>/inbox' (override is load-bearing, not just parsed); the WARN fires naming both roots; --root and $ST_ROOT each suppress it.

…state root

st ding gains --root PATH (alias --st-root), overriding $ST_ROOT and the
install default. Because it lives on the COMMAND LINE, it survives a
pty restart (which reuses the stored command but can drop/replace env) —
the failure mode where a daemon relying only on $ST_ROOT silently falls
back to the default root (~/.local/state/smalltalk), watches the wrong
inbox, and re-pokes stranded messages forever (phantom pokes) while never
delivering the agent's real inbox.

Also adds a startup WARN: when $ST_ROOT is unset (and no --root) AND more
than one state root exists under ~/.local/state/, st ding emits a loud
one-line stderr warning naming the roots — the exact ambiguity that
otherwise takes a multi-round investigation to spot.

Additive + back-compat: existing invocations unchanged; single-root setups
never warn. Pairs with convoy writePtyToml emitting --root so pty-restart
can't drop the root.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant