-
Notifications
You must be signed in to change notification settings - Fork 0
Pipeline Design 324
Now I have everything needed. Here is the ADR:
Design: feat(ruflo): close the learning feedback loop — call ruflo_learn_from_shipwright() at pipeline completion
Shipwright's ruflo integration currently handles detection, MCP lifecycle, circuit-breaking, and memory indexing (ruflo-adapter.sh, 195 lines on this branch). The main branch already has 3 functions needed for learning — ruflo_store() (line 257), _ruflo_resolve_repo_hash() (line 314), and ruflo_learn_from_shipwright() (line 900) — totaling ~780 additional lines of adapter code including review/CQ stage helpers. However, none of these functions are called from the pipeline completion paths.
The pipeline has two terminal outcomes: success (end of stage_validate() at pipeline-stages-monitor.sh:115) and failure (threshold exceeded in stage_monitor() at line 254). Neither currently feeds outcome data back to ruflo's HNSW index for semantic recall on future runs. This means ruflo_recall_similar_outcomes() has no data to search — the feedback loop is open.
Constraints:
- All ruflo calls must be fail-open (
|| true) per adapter convention - Must guard with
ruflo_available()+ function-existence check (adapter may not be sourced) - Bash 3.2 compatible — no associative arrays, no
${var,,} - Outcome artifacts must go to
$ARTIFACTS_DIRfor pipeline traceability - Event schema (
config/event-schema.json) must register new event types
Direct function calls at two pipeline exit points, with fail-open guards. Extract the three missing functions from main into this branch's ruflo-adapter.sh, then add call sites in pipeline-stages-monitor.sh.
stage_validate() success stage_monitor() threshold exceeded
│ │
▼ ▼
Build outcome JSON Build outcome JSON
{status:"success", issue, {status:"failure", issue,
goal, task_type, duration_s} goal, task_type, errors,
│ error_threshold}
▼ │
Write to ARTIFACTS_DIR/ ▼
pipeline-outcome-validate.json Write to ARTIFACTS_DIR/
│ pipeline-outcome-monitor-failure.json
▼ │
ruflo_learn_from_shipwright(file) ruflo_learn_from_shipwright(file)
│ │
├─ _ruflo_resolve_repo_hash() (same flow)
├─ jq parse task_type
├─ ruflo_store(key, content,
│ "learning-<hash>",
│ "skill-memory,outcome,<type>")
└─ emit_event "ruflo.learn_from_shipwright"
if [[ -n "${ARTIFACTS_DIR:-}" ]]; then # ... build and write outcome JSON ... if ruflo_available && type ruflo_learn_from_shipwright >/dev/null 2>&1; then ruflo_learn_from_shipwright "$_outcome_file" || true fi fi
Three layers of protection: (1) ARTIFACTS_DIR existence, (2) ruflo_available() boolean + function existence, (3) || true catch-all. The function itself has internal guards: ruflo_available || return 0 and _ruflo_resolve_repo_hash || return 0.
-
ruflo unavailable:
ruflo_available()returns 1 → skip silently, pipeline unaffected -
Function not sourced:
type ruflo_learn_from_shipwrightfails → skip silently - Bad JSON / jq failure: Function returns 0 (fail-open), no outcome indexed
-
ruflo timeout: Circuit-breaker fires (
ruflo_with_timeout), disables ruflo for remainder of run -
Disk write failure:
echo > file 2>/dev/null || true— outcome not persisted, pipeline continues
-
Inline learning code at call sites — Pros: no function extraction, self-contained / Cons: duplicates ~30 lines of jq + store + emit logic across two sites, violates DRY, breaks if learning logic evolves. Rejected.
-
Batch learning via post-pipeline job — Pros: decouples learning from pipeline, easier standalone testing / Cons: adds async orchestration, learning doesn't feed back to the next run's
stage_plan/stage_designrecall, more operational surface. Rejected. -
Event-callback mechanism — Pros: flexible, could enable/disable per template / Cons: current
emit_eventis fire-and-forget (writes JSONL), not a callback dispatch; building callback infra for one call site is over-engineering. Rejected.
| File | Change | Estimated lines |
|---|---|---|
scripts/lib/ruflo-adapter.sh |
Cherry-pick ruflo_store(), _ruflo_resolve_repo_hash(), ruflo_learn_from_shipwright() and their transitive dependencies (_ruflo_run_quiet, ruflo_recall, _ruflo_repo_hash_candidates, _ruflo_shipwright_memory_dir) from main (lines 230–940) |
~700 lines (extract, not new code) |
scripts/lib/pipeline-stages-monitor.sh |
Add outcome JSON + ruflo_learn_from_shipwright call at end of stage_validate() (before line 115) and after emit_event "monitor.alert" in stage_monitor() (after line 264) |
~30 lines |
config/event-schema.json |
Add ruflo.learn_from_shipwright event type |
~4 lines |
scripts/sw-ruflo-adapter-test.sh |
Add unit test for ruflo_learn_from_shipwright + integration tests for both call sites |
~80 lines |
None.
None (all ruflo dependencies already present via MCP and the adapter's fail-open pattern).
| Risk | Mitigation |
|---|---|
| Cherry-pick from main brings unrelated code | Only extract the 3 target functions + their direct helpers; verify with grep that no new globals or side-effects leak |
now_epoch / PIPELINE_START_EPOCH not available in validate context |
Both are set by pipeline-stages.sh before any stage runs; verify with read of pipeline-stages.sh |
Outcome JSON missing task_type |
Function handles this: falls back to issue_type, then "unknown" (line 917 on main) |
jq not installed |
jq is already a hard dependency of the pipeline (used in every stage config read); not a new requirement |
| Monitor failure path has complex branching (rollback, hotfix issue, etc.) | Insert call before rollback logic so outcome is captured regardless of rollback success |
-
ruflo_learn_from_shipwrightexists inscripts/lib/ruflo-adapter.shand accepts a file path argument -
stage_validate()writespipeline-outcome-validate.jsonto$ARTIFACTS_DIRand callsruflo_learn_from_shipwrightwith it -
stage_monitor()failure path writespipeline-outcome-monitor-failure.jsonand callsruflo_learn_from_shipwrightwith it - Both call sites are wrapped with
ruflo_available && type ruflo_learn_from_shipwright >/dev/null 2>&1guard and|| truefallback -
ruflo.learn_from_shipwrightevent type registered inconfig/event-schema.jsonwithoptional: ["task_type", "repo"] - When
RUFLO_AVAILABLE=false, neither call site produces errors or slows the pipeline - Existing 13 tests in
sw-ruflo-adapter-test.shremain green - New unit test:
ruflo_learn_from_shipwrightreturns 0 and emits event when given valid JSON - New unit test:
ruflo_learn_from_shipwrightreturns 0 silently when ruflo unavailable - Integration test: mock
stage_validatesuccess path produces outcome artifact - Integration test: mock
stage_monitorfailure path produces outcome artifact -
npm testpasses with no regressions