Repository navigation
Description
Problem
PR #808 introduces the shared line grammar (pkgs/id/src/world_line.rs, branch id/phase-11) whose stated contract is that one line "works identically as an SSH command, a piped script line, and a CLI one-off" — and the PR body claims the id world join --command-mode pump and SSH command mode both speak it (#546). Two places break that parity:
1. A typo in the join pump kills the session; on SSH it just shows a message
world_line.rsdefinesWorldLine::Message(String)as "A command that did not parse; the message is shown to the user" (unknown commands,usage: /input <hex>,usage: /logs [seconds],usage: /document <name>).- SSH command mode honours that:
pkgs/id/src/world_ssh.rs:667-672renders{message}\r\nworld>and the session continues. - The join pump does the opposite:
pkgs/id/src/commands/world.rs:1054-1056mapsWorldLine::Message(message)toanyhow::bail!("{message}"), and the pump loop callspump_command_frame(line)?(commands/world.rs:1007), so the error breaks the writer loop, closes the connection, and endsid world joinwith a failure exit.
One mistyped /imput … or /logs soon in --command-mode therefore disconnects the user from the world instead of showing the usage line and a fresh prompt. The pump's own test even enshrines the divergence: assert!(pump_command_frame("/nope").is_err()).
2. /logs [seconds] is parsed, validated — and silently discarded by both consumers
world_line.rs:29, 78-87—WorldLine::Logs { seconds: Option<u64> }; a non-numeric argument is a usage error, so the grammar promises the argument means something.- SSH:
world_ssh.rs:846mapsWorldLine::Logs { .. }toWorldCommand::Logs, discardingseconds(the handler then prints the "event tailing is not available in command mode" stub regardless of the argument). - Pump:
commands/world.rs:1051mapsWorldLine::Logs { .. }to{"type": "logs"}with no seconds field.
So /logs 5 and /logs 5000 behave identically everywhere, with no hint to the user. Either the frame/handler needs to carry the value, or the grammar should stop accepting (and validating) an argument nothing uses.
Why it matters
The whole point of #546 / F11.5 is one grammar with one behaviour per surface; a shared parser whose error and argument semantics differ per consumer re-creates the divergence the refactor exists to remove, and the pump case is user-hostile: a recoverable typo becomes a disconnect (and a nonzero exit for scripted/piped use of --command-mode).
Evidence
- PR id: Phase 11 foundations — F11.10 module split (world.rs, world_session.rs) #808 (OPEN, branch
id/phase-11); file:line on the PR branch as fetched this run (gh api .../contents/...?ref=id/phase-11). Not onmainyet — fix-before-merge. - Dedup: id: one line grammar for SSH command mode, the
id world joinpump and CLI verbs (--command-mode) #546 is the feature tracker this PR implements; id: F12.16id world doctor#559/id: F12.1 apply wiring — module install + schedules reconciliation #807-style searches plus "pump command" found no issue covering the Message//logsbehaviour. The PR body itself notes "/logs in command mode is a documented stub" for SSH — it does not note the pump's session-killing Message handling or that the pump sends a barelogsframe.
Acceptance
- In
--command-mode, a line that parses toWorldLine::Messageis shown to the user and the pump keeps running (matching SSH command mode); only/quit/ EOF / a real I/O error ends the session. The pump test asserts the message path does not error and a following valid line still produces its frame. /logs [seconds]either takes effect identically on both surfaces (value carried into the logs request / stub message states what is ignored), orworld_linerejects the argument with a usage message that says it is unsupported — in both cases, SSH and the pump behave the same.- A parity test runs the same line corpus through both consumers' mappings (the structural-guard style PR id: Phase 11 foundations — F11.10 module split (world.rs, world_session.rs) #808 already uses for the projection) so the two mappings cannot silently drift again.
Activity
dezren39 commentedon Oct 25, 2026
Triage re-verification on current main af75c8c (2026-10-25 sweep): both halves still reproduce exactly as filed. (1)
commands/world.rs:1264mapsWorldLine::Message(message)toanyhow::bail!, and the pump test atworld.rs:1301still enshrines it (pump_command_frame("/nope").is_err()); SSH atworld_ssh.rs:850maps the same variant toWorldCommand::Messageand continues. The commands::world suite (5/5 PASS locally this run on a sibling branch) passes with the divergent assertion in place. (2)WorldLine::Logs { .. }discardssecondsat both consumers:world.rs:1261(frame has no seconds field) andworld_ssh.rs:846. No fix attempted this run — the pump half touches the same file as PR #860 (#818), so it should land after that merges to avoid a stacked conflict; the /logs half still needs the carry-vs-drop design choice.dezren39 commentedon Oct 25, 2026
Scope narrowed by the 2026-10-25 sweep (PR #868 closed as superseded):
Fixed/superseded on main
74b849b8:Messageno longer kills the session — main'spump_command()maps it toPumpLine::Say(printed, session continues), with a parity test in the shell-contract test set./logs [seconds]: main deliberately replies with a redirect message instead of sending a frame (no logs reader on the join pump; same treatment as/documents), so the "carry seconds in the pump frame" half is superseded by design.Still open (the only remainder):
WorldCommand::Logsis a unit variant, so/logs 5discards the 5-second window silently. Either carry the seconds through and note in the stub reply that the window is ignored in command mode (the approach PR fix(id-world): pump shows parse Messages and keeps running; /logs seconds carried (#819) #868 took), or document the discard explicitly. Small, self-contained.dezren39 commentedon Oct 25, 2026
Update from the 2026-10-25 13:00 CDT sweep: the remaining SSH half is now implemented in PR #909.
WorldCommand::Logscarriesseconds: Option<u64>,world_command()threads the parsed value through, and the command-mode reply names the requested window it ignores. Parse tests pin/logs→ None and/logs 5→ Some(5). #909 carriesFixes #819and closes this on merge.fix(id): carry /logs seconds in SSH command mode (#819) (#909)