From f90c72994913211e72973435fbabc8a913a410f1 Mon Sep 17 00:00:00 2001 From: Chris Phillipson Date: Thu, 13 Aug 2026 00:09:42 -0400 Subject: [PATCH 1/2] chore: HNSW badge claims the artifact, not the algorithm; widen nightly's #2885 scope note MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The footer's SONA line showed a green "⚡ HNSW" badge purely on .swarm/hnsw.index existing. Upstream ruflo#2922 (3.38.7) established that the default memory search path is brute-force cosine even when that index exists — they renamed their own APIs over exactly this overclaim. The badge now reads "HNSW idx": the file proves an index was BUILT, never that search uses it. Revisit if upstream wires HNSW into the default path or persists an algorithm signal the footer can read. The badge gains the segment tests it never had (plan 45 → 47). nightly.yml's non-blocking guard cited ruflo#2885 as a neural-train crash; upstream evidence (2026-08-12) shows the same macOS teardown abort poisoning exit codes of store-touching commands (memory search → correct output, rc 134), so the comment now describes the widened scope — a future x verify memory step would need the same guard. The guard itself is unchanged and stays until #2885 closes. Fixes #139 Fixes #140 --- .github/workflows/nightly.yml | 9 ++++++--- src/templates/statusline-footer.cjs | 7 ++++++- tests/statusline-segments.test.cjs | 22 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 4c7b80d..7032b7f 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -62,9 +62,12 @@ jobs: APPDATA: ${{ runner.temp }}/kit-home/AppData/Roaming run: node bin/agentic-kit.mjs x verify security - # Non-blocking: ruflo neural train crashes on macos-latest with a native - # libc++abi mutex abort, tracked upstream at ruvnet/ruflo#2885 (open as of - # 2026-08-06). Remove continue-on-error once that issue closes. + # Non-blocking: a native libc++abi mutex abort on macos-latest poisons ruflo + # exit codes, tracked upstream at ruvnet/ruflo#2885 (open as of 2026-08-13). + # Scope is NOT neural-train-specific: upstream evidence (2026-08-12) shows the + # same teardown abort on store-touching commands (`memory search` → correct + # output, rc 134), so an `x verify memory` step added here would need the same + # guard. Remove continue-on-error once that issue closes. - name: Deep proof against the live packages (learning) continue-on-error: true env: diff --git a/src/templates/statusline-footer.cjs b/src/templates/statusline-footer.cjs index 71bc507..62d4f32 100644 --- a/src/templates/statusline-footer.cjs +++ b/src/templates/statusline-footer.cjs @@ -69,7 +69,12 @@ function rufloActivationSegments(cwd){ if (pn > 0 || tj > 0) { if (pn > 0) parts.push(pn + " patterns"); if (tj > 0) parts.push(tj + " traj"); - if (fs.existsSync(path.join(cwd, ".swarm", "hnsw.index"))) parts.push(G + "⚡ HNSW" + R); + // "HNSW idx" claims the ARTIFACT (an index was built), never the algorithm: + // upstream's default search path is brute-force cosine even when this file + // exists (ruflo#2922 renamed its own APIs over that exact overclaim). Revisit + // if upstream wires HNSW into the default path or persists an algorithm + // signal the footer can read (#140). + if (fs.existsSync(path.join(cwd, ".swarm", "hnsw.index"))) parts.push(G + "HNSW idx" + R); var dots = Math.max(0, Math.min(5, Math.round(pn / 10))); // volume gauge: ~10 patterns per dot learn = C + "🧠 SONA" + R + " " + DIM + bar(dots, 5) + R + " " + parts.join(DIM + " · " + R); } diff --git a/tests/statusline-segments.test.cjs b/tests/statusline-segments.test.cjs index 7f62eb0..817d5a3 100644 --- a/tests/statusline-segments.test.cjs +++ b/tests/statusline-segments.test.cjs @@ -107,6 +107,26 @@ test('SONA segment absent when counts are zero', () => { absent(out, '🧠 SONA'); }); +// #140 / upstream ruflo#2922: the index FILE existing proves an HNSW index was +// BUILT — not that the search path uses it (upstream's default is brute-force +// cosine; they renamed their own APIs over exactly this overclaim). The badge +// may claim the artifact, never the algorithm. +test('a built hnsw.index shows the artifact badge, not an algorithm claim (#140)', () => { + const out = strip(rufloActivationSegments(mkFixture({ + '.claude-flow/neural/stats.json': { patternsLearned: 50, trajectoriesRecorded: 110 }, + '.swarm/hnsw.index': 'binary-ish', + }))); + contains(out, 'HNSW idx'); + absent(out, '⚡ HNSW'); +}); + +test('no hnsw.index → no HNSW mention at all', () => { + const out = strip(rufloActivationSegments(mkFixture({ + '.claude-flow/neural/stats.json': { patternsLearned: 50, trajectoriesRecorded: 110 }, + }))); + absent(out, 'HNSW'); +}); + // ── route Q-learner segment ─────────────────────────────────────────────── test('route 📈 RL renders ε/δ̄/|Q|/upd when updateCount > 0', () => { const out = strip(rufloActivationSegments(mkFixture({ @@ -521,7 +541,7 @@ test('unresolvable ruflo → silent (a probe miss must never fail loud and wrong // Test-quality Finding 5: bump deliberately when adding/removing a test — // see admin-model.test.cjs's identical guard for the full rationale. -const EXPECTED = 45; +const EXPECTED = 47; if (passed + failed !== EXPECTED) { console.error(`\nPLAN MISMATCH: expected ${EXPECTED} tests, ran ${passed + failed}`); process.exit(1); From 9eb85d9a9afa4fd0f04ddab8859fca4f84866233 Mon Sep 17 00:00:00 2001 From: Chris Phillipson Date: Thu, 13 Aug 2026 00:17:13 -0400 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20remove=20the=20HNSW=20badge=20?= =?UTF-8?q?=E2=80=94=20index-file=20existence=20proves=20no=20active=20fea?= =?UTF-8?q?ture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The activation footer shows only features genuinely active in the project (its founding contract). Upstream ruflo#2922 established the default search path is brute-force cosine even when .swarm/hnsw.index exists, so the file proves nothing a user can act on. Removed rather than relabeled; reintroduce only if upstream wires HNSW into the default path or persists an algorithm signal the footer can read. --- src/templates/statusline-footer.cjs | 8 +------- tests/statusline-segments.test.cjs | 19 +++++-------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/templates/statusline-footer.cjs b/src/templates/statusline-footer.cjs index 62d4f32..5992119 100644 --- a/src/templates/statusline-footer.cjs +++ b/src/templates/statusline-footer.cjs @@ -56,7 +56,7 @@ function rufloActivationSegments(cwd){ } } catch(e){ rufloStatuslineDebug("quota-tee", e); } function bar(n, max){ n = Math.max(0, Math.min(max, n)); return "[" + "●".repeat(n) + "○".repeat(max - n) + "]"; } - // ── self-learning (SONA): own line with a volume bar (patterns/traj/HNSW) plus a + // ── self-learning (SONA): own line with a volume bar (patterns/traj) plus a // LIVE micro-LoRA adaptation field (Δ‖W‖, appended further below). The Δ‖W‖ tracker // is maintained inline in this same function — see the "micro-LoRA LIVE adaptation" // block after the route-Q segment. @@ -69,12 +69,6 @@ function rufloActivationSegments(cwd){ if (pn > 0 || tj > 0) { if (pn > 0) parts.push(pn + " patterns"); if (tj > 0) parts.push(tj + " traj"); - // "HNSW idx" claims the ARTIFACT (an index was built), never the algorithm: - // upstream's default search path is brute-force cosine even when this file - // exists (ruflo#2922 renamed its own APIs over that exact overclaim). Revisit - // if upstream wires HNSW into the default path or persists an algorithm - // signal the footer can read (#140). - if (fs.existsSync(path.join(cwd, ".swarm", "hnsw.index"))) parts.push(G + "HNSW idx" + R); var dots = Math.max(0, Math.min(5, Math.round(pn / 10))); // volume gauge: ~10 patterns per dot learn = C + "🧠 SONA" + R + " " + DIM + bar(dots, 5) + R + " " + parts.join(DIM + " · " + R); } diff --git a/tests/statusline-segments.test.cjs b/tests/statusline-segments.test.cjs index 817d5a3..fd69108 100644 --- a/tests/statusline-segments.test.cjs +++ b/tests/statusline-segments.test.cjs @@ -107,23 +107,14 @@ test('SONA segment absent when counts are zero', () => { absent(out, '🧠 SONA'); }); -// #140 / upstream ruflo#2922: the index FILE existing proves an HNSW index was -// BUILT — not that the search path uses it (upstream's default is brute-force -// cosine; they renamed their own APIs over exactly this overclaim). The badge -// may claim the artifact, never the algorithm. -test('a built hnsw.index shows the artifact badge, not an algorithm claim (#140)', () => { +// #140: index-file existence proves nothing about the active search path +// (upstream default is brute-force cosine, ruflo#2922) — the footer shows only +// genuinely active features, so no HNSW claim at all. +test('hnsw.index on disk produces no HNSW claim (#140)', () => { const out = strip(rufloActivationSegments(mkFixture({ '.claude-flow/neural/stats.json': { patternsLearned: 50, trajectoriesRecorded: 110 }, '.swarm/hnsw.index': 'binary-ish', }))); - contains(out, 'HNSW idx'); - absent(out, '⚡ HNSW'); -}); - -test('no hnsw.index → no HNSW mention at all', () => { - const out = strip(rufloActivationSegments(mkFixture({ - '.claude-flow/neural/stats.json': { patternsLearned: 50, trajectoriesRecorded: 110 }, - }))); absent(out, 'HNSW'); }); @@ -541,7 +532,7 @@ test('unresolvable ruflo → silent (a probe miss must never fail loud and wrong // Test-quality Finding 5: bump deliberately when adding/removing a test — // see admin-model.test.cjs's identical guard for the full rationale. -const EXPECTED = 47; +const EXPECTED = 46; if (passed + failed !== EXPECTED) { console.error(`\nPLAN MISMATCH: expected ${EXPECTED} tests, ran ${passed + failed}`); process.exit(1);