feat(#351): /setup seeds agent-routing.yaml + 8th portfolio config key (Wave 2 PR 3)#363
Conversation
…y (Wave 2 PR 3)
Split-portfolio adopters running `/setup --split-portfolio` no longer
need to manually `cp ~/ops/apexyard/agent-routing.yaml.example ~/ops/
apexyard-portfolio/agent-routing.yaml` after the bootstrap finishes —
the skill now copies it as part of Step 5 (private-repo init), and
writes the matching `agent_routing` key into the public fork's
.claude/project-config.json `portfolio:` block in Step 6.
Single-fork adopters are deliberately NOT auto-seeded; the framework
already gitignores `/agent-routing.yaml` (so no leak risk on a stray
push), and adopters who never want to customise routing should not
have an empty `agents: {}` file accumulating in the fork root. New
Step 7a is purely advisory — it tells single-fork adopters where to
start when they DO want to customise, with the explicit `cp` command.
Files changed:
- .claude/skills/setup/SKILL.md
- Step 5 (private-repo init): new bullet for seeding
`agent-routing.yaml` from `<fork>/agent-routing.yaml.example`
- Step 6 (public-fork config-block JSON): new `agent_routing` key
pointing at `../<sibling>/agent-routing.yaml`; updated trailing
prose to note the key is optional (defaults to ./agent-routing.yaml
against the ops-fork root, so single-fork adopters can skip it)
- New Step 7a (single-fork agent-routing seeding, advisory): tells
single-fork adopters about the cp + edit path; writes no files
- .claude/skills/setup/tests/test_setup_split_portfolio_v2.sh
- build_pre_setup_v2() now seeds an `agent-routing.yaml.example` in
the public fork (the framework artefact #353 ships)
- apply_setup_v2() extended: writes the 8th portfolio key
`agent_routing`, and copies `agent-routing.yaml.example` →
`<sibling>/agent-routing.yaml` (mirrors SKILL.md Step 5 cp)
- EXPECTED_KEYS array bumped from 7 to 8 (adds `agent_routing`)
- New Assertion 1b: agent-routing.yaml exists in the private repo
post-setup AND carries the `agents:` key (framework example shape)
- Updated success message from "all 7" to "all 8 v2 portfolio keys"
- Test PASSES at 11/11.
- docs/multi-project.md
- "Seed from the framework example" prose now notes split-portfolio
is automated by `/setup --split-portfolio` (#351 PR 3); single-fork
stays manual + only-when-ready-to-customise
- "What ships next" list drops the now-landed PR 3 row
Refs #351
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
atlas-apex
left a comment
There was a problem hiding this comment.
Code Review: PR #363
Commit: 543d1823d8678f486ebd61c95cd5422fc39519c8
Summary
Wave 2 PR 3 of #351: /setup --split-portfolio auto-seeds agent-routing.yaml in the private repo (Step 5) and writes the 8th portfolio.agent_routing key into the public fork's .claude/project-config.json (Step 6). Adds advisory Step 7a for single-fork adopters (no auto-seed, gitignore covers leak risk). 3 files, +61/-11. Updated split-portfolio v2 test bumps EXPECTED_KEYS from 7→8 and adds Assertion 1b for the seeded file's presence + agents: key. Test suite passes 11/11 locally.
Checklist Results
- ✅ Architecture & Design: Pass
- ✅ Code Quality: Pass
- ✅ Testing: Pass — Assertion 1b is tight (checks file exists AND grep
^agents:, sotouchregression would fail) - ✅ Security: Pass (no auth/secret/crypto surface)
- ✅ Performance: Pass (one extra
cpin a bootstrap-class skill — negligible) - ✅ PR Description & Glossary: Pass — glossary covers seed-vs-fill, the 8-key list, and the single-fork manual rationale
- ✅ Summary Bullet Narrative: Pass — every bullet names what changed + why (no label-only)
- ✅ Technical Decisions (AgDR):N/A — wiring follows AgDR-0050 § Axis 3 (no new decision introduced)
- ✅ Adopter Handbooks: N/A — no handbooks loaded (diff is markdown + bash test)
- ✅ CI checks: lychee + markdownlint + ticket-id + site-counts all green
Verifications performed against framework artefacts
-
SKILL.md Step 5 bullet shape — the new
agent-routing.yamlbullet sits immediately aftercustom-handbooks/and mirrors the established bullet shape: bold filename → one-sentence purpose → why-it-matters → cross-ref to the canonical doc →(Added in #351 PR 3.)provenance. Reading flow is consistent with thecustom-skills/custom-handbooks/onboarding.yamlbullets above it. -
SKILL.md Step 6 config-block JSON —
agent_routingis the 8th key (afterregistry,projects_dir,ideas_backlog,onboarding,workspace_dir,custom_skills_dir,custom_handbooks_dir). Path matches the v2 convention../apexyard-portfolio/agent-routing.yaml. Trailing prose correctly explains both that the key is optional (default./agent-routing.yamlagainst ops-fork root) AND that setting it explicitly is the v2 shape. -
Step 7a (single-fork advisory) — rationale is sound and internally consistent. The framework's
.gitignore(verified: line 20/agent-routing.yaml) already covers the leak risk, and the SessionStart hookapply-agent-routing.sh(verified: lines 97–101) reads via the safe[ -z "$ROUTING_PATH" ] || [ ! -f "$ROUTING_PATH" ]pattern — missing file is a zero-config no-op exit. So Step 7a's "don't auto-seed" choice is properly load-bearing on a graceful-degrade contract that already exists in #357's hook. Contrast withcustom-skills/andcustom-handbooks/in Step 5: those DO need to exist as empty dirs because the symlink/discovery mechanisms walk them at SessionStart;agent-routing.yamldoesn't need that and Step 7a is consistent with the rule "auto-seed only what the framework's read-path requires to exist". -
Test extension — verified locally:
build_pre_setup_v2()seeds an example file with exactlyversion: 1+agents: {}— matches the real framework example's first two non-comment lines (verified by grep: lines 51 and 92 ofagent-routing.yaml.example).apply_setup_v2()adds the 8th key to the JSON block AND copies the example into the private repo (guarded by[ -f example ] && [ ! -f target ]— idempotent + safe).EXPECTED_KEYSupdated 7→8 (verified the array's contents match the JSON block keys).- Assertion 1b:
[ -f "$PRIVATE_ROUTING" ] && grep -q '^agents:' "$PRIVATE_ROUTING"— would correctly fail on atouchregression because grep wouldn't match. - Test ran locally: Passed 11 / Failed 0.
-
docs/multi-project.md update — accurately reflects the new automation. The "Seed from the framework example" prose now leads with the automation + uses "Manual fallback" framing for the split-portfolio command (right for adopters re-running
/setupon an already-migrated fork or hitting a corner case). The "What ships next" list correctly drops the PR 3 row, leaving only PR 4 (gated on #348). No false claims about PR 4 status. -
Scope discipline — 3 files, no drive-by edits. Verified
git show --stat: only.claude/skills/setup/SKILL.md,.claude/skills/setup/tests/test_setup_split_portfolio_v2.sh, anddocs/multi-project.mdtouched. No CLAUDE.md / site / AGENTS.md / handbooks / unrelated rules changes. -
Compatibility with #353 + #357 — verified directly:
_lib-portfolio-paths.shline 292 definesportfolio_agent_routing()reading.portfolio.agent_routingwith default./agent-routing.yaml. The new key written by Step 6 is exactly the one the resolver expects.apply-agent-routing.shline 97 callsportfolio_agent_routingand (lines 98–101) gracefully exits on missing file. The seeded YAML's shape (version: 1+agents: {}) matches what the hook's parser expects for a zero-override config — no warnings on a freshly-bootstrapped fork.
Issues Found
None.
Suggestions
None blocking. Minor observations the author may or may not care to action in a follow-up:
- nit (advisory, not blocking): Step 7a's pseudo-code block uses
$EDITOR— fine for the advisory, but the single-fork section is the one place where adopters who've never used the framework before see acp + editflow without surrounding context. Consider whether a one-line "(orvim/code/ your editor of choice)" note is worth adding. Pure ergonomics, not load-bearing.
Verdict
APPROVED
Clean, focused, well-tested. Test PASS at 11/11 with the new Assertion 1b covering the seed correctness. Step 7a's "no auto-seed" rationale is internally consistent with the framework's existing graceful-degrade contract from #357. Documentation in docs/multi-project.md accurately captures the new automation. No scope creep. The 8th key wires cleanly into the resolver shipped in #353.
Ready to merge once CEO records per-PR approval via /approve-merge 363.
🤖 Reviewed by Rex (Code Reviewer Agent)
📌 Reviewed commit: 543d1823d8678f486ebd61c95cd5422fc39519c8
…y (Wave 2 PR 3) (#363) Split-portfolio adopters running `/setup --split-portfolio` no longer need to manually `cp ~/ops/apexyard/agent-routing.yaml.example ~/ops/ apexyard-portfolio/agent-routing.yaml` after the bootstrap finishes — the skill now copies it as part of Step 5 (private-repo init), and writes the matching `agent_routing` key into the public fork's .claude/project-config.json `portfolio:` block in Step 6. Single-fork adopters are deliberately NOT auto-seeded; the framework already gitignores `/agent-routing.yaml` (so no leak risk on a stray push), and adopters who never want to customise routing should not have an empty `agents: {}` file accumulating in the fork root. New Step 7a is purely advisory — it tells single-fork adopters where to start when they DO want to customise, with the explicit `cp` command. Files changed: - .claude/skills/setup/SKILL.md - Step 5 (private-repo init): new bullet for seeding `agent-routing.yaml` from `<fork>/agent-routing.yaml.example` - Step 6 (public-fork config-block JSON): new `agent_routing` key pointing at `../<sibling>/agent-routing.yaml`; updated trailing prose to note the key is optional (defaults to ./agent-routing.yaml against the ops-fork root, so single-fork adopters can skip it) - New Step 7a (single-fork agent-routing seeding, advisory): tells single-fork adopters about the cp + edit path; writes no files - .claude/skills/setup/tests/test_setup_split_portfolio_v2.sh - build_pre_setup_v2() now seeds an `agent-routing.yaml.example` in the public fork (the framework artefact #353 ships) - apply_setup_v2() extended: writes the 8th portfolio key `agent_routing`, and copies `agent-routing.yaml.example` → `<sibling>/agent-routing.yaml` (mirrors SKILL.md Step 5 cp) - EXPECTED_KEYS array bumped from 7 to 8 (adds `agent_routing`) - New Assertion 1b: agent-routing.yaml exists in the private repo post-setup AND carries the `agents:` key (framework example shape) - Updated success message from "all 7" to "all 8 v2 portfolio keys" - Test PASSES at 11/11. - docs/multi-project.md - "Seed from the framework example" prose now notes split-portfolio is automated by `/setup --split-portfolio` (#351 PR 3); single-fork stays manual + only-when-ready-to-customise - "What ships next" list drops the now-landed PR 3 row Refs #351 Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
/setup --split-portfolionow auto-seedsagent-routing.yamlin the private repo. Step 5 (private-repo init) copies<fork>/agent-routing.yaml.exampleto<private_repo>/agent-routing.yaml. Adopters no longer need to remember the manualcp ~/ops/apexyard/agent-routing.yaml.example ~/ops/apexyard-portfolio/agent-routing.yamlpost-bootstrap step — the routing config lands ready to edit. The seeded file starts at the framework example'sagents: {}empty-overrides shape, so adopters get framework defaults out-of-box and only need to touch the file when they want to customise./setup --split-portfolioStep 6 now writes the 8thportfolio.*config key —agent_routing: ../<sibling>/agent-routing.yaml— into the public fork's.claude/project-config.json. This wiresportfolio_agent_routing(resolver from feat(#351): agent-routing.yaml schema + portfolio_agent_routing resolver (Wave 1 PR 1) #353) to the just-seeded private file. The key is documented as optional in the SKILL.md prose: single-fork adopters can omit it and rely on the default./agent-routing.yamlresolution against the ops-fork root.cpcommand, but the skill writes no files for them. Rationale: the framework already gitignores/agent-routing.yaml(so there's no leak risk on a stray push), and adopters who never customise shouldn't have an emptyagents: {}file accumulating in the fork root. Theycponce they're ready to override.docs/multi-project.mdupdated: the "Seed from the framework example" recipe section now notes split-portfolio gets automated by/setup --split-portfolio; the "What ships next" list drops the PR 3 row.test_setup_split_portfolio_v2.shextended:build_pre_setup_v2()seeds anagent-routing.yaml.examplein the public fork (the framework artefact feat(#351): agent-routing.yaml schema + portfolio_agent_routing resolver (Wave 1 PR 1) #353 ships).apply_setup_v2()extends to write the 8th portfolio key + copy the example into the private repo.EXPECTED_KEYSarray bumped from 7 to 8 (addsagent_routing). New Assertion 1b verifies the seed actually lands in the private repo with the right shape. Test PASSES at 11/11.Testing
bash .claude/skills/setup/tests/test_setup_split_portfolio_v2.sh— PASS at 11/11 (was 9/9 before this PR's two new assertions).bash .claude/skills/setup/tests/test_setup_single_fork.sh— unchanged + still PASS (no single-fork file-writes in this PR).bash .claude/hooks/tests/test_portfolio_agent_routing.sh— verifies theportfolio_agent_routingresolver from feat(#351): agent-routing.yaml schema + portfolio_agent_routing resolver (Wave 1 PR 1) #353 reads the newagent_routingkey correctly. Still PASSES with the post-PR-3 key layout./setup --split-portfolioagainst a fresh fork-and-sibling pair; verify the private repo hasagent-routing.yamland the public fork's project-config.json has theagent_routingkey. Not blocking — covered by the automated test.Glossary
agent-routing.yaml.exampletoagent-routing.yamlwithout modification. Adopters get the framework's worked-examples shape (commented schema + an emptyagents: {}block at the top). Editing is opt-in — the file is functional from the start because empty overrides == framework defaults.portfolio.agent_routingjoins the v2 portfolio block alongsideregistry,projects_dir,ideas_backlog,onboarding,workspace_dir,custom_skills_dir,custom_handbooks_dir. The default resolution is./agent-routing.yamlagainst the ops-fork root, so the key is optional for single-fork adopters. Split-portfolio adopters set it explicitly to the sibling-repo path./agent-routing.yaml, so the cost of "I have to remember tocp" is one shell line when the adopter is ready to customise. Split-portfolio is different because the seeded file IS the canonical adopter-routing source for the private repo + an artefact a teammate cloning the private sibling repo would expect to see.Refs #351 (3/4 PRs of the wave plan landed; PR 4 — local-routing entries — remains, gated on #348 spike verdict)