-
Notifications
You must be signed in to change notification settings - Fork 0
Pipeline Plan 203
Plan stage complete. The implementation plan is written to .claude/pipeline-artifacts/plan.md with:
- ADR: 3 alternatives evaluated, chose modular extraction with thin orchestrator
-
3 modules:
sw-role-manager.sh(18 functions — roles, matching, evaluation, promotion),sw-team-composer.sh(5 functions — team, onboard, mind, decompose, invent),sw-config-validator.sh(6 functions — audit, reflect, self-tune, meta-learning, help) -
Orchestrator:
sw-recruit.shretains ~200 lines of shared infra (storage paths, locking, policy, Claude helpers, CLI router) -
Source order: config-validator first (so role-manager can call
_recruit_meta_learning_check) -
Zero caller changes: all external scripts continue invoking
sw-recruit.sh <subcommand> - 10 tasks, 30 unit tests planned across 3 test files, plus existing integration suite for behavioral parity parity guarantee
- Split into 6+ micro-modules — Rejected: over-engineering for a shell script; three modules match the natural domain boundaries
- Keep monolith, add tests only — Rejected: doesn't address the core maintainability issue
- Each module can be tested in isolation
- Changes to role matching don't risk breaking team composition
-
sw-recruit.shdrops from ~2644 to ~200 lines (orchestrator + shared infra) - All callers (
sw-pipeline.sh,sw-loop.sh,sw-triage.sh, etc.) continue callingsw-recruit.shunchanged
┌─────────────────────────────────────────────────┐
│ sw-recruit.sh (orchestrator) │
│ ┌───────────────────────────────────────────┐ │
│ │ Shared: VERSION, storage paths, helpers, │ │
│ │ _recruit_locked_write, _recruit_policy, │ │
│ │ ensure_recruit_dir, _recruit_has_claude, │ │
│ │ _recruit_call_claude, CLI router │ │
│ └──────────┬──────────┬──────────┬──────────┘ │
│ │ │ │ │
│ source │ source │ source │ │
│ ┌─────┘ ┌─────┘ ┌─────┘ │
│ ▼ ▼ ▼ │
│ ┌─────────┐┌─────────┐┌──────────────┐ │
│ │ role- ││ team- ││ config- │ │
│ │ manager ││composer ││ validator │ │
│ └─────────┘└─────────┘└──────────────┘ │
└─────────────────────────────────────────────────┘
External callers (sw-pipeline.sh, sw-loop.sh, sw-triage.sh, etc.)
invoke sw-recruit.sh directly — no change to integration points.
- Orchestrator sources all three modules
- Modules depend on shared functions in orchestrator (helpers, storage paths, locking)
- Modules do NOT source each other (no circular deps)
- Exception:
cmd_record_outcome(role-manager) calls_recruit_meta_learning_check(config-validator) — solved by having orchestrator source config-validator before role-manager
// Functions moved here: initialize_builtin_roles(): void // Initialize 10 built-in roles _recruit_keyword_match(task: string): void // Fast regex matching, prints JSON _recruit_llm_match(task: string): void // LLM semantic matching, prints JSON _recruit_record_match(task, role, method, confidence, agent_id?): void // Log match, sets LAST_MATCH_ID _recruit_track_role_usage(role, outcome): void // Update role stats cmd_create_role(...args): void // Create/auto-gen role cmd_record_outcome(agent_id, role, outcome, quality, duration): void // Record result cmd_ingest_pipeline(limit?): void // Backfill from events cmd_evolve(): void // Role evolution analysis cmd_specializations(): void // Agent specialization view cmd_route(role): void // Smart routing cmd_roles(): void // List roles cmd_match(...args): void // Match task to role cmd_evaluate(agent_id): void // Evaluate agent cmd_profiles(): void // Show profiles cmd_promote(agent_id): void // Promote recommendation cmd_stats(): void // Usage statistics _recruit_compute_population_stats(): void // Population stats helper // Errors: exits 1 on missing required args, warns on LLM unavailable // Depends on: ROLES_DB, PROFILES_DB, MATCH_HISTORY, ROLE_USAGE_DB, HEURISTICS_DB
// Functions moved here: cmd_team(...args): void // Team composition (heuristic/LLM) cmd_onboard(role, agent_id?): void // Generate onboarding context cmd_mind(agent_id?): void // Theory of mind profiles cmd_decompose(goal): void // Goal decomposition cmd_invent(): void // Autonomous role invention // Errors: exits 1 on missing goal/role, warns on LLM unavailable // Depends on: ROLES_DB, PROFILES_DB, AGENT_MINDS_DB, INVENTED_ROLES_LOG, MATCH_HISTORY
// Functions moved here: _recruit_meta_learning_check(agent, role, method, outcome): void // Post-outcome meta check cmd_reflect(): void /_recruit_reflect():void// Accuracy analysis _recruit_meta_validate_self_tune(): void // Validate self-tune effectiveness cmd_self_tune(): void // Learn keyword→role weights cmd_audit(): void // Full system audit cmd_help(): void // Help text // Errors: audit returns 1 on failures, reflect warns on low accuracy // Depends on: META_LEARNING_DB, HEURISTICS_DB, MATCH_HISTORY, all DB files (audit)
User/Script → sw-recruit.sh CLI router
│
├── match/evaluate/promote/roles → sw-role-manager.sh
│ ├── reads ROLES_DB, PROFILES_DB, HEURISTICS_DB
│ ├── writes MATCH_HISTORY, ROLE_USAGE_DB, PROFILES_DB
│ └── calls _recruit_meta_learning_check (config-validator)
│
├── team/onboard/mind/decompose/invent → sw-team-composer.sh
│ ├── reads ROLES_DB, PROFILES_DB, AGENT_MINDS_DB
│ └── writes AGENT_MINDS_DB, INVENTED_ROLES_LOG, ROLES_DB
│
└── audit/reflect/self-tune → sw-config-validator.sh
├── reads all DB files, other scripts (audit)
└── writes META_LEARNING_DB, HEURISTICS_DB
| Component | Handles | Propagates |
|---|---|---|
| Orchestrator | Missing subcommand, unknown command | Exit 1 with help |
| Role Manager | LLM unavailable (fallback to keywords), missing agent profiles (skip) | Exit 1 on missing required args |
| Team Composer | LLM unavailable (fallback to heuristics), empty roles DB | Exit 1 on missing goal |
| Config Validator | Invalid JSON DBs (report in audit), accuracy below floor (revert heuristics) | Audit exit 1 on failures |
-
scripts/sw-role-manager.sh— Role management functions extracted from sw-recruit.sh -
scripts/sw-team-composer.sh— Team composition functions extracted from sw-recruit.sh -
scripts/sw-config-validator.sh— Config validation functions extracted from sw-recruit.sh -
scripts/sw-role-manager-test.sh— Unit tests for role manager -
scripts/sw-team-composer-test.sh— Unit tests for team composer -
scripts/sw-config-validator-test.sh— Unit tests for config validator
-
scripts/sw-recruit.sh— Becomes thin orchestrator sourcing the three modules -
scripts/sw-recruit-test.sh— Verify existing tests still pass (integration tests)
Extract from sw-recruit.sh (lines):
-
_recruit_meta_learning_check(1187-1237) -
cmd_reflect/_recruit_reflect(1239-1323) -
_recruit_meta_validate_self_tune(1325-1374) -
cmd_self_tune(1755-1876) -
cmd_audit(2383-2605) -
cmd_help(2318-2381)
File structure:
#\!/usr/bin/env bash # sw-config-validator.sh — Config validation, meta-learning, audit # Sourced by sw-recruit.sh — do not execute directly [functions]
Extract from sw-recruit.sh (lines):
-
initialize_builtin_roles(156-295) -
_recruit_keyword_match(297-355) -
_recruit_llm_match(357-388) -
_recruit_record_match(390-435) -
cmd_create_role(437-558) -
cmd_record_outcome(560-681) -
cmd_ingest_pipeline(683-744) -
_recruit_track_role_usage(746-764) -
cmd_evolve(766-880) -
_recruit_compute_population_stats(882-907) -
cmd_specializations(909-953) -
cmd_route(955-1004) -
cmd_roles(1878-1888) -
cmd_match(1890-2000) -
cmd_evaluate(2002-2069) -
cmd_profiles(2071-2085) -
cmd_promote(2087-2163) -
cmd_stats(2261-2316)
Extract from sw-recruit.sh (lines):
-
cmd_team(1006-1185) -
cmd_onboard(2165-2259) -
cmd_mind(1494-1652) -
cmd_decompose(1654-1753) -
cmd_invent(1376-1492)
Keep in sw-recruit.sh:
- Shebang, set -euo pipefail, ERR trap (1-12)
- SCRIPT_DIR, VERSION (14-15)
- Dependency check for jq (17-24)
- Library sourcing: compat.sh, helpers.sh, fallbacks (26-49)
-
_recruit_locked_write(50-65) - Storage paths (67-78)
-
_recruit_policy(80-102) -
ensure_recruit_dir(104-124) -
_recruit_has_claude/_recruit_call_claude(126-154) - Source the three new modules (order: config-validator, role-manager, team-composer)
- CLI router (2607-2644)
-
sw-config-validator-test.sh: Test audit, reflect, self-tune, meta-learning -
sw-role-manager-test.sh: Test role CRUD, matching, evaluation, promotion -
sw-team-composer-test.sh: Test team composition, decompose, mind, onboard
Run scripts/sw-recruit-test.sh to confirm behavioral parity.
Run npm test for full regression.
- Task 1: Create
scripts/sw-config-validator.shwith meta-learning, audit, self-tune, reflect, help functions - Task 2: Create
scripts/sw-role-manager.shwith role CRUD, matching, evaluation, promotion, evolution functions - Task 3: Create
scripts/sw-team-composer.shwith team composition, onboard, mind, decompose, invent functions - Task 4: Rewrite
scripts/sw-recruit.shas thin orchestrator that sources the three modules and retains shared infra + CLI router - Task 5: Run existing
sw-recruit-test.shto verify behavioral parity — all tests must pass - Task 6: Create
scripts/sw-config-validator-test.shwith unit tests for audit, reflect, self-tune - Task 7: Create
scripts/sw-role-manager-test.shwith unit tests for matching, evaluation, role creation - Task 8: Create
scripts/sw-team-composer-test.shwith unit tests for team composition, decompose, mind - Task 9: Run full test suite (
npm test) to verify no regressions - Task 10: Verify version consistency with
scripts/check-version-consistency.sh
- Unit tests (~30 tests): 10 per module test file covering individual functions in isolation
-
Integration tests (~21 tests): Existing
sw-recruit-test.shserves as integration test (6 sections, ~21 test cases) -
E2E tests:
npm testruns all 133+ test suites as regression check
- Each module: all public
cmd_*functions tested with at least one happy path and one error case - Integration: all CLI subcommands routed correctly through orchestrator
- Critical paths: match→record-outcome→meta-learning feedback loop, audit validation
Happy path:
-
sw-recruit.sh match "implement auth"→ returns role via keyword matching -
sw-recruit.sh team "build feature X"→ returns team composition JSON -
sw-recruit.sh audit→ validates all DBs and returns score
Error cases:
-
sw-recruit.sh match(no task) → exit 1 with usage -
sw-recruit.sh record-outcome(missing args) → exit 1 with usage - Audit with corrupted JSON DB → reports failure, doesn't crash
Edge cases:
- Empty roles DB → match falls back to "builder" default
- No match history → self-tune completes with no changes
- Population with single agent → evaluate uses absolute thresholds
Minimum viable change: Move functions into three files, source them from orchestrator, tests pass. Implicit requirements: Callers must not change (sw-pipeline.sh etc. call sw-recruit.sh, not modules directly). Version variable must stay accessible. Acceptance criteria: As stated in issue plus all tests green.
What could go wrong:
- Functions reference globals defined in orchestrator → solved by sourcing order (orchestrator defines globals before sourcing modules)
-
cmd_record_outcomecalls_recruit_meta_learning_checkacross module boundary → solved by source order: config-validator before role-manager - Test environments that override
SCRIPT_DIRmight not find new module files → modules use guard via sourcing from orchestrator's SCRIPT_DIR
Existing functionality that could break: Any script that sources sw-recruit.sh (check: none do — all call it as subprocess via bash sw-recruit.sh <cmd>)
- Could solve with fewer files: yes, but two modules would still mix concerns
- Three modules directly match the three domains in the issue acceptance criteria
- No new abstractions needed — just file boundaries
Not applicable — no schema changes. All JSON database files remain unchanged. The refactor is purely at the code organization level.
Not applicable — no new data operations. Existing atomic writes via _recruit_locked_write are preserved.
Not applicable for schema. Code rollback is a simple git revert of the PR.
-
sw-recruit.shis <250 lines (orchestrator + shared infra) -
sw-role-manager.sh,sw-team-composer.sh,sw-config-validator.shexist with proper headers - All functions accessible via
sw-recruit.sh <subcommand>(behavioral parity) -
scripts/sw-recruit-test.shpasses all existing tests - New modular test files exist and pass
-
npm testpasses with no regressions - No module sources another module (no circular deps)
- Version variable (
RECRUIT_VERSION) accessible from all modules