-
Notifications
You must be signed in to change notification settings - Fork 0
Pipeline Design 371
The build stage (stage_build()) launches a hive-mind agent team with a goal string containing plan and design context, but no historical signal about how similar issues were built in the past. Ruflo memory stores vector-indexed build outcomes from prior executions; recalling similar outcomes before hive dispatch would seed agents with probabilistic guidance based on past patterns.
Constraints:
- Must not modify
ruflo_execute_build_hive()signature (issue #371 explicitly forbids this) - Must be safe when ruflo unavailable (guard with
declare -f+ruflo_available) - Must never block the pipeline (
|| truesemantics) - Must follow existing injection patterns from
stage_planandstage_designinstage_intake.sh - Scope: single file, minimal code footprint (~15–45 lines for 3 injection points)
Inject ruflo_recall_similar_outcomes before hive dispatch by appending its output to the enriched_goal string.
The recall result is appended under a clear ## Historical Build Context header, making it visible in the goal string passed to the hive. This approach:
- Requires no changes to
ruflo_execute_build_hive()or other function signatures - Leverages the existing goal-string enrichment pattern already used in prior stages
- Fails gracefully when ruflo is unavailable or function missing
- Bounds output to 2000 chars to prevent argv overflow
- Works across all three build paths: hive dispatch, single-agent fallback, and native sw loop
┌─────────────────────────────────────────────────────────────────┐
│ stage_build() — Build Stage Main Entry Point │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. Initialization │ │
│ │ (Unchanged: load context, construct base goal) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 2. Historical Context Injection (NEW) │ │
│ │ • Guard: function exists + ruflo available │ │
│ │ • Recall: ruflo_recall_similar_outcomes(...) │ │
│ │ • Bound: head -c 2000 (prevent overflow) │ │
│ │ • Append: enriched_goal += context header + result │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 3. Execution Dispatch │ │
│ │ Path A: Hive (if hive available) │ │
│ │ → ruflo_execute_build_hive "$enriched_goal" │ │
│ │ Path B: Single-agent fallback │ │
│ │ → ruflo_execute_build "$enriched_goal" │ │
│ │ Path C: Native sw loop fallback │ │
│ │ → shipwright loop (enriched goal in prompt) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 4. Result & Outcome Recording (Unchanged) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Components:
-
Guard Layer — Availability checks
- Validates
ruflo_recall_similar_outcomesfunction exists - Validates
ruflo_availablefunction exists and returns true - Responsibility: Prevent failures when ruflo unavailable
- Validates
-
Recall Layer — Historical outcome retrieval
- Calls
ruflo_recall_similar_outcomes(issue_type, labels) - Captures output with
2>/dev/null || true(never fails) - Responsibility: Fetch similar past outcomes from memory
- Calls
-
Integration Layer — Goal enrichment
- Bounds output to 2000 chars with
head -c 2000 - Appends under
## Historical Build Contextheader - Updates
enriched_goalvariable - Logs injection via
infomessage - Responsibility: Safely integrate context into goal string
- Bounds output to 2000 chars with
-
Dispatch Layer — Unchanged, consumes enriched goal
- Passes updated
enriched_goalto hive/fallback paths - Responsibility: Execute build with historical context
- Passes updated
# Input
issue_type: string # e.g., "backend", "frontend", "devops"
labels: string # comma-separated: "bug,urgent,regression"
# Output
stdout: string # Plain text (NOT JSON) of similar past outcomes
# Empty string if no matches found
# May span multiple lines
# Error handling
# If function missing or ruflo unavailable:
# Guard prevents call → enriched_goal unchanged
# If recall fails:
# 2>/dev/null captures stderr, || true continues
# enriched_goal unchanged
# Example return value (plain text):
# "Similar build failed due to missing dependency lodash@4.17.20 in stage_intake.
# Previous fix: updated npm lockfile and re-ran bootstrap.
# Another match: build succeeded with plan-first approach on retry."# Input: (none)
# Output
# Returns 0 (success) if ruflo memory is available
# Returns non-zero if unavailable or uninitialized
# Side effects: None (pure availability check)# Before injection:
enriched_goal="## Plan Context\n..."
# After injection:
enriched_goal="## Plan Context\n...
## Design Context\n...
## Historical Build Context\n<recall_output>"
# Invariant: Goal string is passed as-is to hive/fallback executors
# No parsing or transformation; treated as opaque string╔════════════════════════════════════════════════════════════════╗
║ Upstream: stage_plan → stage_design ║
╠════════════════════════════════════════════════════════════════╣
║ enriched_goal contains plan + design context ║
║ INTELLIGENCE_ISSUE_TYPE = intake detection (e.g., "backend") ║
║ ISSUE_LABELS = comma-sep intake extraction ║
╚════════════════════════════════════════════════════════════════╝
↓
╔════════════════════════════════════════════════════════════════╗
║ [NEW] stage_build: Historical Context Injection ║
╠════════════════════════════════════════════════════════════════╣
║ IF declare -f ruflo_recall_similar_outcomes ✓ ║
║ AND declare -f ruflo_available ✓ ║
║ AND ruflo_available ✓: ║
║ ║
║ _ruflo_build_ctx = ruflo_recall_similar_outcomes( ║
║ INTELLIGENCE_ISSUE_TYPE, ISSUE_LABELS) ║
║ ║
║ IF _ruflo_build_ctx not empty: ║
║ Bound to 2000 chars ║
║ enriched_goal += "\n\n## Historical Build Context\n" ║
║ + _ruflo_build_ctx ║
║ Log: "Ruflo build context injected (N bytes)" ║
║ ELSE: ║
║ enriched_goal unchanged (silent pass-through) ║
╚════════════════════════════════════════════════════════════════╝
↓
╔════════════════════════════════════════════════════════════════╗
║ Dispatch Paths (all receive updated enriched_goal) ║
╠════════════════════════════════════════════════════════════════╣
║ Path A: ruflo_execute_build_hive "$enriched_goal" ║
║ Path B: ruflo_execute_build "$enriched_goal" ║
║ Path C: shipwright loop <goal embedded in prompt> ║
╚════════════════════════════════════════════════════════════════╝
↓
╔════════════════════════════════════════════════════════════════╗
║ Hive Agents / Single Agent / Loop Prompt ║
║ (sees full context: plan + design + history) ║
╚════════════════════════════════════════════════════════════════╝
| Layer | Error Case | Handling | Consequence |
|---|---|---|---|
| Guard |
ruflo_recall_similar_outcomes missing |
Skip entire block, enriched_goal unchanged | Safe: builds without history |
| Guard |
ruflo_available missing |
Skip entire block, enriched_goal unchanged | Safe: builds without history |
| Guard |
ruflo_available() returns false |
Skip entire block, enriched_goal unchanged | Safe: builds without history |
| Recall |
ruflo_recall_similar_outcomes() fails/hangs |
2>/dev/null || true captures error, empty string |
Safe: enriched_goal unchanged |
| Recall | Returns empty string |
[[ -n "$_ruflo_build_ctx" ]] check skips append |
Safe: no empty headers in goal |
| Bound | Output > 2000 chars |
head -c 2000 truncates silently |
Safe: prevents argv overflow |
| Append | Variable expansion in heredoc | Info log message uses printf, not unquoted | Safe: no shell injection |
| Dispatch | Hive receives invalid goal string | Hive processes as-is; malformed context ≠ blocker | Degraded: agents may ignore context |
| Alternative | Rationale | Trade-offs | Decision |
|---|---|---|---|
Separate parameter to ruflo_execute_build_hive() |
Cleaner separation, structured data | ❌ Modifies function signature, breaks existing callers, issue forbids it | REJECTED |
| Pre-process goal in enriched_goal construction | Earlier in pipeline, before branching | ❌ Spreads logic across stages, harder to test in isolation, implicit intent | REJECTED |
| Store context in temp file, pass path | Avoids goal string length concerns | ❌ Over-engineering for bash, goal string already works, adds I/O | REJECTED |
| Inject context as prompt prefix, not goal | Hive prompt more flexible than goal | ❌ Requires modifying hive invocation, out of scope | REJECTED |
| Append to goal (CHOSEN) | Minimal code, follows existing pattern, no signature changes | ✓ Goal string grows (mitigated: 2000-char cap), accepted trade-off | ACCEPTED |
| File | Lines | Changes |
|---|---|---|
scripts/lib/pipeline-stages-build.sh |
~412 (hive path), ~439 (single-agent), ~538 (native loop) | Add 15–16 line recall injection block before each dispatch; 3 copies with local variable scoping |
None. Changes are isolated to one existing file.
None. Leverages existing ruflo-adapter functions and bash builtins.
-
Argument Length Overflow
-
Risk: enriched_goal grows unbounded, exceeds shell
ARG_MAXlimit (~131KB on Linux) -
Mitigation: Bound recall output to 2000 chars with
head -c 2000 - Probability: Low (2000 chars safe for bash/C arg limits)
-
Risk: enriched_goal grows unbounded, exceeds shell
-
Namespace Mismatch
-
Risk:
ruflo_recall_similar_outcomessearches wrong namespace, returns empty - Mitigation: Use namespace derived from issue type/labels (implementation detail of ruflo adapter)
- Probability: Low (ruflo-adapter defines contract)
-
Risk:
-
Silent Failures
- Risk: Recall fails silently, goal unchanged but no visibility
-
Mitigation: Add
infolog when context injected; errors captured by2>/dev/null - Probability: Medium (network/memory failures possible)
-
Hive Confusion
- Risk: Historical context confuses hive agents, degrades decision quality
-
Mitigation: Clear header
## Historical Build Contextmakes source explicit; hive can ignore if irrelevant - Probability: Low (agents are trained to handle long context)
-
Performance Regression
- Risk: Recall adds latency to build stage startup
- Mitigation: Non-blocking call, pipeline continues regardless; issue #313 blocks real benefit anyway
- Probability: Low (semantic search is <100ms)
- Code Review: Diff shows only expected recall injection blocks in
pipeline-stages-build.sh; no unrelated changes - Guard Logic: Both
declare -fchecks pass; function signatures match ruflo-adapter - Output Bounds:
head -c 2000truncates outputs > 2000 chars; verify with test input - Variable Isolation: Local
_ruflo_build_ctxvariable scoped to block; doesn't leak to outer scope - Enriched Goal: Appended text follows format
\n\n## Historical Build Context\n<result>; no extra headers - Info Logging:
infomessage logs bytes appended when context injected - Error Handling: Enriched goal unchanged when:
-
ruflo_recall_similar_outcomesfunction missing -
ruflo_availablefunction missing -
ruflo_available()returns false - Recall function fails (stderr captured, stdout empty)
-
- All Paths Covered: Recall injection implemented at all 3 dispatch points (hive ~412, single-agent ~439, native loop ~538)
- Test Suite:
./scripts/sw-pipeline-test.shpasses with zero new failures - General Tests:
npm testpasses; all vitest suites green - Build Success:
npm run buildcompletes without errors - No Regressions: Hive behavior unchanged when ruflo unavailable; fallback paths behave identically to pre-change
- Commit Message: References issue #371; explains "why" not just "what"
-
Acceptance Criteria from Issue #371: All 6 criteria met
- ✓
ruflo_recall_similar_outcomescalled before hive dispatch - ✓ Result appended to
enriched_goalwith## Historical Build Contextheader - ✓ Guard uses
declare -f+ruflo_availablepattern - ✓ Never blocks pipeline (
|| true) - ✓ Works when ruflo unavailable (goal unchanged)
- ✓ Single-agent + native loop fallbacks also covered
- ✓
-
Code Quality: Single file, ~45 lines total (3 copies × 15 lines); follows existing patterns
-
Safety: Zero breaking changes; backward-compatible when ruflo missing
-
Test Coverage: Pipeline tests + npm test suite pass; no regressions
- Read
scripts/lib/pipeline-stages-build.shto locate hive (~412), single-agent (~439), native loop (~538) dispatch blocks - Read
scripts/lib/pipeline-stages-intake.shlines 374–400 to copy guard/append pattern - Verify
scripts/lib/ruflo-adapter.shforruflo_recall_similar_outcomes(issue_type, labels)signature - Implement recall injection block before hive dispatch
- Implement recall injection block before single-agent fallback
- Implement recall injection block before native loop fallback
- Add 2000-char bound with
head -c 2000 - Add info log message when context injected
- Run
./scripts/sw-pipeline-test.sh— verify no new failures - Run
npm test— verify all tests pass - Run
npm run build— verify build succeeds - Stage changes:
git add scripts/lib/pipeline-stages-build.sh - Commit with message:
feat(ruflo): inject ruflo_recall_similar_outcomes into stage_build - Verify final git diff shows ~45 lines of additions only (no deletions/modifications)
- Monitor: Track how often recall context is used vs. ignored in hive decisions
- Unblock #313: Implement CI memory persistence to realize full performance benefit
- Iterate: Gather telemetry on hive accuracy with/without historical context