Skip to content

fix(queue): make dispatch answer trust dialogs and render profiles without bash - #94

Open
LeTuR wants to merge 2 commits into
mainfrom
feat/dispatch-no-bash
Open

LeTuR wants to merge 2 commits into
mainfrom
feat/dispatch-no-bash

Conversation

@LeTuR

@LeTuR LeTuR commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Intent

Implement task 4 of the native-Windows port of fleet: native dispatch must not call bash. On Windows, scripts/lib/queue.py's shell-out to ./scripts/session-flags.sh silently dropped a task's profile (profile_flags swallowed WinError 193), and its shell-out to ./scripts/session-trust.sh crashed dispatch after session create (trust_and_send let the same error through), leaving a session never sent its brief. Requirements from the brief: reproduce both in tests first (test-first is an operator rule); replace session-flags with an in-process call into the existing session_profiles module; port session-trust.sh to Python keeping EVERY rule it has today — per-agent gate table (claude down+enter for folder trust, enter for the external-imports dialog, codex/pi enter, grok/kimi none, cursor/muse refused as flag-only), dialogs queued behind each other answered in turn with a settle window and a max-answers bound, TRUST_SIGNATURE/TRUST_KEYS teaching from orchestration/agent.conf (TRUST_KEYS=none), #84's whitespace-insensitive matching of psmux captures, and sending Enter alone when 'Yes' is already selected — and call it in-process from dispatch; turn any sh -c override (the FLEET_QUEUE_WATCH_CMD watch override) into an argv list; keep scripts/session-flags.sh and scripts/session-trust.sh as thin forwarders with the same CLI and exit codes so skills and hooks that name them still work; extend the existing bash selftest sections rather than starting pytest (another task ports tests to pytest). Deliberate decisions: session-flags.sh was already a thin forwarder to session_profiles.py, so it is left unchanged and only queue.py's call became in-process; the Python keeps the bash script's messages and --json shape ({session,agent,outcome,detail}, compact) byte-for-byte where possible, including reporting the table's key sequence in the 'answered' message; a missing or invalid profile still renders no flags, as before (scope kept to the bash seam); the override is split with shlex.split, so §15's compound shell override became a small script file; the lint/docs references that said session-trust.sh's header owns the table now point at scripts/lib/session_trust.py; the CI queue path filter gained the trust and profiles files. New queue-selftest §21b runs queue.py dispatch, watch and session_trust.py with neither bash nor sh on PATH and failed on main for exactly the brief's reasons. Hard constraints: fleet is a public repo, so no lab host names, usernames, home paths, IPs or local evidence paths in code, comments, commits or the PR body (two existing comments naming a lab host were rewritten as 'a Windows 11 host'); Linux must keep working and ./scripts/check.sh must be green; keep it simple, no new dependency; squash-merge only and do not merge.

What Changed

  • scripts/lib/queue.py's profile_flags now calls session_profiles.load_profiles/render in-process instead of shelling out to ./scripts/session-flags.sh, so a missing shell no longer silently drops a task's profile (still renders no flags on a missing/invalid profile, as before).
  • Added scripts/lib/session_trust.py, a Python port of scripts/session-trust.sh's full trust-and-send logic (per-agent gate table, queued dialogs answered in turn with a settle window and max-answers bound, TRUST_SIGNATURE/TRUST_KEYS teaching from orchestration/agent.conf, whitespace-insensitive capture matching, sending Enter alone when "Yes" is already selected), and trust_and_send now calls it in-process; scripts/session-trust.sh becomes a thin forwarder to that module with the same CLI, --json shape and exit codes.
  • watch_command's FLEET_QUEUE_WATCH_CMD override is now split into an argv list with shlex.split instead of being passed to sh -c.
  • Extended scripts/queue-selftest.sh with a new section exercising dispatch, watch and session_trust.py with neither bash nor sh on PATH; updated the CI queue path filter, .no-mistakes.yaml, orchestration/agent.example.conf, and the fleet-queue/thurbox-session skill docs and AGENTS.md to point at scripts/lib/session_trust.py as the table's owner.

Risk Assessment

✅ Low: The change is a faithful, well-scoped port: profile_flags now calls session_profiles.load_profiles/render in-process with identical fallback semantics (missing/invalid profile or file errors still yield []), session_trust.py reproduces every rule of the bash original (per-agent gate table, claude's down+enter vs enter-only dialogs, flag-only refusal for cursor/muse, TRUST_SIGNATURE/TRUST_KEYS teaching, whitespace-insensitive matching, the already-selected-Yes special case, settle window and max-answers bound) with matching exit codes and byte-for-byte JSON/message shapes; the FLEET_QUEUE_WATCH_CMD override via shlex.split preserves the same POSIX-style word-splitting semantics the old sh -c path already had (verified: bash's sh -c already strips backslashes from unquoted Windows-style paths, so this is not a new regression); thin forwarders (session-flags.sh unchanged, session-trust.sh reduced to an exec wrapper) preserve CLI/exit-code compatibility; a new queue-selftest §21b exercises dispatch, watch, and session_trust.py with neither bash nor sh on PATH; no lab-identifying strings were introduced (existing ones were replaced with a generic description); no new dependencies were added; and all doc/CI cross-references were updated consistently.

Testing

Baseline ./scripts/check.sh already passed; I additionally ran the targeted scripts/queue-selftest.sh directly at the target commit (all pass, including new §21b) and re-ran the same test grafted onto the pre-fix base commit in an isolated throwaway worktree to prove it is a true regression test — it fails there for exactly the bug described (dropped profile, crashed trust dialog, sh-less watch override), confirming test-first reproduction and a real fix.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • ./scripts/check.sh
  • ./scripts/queue-selftest.sh at target commit e654e49 (full run, 0 failures, §21b's 10 assertions all pass)
  • Same scripts/queue-selftest.sh (with only its §21b addition grafted in) run against base commit 8b39fe9 in a throwaway git worktree — reproduces both reported bugs (dropped profile flags, crashed trust dialog leaving session unprompted) and the watch-override crash, then the worktree was removed
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

`dispatch` shelled out to `scripts/session-flags.sh` for a task's profile and
`scripts/session-trust.sh` for the trust dialog. On a machine with no bash the
first failure was swallowed, so a worker started without its profile, and the
second came after `session create`, leaving a session that was never sent its
brief. On native Windows these are a swallowed and an uncaught
`WinError 193`.

- Profiles render in-process through `session_profiles`.
- The trust handshake is ported to `scripts/lib/session_trust.py` with every
  rule it had: per-agent gates, dialogs queued behind each other, the
  `agent.conf` teaching, whitespace-insensitive matching of psmux captures,
  and Enter alone when "Yes" is already selected. Dispatch calls it
  in-process; `scripts/session-trust.sh` forwards to it with the same CLI.
- `FLEET_QUEUE_WATCH_CMD` is split into argv instead of run through `sh -c`.
- queue-selftest §21b drives dispatch, watch and the trust CLI with neither
  bash nor sh on PATH.

Claude-Session: https://claude.ai/code/session_01DZe2ZfGL5BpKrvf1BXzT83
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant