feat(onboarding): guide fleet setup with dependency, owner and pane-placement scripts - #66
Merged
Conversation
… with Onboarding probed prerequisites in prose, asked the operator to type owners the machine already knows, and printed a layout.lua block for them to paste — which is how a setup ends with an invisible queue pane. Four scripts now own the mechanical halves, and the skill asks at the four points where the answer is genuinely the operator's. - scripts/preflight.sh: every dependency in one pass, in three tiers, each row carrying what breaks without it and the command that fixes it. quota-axi and glab join the list; so does the git commit-signing configuration, which fails check.sh queue in a dozen unrelated-looking ways. --commands hands over the runnable lines, --tier narrows them. - scripts/discover-owners.sh: owner candidates from the gh session, the git config and the remotes of the clones already on disk, each with its evidence. It matches an ssh host alias, so a machine with two GitHub accounts is not invisible to it. GitLab remotes are evidence, never owners. - scripts/place-pane.sh: writes the guarded block into layout.lua, right of the terminal by default. On the operator's word only — it refuses a layout it cannot read, backs up first, re-reads its own edit with lua, and verifies with plugin check. The slot comes from the pane. - scripts/onboarding-selftest.sh + check.sh onboarding + a CI job: all three driven offline against stubs and a stock layout fixture. The skill is now seven announced steps with four asks: install what is missing, which owners the map covers, where the pane goes, and whether the reconciler comes up.
GIT_CONFIG_COUNT/KEY/VALUE outrank GIT_CONFIG_GLOBAL, so §1f's answer was decided by whoever invoked the selftest — and the invocation that does set them is `check.sh` run with commit.gpgsign forced off, which is exactly how this repo gets gated on a machine whose signing is misconfigured. The test now clears them, so it passes and fails for its own reasons either way.
… global signing config
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Improve the fleet control plane's onboarding process so it is more guided and clearer, and so it stops leaving parts of the setup to the operator that a script can do. The user asked for four things specifically: (1) onboarding should ALWAYS ask to install the custom TUI queue pane and do the layout setup, with the recommended layout being the pane on the RIGHT — this deliberately reverses the repo's previous standing rule that nothing here writes the operator's thurbox layout.lua, because 'print the block and stop' is what left operators finishing setup with an installed pane that draws nothing; the write is still never unasked, it now happens through scripts/place-pane.sh after an explicit question, with a backup, a refusal on any layout it cannot recognise, a lua re-read that restores the backup on a parse failure, and thurbox-cli plugin check as the verification. (2) It should ask about auto-detecting repos, or find potential config via .gitconfig or other config files — scripts/discover-owners.sh reads the gh session, the git config (github.user and a users.noreply.github.com commit email) and the remotes of every clone already on disk, prints candidates with their evidence, and the skill then asks ONE question about which owners the map covers; GitLab remotes are reported as evidence and deliberately never as owner candidates, since registry/owners.txt is read by gh. (3) Onboarding should be more guided and clearer — the skill is now seven announced steps with exactly four asks, each at the step it belongs to, and each step reports what it landed with evidence. (4) It should ask to install fleet's required dependencies, and the user then added 'dependencies like quota-axi' — scripts/preflight.sh is the one dependency table, in three tiers (required / recommended / gate), each row naming what breaks without it and the command that installs it; quota-axi is recommended because the pane's fuel rows, fleet-status.sh and queue.sh refuel's quota check all depend on it. Decisions a reviewer reading only the diff would not know: preflight probes and prints but never installs, because a package manager is the one part of setup that touches the machine outside the checkout — the skill asks and runs the lines, and --tier exists so 'required only' is a flag rather than the agent's judgement about which lines to copy. Preflight also carries a row that is not a tool at all, the git commit-signing configuration, because commit.gpgsign=true with a key scoped by an includeIf gitdir: block makes every commit in a sandbox repo fail and makes check.sh queue report a dozen unrelated failures; it is probed from a directory OUTSIDE the checkout for exactly that reason, and that row is not hypothetical — this very pipeline's first run failed on it. place-pane.sh never spells the pane's slot name (it reads it from interface/fleet_queue.lua so a rename cannot half-land) and check.sh onboarding asserts that. Records are separated by 0x1f rather than tabs in preflight because a tab is IFS whitespace and collapses empty fields. The clone scan matches ssh host ALIASES (git@github-perso:owner/repo), which was a real bug: matching the literal github.com found none of the clones on this machine, including this checkout. The second commit on this branch fixes a fragility in the new selftest itself: GIT_CONFIG_COUNT/KEY/VALUE outrank GIT_CONFIG_GLOBAL, so the signing case's answer was decided by the caller's environment; it now clears them. All of it is covered offline by scripts/onboarding-selftest.sh, wired in as check.sh onboarding and as an unfiltered CI job that installs lua. Docs updated to match the reversed layout.lua stance: the fleet-pane and update-fleet skills, AGENTS.md, README.md and install-extension.sh's own closing message. The full local gate (./scripts/check.sh) is green on this branch.
What Changed
scripts/preflight.shprobes every dependency in one pass across three tiers (required / recommended / gate, includingquota-axiand a git commit-signing row probed from outside the checkout) and prints install commands via--commands/--tierwithout ever installing;scripts/discover-owners.shprints GitHub owner candidates with evidence from theghsession, git config and theoriginof local clones (matching ssh host aliases, and reporting GitLab remotes as evidence only);scripts/place-pane.shwrites the queue pane's guarded block into the operator'slayout.lua— right side by default — reading the slot name frominterface/fleet_queue.lua, refusing unrecognised layouts, backing up, re-reading the edit withluaand restoring on a parse failure, then verifying withthurbox-cli plugin check.fleet-onboardingskill into seven announced steps with exactly four asks (dependencies, owners, pane placement, reconciler), each step reporting what it landed, and updatesfleet-pane,update-fleet,AGENTS.md,README.md,CONTRIBUTING.md,extension.toml.inandinstall-extension.sh's closing message for the reversed stance thatlayout.luais now written by a script after an explicit question.scripts/onboarding-selftest.shcovering all three scripts offline against PATH stubs and a stock-layout fixture (scripts/fixtures/layout/), wired in as./scripts/check.sh onboardingand an unfiltered CI job that installs lua;scripts/queue-selftest.shnow exports theGIT_CONFIG_COUNTtriple to forcecommit.gpgsign=falsein its sandbox repos.Risk Assessment
--commands, one unrequested fix-round scope change that quietly narrows owner discovery, and one incomplete test-isolation boundary — all safe to land and address as follow-ups.Testing
The configured gate
./scripts/check.shhad already passed at baseline; on top of that I stood each onboarding script up the way an operator runs it. preflight was driven on this machine and on sandboxed PATHs built from scratch: three missing required tools give exit 1 with a remedy per row,--tier gatenarrows the view without softening the verdict, a stubbed thurbox 2.18.0 is reportedstaleagainst the floor read from extension.toml.in, and quota-axi is reported as a recommended gap without failing the run. The commit-signing row was driven across three git configurations, including the intent's own case — a key scoped to the checkout byincludeIf gitdir:— where git inside the checkout answers with a key and preflight, probing outside, still reports the gap. That gap is real on this machine, so I reproduced the failure it explains: the pre-fix queue selftest gives 18 failures here, the current one gives none. Discovery was run for real (gh account, orgs, clone counts, self-hosted GitLab reported only as evidence) and against a fixture clone tree that tries to break it: an ssh host alias is found,ssh://…:443/yields the owner and not the port, a fork's upstream owner never appears, and vendorednode_modules/dot-directory clones are pruned; a machine with nothing to say exits 1 instead of inventing an owner. Placement was only ever driven against copies of the tracked layout fixture and never the operator's file: the default lands the guarded block to the right of the centre column with a timestamped backup,luare-reads it,thurbox-cli plugin checkcame back green, a re-run changes nothing, a commented-out block is correctly not a placement, three unrecognisable arrangements are refused untouched with the block printed, and an edit into a non-parsing layout is rolled back byte-identically. A pane file declaring a different slot places that slot, so the block genuinely follows the pane. Visual evidence is CLI transcripts and the layout diff rather than screenshots: the only rendered surface here is a thurbox TUI column, and driving it would mean editing the operator's live layout outside the worktree, so I verified it withplugin checkand the placed-block diff instead. The worktree is clean and all sandboxes were removed../scripts/preflight.sh→ exit 0, required/recommended/gate sections; evidence/preflight-table.txtenv -i PATH=<sandbox> bash ./scripts/preflight.sh→ exit 1, "3 required dependencies missing"; evidence/preflight-missing-required.txt--tier gateon a machine missing three required tools still exits 1;--tier bogusexits 2; evidence/preflight-tier-gate-still-fails.txt./scripts/preflight.sh --commandsprints the remedies for the gaps and drops thesee <url>rows; evidence/preflight-commands.txtstale ... sets the floor at 2.19.0; evidence/preflight-stale-thurbox.txtmissing commit signing; ok when the key is truly global; evidence/preflight-signing-row.txtscripts/queue-selftest.shfrom 2cf6088 → 18 FAIL on this machine; current → 0 FAIL, "every claim holds"; evidence/queue-selftest-{prev,after}-signing.txt./scripts/discover-owners.sh→ gh account, gh orgs and local clone counts per owner; evidence/discover-owners-real.txtmeandThurbeen; evidence/discover-owners-adversarial.txt*beside Thurbeen and "* already in registry/owners.txt"; worktree clean afterwards; evidence/discover-owners-rerun-marker.txt./scripts/place-pane.sh --layout <copy of stock.lua>→ block after thecentercolumn with the panels.shown guard, layout.lua.bak-<ts>, lua loadfile ok,thurbox-cli plugin checkgreen; evidence/p…columns[...] = { slot = "center" }; evidence/place-pane-left.txtcenteranchor, nopanels.shown(, and nofilled(ctx,each exit 3 naming what was missing and leave no backup; a missing layout.lua exits 2; evidence/place-pane-refusals.txtcmpreports the file byte-identical to before the run--checkon a layout whose block is commented out → exit 1 "loads, lists, and draws nothing"; placing over it then succeeds--pane <copy declaring queue_v2>→ the written block guards and carvesqueue_v2; evidence/place-pane-renamed-slot.txt--layout "/tmp/.../o'brien/layout.lua"→ exit 0, block present; evidence/place-pane-quoted-path.txt./scripts/check.sh onboardingok;./scripts/onboarding-selftest.shgreen bare and under GIT_CONFIG_COUNT/KEY_0/VALUE_0 forcing gpgsign=false; evidence/onboarding-selftest.txt, selftest-hostile-git…Evidence: preflight on this machine — the three-tier table, with the commit-signing row firing for real
Evidence: preflight on a machine missing gh, jq and thurbox-cli — exit 1, every gap with a remedy
Evidence: preflight --tier gate on that same machine — the view narrows, the verdict does not (exit 1)
Evidence: preflight with only recommended/gate gaps — exit 0, quota-axi named with what it costs
Evidence: a thurbox below the manifest floor is stale, not ok
Evidence: the signing row across three git configurations, including a key scoped to the checkout by includeIf
Evidence: the failure that row diagnoses: pre-fix queue selftest on this machine (18 FAIL)
~/.no-mistakes/evidence/01M26PR6EYCZSJZ2ZE7AD0JJJQ/queue-selftest-after-signing.txt)Evidence: owner discovery on this machine — gh account, orgs, clone counts, GitLab as evidence only
Evidence: owner discovery against a hostile clone tree — ssh alias found, port not an owner, upstream and vendored clones excluded
Evidence: a machine that says nothing exits 1 rather than inventing an owner
Evidence: placing the pane: the block landed right of the centre column, backup, lua re-read, plugin check green, idempotent re-run
Evidence: the three arrangements place-pane refuses, each with the block printed and the file untouched
Evidence: a renamed pane places the slot the pane declares, not one the script spells
Evidence: --left places the column before the terminal
~/.no-mistakes/evidence/01M26PR6EYCZSJZ2ZE7AD0JJJQ/selftest-hostile-gitenv.txt)Evidence: rollback proof: an edit into a non-parsing layout is restored byte-identically
Pipeline
Updates from git push no-mistakes
... (8 earlier update rounds omitted to keep the PR body within GitHub's 65536-char limit; full history is in the run log.)
🔧 **Test** - 2 issues found → auto-fixed ✅
🔧 Fix applied.
✅ Re-checked - no issues remain.
./scripts/preflight.sh→ exit 0, required/recommended/gate sections; evidence/preflight-table.txtenv -i PATH=<sandbox> bash ./scripts/preflight.sh→ exit 1, "3 required dependencies missing"; evidence/preflight-missing-required.txt--tier gateon a machine missing three required tools still exits 1;--tier bogusexits 2; evidence/preflight-tier-gate-still-fails.txt./scripts/preflight.sh --commandsprints the remedies for the gaps and drops thesee <url>rows; evidence/preflight-commands.txtstale ... sets the floor at 2.19.0; evidence/preflight-stale-thurbox.txtmissing commit signing; ok when the key is truly global; evidence/preflight-signing-row.txtscripts/queue-selftest.shfrom 2cf6088 → 18 FAIL on this machine; current → 0 FAIL, "every claim holds"; evidence/queue-selftest-{prev,after}-signing.txt./scripts/discover-owners.sh→ gh account, gh orgs and local clone counts per owner; evidence/discover-owners-real.txtmeandThurbeen; evidence/discover-owners-adversarial.txt*beside Thurbeen and "* already in registry/owners.txt"; worktree clean afterwards; evidence/discover-owners-rerun-marker.txt./scripts/place-pane.sh --layout <copy of stock.lua>→ block after thecentercolumn with the panels.shown guard, layout.lua.bak-<ts>, lua loadfile ok,thurbox-cli plugin checkgreen; evidence/p…columns[...] = { slot = "center" }; evidence/place-pane-left.txtcenteranchor, nopanels.shown(, and nofilled(ctx,each exit 3 naming what was missing and leave no backup; a missing layout.lua exits 2; evidence/place-pane-refusals.txtcmpreports the file byte-identical to before the run--checkon a layout whose block is commented out → exit 1 "loads, lists, and draws nothing"; placing over it then succeeds--pane <copy declaring queue_v2>→ the written block guards and carvesqueue_v2; evidence/place-pane-renamed-slot.txt--layout "/tmp/.../o'brien/layout.lua"→ exit 0, block present; evidence/place-pane-quoted-path.txt./scripts/check.sh onboardingok;./scripts/onboarding-selftest.shgreen bare and under GIT_CONFIG_COUNT/KEY_0/VALUE_0 forcing gpgsign=false; evidence/onboarding-selftest.txt, selftest-hostile-git…./scripts/check.sh./scripts/preflight.shon this machine (real table, exit 0)./scripts/preflight.sh --commands,--tier required,--tier bogus(exit 2)env -i PATH=<sandbox> ./scripts/preflight.shwith gh/jq/thurbox-cli absent → exit 1, 3 required gaps namedenv -i PATH=<sandbox> ./scripts/preflight.sh --tier gateon the same machine → still exit 1 (view filtered, verdict not)./scripts/preflight.shwith all required present, quota-axi/glab/gate tools absent → exit 0./scripts/preflight.sh --tier requiredagainst a stubbed thurbox-cli 2.18.0 vs the manifest floor 2.19.0 →stalerow./scripts/preflight.sh --tier gateunder three fake HOMEs: gpgsign+no key, gpgsign+key, key scoped byincludeIf gitdir:<checkout>git show 2cf6088:scripts/queue-selftest.shrun on this machine (18 FAIL) vs./scripts/queue-selftest.sh(0 FAIL)./scripts/discover-owners.shon this machine./scripts/discover-owners.sh <fixture root>with an ssh-alias clone, anssh://git@ssh.github.com:443/...clone, a fork with an upstream remote, a node_modules clone, a.vim/pluggedclone and a GitLab clone./scripts/discover-owners.sh <empty root>with an empty HOME → exit 1./scripts/discover-owners.shwith onlygithub.userand a users.noreply commit email in HOME./scripts/discover-owners.shwith a temporary registry/owners.txt →*marker./scripts/place-pane.sh --check|--dry-run|(place)|--left|--pane <renamed>against copies of scripts/fixtures/layout/stock.lua./scripts/place-pane.shinto layouts with nocenteranchor, nopanels.shown(, nofilled(ctx,, and no layout file at all./scripts/place-pane.shinto a layout that does not parse as Lua → backup restored, file byte-identical (cmp)./scripts/place-pane.shinto a layout under a path containing an apostrophe./scripts/place-pane.sh --checkagainst the operator's real ~/.config/thurbox/ui/layout.lua (read-only)./scripts/onboarding-selftest.sh(bare, and underGIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=commit.gpgsign GIT_CONFIG_VALUE_0=false)./scripts/check.sh onboardingscripts/preflight.sh:296- Judgment call left to the author: the commit-signing row sits in thegatetier, whose heading prints "GATE — only ./scripts/check.sh needs these". Since the last commit made scripts/queue-selftest.sh forcecommit.gpgsign=falsefor the repos it builds, the gate no longer needs that configuration fixed — the row is now about any other sandbox or worktree commit (a worker's worktree outside the tree anincludeIf gitdir:block names). I made the prose accurate in preflight's comment, its printedwhyand the onboarding skill, but whether the row should stay ingateor move torecommendedis a tiering decision that changes program output and exit semantics, so it is out of the documentation phase's scope.🔧 Fix applied.
2 infos still open:
scripts/preflight.sh:262- Unresolved from the previous document round, and out of this phase's authority: the commit-signing row is recorded under thegatetier, whose printed heading is "GATE — only ./scripts/check.sh needs these" and whose header definition is "only./scripts/check.shneeds it. A control plane that never pushes a change never needs these." Since c4de77a made scripts/queue-selftest.sh forcecommit.gpgsign=falsefor the repos it builds (and it is the only selftest that commits —grep -n 'git commit' scripts/*.shfinds no other), the gate no longer needs that configuration fixed. The row's ownwhyis now accurate ("any sandbox or worktree"), so an operator reads a heading and a row that disagree. Resolving it either way is a code change I may not make here: move the row torecommended(record gate "commit signing"→record recommended, twice, at lines 262 and 265), or broaden thegateheading and tier definition. Documentation cannot close it without asserting one of those choices.scripts/place-pane.sh:73-./scripts/place-pane.sh --helpprints the lineset -uo pipefailafter the exit-code paragraph: the help renderer issed -n '2,48p'but the header block ends at line 46 (47 is blank, 48 is thesetline). preflight.sh ('2,33p') and discover-owners.sh ('2,31p') both stop exactly on their last header line, so this is an off-by-two in the new script only. It is a documentation defect whose fix is a one-character code edit ('2,48p' → '2,46p'), which this phase may not make. I also left the header's line count unchanged for that reason — adding lines to it would push real usage text out of the rendered range.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.