Skip to content

fix: move the intake dialogue into the main thread (0.3.4) - #4

Merged
CallMeTechie merged 1 commit into
mainfrom
fix/intake-agent-noninteractive
Aug 3, 2026
Merged

fix: move the intake dialogue into the main thread (0.3.4)#4
CallMeTechie merged 1 commit into
mainfrom
fix/intake-agent-noninteractive

Conversation

@CallMeTechie

Copy link
Copy Markdown
Owner

Replaces #3, which GitHub auto-closed when its base branch was deleted on merging #2. Same branch, rebased onto main; content is unchanged.

The bug

/first-run cannot onboard a server. Dispatching the agent produces:

Blocker: AskUserQuestion is not available in my tool set. My tools this session are only Bash, Read, Write, and Edit — so I cannot ask the user the intake questions inline.

plugin/agents/fleet-intake.md declared:

tools: Bash, Read, Write, Edit, AskUserQuestion

Subagents are not granted AskUserQuestion — the interaction channel belongs to the main thread. The declaration is accepted and then silently dropped, so the agent reaches step 2 ("Gather connection details, one at a time, via AskUserQuestion") and dies. Every path into onboarding is affected: /add-server dispatches the same agent.

/first-run did not list AskUserQuestion in its own allowed-tools either, so even the main thread could not have asked.

The fix

The dialogue moves to where the user actually is. /first-run gathers name, host, port, user, description and scopes via AskUserQuestion, validates each answer, then dispatches fleet-intake with everything in hand. /add-server reuses that dialogue — its re-add branch already asked in the main thread, so this makes the command internally consistent.

fleet-intake becomes non-interactive and says so in its own instructions. It re-validates every input rather than trusting the caller, and hands control back instead of waiting:

  • NEEDS_KEY_DEPLOY: <name> + the exact ! ssh-copy-id … line — the profile is already on disk, the caller presents the line and re-dispatches after the user confirms
  • NEEDS_INPUT: <reason> — missing or invalid input
  • FAILED: <cause> — SSH broken after key deployment

ssh-copy-id is still never executed by the agent: it needs a TTY, hangs without one, and the user should see what they are authorizing.

set_active becomes an input. Previously the agent set the active pointer unconditionally, which is right for /first-run and wrong for /add-server — adding a second server silently redirected every subsequent unqualified command to it.

Regression guard

tests/static/frontmatter-check.sh now rejects AskUserQuestion in any agent frontmatter. Verified in both directions: it passes on this branch, and fails with FORBIDDEN AskUserQuestion in agent frontmatter when the declaration is reintroduced.

Verification

All five static checks green locally — shellcheck and markdownlint included, after installing both toolchains. markdownlint caught an MD040 in the new agent file, fixed here. Unit tests: 51/51, 14/14, 11/11, 3/3, plus test-compose-lib's usual 2 local docker/jq failures that pass in CI. CI was green on #3 before the rebase.

Not verified: the end-to-end onboarding flow. It needs a real server.

/first-run and /add-server could not onboard a server at all. The fleet-intake
agent declared AskUserQuestion in its frontmatter, but subagents are not granted
that tool -- the interaction channel belongs to the main thread -- so the agent
aborted at its first question. /first-run did not list AskUserQuestion in
allowed-tools either, so neither side could ask.

The dialogue now runs in the command, where the user actually is. fleet-intake
is dispatched non-interactively with every value in hand, re-validates them, and
hands control back via NEEDS_KEY_DEPLOY / NEEDS_INPUT / FAILED rather than
waiting for a confirmation it can never receive. The ssh-copy-id line is still
presented as copy-paste and never executed.

set_active becomes an input so /add-server stops silently stealing the active
pointer; /first-run passes yes.

frontmatter-check now rejects AskUserQuestion in any agent frontmatter. Verified
it fails when the declaration is reintroduced, so the dead end cannot come back.
@CallMeTechie
CallMeTechie merged commit 2627a8a into main Aug 3, 2026
4 checks passed
@CallMeTechie
CallMeTechie deleted the fix/intake-agent-noninteractive branch August 3, 2026 20:08
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