Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Pipeline Design 324

ezigus edited this page Apr 5, 2026 · 2 revisions

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

Context

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_DIR for pipeline traceability
  • Event schema (config/event-schema.json) must register new event types

Decision

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.

Data Flow

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"

Guard Pattern (both call sites identical)

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.

Error Handling

  • ruflo unavailable: ruflo_available() returns 1 → skip silently, pipeline unaffected
  • Function not sourced: type ruflo_learn_from_shipwright fails → 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

Alternatives Considered

  1. 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.

  2. 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_design recall, more operational surface. Rejected.

  3. Event-callback mechanism — Pros: flexible, could enable/disable per template / Cons: current emit_event is fire-and-forget (writes JSONL), not a callback dispatch; building callback infra for one call site is over-engineering. Rejected.

Implementation Plan

Files to modify

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

Files to create

None.

Dependencies

None (all ruflo dependencies already present via MCP and the adapter's fail-open pattern).

Risk Areas

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

Validation Criteria

  • ruflo_learn_from_shipwright exists in scripts/lib/ruflo-adapter.sh and accepts a file path argument
  • stage_validate() writes pipeline-outcome-validate.json to $ARTIFACTS_DIR and calls ruflo_learn_from_shipwright with it
  • stage_monitor() failure path writes pipeline-outcome-monitor-failure.json and calls ruflo_learn_from_shipwright with it
  • Both call sites are wrapped with ruflo_available && type ruflo_learn_from_shipwright >/dev/null 2>&1 guard and || true fallback
  • ruflo.learn_from_shipwright event type registered in config/event-schema.json with optional: ["task_type", "repo"]
  • When RUFLO_AVAILABLE=false, neither call site produces errors or slows the pipeline
  • Existing 13 tests in sw-ruflo-adapter-test.sh remain green
  • New unit test: ruflo_learn_from_shipwright returns 0 and emits event when given valid JSON
  • New unit test: ruflo_learn_from_shipwright returns 0 silently when ruflo unavailable
  • Integration test: mock stage_validate success path produces outcome artifact
  • Integration test: mock stage_monitor failure path produces outcome artifact
  • npm test passes with no regressions

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /