design: New dispatch workflow default to be included with agentfactory (#73)#74
design: New dispatch workflow default to be included with agentfactory (#73)#74stempeck wants to merge 9 commits into
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
- source.md (verbatim requirements) - codebase-snapshot.md (verified ground truth for sub-agents) - verification.md (Gate A: forced-enumeration AC/constraint table) - dimension files (api/data/ux/scale/security/integration) - audit.md, conflicts.md, dependencies.md (dimension analysis) - elevation_assessment.md (architecture elevation verdict) - six_sigma_gaps.md (six-sigma gap analysis) - verification-report.md (fidelity verification of all codebase claims) - synthesis-checklist.md (Gate B: pre-synthesis re-grounding) - design-doc.md (AC Traceability, elevation verdict, six-sigma caveats) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
…spatch workflow default to be included with agentfactory) Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
|
agentfactory seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
…er (#73) Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
Independent rootcause-review (Mode A) appended a '# Peer Review' section: all code anchors re-verified; outline correctly corrects design-doc's install.go:176 mis-citation. Found 3 actionable defects (E-1 Phase-1 AC references an integration-tagged test invisible to make test; E-2 wrong path for formula_drift_test.go; G-1 K8 discovery_failed state not derivable from disk). Verdict: PARTIALLY VALIDATED, proceed to human review with corrections. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
design-plan-impl: implementation plan outline addedOutline Summary
Independent Peer Review (appended to the outline)
Next StepReview the outline (with the appended peer review). After approval, extract phases one at a time via: |
…rmula done Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
A fresh `af install --init` now produces a valid-by-construction, ready-to-use dispatch configuration so a bootstrapped factory can drive label-triggered work with no hand-editing (issue #73). - K1 config.DefaultDispatchConfigJSON(repo): single-source dispatch.json default built from the DispatchConfig struct (4 label->agent mappings + feature-workflow + trigger_label "agentic"); empty repo degrades to the loadable empty shape. notify_on_complete is omitted (defaults to "manager" at runtime; +omitempty tag). - K2/K3 discoverRepo: non-interactive owner/name discovery (gh repo view -> git remote origin fallback) via the runGitDetect seam, validated by a strict owner/name allowlist before it reaches disk/banner/gh (flag-injection guard). - K4 wire runInstallInit to the builders; additive escape-safe banner line. - K5 config.DefaultAgentsConfigJSON(): seeds the four specialists (rapid-soldesign-plan, rapid-implement, ultra-review, rapid-increment) into the default agents.json so every dispatch mapping resolves (cross-review C1). Each carries a description (validateAgentConfig requires it) + its formula. - K6 dispatch loop tolerates a partial factory: skip-and-warn on unprovisioned mapping agents, dispatch the rest; the write path (af config dispatch set) stays strict. - K8 `af dispatch status --json` and the `af up` pre-flight surface a config_state (ok / not_configured / references_unprovisioned_agents / invalid). - K9 hoist dispatcher auto-start out of the blanket-only gate so the documented positional `af up manager` also starts the polling loop (idempotent; cross-review C2). - K7 golden + cross-file tests pin the default's validity against the seeded agents; updated the scaffold + status-snapshot + install-integration tests; docs note the two-label requirement and net-new-install scope. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: agentfactory-cli <293373236+agentfactory-cli@users.noreply.github.com>
rapid-implement: implementation landed on this PR's branchResolves the implementation for #73 via the rapid-implement process (classify → test-first → implement → verify → blind review). The code continues this PR's branch ( Implemented
Gates: test-first failing test proven (GATE 2) → target tests pass (GATE 3) → full suite green across root + web modules (GATE 4, 0 FAIL) → blind review 9/10 (GATE 5). Deviations (each serves the design's goal): added |
stempeck
left a comment
There was a problem hiding this comment.
Code review
Found 4 issues. 3 are posted as inline comments on the diff; 1 is below (its lines are outside the diff hunks):
- Stale
af uphelp text and comment after the K9 hoist. This PR movesstartDispatch/launchWatchdogoutside theif blanket { }gate, sostart_dispatch: truenow fires on the positional path too (af up managerauto-starts the dispatcher). But theupCmd.Longhelp text still promises the old behavior — "Positional 'af up ' ignores startup.json and starts exactly those agents." — and the inline comment that documents the blanket-only invariant was not updated either. Stale-by-consequence of this diff.
agentfactory/internal/cmd/up.go
Lines 39 to 41 in b2b3305
(the now-stale invariant comment is at
agentfactory/internal/cmd/up.go
Lines 87 to 89 in b2b3305
🤖 Generated with Claude Code
- If this code review was useful, please react with 👍. Otherwise, react with 👎.
| for _, agent := range unknownAgents { | ||
| fmt.Fprintf(cmd.ErrOrStderr(), "warning: skipping dispatch mappings for unprovisioned agent %q (not in agents.json)\n", agent) | ||
| } | ||
| dispatchCfg.Mappings = knownMappings |
There was a problem hiding this comment.
K6 reassigns dispatchCfg.Mappings = knownMappings to drop unprovisioned agents, but dispatchCfg.Workflows is left unfiltered. matchWorkflow still matches workflow-labeled items against the unfiltered Workflows and routes them to handleWorkflowItem, where phaseMapping(w.dispatchCfg.Mappings, phase) returns !ok for any stripped phase and hits w.stall(...). Because stall does not mutate the item's labels, this fires on every dispatch cycle (default 300s), incrementing stats.errors — a repeating error-level stall, not the clean stats.skipped skip that non-workflow items get. The CRITICAL-2 guard comment calls this path "belt-and-suspenders for the Phase-1 validator", i.e. assumed unreachable for a valid config — but the K6 partition makes it reachable (the post-filter ValidateDispatchConfig continues over the stripped phase). The K8 pre-flight warning in up.go also tells the operator the dispatcher will "skip those mappings", which is inaccurate for workflow-labeled items.
| // K8 (mandatory with K6): pre-flight the dispatch config against agents.json and warn | ||
| // (never abort) when it references unprovisioned agents — else a fresh/partial factory | ||
| // launches a dispatcher the K6 loop silently skip-and-warns on every cycle. | ||
| if loadDispatchConfigState(root) == dispatchStateUnprovisioned { |
There was a problem hiding this comment.
This pre-flight only warns when the state is dispatchStateUnprovisioned; dispatchStateInvalid is never surfaced. When the config loads at the struct level but fails ValidateDispatchConfig cross-file checks (e.g. notify_on_complete names an absent agent, or a workflow phase maps to a formula-less agent), no warning is printed here, and startDispatch's guard only catches ErrNotFound/ErrMissingField, so the dispatcher session still launches. The loop then fails ValidateDispatchConfig every cycle, logging only to the tmux pane — so af up exits cleanly and reports "Dispatcher started" while silently dispatching nothing, defeating the K8 observability goal for the invalid state.
| // scheme://host/owner/repo → strip "scheme://host". | ||
| rest := s[i+3:] | ||
| j := strings.IndexByte(rest, '/') | ||
| if j < 0 { | ||
| return "" | ||
| } | ||
| s = rest[j+1:] | ||
| } else if i := strings.LastIndex(s, ":"); i >= 0 { | ||
| // scp-like user@host:owner/repo → keep the part after ':'. |
There was a problem hiding this comment.
These two inline comments — // scheme://host/owner/repo -> strip "scheme://host". here and // scp-like user@host:owner/repo -> keep the part after ':'. at line 43 — restate what the adjacent code does rather than why, and the function-level doc comment already enumerates the URL shapes handled. Per CLAUDE.md (Code comments): "Code comments should ONLY exist when it makes sense to explain WHY the code is doing what it does ... Comments should be minimal or ideally, not exist at-all UNLESS they add VALUE to the code."
Issue
Design for #73 — New dispatch workflow default to be included with agentfactory
#73
A freshly bootstrapped factory cannot drive autonomous work from GitHub labels:
af install --initwrites an emptydispatch.json(repos:[],mappings:[],no
workflows—internal/cmd/install.go:145), so a new user must hand-edit thefile before label-triggered dispatch works. The issue asks for a useful baked-in
default, populated with the real
owner/repodiscovered at install time.Root cause
runInstallInitships an emptydispatch.jsonand performs no repo-namediscovery, even though quickstart has already
cd'd into the repo (the fact isdiscarded). —
install.go:145, verified.sufficient: the default's four mappings reference specialist agents
(
rapid-soldesign-plan,rapid-implement,ultra-review,rapid-increment)that a fresh
agents.jsondoes not contain (install ships onlymanager+supervisor), andValidateDispatchConfighard-fails the entiredispatch cycle on the first unknown mapped agent (
internal/config/dispatch.go,invoked unconditionally at
internal/cmd/dispatch.go:146). So the default alonewould break dispatch on every fresh factory.
Proposed solution
A single systemic change (valid-by-construction), not just a literal default:
DefaultDispatchConfigJSON(repo)— single-source builder besideDefaultFactoryConfigJSON()(config.go:111), emitting the 4 label→agentmappings +
feature-workflow+trigger_label:"agentic".gh repo view --json nameWithOwner, withgit remote get-url originfallback) feedingrepos; warn-don't-abort.owner/namevalidator at the write boundary (guards flag/escapeinjection from a crafted remote).
DefaultAgentsConfigJSON()— seeds the 4 specialists into the defaultagents.jsonwithinrunInstallInititself (the role templates are alreadyembedded), making the default valid on every init path, including the bare
af install --init"hard way" — not just quickstart.blanket-only gate so thedocumented
af up manager(positional) also starts the polling loop (idempotent).mandatory observability (K8), plus a golden cross-file drift test (K7).
Architecture-elevation verdict: Frame correct (the dispatch fields must exist;
deleting
dispatch.jsononly relocates them) with one offered lift adopted —repo self-derivation (K2).
Cross-review (round 1)
Analyst (
rootcause-all) reviewed the design grounded in its root-cause analysis(9 concerns; 8 validated). It converged with the design on every primary point
and raised, the designer (
design-v7) incorporated, all findings:af install --initleft the populated default referencing unregistered agents.→ Fixed by K5 seeding specialists in
runInstallInititself.af up manager(positional) does notauto-start the dispatcher (gated to blanket
af up). → Fixed by K9 hoistingthe auto-start.
agent-gen-all.sh). → K5 now commits to directagents.jsonseeding.enabled (else a "running-but-dispatching-nothing" loop hides the failure).
Both CRITICAL items were genuine entry-point/sequencing gaps; both are small,
localized, and strengthen the valid-by-construction thesis rather than redirect
it. With C1+C2 incorporated, the design satisfies AC-2 and AC-3 on every documented
setup path. (design-doc.md grew 319 → 365 lines.)
Artifacts
.designs/73/design-doc.md— full design (dimension analyses, AC traceability6/6, elevation verdict, risk registry, 3-phase implementation plan)
.designs/73/cross-review/analyst-review-design.md— analyst round-1 review.designs/73/cross-review/designer-update-log.md— incorporation log.designs/73/problem-summary-73.md,.designs/73/design-refinement-progress.md