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 Plan 313

ezigus edited this page Apr 18, 2026 · 2 revisions

Implementation plan written to .claude/pipeline-artifacts/plan.md.

Summary of the plan:

3 files to modify:

  1. scripts/lib/ruflo-adapter.sh — add 4 functions: ruflo_prune_memory_export(), ruflo_merge_memory_exports(), ruflo_ci_memory_pull(), ruflo_ci_memory_push()
  2. .github/workflows/shipwright-pipeline.yml — add 2 steps (restore before pipeline, persist after)
  3. scripts/sw-ruflo-adapter-test.sh — add 6 unit tests

Key design decisions:

  • Uses the same orphan-branch + tmp-dir + commit + push pattern already proven by shipwright-data (the issue's pseudocode git push syntax was invalid)
  • Chose separate refs/ruflo-memory branch over reusing shipwright-data for separation of concerns
  • Merge strategy: union of keys, newer timestamp wins — acceptable that worst-case concurrent conflicts lose 2/3 jobs' learning
  • 90-day pruning prevents unbounded growth
  • All paths return 0 (fail-open) — pipeline never fails over memory persistence
  • ruflo memory export may only capture KV store (not HNSW/Q-weights) — documented as known limitation, infrastructure works regardless

Alternative A: Orphan git branch (chosen)

  • Pros: Zero external infrastructure, works with any GitHub repo, GITHUB_TOKEN sufficient, mirrors existing shipwright-data pattern in the workflow
  • Cons: Git push conflicts with concurrent jobs, limited merge granularity
  • Blast radius: 2 functions added to ruflo-adapter.sh, 2 steps added to workflow

Alternative B: GitHub Actions artifact + download

  • Pros: No git conflicts, built-in retention policies
  • Cons: Artifacts are per-workflow-run and expire; cross-workflow retrieval requires API calls; not persistent long-term
  • Rejected: Artifacts are ephemeral, not suitable for cross-run learning

Alternative C: Dedicated shipwright-data branch (reuse existing)

  • Pros: Already exists in workflow; less orphan branch proliferation
  • Cons: Mixes concerns (events/costs/budget vs ruflo memory); concurrent push conflicts already a problem there; ruflo memory could be large and noisy
  • Rejected: Separation of concerns — ruflo memory has different lifecycle and ownership

Risk Assessment

Risk Impact Mitigation
Push conflict with concurrent CI jobs 2/3 jobs lose memory in worst case 3-retry loop with jitter; acceptable per issue spec
ruflo memory export doesn't capture HNSW/Q-weights Reduced cross-run learning value Document as known limitation; KV store still persists
Unbounded memory file growth Slow fetches, large git objects 90-day pruning before every push
Orphan branch pollutes repo Confusion for contributors Uses refs/ruflo-memory (not visible in git branch)
Merge logic (timestamp union) has bugs Corrupted memory state Defensive: if merge fails, push local-only export

Dependency Analysis

Depends on:

  • scripts/lib/ruflo-adapter.sh — existing ruflo_available, ruflo_with_timeout, _ruflo_run, ruflo_export_memory, ruflo_import_memory
  • .github/workflows/shipwright-pipeline.yml — the CI workflow to wire into
  • jq — already installed in CI (system dependencies step)

Depended on by: Nothing — this is additive, new functions only.

No circular dependency risk.

Simplicity Check

The issue's pseudocode uses git push origin ".claude-flow/data/memory-export.json:refs/ruflo-memory/memory-export.json" which is not valid git syntax. We need the same tmp-dir + orphan-branch + commit + push pattern already used for shipwright-data (workflow lines 803-852). This is proven infrastructure.


Architecture

Component Diagram

shipwright-pipeline.yml ruflo-adapter.sh
┌─────────────────────┐ ┌──────────────────────────────┐
│ Restore ruflo memory│────────────>│ ruflo_ci_memory_pull() │
│ (before pipeline) │ │ ├─ git fetch refs/ruflo-mem │
└─────────────────────┘ │ ├─ git show memory-export │
┌─────────────────────┐ │ └─ ruflo memory import │
│ Save ruflo memory │────────────>│ ruflo_ci_memory_push() │
│ (after, always) │ │ ├─ ruflo memory export │
└─────────────────────┘ │ ├─ ruflo_prune_memory_export│
 │ ├─ ruflo_merge_memory_expor │
 │ └─ git commit + push (3x) │
 └──────────────────────────────┘

Interface Contracts

ruflo_ci_memory_pull() → exit 0 (always)
ruflo_ci_memory_push() → exit 0 (always)
ruflo_prune_memory_export(file, days) → exit 0|1
ruflo_merge_memory_exports(local, remote, out) → exit 0|1

Data Flow

CI Start → ruflo_ci_memory_pull()
 1. git fetch origin refs/ruflo-memory:refs/ruflo-memory
 2. git show refs/ruflo-memory:memory-export.json > local file
 3. ruflo memory import --input <file>
 4. Log byte count for observability
CI End → ruflo_ci_memory_push()
 1. ruflo memory export --output <file>
 2. ruflo_prune_memory_export(<file>, 90)
 3. Retry loop (3x):
 a. git fetch refs/ruflo-memory
 b. git show remote memory-export.json
 c. ruflo_merge_memory_exports(local, remote, merged)
 d. Create tmp git dir, checkout orphan, copy, commit, push
 e. On push fail: sleep jitter, retry

Error Boundaries

  • ruflo_ci_memory_pull: All errors → return 0, log warning
  • ruflo_ci_memory_push: All errors → return 0, log warning. Push retries 3x then gives up
  • ruflo_prune_memory_export: Returns 1 on jq failure; caller uses || true
  • ruflo_merge_memory_exports: Returns 1 on failure; caller falls back to local-only
  • Workflow steps: Both use continue-on-error: true

Critical Unknown: ruflo memory export contents

Decision: Implement persistence regardless. If ruflo memory export only captures the KV store (not HNSW/Q-weights), the KV store alone is valuable. Document as known limitation.


Files to Modify

1. scripts/lib/ruflo-adapter.sh (modify)

Add 4 functions after ruflo_export_memory() (line 529):

  • ruflo_prune_memory_export() — prune entries older than N days
  • ruflo_merge_memory_exports() — union merge with timestamp tiebreaker
  • ruflo_ci_memory_pull() — fetch from orphan branch + import
  • ruflo_ci_memory_push() — export + prune + merge + push

2. .github/workflows/shipwright-pipeline.yml (modify)

Add 2 steps in the pipeline job:

  • Before "Run Shipwright pipeline": restore ruflo memory from git
  • After "Save ruflo memory cache": persist ruflo memory to git

3. scripts/sw-ruflo-adapter-test.sh (modify)

Add tests for the 4 new functions


Implementation Steps

Step 1: Add ruflo_prune_memory_export() to ruflo-adapter.sh (after line 529)

  • Accepts file_path and max_age_days parameters
  • Uses jq to filter entries older than max_age_days using .timestamp or .updated_at
  • Atomic rewrite via tmp file + mv
  • Returns 0 on success, 1 on error; emits event with pruned count

Step 2: Add ruflo_merge_memory_exports() to ruflo-adapter.sh

  • Accepts local_file, remote_file, output_file
  • Uses jq to merge: union of keys, newer timestamp wins on conflict
  • Atomic write to output via tmp + mv
  • Returns 0 on success, 1 on failure

Step 3: Add ruflo_ci_memory_pull() to ruflo-adapter.sh

  • Guards: ruflo_available || return 0, [[ "${CI:-}" == "true" ]] || return 0
  • git fetch, git show, ruflo memory import
  • Log byte count, emit event

Step 4: Add ruflo_ci_memory_push() to ruflo-adapter.sh

  • Same guards as pull
  • Export via existing ruflo_export_memory
  • Prune with 90-day threshold
  • 3-attempt retry loop: fetch, merge, create tmp dir, orphan checkout, commit, push
  • On all retries exhausted: warn, return 0

Step 5: Wire into CI workflow

Add two steps to .github/workflows/shipwright-pipeline.yml:

  • "Restore ruflo memory from git" before pipeline run
  • "Persist ruflo memory to git" after pipeline (always)

Step 6: Add tests to sw-ruflo-adapter-test.sh

  • Prune: mixed timestamps, all-fresh entries
  • Merge: overlapping keys (newer wins), disjoint keys
  • CI pull/push: guard conditions (CI=false → no-op)

Task Checklist

  • Task 1: Add ruflo_prune_memory_export() to scripts/lib/ruflo-adapter.sh
  • Task 2: Add ruflo_merge_memory_exports() to scripts/lib/ruflo-adapter.sh
  • Task 3: Add ruflo_ci_memory_pull() to scripts/lib/ruflo-adapter.sh
  • Task 4: Add ruflo_ci_memory_push() to scripts/lib/ruflo-adapter.sh
  • Task 5: Add "Restore ruflo memory from git" step to workflow
  • Task 6: Add "Persist ruflo memory to git" step to workflow
  • Task 7: Add unit tests for prune function
  • Task 8: Add unit tests for merge function
  • Task 9: Add unit tests for CI pull/push guard conditions
  • Task 10: Run test suite and verify all tests pass

Testing Approach

Test Pyramid Breakdown

  • Unit tests (6): prune mixed, prune all-fresh, merge overlapping, merge disjoint, CI pull guards, CI push guards
  • Integration tests (0): Functions are self-contained shell
  • E2E tests (0): Verified by first actual CI pipeline run

Coverage Targets

  • 100% of guard conditions (CI=false, ruflo unavailable)
  • Prune: old entries removed, new entries kept
  • Merge: union semantics, newer timestamp wins

Critical Paths

  • Happy path: Export → prune → merge → push succeeds
  • Error case 1: No orphan branch (first run) → pull no-ops, push creates branch
  • Error case 2: Push conflict → retry fires, succeeds or gives up gracefully
  • Edge case 1: Empty memory export → prune/merge handle empty JSON
  • Edge case 2: Malformed remote JSON → merge falls back to local-only

Definition of Done

  • ruflo_ci_memory_pull() fetches from orphan branch and imports into ruflo
  • ruflo_ci_memory_push() exports, prunes, merges, and pushes to orphan branch
  • 90-day pruning removes old entries before every push
  • Pipeline never fails due to memory persistence errors (all paths return 0)
  • Concurrent push conflicts handled with 3-retry loop + jitter
  • CI workflow has restore/save steps wired correctly
  • All new functions have unit tests
  • Existing tests still pass
  • Code follows project conventions: Bash 3.2 compat, atomic writes, jq --arg

Risk Analysis

Risk What Could Break Mitigation
jq not available Prune/merge fail Already installed in CI; guard with command -v jq
Wrong ref format Fetch/push fail silently Use proven shipwright-data pattern
Invalid JSON export jq errors Validate before merge; fall back to local-only
Missing write permission Push fails Already in workflow permissions: contents: write
Concurrent corruption Stale data Retry with fetch-before-push; worst case: one run lost

Performance

Baseline

  • Current: ruflo memory lost between CI runs
  • After: persists; pull ~2-5s, push ~5-10s

Targets

  • Pull: < 10s, Push: < 30s (including retries)
  • File size: bounded by 90-day pruning (< 1MB typical)

Clone this wiki locally

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