issue-triage — Triagy
Single-shot card router: fired by the trigger spine on triage:auto (consumed one-shot), reads ONE board card, stamps the handler bot (set_bot) + source:issue-triage, comments its rationale, leaves the card in inbox. Companion of the ingest author-trust gate (trusted authors → triage:auto, external authors → needs:approval + studio "Approve & triage").
2026-07-22 — treatment follow-through: 3 triaged cards driven to delivery (runs 019f8949 / 019f8979 / 019f898e)
- Status: validated (triage→ready→dispatch→feature-dev→delivery, end-to-end)
- Versions: iterion main @0da792861 → @e6f419892 · feature-dev v2
- Method: cards #250/#246/#202 dragged to ready one wave at a time; native dispatcher (studio-embedded) claimed and ran feature-dev per card; runs observed live; deliveries landed on local main (cherry-pick when finalize couldn't FF). ~$14 total for 3 real engine fixes by Viczei's specs.
- Result: 3/3 features delivered on main — #250 json-field schema type union (+ADR-083), #246 quoted loop-cap fix, #202 subbot child Manager registration. Cards ended in review with claims released.
- Engine/bot hardening from observed frictions (all committed same-day):
- orphan reconciler killed a live dispatcher run 16s after dispatch (no flock + slow boot scan) → EngineRunner run-lock + 2-min grace.
- stale committed catalog → every worktree run wip-banked a garbage branch each 15s heartbeat; the freshness guard had passed on a stale go-test CACHE (reads files outside the package) → catalog refreshed; follow-up: move the freshness check to a cache-proof surface.
- drift-gate precheck false positive on brew-update.yml's commit-if-changed
git diff --staged --quiet→ heuristic now demands build-failing semantics; regression subtests run the real command. - author-quoted ref
ITER="{{input.iteration}}"→ shellEscape's own quotes made python int() fail → probe stuck on "first pass", paying verify_build + rewriting verify.sh EVERY pass → ref unquoted across 6 bots; e2e pins the engine mapping (which was correct). Diagnostic candidate: compile warning for quoted refs in tool commands. - mid-flight "recovered finalize" marked the run finalized → the true completion finalize skipped and stranded delivery on the per-node GC refs → finalize now re-runs when the worktree HEAD moved past the recorded FinalCommit.
- verify_build generated gateless verify.sh (skill 1b ignored) → MANDATORY CI-drift-mirror clause added to the authoring prompts fleet-wide.
- Wave 3 addendum (#204, #205 — same day): both delivered on main (#204: M3 ParentRunID + M4 atomic unique title + L5 ?since= pruning; #205: subbot re-attach across restarts, ADR renumbered 084 at landing — the run had reused 083). #205's in-loop adversarial review caught a REAL blocking lifecycle bug (re-attach record cleared on mid-re-park restart) and pass 2 fixed it — the review gate earning its keep. Two more frictions: (7) the dispatcher auto-RETRIES an operator-cancelled run (resume) — operator cancel should be terminal for the retry policy; (8) a dispatched run's worktree forks the REPO-ROOT checkout, not the studio's --dir — #205's commits landed on top of an unrelated test branch the operator had checked out mid-session (delivery had to be re-based commit-by-commit; #203/Willy deferred for the same reason — it edits its workspace in place).
- Wave 4 (#203, Willy/whole-improve-loop): the reference-quality run. Launched via CLI from a CLONE pinned to main (friction 8 workaround — nested worktrees fork the PRIMARY checkout's HEAD, and the operator's checkout was on a test branch), improvement_prompt = the card body. Converged FIRST pass: ~$3.2 / ~15 min for both axes (M2 atomic ClaimForLaunch CAS + M1 pipeline-board memoization), 254+ added lines incl. tests, drift mirror included up front by the hardened verify_build prompt (no exit-3 wall), auto squash-merged into the clone's main by finalize. Cost/value profile exactly on target.
- Lessons: dispatcher-claimed treatment is solid once the above are in; the campaign/precheck tug-of-war (agent stripping "irrelevant" gates) is fully resolved by fixing the probe reuse (bug 4) + prompt (6); remaining cards (#204/#205/#203) intentionally deferred — the operator's checkout moved to a test branch mid-session and fresh worktrees would have forked it.
2026-07-22 — first dogfood: 7 real GitHub-synced cards (runs 019f88e7…019f88f2)
- Status: validated (local engine; the cloud spine shipped the same day, un-dogfooded — see "next run")
- Versions: bot 0.1.0 · iterion worktree-issue-auto-triage @5594b6395
- Method:
iterion issue import --forge github --repo SocialGouv/iterion --min-author-roledefault (developer) → 17 cards (open ones stampedtriage:auto— Viczei + devthejo both hold write; closed ones landed in done, unstamped, author persisted on every card). Dedicated studio from the worktree binary on :4899 bound to the WORKSPACE store (--store-dir $PWD/.iterion, operator-visible), sandbox off (ITERION_SANDBOX_DEFAULT=none), triage fired via the spine by re-emitting a card event (identity label update). Backend claw, final model pinopenai/gpt-5.5. - Result: 7/7 cards triaged end-to-end (spine → consume → direct launch with
vars.issue_id→ get_issue → skill catalog → set_bot → set_labels → comment). ~$0.005–0.012 and ~20–40s per card, ≈5¢ total. Cards stayed in inbox; label consumed exactly once per fire; re-addingtriage:autore-armed correctly. - Value: exactly the intended operator loop — fresh issues arrive pre-routed; launching = one drag to Ready. Classifications all plausible: Renovate Dependency Dashboard →
secured-renovacy, "improve existing pipeline-board behaviors" →whole-improve-loop, concrete bugs/features (#202/#204/#205/#246/#250) →feature-dev. - Findings / misses (bot-side, all fixed in-run):
max_iterations: 1in the budget killed the run after the FIRST LLM step — dropped (duration+cost caps suffice for a 1-node bot).- claw with an empty
tools:list = a TOOL-LESS LLM call; the capability-granted board tools are only appended whentools:is non-empty.tools: [skill]fixed it (and the skill tool is needed anyway for the catalog). - gpt-5.4-mini (claw auto-default) skipped procedure steps (no skill read, no labels, no comment) even under a MANDATORY-labelled system prompt. gpt-5.5 + a NUMBERED tool sequence in the USER prompt follows the contract fully → model pinned.
- Engine hardening (found by this run):
set_bot's own input schema suggested the obsolete underscore spelling (e.g. feature_dev) — both models faithfully copied it over the catalog's dash form. Fixed in boardops; a stale example in a tool description outweighs a whole skill.- The whats-next catalog regen was mono-bundle; generalized to every bundle shipping the static template (issue-triage ships its own).
- Same-day follow-up (@8f2b10934): the CLOUD half of the board spine (board_events poll-tail + CAS cursor + atomic ConsumeLabels + team-scoped /api/v1/triggers) so the flow works on prod — written, tested (mongo conformance), NOT yet dogfooded.
- Lessons for next run:
- Dogfood on the PROD CLOUD instance (operator's ask): enable Triagy's board trigger for the team (
POST /api/v1/bots/issue-triage/triggers/ from-invocation), sync a repo withMinAuthorRoleset, verify an external author's issue parks (needs:approval+ banner) and that "Approve & triage" fires exactly one triage run across replicas. - The trigger-label nudge (identity label re-set) is the manual replay gesture; document it for operators (already in the vocabulary skill).
- Watch for
axis:label reuse quality on boards with a rich existing vocabulary — this board's history made the model reusearea:*(anti-pattern) once before the source-labels rule was tightened.
- Dogfood on the PROD CLOUD instance (operator's ask): enable Triagy's board trigger for the team (
