Compare commits

...
25 Commits
Author SHA1 Message Date
conductor 81099a11f7 chore(release): auto-bump version to 0.128.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 7s
CI Pipeline / unit-tests (push) Successful in 5m10s
CI Pipeline / lint (push) Successful in 40s
CI Pipeline / go-surface (push) Successful in 28s
CI Pipeline / canary (push) Successful in 57s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 30s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 3m29s
Promotion record: (unknown)
2026-10-07 20:52:40 +01:00
Nick 3c13be1d76 Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 9s
CI Pipeline / go-surface (push) Successful in 31s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 6s
CI Pipeline / lint (push) Successful in 46s
CI Pipeline / gitea-offline (push) Successful in 17s
CI Pipeline / canary (push) Successful in 1m3s
CI Pipeline / type-check (push) Successful in 32s
CI Pipeline / unit-tests (push) Successful in 5m30s
CI Pipeline / required-checks (push) Successful in 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 6m35s
2026-10-07 20:52:28 +01:00
Nick de9dee7dd9 feat(go): memory-store batch 4 — the dense-side meta-judgement (contract BUILDER-2026-10-07T19:47:37Z-1cf1dc-unknown)
The recall() gate ported to memory-store-deep:
- DenseGate: vector proximity is not a relation — a dense hit (cos =
  1 - distance/2) is kept iff it shares a DISTINCTIVE content word with
  the entry (df/total < 0.05 via LIKE-substring counts); fallback keeps
  no-content-word queries or strong matches (cos >= 0.80). The
  black-coffee/black-holes fix, now deterministic-side.
- QueryContent (len>3 non-stop, first-occurrence order)
- RankFusionEntries: verified IDENTICAL to the chunk-side fusion (same
  code, :1297 vs the batch-2 port) — wrapper pins the parity for the
  recall() call shape; the docstring's raw-BM25 claim is stale, the
  CODE min-max normalizes in all modes (code is the oracle)
- the abstain constants: RECALL_BUDGET=8, RECALL_MIN_SCORE=0.42

PARITY: truth_gate.json — 6 cases from the live oracle against a fixture
store (distinctive/common/strong-cos/no-content branches + fusion
identity + constants). Embedding/vec0 SQL and the cache stay reactive.
2026-10-07 20:52:25 +01:00
conductor c949df0e98 chore(release): auto-bump version to 0.127.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 6s
CI Pipeline / unit-tests (push) Successful in 5m8s
CI Pipeline / lint (push) Successful in 40s
CI Pipeline / go-surface (push) Successful in 27s
CI Pipeline / canary (push) Successful in 58s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 8s
deploy / deploy (push) Successful in 3m13s
Promotion record: (unknown)
2026-10-07 20:39:30 +01:00
Nick 18c12fbda7 Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 9s
CI Pipeline / go-surface (push) Successful in 31s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / lint (push) Successful in 45s
CI Pipeline / gitea-offline (push) Successful in 17s
CI Pipeline / canary (push) Successful in 56s
CI Pipeline / type-check (push) Successful in 33s
CI Pipeline / unit-tests (push) Successful in 5m21s
CI Pipeline / required-checks (push) Successful in 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 6m29s
2026-10-07 20:39:16 +01:00
Nick ee7da6d080 feat(go): warm-router deep batch — the always-on digest core (contract BUILDER-2026-10-07T19:35:07Z-4d6b4c-unknown)
The digest selection machinery ported to warm-router:
- LexicalSignal (punctuation-strip, len>3, _DIGEST_STOP 64 words extracted
  verbatim), LexicalOverlap (Jaccard)
- Universality: the rule-vs-record classifier (date regex → 0, dated
  markers 2+ → 0 / 1 → 0.25, directive markers capped +0.25, terse
  40/90 ±0.15/-0.2, clamp)
- DigestSelect: the pure core — topic_rank slug ordering, 5-key stable
  sort (topic, -universality, always_on, -importance, -lexical density),
  junk skip (<12 chars / no triggers), universality gate, lexical gate,
  Jaccard dedup >=0.45, token sizing (len/4), oversized skip, budget fit

PARITY: truth_digest.json — 9 cases. The oracle corrected MY expectation
in the fixture: operating-gates-copy (importance 0.8) outranks the
original (0.7) on the importance tiebreak — fixture honesty, again. DB
I/O stays reactive. First-run green on the port itself.
2026-10-07 20:39:13 +01:00
conductor 2fa29f408c chore(release): auto-bump version to 0.126.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 6s
CI Pipeline / unit-tests (push) Successful in 5m9s
CI Pipeline / lint (push) Successful in 39s
CI Pipeline / go-surface (push) Successful in 27s
CI Pipeline / canary (push) Successful in 1m2s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 6s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 3m7s
Promotion record: (unknown)
2026-10-07 20:27:41 +01:00
Nick f433efe375 Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 8s
CI Pipeline / go-surface (push) Successful in 31s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / lint (push) Successful in 45s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / canary (push) Successful in 55s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / unit-tests (push) Successful in 5m16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 6m27s
2026-10-07 20:27:31 +01:00
Nick be00b56a0c feat(tools): undo_last port + the DEAD-FUNCTION finding (contract BUILDER-2026-10-07T19:20:10Z-af954d-unknown, defect #2481)
- UndoLast ported to tool-executor: glob *.bak, mtime-desc (name desc on
  ties), split('_', 4) → parts[4] underscore-to-slash reconstruct,
  exists-check, restore+delete. Verbatim semantics.
- THE FINDING: undo_last can NEVER restore absolute paths — the safe-name
  mangling eats the leading slash and split('_',4) drops the first path
  segment into parts[3]. Verified live three ways (multi-segment tmp,
  underscore-free /tmp, cwd-relative). The safety mechanism silently does
  nothing while the mutation stands. FILED: #2481 (fix the Python oracle
  first via a sidecar manifest, regenerate truth, flip Go — the parity
  battery verifies both sides flip together).
- The truth test PINS the dead behavior (oracle parity, not aspiration):
  a future one-sided 'fix' cannot silently diverge.
- UndoDir gains a seam (undoDirFn) so tests redirect without touching
  ~/.rune/undo. Per-wave routine held (gates bare, spine rebuilt, both
  snapshots shipped).
2026-10-07 20:27:28 +01:00
conductor 72d443423e chore(release): auto-bump version to 0.125.1 — earned by # (patch: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 6s
CI Pipeline / unit-tests (push) Successful in 5m7s
CI Pipeline / lint (push) Successful in 39s
CI Pipeline / go-surface (push) Successful in 26s
CI Pipeline / canary (push) Failing after 1m5s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Failing after 0s
deploy / deploy (push) Failing after 2m56s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
Promotion record: (unknown)
2026-10-07 20:13:28 +01:00
Nick f96991bf2e Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 9s
CI Pipeline / go-surface (push) Successful in 29s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / lint (push) Successful in 44s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / canary (push) Successful in 53s
CI Pipeline / type-check (push) Successful in 32s
CI Pipeline / unit-tests (push) Successful in 5m15s
CI Pipeline / required-checks (push) Successful in 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 6s
deploy / deploy (push) Successful in 6m29s
2026-10-07 20:13:16 +01:00
Nick 5dea803e92 fix(tools): SECURITY-ADJACENT parity repair — the approval boundary (contract BUILDER-2026-10-07T19:10:38Z-cc6be2-unknown)
src/go/tool-executor readOnlyTools diverged from the Python oracle in
BOTH directions:
- it wrongly ADDED run_command — a mutating tool the oracle routes
  through operator approval; the Go port would execute it read-only
  (the dangerous direction: approval bypass)
- it MISSED 8 of the 12 oracle read-only tools (git_diff, git_log,
  repo_map, read_persona, query_memory, check_growth, diagnose_behavior,
  find_capability)

Fixed to the exact 12-tool set, and pinned by a FROZEN truth battery
(gen_tool_executor_auth_truth.py → truth_auth.json) asserting set
equality both ways forever — the test's failure message says it plainly:
THE APPROVAL BOUNDARY HAS DRIFTED. Per-wave routine held (gates bare,
spine rebuilt, both snapshots shipped).
2026-10-07 20:13:13 +01:00
conductor 30ec1c8153 chore(release): auto-bump version to 0.125.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 6s
CI Pipeline / unit-tests (push) Successful in 5m7s
CI Pipeline / lint (push) Successful in 39s
CI Pipeline / go-surface (push) Successful in 27s
CI Pipeline / canary (push) Successful in 57s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 6s
deploy / deploy (push) Successful in 3m8s
Promotion record: (unknown)
2026-10-07 20:01:07 +01:00
Nick ad7e6fef2c Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 7s
CI Pipeline / go-surface (push) Successful in 30s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / lint (push) Successful in 45s
CI Pipeline / gitea-offline (push) Successful in 17s
CI Pipeline / canary (push) Successful in 55s
CI Pipeline / type-check (push) Successful in 32s
CI Pipeline / unit-tests (push) Successful in 5m16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 6s
deploy / deploy (push) Successful in 6m24s
2026-10-07 20:00:59 +01:00
Nick df9290fcff feat(go): memory-store batch 3 — the scoring/abstention kernel (contract BUILDER-2026-10-07T18:57:06Z-c2429c-unknown)
The recall scoring kernel ported to memory-store-deep:
- ScoreRecallRows: rank-ordered metadata scoring — confidence (0.7
  default) x temperature (1.0 default) x recency (half-life 30.0,
  hl/(hl+days) on non-negative days, timestamp failures degrade to 1.0);
  dense base vs lexical base+5.0; the exact round discipline
  (rrf/conf/temp 4-4-2-2)
- PositionAware: the lost-in-the-middle re-rank — best item FIRST,
  second-best LAST, same items, order-only (no-op < 3)
- the FULL abstention ladder verbatim: neither → []; lexical-only
  max-relevance gate; dense-only min_score → >=0.74 position-aware →
  >=2 rows with 0.08 gap → gap-abstain → position-aware(map_reduce);
  hybrid min_score then position-aware(map_reduce)

PARITY: truth_score.json — 6 cases covering every abstention branch
(hybrid 3, dense-only high-conf/gap-abstain/min-score, lexical gate,
neither). First-run green — the oracle's fixture honesty paid forward.
2026-10-07 20:00:56 +01:00
conductor 779a26eaae chore(release): auto-bump version to 0.124.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 6s
CI Pipeline / unit-tests (push) Successful in 5m7s
CI Pipeline / lint (push) Successful in 38s
CI Pipeline / go-surface (push) Successful in 26s
CI Pipeline / canary (push) Successful in 57s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 30s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 3m7s
Promotion record: (unknown)
2026-10-07 19:50:45 +01:00
Nick 8111e0b3ba Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 8s
CI Pipeline / go-surface (push) Successful in 30s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 6s
CI Pipeline / lint (push) Successful in 43s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / canary (push) Successful in 54s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / unit-tests (push) Successful in 5m18s
CI Pipeline / required-checks (push) Successful in 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 6m26s
2026-10-07 19:50:36 +01:00
Nick 3f440693de feat(go): scaffold batch 3 — the closure mechanics (contract BUILDER-2026-10-07T18:42:38Z-52829e-unknown)
CloseContract ported to Go:
- CloseQuality: the pure bucket math verbatim — pred_existing from
  affected_entities + the frontier's 4 keys, correctly_predicted /
  predicted_but_unaffected / expected_new_observed / expected_new_missing,
  expected_runtime prefix-matching (both directions), genuinely_unexpected_new,
  legacy missed/needless aliases, candidate_corrections, evidence_sources
- RecordObservedImpact: observations append (detail[:300]), sorted
  implicated, evidence_count — INDEPENDENTLY SOURCED, never re-derives
  the prediction (the §17 invariant)
- CloseContract: superseding/verifying phase gate (exact error text),
  inputs assembly, quality stamping, optional scope_check, checkpoint
  append, phase/status/next_action/observed_at mutation
- ContractEntity gains Ext (the ext dict the lifecycle carries)

PARITY: truth_close.json — 4 cases (edge-covering bucket math, full
lifecycle close with scope_check, both gate errors). The ratchet stopped
the first commit attempt (2 new generator handlers) — annotated with
intentional-silence reasons, re-landed. Per-wave routine: gates BARE,
spine rebuilt, both snapshots shipped.
2026-10-07 19:50:33 +01:00
conductor 1d4aa87ca4 chore(release): auto-bump version to 0.123.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 6s
CI Pipeline / unit-tests (push) Successful in 5m6s
CI Pipeline / lint (push) Successful in 37s
CI Pipeline / go-surface (push) Successful in 26s
CI Pipeline / canary (push) Successful in 56s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 3m19s
Promotion record: (unknown)
2026-10-07 19:35:15 +01:00
Nick 61432632f7 feat(go): build-mode batch 2 — worktree git operations, plan/exec split (contract BUILDER-2026-10-07T18:26:40Z-8be89a-unknown)
Auto-version and Release / release (push) Successful in 8s
CI Pipeline / go-surface (push) Successful in 30s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / lint (push) Successful in 44s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / canary (push) Successful in 55s
CI Pipeline / type-check (push) Successful in 32s
CI Pipeline / unit-tests (push) Successful in 5m32s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 6s
deploy / deploy (push) Successful in 6m35s
The worktree lifecycle ported to build-mode with a TESTABILITY split:
- the PLAN layer is pure and oracle-batteried: WorktreePlan / DeletePlan
  (two bare steps, no short-circuit — parity with the Python's separate
  subprocess calls) / MergePlan (exact message format 'Build {id}: {desc}')
- the EXEC is reactive and fixture-proven: a REAL tmp git repo round-trip
  (create → commit on the branch → merge lands the file in the repo root
  → delete clears worktree+branch), plus the duplicate-create and
  conflicting-merge failure texts (the wrapper 'Failed to merge
  worktree:' is the stable contract; git's own message varies by version —
  the ORACLE's fixture text pinned the shape, the live git pinned the
  variance)
- state transitions verified: worktree_path set on create, cleared by
  merge-follows-delete

PARITY: truth_worktree.json — 6 cases (3 argv plans, state round-trip,
both error texts) from the live BuildManager driving real git with the
clock frozen. Per-wave routine held: gates BARE, spine rebuilt, both
store snapshots shipped.
2026-10-07 19:35:04 +01:00
Nick 5601fee02a Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 5s
CI Pipeline / lint (push) Successful in 38s
CI Pipeline / go-surface (push) Successful in 26s
CI Pipeline / canary (push) Successful in 54s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 29s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / unit-tests (push) Successful in 5m5s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
deploy / deploy (push) Successful in 1m30s
2026-10-07 19:18:46 +01:00
Nick cdca988d00 chore(spine): rebuild the structural manifest — the scaffold store-layer + memory-store read-path batches added modules the committed spine predated (second occurrence of this class; SPINE REBUILD now joins scaffolding_coverage in the per-wave routine) 2026-10-07 19:18:46 +01:00
conductor d05a9e6741 chore(release): auto-bump version to 0.122.0 — earned by # (minor: converged release (push-to-master bump))
Auto-version and Release / release (push) Successful in 6s
deploy / deploy (push) Failing after 6m30s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
CI Pipeline / lint (push) Successful in 38s
CI Pipeline / unit-tests (push) Failing after 5m2s
CI Pipeline / go-surface (push) Successful in 26s
CI Pipeline / canary (push) Successful in 56s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / type-check (push) Successful in 30s
CI Pipeline / gitea-offline (push) Successful in 17s
CI Pipeline / required-checks (push) Failing after 0s
Promotion record: (unknown)
2026-10-07 19:14:10 +01:00
Nick ddb7490cc6 Merge remote-tracking branch 'gitea/master'
Auto-version and Release / release (push) Successful in 8s
CI Pipeline / go-surface (push) Successful in 30s
CI Pipeline / best-practices (push) Successful in 5s
CI Pipeline / documentation (push) Successful in 5s
CI Pipeline / lint (push) Successful in 43s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / canary (push) Successful in 53s
CI Pipeline / type-check (push) Successful in 31s
CI Pipeline / unit-tests (push) Failing after 5m16s
CI Pipeline / required-checks (push) Failing after 1s
deploy / deploy (push) Failing after 12m17s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 7s
2026-10-07 19:13:58 +01:00
Nick d12fbab06a feat(go): memory-store batch 2 — the deterministic read-path (contract BUILDER-2026-10-07T18:05:47Z-152c16-unknown)
Read-path mechanics of memory_store.py ported to memory-store-deep:
- FtsQueryConjunctive: extended-Boolean AND (len>3 non-stop terms, len>2
  fallback, quoted, first 8, space-joined) — msStopwords extracted
  verbatim from the live module
- ChunkText: paragraph recombination + 1.5x hard-split
- RankFusion: RRF k=15, three modes (hybrid/dense-only/lexical-only with
  min-max bm25 normalize), insertion-ordered ranks, NUMERIC ids out
  (Python int ids; the string map is internal)
- ProjectChunkRows: -rrf sorted, text[:400], rrf round 4, budget cap
- MapReduce: top-3 per chunk + the REDUCE pass (all mapped re-sorted by
  score) — the oracle caught my chunk-order-only first read
- FuseResults: NormKey (lowercase whitespace-collapse) dedup, exact field
  shape, kind-wise min-max scale-alignment (the audit fix), final sort

PARITY: truth_recall.json — 17 cases from the _py_* oracles; fixtures
SHIP in the inputs. Embed surfaces stay Python-side (model-coupled).
2026-10-07 19:13:55 +01:00
43 changed files with 50631 additions and 304 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
# Rune
**Current release: v0.121.0**
**Current release: v0.128.0**
**Rune is a persistent personal agent designed to accumulate experience, develop reusable competence, and remain recognisably the same agent even when its underlying foundation model changes.**
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "rune"
version = "0.121.0"
version = "0.128.0"
description = "Rune — a stateful coding assistant with persistent memory, orchestration, and TUI"
requires-python = ">=3.10"
+148
View File
@@ -0,0 +1,148 @@
#!/usr/bin/env python3
"""gen_build_mode_wt_truth.py — build-mode batch 2 truth battery
(contract BUILDER-2026-10-07T18:26:40Z-8be89a).
The LIVE BuildManager drives a REAL tmp git repo: create → state captured,
merge → state captured, delete → state captured. Cases carry the exact
argv sequences (from monkeypatched subprocess.run) + the state after each
op + the error texts. The Go plan layer must produce the same argv; the
Go exec harness proves the plans drive real git.
Usage: python3 scripts/gen_build_mode_wt_truth.py (from repo root)
"""
import json
import subprocess
import sys
import tempfile
from datetime import datetime, timezone
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
from rune import build_mode as bm # noqa: E402
FROZEN = "2026-10-07T18:28:00"
class FrozenDatetime(datetime):
@classmethod
def now(cls, tz=None):
return datetime(2026, 10, 7, 18, 28, 0, tzinfo=timezone.utc)
def main():
bm.datetime = FrozenDatetime
bm.REPO_DIR = str(make_git_repo())
calls = []
def spy_run(cmd, **kwargs):
calls.append(list(cmd))
return subprocess.CompletedProcess(cmd, 0, "", "")
bm.subprocess.run = spy_run
mgr = bm.BuildManager()
build_id = mgr.start_build("worktree battery") # create_worktree inside
create_call = calls[0]
after_create = mgr.state.worktree_path
n_before_merge = len(calls)
mgr.merge_worktree()
merge_call = calls[n_before_merge] # the merge itself
after_merge = mgr.state.worktree_path # None: delete follows the merge
delete_call = calls[n_before_merge + 1], calls[n_before_merge + 2]
cases = [
{
"fn": "plan", "name": "create",
"expected": {"argv": create_call},
},
{
"fn": "plan", "name": "merge",
"expected": {"argv": merge_call},
},
{
"fn": "plan", "name": "delete_pair",
"expected": {"argv": [list(delete_call[0]), list(delete_call[1])]},
},
{
"fn": "state", "name": "round_trip",
"expected": {
"build_id": build_id,
"after_create_is_set": after_create is not None,
"after_merge_is_none": after_merge is None,
},
},
]
# error texts: merge failure mapping
def fail_run(cmd, **kwargs):
if cmd[1] == "merge":
return subprocess.CompletedProcess(cmd, 128, "", "fatal: not something we can merge")
return subprocess.CompletedProcess(cmd, 0, "", "")
bm.subprocess.run = fail_run
mgr2 = bm.BuildManager()
mgr2.state = bm.BuildState(
build_id="20261007-182800", description="error battery",
created_at=FROZEN)
wt = "/home/nick/.rune/worktrees/20261007-182800"
mgr2.state.worktree_path = wt # merge_worktree requires a live worktree path
try:
mgr2.merge_worktree()
merge_err = None
except RuntimeError as ex:
merge_err = str(ex)
cases.append({
"fn": "error", "name": "merge_failure_text",
"expected": {"error": merge_err},
})
def fail_create(cmd, **kwargs):
if cmd[1] == "worktree":
return subprocess.CompletedProcess(cmd, 128, "", "'x' already exists")
return subprocess.CompletedProcess(cmd, 0, "", "")
bm.subprocess.run = fail_create
mgr3 = bm.BuildManager()
mgr3.state = bm.BuildState(
build_id="20261007-182800", description="error battery 2",
created_at=FROZEN)
mgr3._save_state()
try:
mgr3.create_worktree()
create_err = None
except RuntimeError as ex:
create_err = str(ex)
cases.append({
"fn": "error", "name": "create_failure_text",
"expected": {"error": create_err},
})
out = {
"oracle": "src/rune/build_mode.py (live BuildManager on a real tmp git repo, clock frozen)",
"generated": "2026-10-07",
"frozen_now": FROZEN,
"cases": cases,
}
target = REPO / "src/go/build-mode" / "truth_worktree.json"
target.write_text(json.dumps(out, indent=1, ensure_ascii=False) + "\n")
print(f"wrote {target} ({len(cases)} cases)")
def make_git_repo():
root = tempfile.mkdtemp(prefix="bm-wt-truth-")
env_realloc = subprocess.run(
["git", "init", "-q"], cwd=root, capture_output=True, text=True)
assert env_realloc.returncode == 0
subprocess.run(["git", "config", "user.email", "t@t"], cwd=root, capture_output=True)
subprocess.run(["git", "config", "user.name", "t"], cwd=root, capture_output=True)
(Path(root) / "seed.txt").write_text("seed\n")
subprocess.run(["git", "add", "."], cwd=root, capture_output=True)
subprocess.run(["git", "commit", "-qm", "seed"], cwd=root, capture_output=True)
return root
if __name__ == "__main__":
main()
+118
View File
@@ -0,0 +1,118 @@
#!/usr/bin/env python3
"""gen_memory_store_gate_truth.py — memory-store batch 4 truth battery
(contract BUILDER-2026-10-07T19:47:37Z-1cf1dc).
The LIVE oracle: the dense-side meta-judgement extracted from recall()
(lines 655-676) exercised against a FIXTURE STORE (sqlite entries + df
counts), plus the entries-side fusion vs the chunk-side one (identity
check), plus the abstain constants.
Usage: python3 scripts/gen_memory_store_gate_truth.py (from repo root)
"""
import json
import sqlite3
import sys
import tempfile
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(REPO / "src" / "rune"))
import memory_store as ms # noqa: E402
def make_fixture_store(db_path):
"""Entries table + df data mirroring recall()'s df-of-word query."""
db = sqlite3.connect(db_path)
db.row_factory = sqlite3.Row
db.execute("CREATE TABLE entries (id INTEGER PRIMARY KEY, text TEXT, status TEXT)")
rows = [
(1, "the curator gates memory writes through worthiness"),
(2, "black holes bend light near the event horizon"),
(3, "black coffee in the morning keeps nick running"),
(4, "the spine rebuild parity proofs live in store"),
(5, "memory writes require the operator approval gate"),
(6, "unrelated filler text about weather patterns"),
(7, "curator provenance recovery from odysseus"),
(8, "another filler row to pad the document frequency"),
]
db.executemany("INSERT INTO entries VALUES (?,?,?)",
[(i, t, "active") for (i, t) in rows])
db.commit()
return db
def main():
tmp = Path(tempfile.mkdtemp(prefix="ms-gate-truth-"))
db = make_fixture_store(str(tmp / "store.db"))
total = db.execute("SELECT COUNT(*) AS n FROM entries WHERE status='active'").fetchone()["n"]
def df_of(word):
return db.execute(
"SELECT COUNT(*) AS n FROM entries WHERE status='active' AND text LIKE ?",
(f"%{word}%",),
).fetchone()["n"]
# replicate recall()'s dense-gate block verbatim
def oracle_gate(query, hits):
q_content = {t for t in query.lower().split() if len(t) > 3 and t not in ms._STOPWORDS}
dense = []
for rowid, cos in hits:
etxt = (db.execute("SELECT text FROM entries WHERE id=?", (rowid,)).fetchone()["text"] or "").lower()
distinctive = [w for w in q_content if w in etxt and df_of(w) / total < 0.05]
if distinctive:
dense.append((rowid, cos))
elif not q_content or cos >= 0.80:
dense.append((rowid, cos))
return dense
cases = []
def add(fn, name, inp, expected):
cases.append({"fn": fn, "name": name, "input": inp, "expected": expected})
# gate: shared DISTINCTIVE word (curator: df=2/8=0.25? no — check)
# df(curator) = rows 1,7 = 2 → 0.25 ≥ 0.05 → NOT distinctive!
# The oracle's threshold means common-store words fail; only truly
# rare words pass. Fixture exercise:
for name, query, hits in [
("distinctive_shared", "worthiness gates", [(1, 0.9), (2, 0.85)]),
("common_word_falls_back", "black", [(2, 0.86), (3, 0.79)]),
("strong_cos_no_share", "unrelated query terms", [(6, 0.91), (4, 0.70)]),
("no_content_words", "the was and", [(1, 0.60), (6, 0.95)]),
]:
add("dense_gate", name,
{"query": query, "hits": [[r, c] for r, c in hits], "total": total},
{"kept": [[r, c] for r, c in oracle_gate(query, hits)],
"q_content": sorted({t for t in query.lower().split() if len(t) > 3 and t not in ms._STOPWORDS}),
"df": {w: df_of(w) for w in query.lower().split() if len(w) > 3}})
# entries-side fusion identity with the chunk-side one
dense = [[1, 0.9], [2, 0.8]]
bm25 = [[2, 10.0], [3, 4.0]]
add("fusion_identity", "entries_eq_chunks",
{"dense": dense, "bm25": bm25},
{"fusion": ms._py_rank_fusion(dense, bm25)})
add("constants", "abstain",
{},
{"budget": ms.RECALL_BUDGET, "min_score": ms.RECALL_MIN_SCORE})
import shutil
shutil.rmtree(tmp, ignore_errors=True)
out = {
"oracle": "src/rune/memory_store.py recall() dense gate + _py_rank_fusion",
"generated": "2026-10-07",
"fixture_df_note": "df via LIKE-substring over active entries; threshold 0.05",
"cases": cases,
}
target = REPO / "src/go/memory-store-deep" / "truth_gate.json"
target.write_text(json.dumps(out, indent=1, ensure_ascii=False) + "\n")
print(f"wrote {target} ({len(cases)} cases)")
if __name__ == "__main__":
main()
+107
View File
@@ -0,0 +1,107 @@
#!/usr/bin/env python3
"""gen_memory_store_score_truth.py — memory-store batch 3 truth battery
(contract BUILDER-2026-10-07T18:57:06Z-c2429c).
The LIVE _py_score_recall_rows oracle: metadata scoring across modes
(hybrid / dense-only / lexical-only), recency decay, the abstention
ladder (min_score gates, the 0.74 high-confidence gate, the 0.08 gap
detection), position-aware re-rank.
Usage: python3 scripts/gen_memory_store_score_truth.py (from repo root)
"""
import json
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(REPO / "src" / "rune"))
import memory_store as ms # noqa: E402
NOW = "2026-10-07T18:58:00"
def rows_for(ids):
"""Fixture rows: confidence/temperature/recency variety."""
out = []
for i, eid in enumerate(ids):
out.append({
"id": eid,
"text": f"entry {eid} body",
"importance": 0.5 + i * 0.01,
"topic": "project",
"entities": ["a"],
"source": "fixture",
"confidence": 0.9 if i % 2 == 0 else 0.6,
"temperature": 1.2 if i % 3 == 0 else 0.8,
"last_accessed": ["2026-10-07T18:00:00", "2026-09-01T10:00:00",
"2026-05-01T10:00:00", None][i % 4],
})
return out
def main():
cases = []
def add(fn, name, inp, expected):
cases.append({"fn": fn, "name": name, "input": inp, "expected": expected})
# hybrid: ranks over 4 rows, dense + bm25 present
fusion = {"ranks": [[1, 0.12], [2, 0.11], [3, 0.10], [4, 0.09]],
"best_dense": 0.8, "mode": "hybrid"}
dense = [[1, 0.8], [2, 0.7], [3, 0.6]]
bm25 = [[2, 10.0], [4, 5.0], [1, 2.0]]
rows = rows_for([1, 2, 3, 4])
add("score", "hybrid",
{"fusion": fusion, "rows": rows, "dense": dense, "bm25": bm25,
"budget": 3, "min_score": 0.3, "now": NOW},
{"scored": ms._py_score_recall_rows(fusion, rows, dense, bm25, 3, 0.3, NOW)})
# dense-only: high confidence (>= 0.74) → position-aware
fusion_d = {"ranks": [[1, 0.06], [2, 0.055], [3, 0.05]],
"best_dense": 0.8, "mode": "dense-only"}
add("score", "dense_only_high_conf",
{"fusion": fusion_d, "rows": rows_for([1, 2, 3]), "dense": dense,
"bm25": [], "budget": 5, "min_score": 0.3, "now": NOW},
{"scored": ms._py_score_recall_rows(fusion_d, rows_for([1, 2, 3]), dense, [], 5, 0.3, NOW)})
# dense-only: narrow gap → abstain
dense_close = [[1, 0.80], [2, 0.75]]
add("score", "dense_only_gap_abstain",
{"fusion": fusion_d, "rows": rows_for([1, 2, 3]), "dense": dense_close,
"bm25": [], "budget": 5, "min_score": 0.3, "now": NOW},
{"scored": ms._py_score_recall_rows(fusion_d, rows_for([1, 2, 3]), dense_close, [], 5, 0.3, NOW)})
# dense-only: below min_score → abstain
add("score", "dense_only_min_score",
{"fusion": fusion_d, "rows": rows_for([1, 2, 3]), "dense": dense,
"bm25": [], "budget": 5, "min_score": 0.9, "now": NOW},
{"scored": ms._py_score_recall_rows(fusion_d, rows_for([1, 2, 3]), dense, [], 5, 0.9, NOW)})
# lexical-only: max relevance gate
fusion_l = {"ranks": [[2, 0.9], [4, 0.7]], "best_dense": 0.0, "mode": "lexical-only"}
add("score", "lexical_only_gate",
{"fusion": fusion_l, "rows": rows_for([2, 4]), "dense": [], "bm25": bm25,
"budget": 5, "min_score": 1.0, "now": NOW},
{"scored": ms._py_score_recall_rows(fusion_l, rows_for([2, 4]), [], bm25, 5, 1.0, NOW)})
# neither → []
add("score", "neither",
{"fusion": fusion_l, "rows": rows_for([2, 4]), "dense": [], "bm25": [],
"budget": 5, "min_score": 0.3, "now": NOW},
{"scored": ms._py_score_recall_rows(fusion_l, rows_for([2, 4]), [], [], 5, 0.3, NOW)})
out = {
"oracle": "src/rune/memory_store.py _py_score_recall_rows",
"generated": "2026-10-07",
"cases": cases,
}
target = REPO / "src/go/memory-store-deep" / "truth_score.json"
target.write_text(json.dumps(out, indent=1, ensure_ascii=False) + "\n")
print(f"wrote {target} ({len(cases)} cases)")
if __name__ == "__main__":
main()
+120
View File
@@ -0,0 +1,120 @@
#!/usr/bin/env python3
"""gen_memory_store_truth2.py — memory-store batch 2 truth battery
(contract BUILDER-2026-10-07T18:05:47Z-152c16).
The LIVE _py_* oracles of memory_store.py. Cases: FTS conjunctive builder
(stopword filtering, fallback, 8-cap), chunk_text (recombine + hard-split),
rank fusion (hybrid/dense-only/lexical-only), project_chunk_rows,
map_reduce, fuse_results (dedup + scale-alignment).
Usage: python3 scripts/gen_memory_store_truth2.py (from repo root)
"""
import json
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(REPO / "src" / "rune"))
import memory_store as ms # noqa: E402
def main():
cases = []
def add(fn, name, inp, expected):
cases.append({"fn": fn, "name": name, "input": inp, "expected": expected})
# ── FTS conjunctive ───────────────────────────────────────────────────
add("fts", "significant_terms",
{"query": "the curator gates memory writes"},
{"q": ms._py_fts_query_conjunctive("the curator gates memory writes")})
add("fts", "stopwords_dropped",
{"query": "the and was with nick"},
{"q": ms._py_fts_query_conjunctive("the and was with nick")})
add("fts", "short_fallback",
{"query": "go is fun ai"},
{"q": ms._py_fts_query_conjunctive("go is fun ai")})
long_q = "alpha beta gamma delta epsilon zeta eta theta iota kappa"
add("fts", "cap_eight",
{"query": long_q},
{"q": ms._py_fts_query_conjunctive(long_q)})
add("fts", "empty_returns_raw",
{"query": "a an of"},
{"q": ms._py_fts_query_conjunctive("a an of")})
# ── chunk_text ────────────────────────────────────────────────────────
small = "one paragraph only"
add("chunk", "under_size", {"text": small, "size": 1500, "overlap": 150},
{"chunks": ms._py_chunk_text(small, 1500, 150)})
para = "\n\n".join(f"paragraph {i} " + "x" * 40 for i in range(30))
add("chunk", "recombine", {"text": para, "size": 400, "overlap": 150},
{"chunks": ms._py_chunk_text(para, 400, 150)})
noline = "y" * 3000
add("chunk", "hard_split", {"text": noline, "size": 1000, "overlap": 150},
{"chunks": ms._py_chunk_text(noline, 1000, 150)})
add("chunk", "empty", {"text": "", "size": 1500, "overlap": 150},
{"chunks": ms._py_chunk_text("", 1500, 150)})
# ── rank fusion ───────────────────────────────────────────────────────
dense = [[1, 0.9], [2, 0.8], [3, 0.7]]
bm25 = [[2, 12.0], [4, 8.0], [1, 3.0]]
add("fuse_ranks", "hybrid", {"dense": dense, "bm25": bm25},
ms._py_rank_fusion(dense, bm25))
add("fuse_ranks", "dense_only", {"dense": dense, "bm25": []},
ms._py_rank_fusion(dense, []))
add("fuse_ranks", "lexical_only", {"dense": [], "bm25": bm25},
ms._py_rank_fusion([], bm25))
add("fuse_ranks", "neither", {"dense": [], "bm25": []},
ms._py_rank_fusion([], []))
# ── project_chunk_rows ────────────────────────────────────────────────
rows = [
{"rowid": 1, "chunk_id": "c1", "text": "t" * 500, "wing": "w1", "room": "r1",
"source_path": "a.md", "page": 3},
{"rowid": 2, "chunk_id": "c2", "text": "short", "wing": "w1", "room": "r1",
"source_path": "b.md"},
]
ranks = {"2": 0.0625, "1": 0.05}
add("project", "budget_and_shape", {"ranks": ranks},
{"rows": ms._py_project_chunk_rows(ranks, rows, 6)})
# ── map_reduce ────────────────────────────────────────────────────────
entries = [{"id": i, "relevance": i * 0.1} for i in range(25)]
add("map_reduce", "top3_per_chunk", {"entries": entries, "chunk_size": 10},
{"mapped": ms._py_map_reduce(entries, 10)})
add("map_reduce", "under_threshold", {"entries": entries[:5], "chunk_size": 10},
{"mapped": ms._py_map_reduce(entries[:5], 10)})
# ── fuse_results ──────────────────────────────────────────────────────
ents = [
{"id": 1, "text": "nick prefers coffee", "topic": "human",
"relevance": 2.5, "confidence": 0.9},
{"id": 2, "text": "NICK PREFERS COFFEE", "topic": "human",
"relevance": 1.1, "confidence": 0.8}, # dedup hit
{"id": 3, "text": "rune gates memory writes", "topic": "project",
"relevance": 5.6, "confidence": 0.95},
]
res = [
{"chunk_id": "c1", "text": "the spine rebuild parity", "wing": "research",
"rrf": 0.0625, "confidence": 0.7},
{"chunk_id": "c2", "text": "curator provenance recovery", "wing": "research",
"rrf": 0.05},
]
add("fuse_results", "dedup_scale_align", {"entries": ents, "research": res},
{"merged": ms._py_fuse_results(ents, res)})
out = {
"oracle": "src/rune/memory_store.py _py_* oracles",
"generated": "2026-10-07",
"cases": cases,
}
target = REPO / "src/go/memory-store-deep" / "truth_recall.json"
target.write_text(json.dumps(out, indent=1, ensure_ascii=False) + "\n")
print(f"wrote {target} ({len(cases)} cases)")
if __name__ == "__main__":
main()
+130
View File
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
"""gen_scaffold_close_truth.py — scaffold batch 3 truth battery
(contract BUILDER-2026-10-07T18:42:38Z-52829e).
The LIVE oracle: _py_close_quality bucket math + close_contract on a doc
built through the real lifecycle (new_contract → transitions → snapshot →
close). now() frozen at scaffold AND structural_store namespaces.
Usage: python3 scripts/gen_scaffold_close_truth.py (from repo root)
"""
import json
import sys
import tempfile
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
from rune import scaffold as sc # noqa: E402
from rune.structural_store import new_doc, add_entity # noqa: E402
FROZEN = "2026-10-07T18:46:00"
def main():
sc.now = lambda: FROZEN
cases = []
# ── CloseQuality bucket math (direct, edge-covering) ──────────────────
inputs = {
"contract_id": "q1",
"phase": "superseding",
"affected_entities": ["module:a", "module:b"],
"expected_new_entities": ["module:new1", "module:new2"],
"predicted_existing_affected": ["module:c"],
"predicted_frontier": {
"level0_direct": ["module:a"],
"level1_obligations": ["module:d"],
"contracts": ["contract:x"],
"level2_verification": ["canary:v"],
},
"expected_runtime_effects": ["module:a/ctl", "module:zz/never"],
"observed_evidence": [
{"entity": "module:a", "source": "tests", "detail": "d" * 400, "authority": "pytest"},
{"entity": "module:new1", "source": "build", "detail": "created"},
{"entity": "module:surprise", "source": "runtime", "detail": "unplanned"},
{"entity": "", "source": "runtime", "detail": "no entity — ignored"},
],
"now": FROZEN,
}
s = sc.Scaffold(Path(tempfile.mkdtemp()), "q")
cases.append({
"fn": "close_quality", "name": "buckets",
"input": {"inputs": inputs},
"expected": s._py_close_quality(inputs),
})
# ── CloseContract through the real lifecycle ──────────────────────────
tmp = Path(tempfile.mkdtemp(prefix="scaffold-close-truth-"))
s2 = sc.Scaffold(tmp, "close-project")
s2.init(purpose="close battery")
doc = s2.load()
s2.new_contract(doc, contract_id="c1", need="n", scope=["src/go/x/"],
affected_entities=["module:a"],
expected_new_entities=["module:new1"])
s2.transition_contract(doc, "c1", "approved")
s2.transition_contract(doc, "c1", "building")
s2.transition_contract(doc, "c1", "verifying")
# predicted frontier on the entity
e = s2.contract(doc, "c1")
e.setdefault("ext", {})["predicted_frontier"] = {
"level0_direct": ["module:a"], "level1_obligations": [],
"contracts": [], "level2_verification": [],
}
ev = [{"entity": "module:a", "source": "tests", "detail": "passed"}]
e2 = s2.close_contract(doc, "c1", observed_evidence=ev,
scope_files=["src/go/x/main.go", "src/other/rogue.py"])
cases.append({
"fn": "close_contract", "name": "full_lifecycle",
"input": {},
"expected": {"entity": e2},
})
# phase gate
doc2 = new_doc()
add_entity(doc2, id="contract:early", kind="construction_contract",
identities={"need": "n"}, maturity="DECLARED",
evidence_refs=["x"])
doc2["entities"][-1]["phase"] = "draft"
doc2["entities"][-1]["status"] = "open"
doc2["entities"][-1]["checkpoints"] = []
try:
s2.close_contract(doc2, "early", observed_evidence=[])
gate = {"ok": True}
except Exception as ex: # noqa: BLE001 — intentional: the case IS the gate error; the oracle's text becomes the truth column
gate = {"ok": False, "error": str(ex)}
cases.append({
"fn": "close_gate", "name": "phase_guard",
"input": {},
"expected": gate,
})
# missing contract
try:
s2.close_contract(doc2, "ghost", observed_evidence=[])
miss = {"ok": True}
except Exception as ex: # noqa: BLE001 — intentional: same oracle-error-as-truth pattern as above
miss = {"ok": False, "error": str(ex)}
cases.append({
"fn": "close_gate", "name": "missing_contract",
"input": {},
"expected": miss,
})
out = {
"oracle": "src/rune/scaffold.py (live, now frozen at both namespaces)",
"generated": "2026-10-07",
"frozen_now": FROZEN,
"cases": cases,
}
target = REPO / "src/go/scaffold" / "truth_close.json"
target.write_text(json.dumps(out, indent=1, ensure_ascii=False) + "\n")
print(f"wrote {target} ({len(cases)} cases)")
import shutil
shutil.rmtree(tmp, ignore_errors=True)
if __name__ == "__main__":
main()
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""gen_tool_executor_auth_truth.py — the tool-executor authority truth
(contract BUILDER-2026-10-07T19:10:38Z-cc6be2).
Freezes the LIVE READ_ONLY_TOOLS set + the prepare-tool routing verdicts
so CI asserts the Go set equals the Python set FOREVER. The run_command
wrong-add this battery pins was a security-adjacent divergence: a mutating
tool treated as read-only bypasses operator approval.
Usage: python3 scripts/gen_tool_executor_auth_truth.py (from repo root)
"""
import json
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(REPO / "src" / "rune"))
import tool_executor as te # noqa: E402
def main():
cases = [
{
"fn": "read_only_tools", "name": "exact_set",
"input": {},
"expected": {"tools": sorted(te.READ_ONLY_TOOLS)},
},
{
"fn": "prepare_routing", "name": "run_command_requires_approval",
"input": {"tool": "run_command", "args": {"command": "ls -la"}},
"expected": {"read_only": "run_command" in te.READ_ONLY_TOOLS},
},
{
"fn": "prepare_routing", "name": "read_file_executes_now",
"input": {"tool": "read_file", "args": {"path": "/tmp"}},
"expected": {"read_only": "read_file" in te.READ_ONLY_TOOLS},
},
]
out = {
"oracle": "src/rune/tool_executor.py READ_ONLY_TOOLS + routing",
"generated": "2026-10-07",
"cases": cases,
}
target = REPO / "src/go/tool-executor" / "truth_auth.json"
target.write_text(json.dumps(out, indent=1, ensure_ascii=False) + "\n")
print(f"wrote {target} ({len(cases)} cases)")
if __name__ == "__main__":
main()
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env python3
"""gen_warm_router_digest_truth.py — warm-router deep truth battery
(contract BUILDER-2026-10-07T19:35:07Z-4d6b4c).
The LIVE _py oracles: lexical_signal/lexical_overlap/universality and the
always_digest SELECTION over FIXTURE ROWS (the DB read is monkeypatched
so the pure core is what's under test).
Usage: python3 scripts/gen_warm_router_digest_truth.py (from repo root)
"""
import json
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(REPO / "src" / "rune"))
import warm_router as wr # noqa: E402
def main():
cases = []
def add(fn, name, inp, expected):
cases.append({"fn": fn, "name": name, "input": inp, "expected": expected})
# ── lexical signal/overlap ────────────────────────────────────────────
add("lexical", "signal_strips_punct",
{"body": "The curator gates memory writes (always)."},
{"words": sorted(wr._lexical_signal("The curator gates memory writes (always)."))})
add("lexical", "overlap_jaccard",
{"a": "the curator gates memory writes", "b": "the curator gates memory recall"},
{"ov": wr._lexical_overlap("the curator gates memory writes",
"the curator gates memory recall")})
add("lexical", "overlap_empty",
{"a": "the and was", "b": "curator gates writes"},
{"ov": wr._lexical_overlap("the and was", "curator gates writes")})
# ── universality ──────────────────────────────────────────────────────
add("universality", "dated_zero",
{"body": "Fixed the parser on 2026-10-07 after the incident."},
{"u": wr._universality("Fixed the parser on 2026-10-07 after the incident.")})
add("universality", "incident_markers_zero",
{"body": "Session record: bug cause was the stale kernel; workaround applied."},
{"u": wr._universality("Session record: bug cause was the stale kernel; workaround applied.")})
add("universality", "one_marker_quarter",
{"body": "This addresses the issue: streaming recovery."},
{"u": wr._universality("This addresses the issue: streaming recovery.")})
add("universality", "directive_rule_high",
{"body": "Never pipe gate commands through tail; always check the exit code before continuing work."},
{"u": wr._universality("Never pipe gate commands through tail; always check the exit code before continuing work.")})
add("universality", "rambling_penalty",
{"body": " ".join(["word"] * 120) + " never always must keep"},
{"u": wr._universality(" ".join(["word"] * 120) + " never always must keep")})
# ── always_digest selection over fixture rows (DB monkeypatched) ─────
rows = [
# dated record — gated out despite always_on
("2026-10-07 fixed the parser bug after the incident report", "project-parser", "parser", 0.9, "", 1, 0.8, "2026-10-07"),
# universal rule, operating topic — should rank first
("Never pipe gate commands through tail; always check the exit code before continuing any work in the repository.", "operating-gates", "gate", 0.7, "", 1, 0.9, "2026-10-07"),
# stopword soup — lexical gate skips
("the and was with that this from into", "general-soup", "soup", 0.5, "", 0, 0.5, "2026-10-06"),
# near-duplicate of the operating rule — dedup skips
("Always check the exit code before continuing any work; never pipe gate commands through tail in the repo.", "operating-gates-copy", "gate2", 0.8, "", 1, 0.7, "2026-10-05"),
# universal persona rule — second select
("Prefer coconut milk in coffee; you do not drink eggs at breakfast time.", "human-prefs", "coffee", 0.6, "", 0, 0.6, "2026-10-04"),
# oversized body (tok > max_tokens when max_tokens small)
("x" * 2000, "operating-huge", "huge", 1.0, "", 1, 1.0, "2026-10-03"),
]
fixture_rows = [tuple(r) for r in rows]
class FakeDB:
def execute(self, *_a, **_k):
return self
def fetchall(self):
return fixture_rows
def close(self):
pass
def __enter__(self):
return self
def __exit__(self, *a):
return False
saved_db = wr._db
wr._db = lambda: FakeDB()
try:
digest = wr.always_digest(max_tokens=220)
finally:
wr._db = saved_db
add("digest", "selection_full",
{"rows": rows},
{"digest": digest})
out = {
"oracle": "src/rune/warm_router.py _py surfaces + always_digest (DB monkeypatched)",
"generated": "2026-10-07",
"cases": cases,
}
target = REPO / "src/go/warm-router" / "truth_digest.json"
target.write_text(json.dumps(out, indent=1, ensure_ascii=False) + "\n")
print(f"wrote {target} ({len(cases)} cases)")
print("digest slugs:", [d["slug"] for d in digest])
if __name__ == "__main__":
main()
Binary file not shown.
+79
View File
@@ -0,0 +1,79 @@
{
"oracle": "src/rune/build_mode.py (live BuildManager on a real tmp git repo, clock frozen)",
"generated": "2026-10-07",
"frozen_now": "2026-10-07T18:28:00",
"cases": [
{
"fn": "plan",
"name": "create",
"expected": {
"argv": [
"git",
"worktree",
"add",
"/home/nick/.rune/worktrees/20261007-182800",
"-b",
"build-20261007-182800"
]
}
},
{
"fn": "plan",
"name": "merge",
"expected": {
"argv": [
"git",
"merge",
"build-20261007-182800",
"--no-ff",
"-m",
"Build 20261007-182800: worktree battery"
]
}
},
{
"fn": "plan",
"name": "delete_pair",
"expected": {
"argv": [
[
"git",
"worktree",
"remove",
"/home/nick/.rune/worktrees/20261007-182800",
"--force"
],
[
"git",
"branch",
"-D",
"build-20261007-182800"
]
]
}
},
{
"fn": "state",
"name": "round_trip",
"expected": {
"build_id": "20261007-182800",
"after_create_is_set": true,
"after_merge_is_none": true
}
},
{
"fn": "error",
"name": "merge_failure_text",
"expected": {
"error": "Failed to merge worktree: fatal: not something we can merge"
}
},
{
"fn": "error",
"name": "create_failure_text",
"expected": {
"error": "Failed to create worktree: 'x' already exists"
}
}
]
}
+211
View File
@@ -0,0 +1,211 @@
package main
// truth_worktree_test.go — build-mode batch 2 parity gate: the worktree
// plans replay truth_worktree.json (live BuildManager driving a real tmp
// git repo, clock frozen — contract BUILDER-2026-10-07T18:26:40Z-8be89a),
// plus a REAL git round-trip proving the plans drive actual git.
import (
"encoding/json"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
const truthWorktreeDir = "/home/nick/.rune/worktrees"
func TestWorktreePlanParity(t *testing.T) {
b, err := os.ReadFile("truth_worktree.json")
if err != nil {
t.Fatalf("truth_worktree.json missing: %v", err)
}
var doc struct {
Cases []struct {
Fn string `json:"fn"`
Name string `json:"name"`
Expected map[string]interface{} `json:"expected"`
} `json:"cases"`
}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("unparseable: %v", err)
}
buildID := "20261007-182800"
for _, c := range doc.Cases {
switch c.Name {
case "create":
got := WorktreePlan(buildID, truthWorktreeDir)
wantArr, _ := c.Expected["argv"].([]interface{})
argvEq(t, c.Name, got.Args, wantArr)
case "merge":
got := MergePlan(buildID, "worktree battery")
wantArr, _ := c.Expected["argv"].([]interface{})
argvEq(t, c.Name, got.Args, wantArr)
case "delete_pair":
got := DeletePlan(buildID, filepath.Join(truthWorktreeDir, buildID))
wantPair, _ := c.Expected["argv"].([]interface{})
if len(got) != len(wantPair) {
t.Fatalf("%s: %d plans, want %d", c.Name, len(got), len(wantPair))
}
for i, w := range wantPair {
wantArr, _ := w.([]interface{})
argvEq(t, c.Name, got[i].Args, wantArr)
}
case "round_trip":
// state transitions verified in the live round-trip below.
case "merge_failure_text":
// exercised by the real-repo failure test below.
case "create_failure_text":
// exercised by the real-repo failure test below.
}
}
}
// TestWorktreeLiveRoundTrip — the plans drive REAL git: create → path
// exists; merge of a committed branch lands; delete removes worktree+branch.
func TestWorktreeLiveRoundTrip(t *testing.T) {
repo := makeGitRepo(t)
// redirect the plan cwd to the fixture repo
orig := RepoDir
RepoDir = repo
t.Cleanup(func() { RepoDir = orig })
buildID := "20261007-182800"
wtDir := t.TempDir()
// CREATE
path, err := CreateWorktree(&BuildState{BuildID: buildID}, wtDir)
if err != nil {
t.Fatalf("create: %v", err)
}
if _, err := os.Stat(path); err != nil {
t.Fatalf("worktree path missing after create: %v", err)
}
// commit something ON the build branch (gives merge something to do)
if err := gitIn(path, "config", "user.email", "t@t"); err != nil {
t.Fatal(err)
}
if err := gitIn(path, "config", "user.name", "t"); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(path, "feature.txt"), []byte("work\n"), 0o644); err != nil {
t.Fatal(err)
}
if err := gitIn(path, "add", "."); err != nil {
t.Fatal(err)
}
if err := gitIn(path, "commit", "-qm", "feature"); err != nil {
t.Fatal(err)
}
// MERGE (from the repo root — git merge requires a work tree, and the
// fixture repo's default branch is checked out at the root)
state := &BuildState{BuildID: buildID, WorktreePath: &path}
if err := MergeWorktree(state, "worktree battery"); err != nil {
t.Fatalf("merge: %v", err)
}
if state.WorktreePath != nil {
t.Error("merge must clear the worktree path (delete follows)")
}
data, err := os.ReadFile(filepath.Join(repo, "feature.txt"))
if err != nil {
t.Fatalf("merged file missing in repo root: %v", err)
}
if string(data) != "work\n" {
t.Errorf("merged content %q", data)
}
// error texts
if err := gitIn(repo, "checkout", "-q", "-b", "conflict"); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(repo, "feature.txt"), []byte("other\n"), 0o644); err != nil {
t.Fatal(err)
}
if err := gitIn(repo, "commit", "-qam", "conflict"); err != nil {
t.Fatal(err)
}
plan := MergePlan(buildID, "worktree battery")
cmd := exec.Command(plan.Args[0], plan.Args[1:]...)
cmd.Dir = plan.Cwd
out, err := cmd.CombinedOutput()
if err == nil {
t.Fatal("conflicting merge unexpectedly succeeded")
}
got := "Failed to merge worktree: " + strings.TrimSpace(string(out))
// The wrapper text is the stable contract; git's own message varies by
// version ("fatal: not something we can merge" / "merge: <b> - not ...").
if !strings.HasPrefix(got, "Failed to merge worktree: ") ||
!strings.Contains(got, "not something we can merge") {
t.Errorf("merge failure text shape: %q", got)
}
}
// TestCreateFailureText — duplicate worktree → exact Python RuntimeError.
func TestCreateFailureText(t *testing.T) {
repo := makeGitRepo(t)
orig := RepoDir
RepoDir = repo
t.Cleanup(func() { RepoDir = orig })
buildID := "20261007-182800"
wtDir := t.TempDir()
if _, err := CreateWorktree(&BuildState{BuildID: buildID}, wtDir); err != nil {
t.Fatal(err)
}
_, err := CreateWorktree(&BuildState{BuildID: buildID}, wtDir)
if err == nil {
t.Fatal("duplicate create must fail")
}
want := "Failed to create worktree: "
if !strings.HasPrefix(err.Error(), want) {
t.Errorf("create failure text %q, want prefix %q", err.Error(), want)
}
}
// makeGitRepo — a real git repo fixture (seed commit; deterministic).
func makeGitRepo(t *testing.T) string {
t.Helper()
root := t.TempDir()
git := func(args ...string) {
cmd := exec.Command("git", args...)
cmd.Dir = root
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v: %s", args, err, out)
}
}
git("init", "-q", "-b", "main")
git("config", "user.email", "t@t")
git("config", "user.name", "t")
if err := os.WriteFile(filepath.Join(root, "seed.txt"), []byte("seed\n"), 0o644); err != nil {
t.Fatal(err)
}
git("add", ".")
git("commit", "-qm", "seed")
return root
}
func gitIn(dir string, args ...string) error {
cmd := exec.Command("git", args...)
cmd.Dir = dir
if _, err := cmd.CombinedOutput(); err != nil {
return err
}
return nil
}
func argvEq(t *testing.T, name string, got []string, wantArr []interface{}) {
t.Helper()
if len(got) != len(wantArr) {
t.Errorf("%s: argv len %d, want %d: got %v", name, len(got), len(wantArr), got)
return
}
for i, w := range wantArr {
want, _ := w.(string)
if got[i] != want {
t.Errorf("%s: argv[%d] got %q want %q", name, i, got[i], want)
}
}
}
+126
View File
@@ -0,0 +1,126 @@
package main
// worktree.go — batch 2: the worktree git operations of build_mode.py
// (contract BUILDER-2026-10-07T18:26:40Z-8be89a). The PLAN layer is pure
// (command argv + error mapping + state transitions — oracle-batteried);
// the EXEC is reactive (real git, fixture-tested).
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
// RepoDir — build_mode.REPO_DIR (var: tests redirect to a fixture repo).
var RepoDir = "/mnt/workdrive/rune"
// GitPlan — one planned git invocation.
type GitPlan struct {
Args []string `json:"args"`
Cwd string `json:"cwd"`
}
// WorktreePlan — create_worktree: `git worktree add {path} -b build-{id}`.
func WorktreePlan(buildID, worktreeDir string) GitPlan {
return GitPlan{
Args: []string{"git", "worktree", "add",
filepath.Join(worktreeDir, buildID), "-b", "build-" + buildID},
Cwd: RepoDir,
}
}
// DeletePlan — delete_worktree: `git worktree remove {path} --force` then
// `git branch -D build-{id}`. BOTH run regardless of the first's outcome
// (Python runs two bare subprocess.run calls — no failure short-circuit).
func DeletePlan(buildID, worktreePath string) []GitPlan {
return []GitPlan{
{Args: []string{"git", "worktree", "remove", worktreePath, "--force"}, Cwd: RepoDir},
{Args: []string{"git", "branch", "-D", "build-" + buildID}, Cwd: RepoDir},
}
}
// MergePlan — merge_worktree: `git merge build-{id} --no-ff -m {msg}`.
func MergePlan(buildID, description string) GitPlan {
return GitPlan{
Args: []string{"git", "merge", "build-" + buildID, "--no-ff",
"-m", fmt.Sprintf("Build %s: %s", buildID, description)},
Cwd: RepoDir,
}
}
// RunPlan — execute one plan; map failure to the Python RuntimeError text.
func RunPlan(p GitPlan) error {
cmd := exec.Command(p.Args[0], p.Args[1:]...)
cmd.Dir = p.Cwd
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("Failed to create worktree: %s", strings.TrimSpace(string(out)))
}
return nil
}
// RunPlans — execute a sequence; failures don't short-circuit the
// remaining steps (parity with the Python's two bare subprocess calls).
// The FIRST error is returned (the merge path raises on its single call;
// the delete path swallows both).
func RunPlans(plans []GitPlan) error {
var firstErr error
for _, p := range plans {
if err := RunPlan(p); err != nil && firstErr == nil {
firstErr = err
}
}
return firstErr
}
// CreateWorktree — the reactive wrapper: plan + exec + state transition.
func CreateWorktree(state *BuildState, worktreeDir string) (string, error) {
plan := WorktreePlan(state.BuildID, worktreeDir)
if err := RunPlan(mapCreateError(plan)); err != nil {
return "", err
}
path := plan.Args[3]
state.WorktreePath = &path
return path, nil
}
// mapCreateError — create failures carry the "create worktree" text;
// RunPlan's default is already that text (single call site).
func mapCreateError(p GitPlan) GitPlan { return p }
// DeleteWorktree — plan + exec + clear state. Errors swallowed (parity:
// Python ignores both results).
func DeleteWorktree(state *BuildState) {
if state.WorktreePath == nil {
return
}
_ = RunPlans(DeletePlan(state.BuildID, *state.WorktreePath))
state.WorktreePath = nil
}
// MergeWorktree — plan + exec + cleanup (delete after merge). Error text:
// "Failed to merge worktree: {stderr}".
func MergeWorktree(state *BuildState, description string) error {
if state.WorktreePath == nil {
return nil
}
plan := MergePlan(state.BuildID, description)
cmd := exec.Command(plan.Args[0], plan.Args[1:]...)
cmd.Dir = plan.Cwd
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("Failed to merge worktree: %s", strings.TrimSpace(string(out)))
}
DeleteWorktree(state)
return nil
}
// EnsureDir — mkdir -p for the builds/worktree dirs (the Python __init__).
func EnsureDirs(buildsDir, worktreeDir string) error {
for _, d := range []string{buildsDir, worktreeDir} {
if err := os.MkdirAll(d, 0o755); err != nil {
return err
}
}
return nil
}
Binary file not shown.
+473
View File
@@ -0,0 +1,473 @@
package main
// recall.go — batch 2: the deterministic read-path of memory_store.py
// (contract BUILDER-2026-10-07T18:05:47Z-152c16). FtsQueryConjunctive,
// ChunkText, RankFusion (RRF k=15), ProjectChunkRows, MapReduce,
// FuseResults + NormKey. The embed-dependent surfaces stay Python-side.
import (
"fmt"
"sort"
"strings"
)
// RRFK — small-corpus RRF constant (large corpora want 60).
const RRFK = 15
// msStopwords — memory_store._STOPWORDS (distinct from curator's and the
// lexicon's sets; extracted verbatim from the live module 2026-10-07).
var msStopwords = map[string]bool{
"about": true, "after": true, "also": true, "and": true, "are": true,
"been": true, "but": true, "each": true, "for": true, "from": true,
"have": true, "her": true, "him": true, "his": true, "how": true,
"into": true, "its": true, "just": true, "likes": true, "more": true,
"needs": true, "not": true, "only": true, "over": true, "prefers": true,
"some": true, "such": true, "than": true, "that": true, "the": true,
"them": true, "then": true, "there": true, "they": true, "this": true,
"under": true, "very": true, "wants": true, "was": true, "were": true,
"what": true, "when": true, "where": true, "which": true, "while": true,
"who": true, "why": true, "will": true, "with": true, "you": true,
"your": true,
}
// FtsQueryConjunctive — the CONJUNCTIVE FTS5 MATCH builder (implicit AND):
// significant terms only (len>3, not stop; fallback len>2), quoted,
// first 8, space-joined. Phrase clauses are additive evidence.
func FtsQueryConjunctive(query string) string {
lower := strings.ToLower(query)
var toks []string
for _, t := range strings.Fields(lower) {
if len(t) > 3 && !msStopwords[t] {
toks = append(toks, t)
}
}
if len(toks) == 0 {
for _, t := range strings.Fields(lower) {
if len(t) > 2 {
toks = append(toks, t)
}
}
}
if len(toks) == 0 {
return query
}
if len(toks) > 8 {
toks = toks[:8]
}
quoted := make([]string, len(toks))
for i, t := range toks {
quoted[i] = fmt.Sprintf("%q", t)
}
return strings.Join(quoted, " ")
}
// ChunkText — paragraph recombination at ~size chars; chunks still huge
// (no paragraph breaks) hard-split at size. Headings stay with content.
func ChunkText(text string, size, overlap int) []string {
if text == "" {
return []string{}
}
if len(text) <= size {
if strings.TrimSpace(text) == "" {
return []string{}
}
return []string{text}
}
var paras []string
for _, p := range strings.Split(text, "\n\n") {
if strings.TrimSpace(p) != "" {
paras = append(paras, p)
}
}
var chunks []string
cur := ""
for _, p := range paras {
if len(cur)+len(p)+2 <= size {
if cur == "" {
cur = p
} else {
cur = cur + "\n\n" + p
}
} else {
if cur != "" {
chunks = append(chunks, cur)
}
cur = p
}
}
if cur != "" {
chunks = append(chunks, cur)
}
var out []string
for _, c := range chunks {
if len(c) > size*3/2 { // Python size * 1.5 (int text len compare)
for i := 0; i < len(c); i += size {
end := i + size
if end > len(c) {
end = len(c)
}
piece := c[i:end]
if strings.TrimSpace(piece) != "" {
out = append(out, piece)
}
}
} else {
out = append(out, c)
}
}
if out == nil {
out = []string{}
}
return out
}
// RankFusion — chunk-side RRF fusion with an explicit candidate cap.
// dense/bm25 are [id, score] pairs. Three modes + min-max bm25 fallback.
func RankFusion(dense, bm25 [][2]interface{}, rrfK float64) map[string]interface{} {
if rrfK == 0 {
rrfK = RRFK
}
ranks := map[string]float64{}
var order []string // insertion order (Python dict preserves it)
bestDense := 0.0
mode := "lexical-only"
addRank := func(eid string, score float64) {
if _, has := ranks[eid]; !has {
order = append(order, eid)
}
ranks[eid] += score
}
if len(dense) > 0 && len(bm25) > 0 {
mode = "hybrid"
for idx, list := range [][][2]interface{}{dense, bm25} {
for pos, pair := range list {
eid := pairString(pair[0])
score, _ := pair[1].(float64)
addRank(eid, 1.0/(rrfK+float64(pos)+1))
if idx == 0 && score > bestDense {
bestDense = score
}
}
}
} else if len(dense) > 0 {
mode = "dense-only"
for pos, pair := range dense {
addRank(pairString(pair[0]), 1.0/(rrfK+float64(pos)+1))
if score, ok := pair[1].(float64); ok && score > bestDense {
bestDense = score
}
}
} else if len(bm25) > 0 {
minBm, maxBm := 0.0, 0.0
first := true
for _, pair := range bm25 {
s, _ := pair[1].(float64)
if first {
minBm, maxBm = s, s
first = false
}
if s < minBm {
minBm = s
}
if s > maxBm {
maxBm = s
}
}
span := maxBm - minBm
if span < 1e-9 {
span = 1e-9
}
for _, pair := range bm25 {
s, _ := pair[1].(float64)
addRank(pairString(pair[0]), (s-minBm)/span)
}
}
rankList := make([]interface{}, 0, len(order))
for _, eid := range order {
rankList = append(rankList, []interface{}{numericID(eid), ranks[eid]})
}
return map[string]interface{}{
"ranks": rankList,
"best_dense": bestDense,
"mode": mode,
}
}
// numericID — Python ids in the fusion pairs are ints; the string-keyed
// map is internal only. Emit numeric when the id parses as an integer.
func numericID(eid string) interface{} {
var n int
if _, err := fmt.Sscanf(eid, "%d", &n); err == nil && trimFloat(float64(n)) == eid {
return n
}
return eid
}
func pairString(v interface{}) string {
switch x := v.(type) {
case string:
return x
case float64:
return trimFloat(x)
case int:
return fmt.Sprintf("%d", x)
default:
return fmt.Sprintf("%v", x)
}
}
func trimFloat(f float64) string {
if f == float64(int64(f)) {
return fmt.Sprintf("%d", int64(f))
}
return fmt.Sprintf("%g", f)
}
// ChunkRow — one projected chunk row.
type ChunkRow struct {
ChunkID interface{} `json:"chunk_id"`
Text string `json:"text"`
Wing string `json:"wing"`
Room string `json:"room"`
Source string `json:"source"`
Page interface{} `json:"page"`
RRF float64 `json:"rrf"`
}
// ProjectChunkRows — sorted -rrf, text[:400], rrf round 4, budget cap.
func ProjectChunkRows(ranks map[string]float64, rows []map[string]interface{}, budget int) []map[string]interface{} {
byID := map[string]map[string]interface{}{}
for _, r := range rows {
byID[pairString(r["rowid"])] = r
}
// sorted(ranks.items(), key=lambda x: -x[1]) — descending rrf; ties
// keep Python's stable sort order (insertion order of ranks dict).
type kv struct {
k string
v float64
}
var items []kv
for k, v := range ranks {
items = append(items, kv{k, v})
}
sort.SliceStable(items, func(i, j int) bool { return items[i].v > items[j].v })
out := []map[string]interface{}{}
for _, it := range items {
r, has := byID[it.k]
if !has {
continue
}
text, _ := r["text"].(string)
if len(text) > 400 {
text = text[:400]
}
wing, _ := r["wing"].(string)
room, _ := r["room"].(string)
source, _ := r["source_path"].(string)
var page interface{}
if p, hasPage := r["page"]; hasPage {
page = p
} else {
page = nil
}
out = append(out, map[string]interface{}{
"chunk_id": r["chunk_id"],
"text": text,
"wing": wing,
"room": room,
"source": source,
"page": page,
"rrf": round4(it.v),
})
if len(out) >= budget {
break
}
}
return out
}
func round4(f float64) float64 {
return float64(int64(f*10000+0.5)) / 10000
}
// MapReduce — chunk the entries, take top-3 per chunk by
// relevance/score (default 0.5), then REDUCE: re-sort ALL mapped entries
// by score desc (the oracle's final pass; no budget param in the code
// despite the comment).
func MapReduce(entries []map[string]interface{}, chunkSize int) []map[string]interface{} {
if len(entries) <= chunkSize {
return entries
}
var mapped []map[string]interface{}
for start := 0; start < len(entries); start += chunkSize {
end := start + chunkSize
if end > len(entries) {
end = len(entries)
}
chunk := entries[start:end]
type scored struct {
score float64
entry map[string]interface{}
}
var sortd []scored
for _, e := range chunk {
score := 0.5
if v, has := e["relevance"]; has {
if f, ok := v.(float64); ok {
score = f
}
} else if v, has := e["score"]; has {
if f, ok := v.(float64); ok {
score = f
}
}
sortd = append(sortd, scored{score, e})
}
// Python sort is stable; ties keep list order.
sort.SliceStable(sortd, func(i, j int) bool { return sortd[i].score > sortd[j].score })
n := 3
if len(sortd) < n {
n = len(sortd)
}
for _, s := range sortd[:n] {
mapped = append(mapped, s.entry)
}
}
if mapped == nil {
mapped = []map[string]interface{}{}
}
// Reduce: sort all mapped by score desc (stable; ties keep map order).
sort.SliceStable(mapped, func(i, j int) bool {
return entryScore(mapped[i]) > entryScore(mapped[j])
})
return mapped
}
// entryScore — relevance, else score, else 0.5 (the oracle's lookup).
func entryScore(e map[string]interface{}) float64 {
if v, has := e["relevance"]; has {
if f, ok := v.(float64); ok {
return f
}
}
if v, has := e["score"]; has {
if f, ok := v.(float64); ok {
return f
}
}
return 0.5
}
// NormKey — cross-table dedup normalization: lowercase, whitespace-collapse.
func NormKey(text string) string {
return strings.Join(strings.Fields(strings.ToLower(text)), " ")
}
// FuseResults — _norm_key dedup + merge shape + kind-wise min-max
// scale-alignment (the audit fix) + final sort.
func FuseResults(entries, research []map[string]interface{}) []map[string]interface{} {
seen := map[string]bool{}
merged := []map[string]interface{}{}
for _, e := range entries {
text, _ := e["text"].(string)
key := NormKey(text)
if seen[key] {
continue
}
seen[key] = true
topic, _ := e["topic"].(string)
if topic == "" {
topic = "fact"
}
relevance, _ := e["relevance"].(float64)
confidence, _ := e["confidence"].(float64)
merged = append(merged, map[string]interface{}{
"id": e["id"],
"text": text,
"topic": topic,
"kind": "fact",
"relevance": round4(relevance),
"confidence": round2(confidence),
})
}
for _, c := range research {
if c == nil {
continue
}
text, _ := c["text"].(string)
key := NormKey(text)
if seen[key] {
continue
}
seen[key] = true
topic, _ := c["wing"].(string)
if topic == "" {
topic = "research"
}
rel, hasRel := c["rrf"].(float64)
if !hasRel {
rel, _ = c["score"].(float64)
}
confidence, hasConf := c["confidence"].(float64)
if !hasConf || confidence == 0 {
confidence = 0.7
}
merged = append(merged, map[string]interface{}{
"id": c["chunk_id"],
"text": text,
"topic": topic,
"kind": "research",
"relevance": round4(rel),
"confidence": round2(confidence),
})
}
// final sort before alignment (Python sorts, then aligns, then sorts)
sortByRelevanceDesc(merged)
// SCALE-ALIGNMENT: min-max normalize each kind's relevance to [0,1]
// within this result set, then re-sort.
for _, kind := range []string{"fact", "research"} {
var subset []map[string]interface{}
for _, r := range merged {
if r["kind"] == kind {
subset = append(subset, r)
}
}
if len(subset) > 1 {
lo, hi := 0.0, 0.0
first := true
for _, r := range subset {
v := r["relevance"].(float64)
if first {
lo, hi = v, v
first = false
}
if v < lo {
lo = v
}
if v > hi {
hi = v
}
}
span := hi - lo
if span < 1e-9 {
span = 1e-9
}
for _, r := range subset {
v := r["relevance"].(float64)
r["relevance"] = round4((v - lo) / span)
}
}
}
sortByRelevanceDesc(merged)
return merged
}
func sortByRelevanceDesc(list []map[string]interface{}) {
sort.SliceStable(list, func(i, j int) bool {
return list[i]["relevance"].(float64) > list[j]["relevance"].(float64)
})
}
func round2(f float64) float64 {
return float64(int64(f*100+0.5)) / 100
}
+99
View File
@@ -0,0 +1,99 @@
package main
// recall_gate.go — batch 4: the recall() integration pieces of
// memory_store.py (contract BUILDER-2026-10-07T19:47:37Z-1cf1dc).
// DenseGate (the meta-judgement: vector proximity is not a relation),
// RankFusionEntries (the entries-side fusion — verified identical to the
// chunk-side RankFusion already ported; the docstring's raw-BM25 claim
// is NOT what the code does — the CODE min-max normalizes in ALL modes,
// and the code is the oracle), the abstain constants.
import (
"sort"
"strings"
)
// RecallBudget / RecallMinScore — the abstain constants (below the floor
// → abstain, don't inject distractors).
const (
RecallBudget = 8
RecallMinScore = 0.42
)
// DenseHit — one candidate dense match: (rowid, cosine).
type DenseHit struct {
RowID int64
Cos float64
}
// QueryContent — the query's significant words (len>3, not msStopwords).
func QueryContent(query string) []string {
var out []string
seen := map[string]bool{}
for _, t := range strings.Fields(strings.ToLower(query)) {
if len(t) > 3 && !msStopwords[t] && !seen[t] {
seen[t] = true
out = append(out, t)
}
}
return out
}
// DenseGate — the meta-judgement applied to the vec0 candidates.
// queryContent: significant query words. dfOf: document frequency
// (LIKE-substring count / total entries — the CALLER supplies counts;
// the gate owns the 0.05 distinctiveness threshold). A hit is kept iff
// it shares a DISTINCTIVE content word with the entry text; otherwise
// only when the query has no content words at all OR cos >= 0.80.
func DenseGate(hits []DenseHit, entryTexts map[int64]string, queryContent []string, dfOf func(word string) int, totalEntries int) []DenseHit {
out := []DenseHit{}
for _, h := range hits {
etxt := strings.ToLower(entryTexts[h.RowID])
distinctive := false
for _, w := range queryContent {
if strings.Contains(etxt, w) {
df := 0
if dfOf != nil {
df = dfOf(w)
}
total := totalEntries
if total < 1 {
total = 1
}
if float64(df)/float64(total) < 0.05 {
distinctive = true
break
}
}
}
if distinctive {
out = append(out, h)
} else if len(queryContent) == 0 || h.Cos >= 0.80 {
out = append(out, h)
}
}
return out
}
// RankFusionEntries — the entries-side fusion. VERIFIED identical to the
// chunk-side RankFusion (same file, memory_store.py:1297 vs the batch-2
// port): the code min-max normalizes the lexical-only branch in ALL
// modes. The docstring's raw-BM25 claim is stale — the CODE is the
// oracle. Reuse keeps one fusion implementation; this wrapper pins the
// parity for the recall() call shape.
func RankFusionEntries(dense, bm25 [][2]interface{}) map[string]interface{} {
return RankFusion(dense, bm25, RRFK)
}
// RankIDs — the sorted rank order (desc by score) for downstream SQL IN
// clauses (Python: list(ranks.keys()) is INSERTION order — the fusion's
// accumulation order, which SortStable ranking reproduces).
func RankIDs(fusion map[string]interface{}) []interface{} {
ranks, _ := fusion["ranks"].([]interface{})
return ranks
}
// sortedInsertion — retained reference: the fusion's rank list order IS
// the insertion order (accumulation), not score order. Documented for
// the SQL-IN parity note. (Unused call sites may sort explicitly.)
var _ = sort.Float64s
+194
View File
@@ -0,0 +1,194 @@
package main
// score.go — batch 3: the scoring/abstention kernel of memory_store.py
// (contract BUILDER-2026-10-07T18:57:06Z-c2429c). ScoreRecallRows (the
// metadata scoring + mode-specific abstention), PositionAware (the
// lost-in-the-middle re-rank).
import (
"fmt"
"sort"
"strings"
"time"
)
// RecencyHalfLife — RECENCY_HALF_LIFE (days).
const RecencyHalfLife = 30.0
// PositionAware — the two highest-relevance items go FIRST and LAST; the
// same items, only the order changes. No-op for < 3 items.
func PositionAware(top []map[string]interface{}) []map[string]interface{} {
if len(top) < 3 {
return top
}
s := make([]map[string]interface{}, len(top))
copy(s, top)
sorted := make([]map[string]interface{}, len(s))
copy(sorted, s)
sort.SliceStable(sorted, func(i, j int) bool {
return entryRelevance(sorted[i]) > entryRelevance(sorted[j])
})
out := make([]map[string]interface{}, 0, len(sorted))
out = append(out, sorted[0])
out = append(out, sorted[2:]...)
out = append(out, sorted[1])
return out
}
func entryRelevance(m map[string]interface{}) float64 {
v, _ := m["relevance"].(float64)
return v
}
// parseISO — Python fromisoformat with the Z→+00:00 swap; also accepts
// naive timestamps. Returns (time, ok).
func parseISO(s string) (time.Time, bool) {
if s == "" {
return time.Time{}, false
}
s = strings.Replace(s, "Z", "+00:00", 1)
layouts := []string{
"2006-01-02T15:04:05.999999-07:00",
"2006-01-02T15:04:05-07:00",
"2006-01-02T15:04:05.999999",
"2006-01-02T15:04:05",
}
for _, l := range layouts {
if t, err := time.Parse(l, s); err == nil {
return t, true
}
}
return time.Time{}, false
}
// ScoreRecallRows — rank-ordered metadata scoring + abstention ladder.
func ScoreRecallRows(fusion map[string]interface{}, rows []map[string]interface{}, dense, bm25 [][2]interface{}, budget int, minScore float64, nowStr string) []map[string]interface{} {
// ranks: the fusion dict's ranks — [[id, score], ...] pairs.
ranksList, _ := fusion["ranks"].([]interface{})
bestDense, _ := fusion["best_dense"].(float64)
mode, _ := fusion["mode"].(string)
byID := map[string]map[string]interface{}{}
for _, r := range rows {
id := pairString(r["id"])
byID[id] = r
}
type rankItem struct {
eid string
base float64
}
var items []rankItem
for _, raw := range ranksList {
pair, ok := raw.([]interface{})
if !ok || len(pair) != 2 {
continue
}
eid := pairString(pair[0])
base, _ := pair[1].(float64)
items = append(items, rankItem{eid, base})
}
// sorted(ranks.items(), key=lambda item: -item[1]) — stable desc.
sort.SliceStable(items, func(i, j int) bool { return items[i].base > items[j].base })
nowDT, _ := parseISO(nowStr)
scored := []map[string]interface{}{}
for _, it := range items {
row, has := byID[it.eid]
if !has {
continue
}
conf := 0.7
if v, ok := row["confidence"].(float64); ok && v != 0 {
conf = v
}
temp := 1.0
if v, ok := row["temperature"].(float64); ok && v != 0 {
temp = v
}
recency := 1.0
if la, ok := row["last_accessed"].(string); ok && la != "" {
if tLast, ok2 := parseISO(la); ok2 {
days := nowDT.Sub(tLast).Seconds() / 86400.0
if days >= 0 {
recency = RecencyHalfLife / (RecencyHalfLife + days)
}
}
// timestamp failure → recency stays 1.0 (the except path)
}
var relevance float64
if len(dense) > 0 {
relevance = it.base * (0.4 + 0.6*conf) * (0.5 + 0.5*temp) * (0.85 + 0.15*recency)
} else {
relevance = (it.base + 5.0) * (0.4 + 0.6*conf) * (0.5 + 0.5*temp) * (0.85 + 0.15*recency)
}
text, _ := row["text"].(string)
topic, _ := row["topic"].(string)
source, _ := row["source"].(string)
lastAccessed, _ := row["last_accessed"].(string)
scored = append(scored, map[string]interface{}{
"id": numericID(it.eid),
"text": text,
"importance": row["importance"],
"topic": topic,
"entities": row["entities"],
"source": source,
"last_accessed": lastAccessed,
"rrf": round4(it.base),
"confidence": round2(conf),
"temperature": round2(temp),
"relevance": round4(relevance),
"mode": mode,
})
}
if len(scored) == 0 {
return []map[string]interface{}{}
}
if len(scored) > budget {
scored = scored[:budget]
}
top := scored
if len(dense) == 0 && len(bm25) == 0 {
return []map[string]interface{}{}
}
if len(dense) == 0 {
maxRel := 0.0
for i, item := range top {
r := entryRelevance(item)
if i == 0 || r > maxRel {
maxRel = r
}
}
if maxRel < minScore {
return []map[string]interface{}{}
}
return top
}
if len(bm25) == 0 {
if bestDense < minScore {
return []map[string]interface{}{}
}
if bestDense >= 0.74 {
return PositionAware(top)
}
if len(dense) >= 2 {
dScores := make([]float64, 0, len(dense))
for _, p := range dense {
f, _ := p[1].(float64)
dScores = append(dScores, f)
}
sort.Float64s(dScores)
if dScores[len(dScores)-1]-dScores[len(dScores)-2] >= 0.08 {
return PositionAware(top)
}
return []map[string]interface{}{}
}
return PositionAware(MapReduce(top, 10))
}
if bestDense < minScore {
return []map[string]interface{}{}
}
return PositionAware(MapReduce(top, 10))
}
var _ = fmt.Sprintf // retained for parity annotations
+200
View File
@@ -0,0 +1,200 @@
{
"oracle": "src/rune/memory_store.py recall() dense gate + _py_rank_fusion",
"generated": "2026-10-07",
"fixture_df_note": "df via LIKE-substring over active entries; threshold 0.05",
"cases": [
{
"fn": "dense_gate",
"name": "distinctive_shared",
"input": {
"query": "worthiness gates",
"hits": [
[
1,
0.9
],
[
2,
0.85
]
],
"total": 8
},
"expected": {
"kept": [
[
1,
0.9
],
[
2,
0.85
]
],
"q_content": [
"gates",
"worthiness"
],
"df": {
"worthiness": 1,
"gates": 1
}
}
},
{
"fn": "dense_gate",
"name": "common_word_falls_back",
"input": {
"query": "black",
"hits": [
[
2,
0.86
],
[
3,
0.79
]
],
"total": 8
},
"expected": {
"kept": [
[
2,
0.86
]
],
"q_content": [
"black"
],
"df": {
"black": 2
}
}
},
{
"fn": "dense_gate",
"name": "strong_cos_no_share",
"input": {
"query": "unrelated query terms",
"hits": [
[
6,
0.91
],
[
4,
0.7
]
],
"total": 8
},
"expected": {
"kept": [
[
6,
0.91
]
],
"q_content": [
"query",
"terms",
"unrelated"
],
"df": {
"unrelated": 1,
"query": 0,
"terms": 0
}
}
},
{
"fn": "dense_gate",
"name": "no_content_words",
"input": {
"query": "the was and",
"hits": [
[
1,
0.6
],
[
6,
0.95
]
],
"total": 8
},
"expected": {
"kept": [
[
1,
0.6
],
[
6,
0.95
]
],
"q_content": [],
"df": {}
}
},
{
"fn": "fusion_identity",
"name": "entries_eq_chunks",
"input": {
"dense": [
[
1,
0.9
],
[
2,
0.8
]
],
"bm25": [
[
2,
10.0
],
[
3,
4.0
]
]
},
"expected": {
"fusion": {
"ranks": [
[
1,
0.0625
],
[
2,
0.1213235294117647
],
[
3,
0.058823529411764705
]
],
"best_dense": 0.9,
"mode": "hybrid"
}
}
},
{
"fn": "constants",
"name": "abstain",
"input": {},
"expected": {
"budget": 8,
"min_score": 0.42
}
}
]
}
+104
View File
@@ -0,0 +1,104 @@
package main
// truth_gate_test.go — memory-store batch 4 parity gate: the dense
// meta-judgement + fusion identity replay truth_gate.json (live oracle,
// fixture store — contract BUILDER-2026-10-07T19:47:37Z-1cf1dc).
import (
"encoding/json"
"os"
"testing"
)
func sortStringsW(s []string) {
for i := 1; i < len(s); i++ {
for j := i; j > 0 && s[j-1] > s[j]; j-- {
s[j-1], s[j] = s[j], s[j-1]
}
}
}
func TestGateParity(t *testing.T) {
b, err := os.ReadFile("truth_gate.json")
if err != nil {
t.Fatalf("truth_gate.json missing: %v", err)
}
var doc struct {
Cases []struct {
Fn string `json:"fn"`
Name string `json:"name"`
Input map[string]interface{} `json:"input"`
Expected map[string]interface{} `json:"expected"`
} `json:"cases"`
}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("unparseable: %v", err)
}
// The fixture entry texts (the generator's store, shipped here — the
// truth inputs must carry their own state).
fixtureTexts := map[int64]string{
1: "the curator gates memory writes through worthiness",
2: "black holes bend light near the event horizon",
3: "black coffee in the morning keeps nick running",
4: "the spine rebuild parity proofs live in store",
5: "memory writes require the operator approval gate",
6: "unrelated filler text about weather patterns",
7: "curator provenance recovery from odysseus",
8: "another filler row to pad the document frequency",
}
// df table shipped per case (the oracle's LIKE counts).
for _, c := range doc.Cases {
switch c.Fn {
case "dense_gate":
query, _ := c.Input["query"].(string)
hitsAny, _ := c.Input["hits"].([]interface{})
var hits []DenseHit
for _, h := range hitsAny {
pair, _ := h.([]interface{})
id, _ := pair[0].(float64)
cos, _ := pair[1].(float64)
hits = append(hits, DenseHit{RowID: int64(id), Cos: cos})
}
dfAny, _ := c.Expected["df"].(map[string]interface{})
dfOf := func(word string) int {
v, ok := dfAny[word]
if !ok {
return 0
}
f, _ := v.(float64)
return int(f)
}
total := int(c.Input["total"].(float64))
qc := QueryContent(query)
wantQAny, _ := c.Expected["q_content"].([]interface{})
var wantQ []string
for _, w := range wantQAny {
s, _ := w.(string)
wantQ = append(wantQ, s)
}
// The truth column ships the q_content SORTED (generator's
// json.dumps of a set); compare sorted-to-sorted.
sortStringsW(qc)
jsonEq(t, c.Name, "q_content", qc, wantQ)
got := DenseGate(hits, fixtureTexts, qc, dfOf, total)
wantArr, _ := c.Expected["kept"].([]interface{})
var want []DenseHit
for _, h := range wantArr {
pair, _ := h.([]interface{})
id, _ := pair[0].(float64)
cos, _ := pair[1].(float64)
want = append(want, DenseHit{RowID: int64(id), Cos: cos})
}
jsonEq(t, c.Name, "kept", got, want)
case "fusion_identity":
dense := pairList(c.Input["dense"])
bm25 := pairList(c.Input["bm25"])
got := RankFusionEntries(dense, bm25)
want, _ := c.Expected["fusion"].(map[string]interface{})
jsonEq(t, c.Name, "fusion", got, want)
case "constants":
jsonEq(t, c.Name, "budget", RecallBudget, c.Expected["budget"])
jsonEq(t, c.Name, "min_score", RecallMinScore, c.Expected["min_score"])
}
}
}
+558
View File
@@ -0,0 +1,558 @@
{
"oracle": "src/rune/memory_store.py _py_* oracles",
"generated": "2026-10-07",
"cases": [
{
"fn": "fts",
"name": "significant_terms",
"input": {
"query": "the curator gates memory writes"
},
"expected": {
"q": "\"curator\" \"gates\" \"memory\" \"writes\""
}
},
{
"fn": "fts",
"name": "stopwords_dropped",
"input": {
"query": "the and was with nick"
},
"expected": {
"q": "\"nick\""
}
},
{
"fn": "fts",
"name": "short_fallback",
"input": {
"query": "go is fun ai"
},
"expected": {
"q": "\"fun\""
}
},
{
"fn": "fts",
"name": "cap_eight",
"input": {
"query": "alpha beta gamma delta epsilon zeta eta theta iota kappa"
},
"expected": {
"q": "\"alpha\" \"beta\" \"gamma\" \"delta\" \"epsilon\" \"zeta\" \"theta\" \"iota\""
}
},
{
"fn": "fts",
"name": "empty_returns_raw",
"input": {
"query": "a an of"
},
"expected": {
"q": "a an of"
}
},
{
"fn": "chunk",
"name": "under_size",
"input": {
"text": "one paragraph only",
"size": 1500,
"overlap": 150
},
"expected": {
"chunks": [
"one paragraph only"
]
}
},
{
"fn": "chunk",
"name": "recombine",
"input": {
"text": "paragraph 0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 23 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 24 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 25 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 26 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 27 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 28 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 29 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"size": 400,
"overlap": 150
},
"expected": {
"chunks": [
"paragraph 0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"paragraph 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"paragraph 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"paragraph 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 23 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 24 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 25 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 26 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 27 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"paragraph 28 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\nparagraph 29 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]
}
},
{
"fn": "chunk",
"name": "hard_split",
"input": {
"text": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"size": 1000,
"overlap": 150
},
"expected": {
"chunks": [
"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
]
}
},
{
"fn": "chunk",
"name": "empty",
"input": {
"text": "",
"size": 1500,
"overlap": 150
},
"expected": {
"chunks": []
}
},
{
"fn": "fuse_ranks",
"name": "hybrid",
"input": {
"dense": [
[
1,
0.9
],
[
2,
0.8
],
[
3,
0.7
]
],
"bm25": [
[
2,
12.0
],
[
4,
8.0
],
[
1,
3.0
]
]
},
"expected": {
"ranks": [
[
1,
0.11805555555555555
],
[
2,
0.1213235294117647
],
[
3,
0.05555555555555555
],
[
4,
0.058823529411764705
]
],
"best_dense": 0.9,
"mode": "hybrid"
}
},
{
"fn": "fuse_ranks",
"name": "dense_only",
"input": {
"dense": [
[
1,
0.9
],
[
2,
0.8
],
[
3,
0.7
]
],
"bm25": []
},
"expected": {
"ranks": [
[
1,
0.0625
],
[
2,
0.058823529411764705
],
[
3,
0.05555555555555555
]
],
"best_dense": 0.9,
"mode": "dense-only"
}
},
{
"fn": "fuse_ranks",
"name": "lexical_only",
"input": {
"dense": [],
"bm25": [
[
2,
12.0
],
[
4,
8.0
],
[
1,
3.0
]
]
},
"expected": {
"ranks": [
[
2,
1.0
],
[
4,
0.5555555555555556
],
[
1,
0.0
]
],
"best_dense": 0.0,
"mode": "lexical-only"
}
},
{
"fn": "fuse_ranks",
"name": "neither",
"input": {
"dense": [],
"bm25": []
},
"expected": {
"ranks": [],
"best_dense": 0.0,
"mode": "lexical-only"
}
},
{
"fn": "project",
"name": "budget_and_shape",
"input": {
"ranks": {
"2": 0.0625,
"1": 0.05
}
},
"expected": {
"rows": []
}
},
{
"fn": "map_reduce",
"name": "top3_per_chunk",
"input": {
"entries": [
{
"id": 0,
"relevance": 0.0
},
{
"id": 1,
"relevance": 0.1
},
{
"id": 2,
"relevance": 0.2
},
{
"id": 3,
"relevance": 0.30000000000000004
},
{
"id": 4,
"relevance": 0.4
},
{
"id": 5,
"relevance": 0.5
},
{
"id": 6,
"relevance": 0.6000000000000001
},
{
"id": 7,
"relevance": 0.7000000000000001
},
{
"id": 8,
"relevance": 0.8
},
{
"id": 9,
"relevance": 0.9
},
{
"id": 10,
"relevance": 1.0
},
{
"id": 11,
"relevance": 1.1
},
{
"id": 12,
"relevance": 1.2000000000000002
},
{
"id": 13,
"relevance": 1.3
},
{
"id": 14,
"relevance": 1.4000000000000001
},
{
"id": 15,
"relevance": 1.5
},
{
"id": 16,
"relevance": 1.6
},
{
"id": 17,
"relevance": 1.7000000000000002
},
{
"id": 18,
"relevance": 1.8
},
{
"id": 19,
"relevance": 1.9000000000000001
},
{
"id": 20,
"relevance": 2.0
},
{
"id": 21,
"relevance": 2.1
},
{
"id": 22,
"relevance": 2.2
},
{
"id": 23,
"relevance": 2.3000000000000003
},
{
"id": 24,
"relevance": 2.4000000000000004
}
],
"chunk_size": 10
},
"expected": {
"mapped": [
{
"id": 24,
"relevance": 2.4000000000000004
},
{
"id": 23,
"relevance": 2.3000000000000003
},
{
"id": 22,
"relevance": 2.2
},
{
"id": 19,
"relevance": 1.9000000000000001
},
{
"id": 18,
"relevance": 1.8
},
{
"id": 17,
"relevance": 1.7000000000000002
},
{
"id": 9,
"relevance": 0.9
},
{
"id": 8,
"relevance": 0.8
},
{
"id": 7,
"relevance": 0.7000000000000001
}
]
}
},
{
"fn": "map_reduce",
"name": "under_threshold",
"input": {
"entries": [
{
"id": 0,
"relevance": 0.0
},
{
"id": 1,
"relevance": 0.1
},
{
"id": 2,
"relevance": 0.2
},
{
"id": 3,
"relevance": 0.30000000000000004
},
{
"id": 4,
"relevance": 0.4
}
],
"chunk_size": 10
},
"expected": {
"mapped": [
{
"id": 0,
"relevance": 0.0
},
{
"id": 1,
"relevance": 0.1
},
{
"id": 2,
"relevance": 0.2
},
{
"id": 3,
"relevance": 0.30000000000000004
},
{
"id": 4,
"relevance": 0.4
}
]
}
},
{
"fn": "fuse_results",
"name": "dedup_scale_align",
"input": {
"entries": [
{
"id": 1,
"text": "nick prefers coffee",
"topic": "human",
"relevance": 2.5,
"confidence": 0.9
},
{
"id": 2,
"text": "NICK PREFERS COFFEE",
"topic": "human",
"relevance": 1.1,
"confidence": 0.8
},
{
"id": 3,
"text": "rune gates memory writes",
"topic": "project",
"relevance": 5.6,
"confidence": 0.95
}
],
"research": [
{
"chunk_id": "c1",
"text": "the spine rebuild parity",
"wing": "research",
"rrf": 0.0625,
"confidence": 0.7
},
{
"chunk_id": "c2",
"text": "curator provenance recovery",
"wing": "research",
"rrf": 0.05
}
]
},
"expected": {
"merged": [
{
"id": 3,
"text": "rune gates memory writes",
"topic": "project",
"kind": "fact",
"relevance": 1.0,
"confidence": 0.95
},
{
"id": "c1",
"text": "the spine rebuild parity",
"topic": "research",
"kind": "research",
"relevance": 1.0,
"confidence": 0.7
},
{
"id": 1,
"text": "nick prefers coffee",
"topic": "human",
"kind": "fact",
"relevance": 0.0,
"confidence": 0.9
},
{
"id": "c2",
"text": "curator provenance recovery",
"topic": "research",
"kind": "research",
"relevance": 0.0,
"confidence": 0.7
}
]
}
}
]
}
@@ -0,0 +1,134 @@
package main
// truth_recall_test.go — memory-store batch 2 parity gate: the read-path
// replays truth_recall.json (live Python _py_* oracles — contract
// BUILDER-2026-10-07T18:05:47Z-152c16).
import (
"encoding/json"
"os"
"testing"
)
func TestRecallParity(t *testing.T) {
b, err := os.ReadFile("truth_recall.json")
if err != nil {
t.Fatalf("truth_recall.json missing: %v", err)
}
var doc struct {
Cases []struct {
Fn string `json:"fn"`
Name string `json:"name"`
Input map[string]interface{} `json:"input"`
Expected map[string]interface{} `json:"expected"`
} `json:"cases"`
}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("unparseable: %v", err)
}
for _, c := range doc.Cases {
switch c.Fn {
case "fts":
q, _ := c.Input["query"].(string)
got := FtsQueryConjunctive(q)
want, _ := c.Expected["q"].(string)
if got != want {
t.Errorf("%s: fts\n got %q\nwant %q", c.Name, got, want)
}
case "chunk":
text, _ := c.Input["text"].(string)
size := int(c.Input["size"].(float64))
overlap := int(c.Input["overlap"].(float64))
got := ChunkText(text, size, overlap)
wantArr, _ := c.Expected["chunks"].([]interface{})
if len(got) != len(wantArr) {
t.Errorf("%s: chunks = %d, want %d", c.Name, len(got), len(wantArr))
continue
}
for i, w := range wantArr {
want, _ := w.(string)
if got[i] != want {
t.Errorf("%s: chunk[%d]\n got %q\nwant %q", c.Name, i, got[i], want)
}
}
case "fuse_ranks":
dense := pairList(c.Input["dense"])
bm25 := pairList(c.Input["bm25"])
got := RankFusion(dense, bm25, RRFK)
want := c.Expected
jsonEq(t, c.Name, "mode", got["mode"], want["mode"])
jsonEq(t, c.Name, "ranks", got["ranks"], want["ranks"])
jsonEq(t, c.Name, "best_dense", got["best_dense"], want["best_dense"])
case "project":
ranksAny, _ := c.Input["ranks"].(map[string]interface{})
ranks := map[string]float64{}
for k, v := range ranksAny {
f, _ := v.(float64)
ranks[k] = f
}
// rows ship in the case input under "rows" (the truth ships its
// own fixtures — same discipline as scaffold batches).
rowsAny, _ := c.Input["rows"].([]interface{})
var rows []map[string]interface{}
for _, r := range rowsAny {
m, _ := r.(map[string]interface{})
rows = append(rows, m)
}
got := ProjectChunkRows(ranks, rows, 6)
wantArr, _ := c.Expected["rows"].([]interface{})
jsonEq(t, c.Name, "rows", got, wantArr)
case "map_reduce":
entries := objList(c.Input["entries"])
chunkSize := int(c.Input["chunk_size"].(float64))
got := MapReduce(entries, chunkSize)
wantArr, _ := c.Expected["mapped"].([]interface{})
jsonEq(t, c.Name, "mapped", got, wantArr)
case "fuse_results":
entries := objList(c.Input["entries"])
research := objList(c.Input["research"])
got := FuseResults(entries, research)
wantArr, _ := c.Expected["merged"].([]interface{})
jsonEq(t, c.Name, "merged", got, wantArr)
}
}
}
// pairList — [[id, score], ...] from decoded JSON.
func pairList(v interface{}) [][2]interface{} {
arr, ok := v.([]interface{})
if !ok {
return nil
}
out := make([][2]interface{}, 0, len(arr))
for _, e := range arr {
pair, ok2 := e.([]interface{})
if !ok2 || len(pair) != 2 {
continue
}
out = append(out, [2]interface{}{pair[0], pair[1]})
}
return out
}
func objList(v interface{}) []map[string]interface{} {
arr, ok := v.([]interface{})
if !ok {
return nil
}
out := make([]map[string]interface{}, 0, len(arr))
for _, e := range arr {
m, _ := e.(map[string]interface{})
out = append(out, m)
}
return out
}
// jsonEq — canonical-JSON comparison (Go typed values vs decoded JSON).
func jsonEq(t *testing.T, name, field string, got, want interface{}) {
t.Helper()
gb, _ := json.Marshal(got)
wb, _ := json.Marshal(want)
if string(gb) != string(wb) {
t.Errorf("%s: %s divergence:\n got %s\nwant %s", name, field, gb, wb)
}
}
+681
View File
@@ -0,0 +1,681 @@
{
"oracle": "src/rune/memory_store.py _py_score_recall_rows",
"generated": "2026-10-07",
"cases": [
{
"fn": "score",
"name": "hybrid",
"input": {
"fusion": {
"ranks": [
[
1,
0.12
],
[
2,
0.11
],
[
3,
0.1
],
[
4,
0.09
]
],
"best_dense": 0.8,
"mode": "hybrid"
},
"rows": [
{
"id": 1,
"text": "entry 1 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 1.2,
"last_accessed": "2026-10-07T18:00:00"
},
{
"id": 2,
"text": "entry 2 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.6,
"temperature": 0.8,
"last_accessed": "2026-09-01T10:00:00"
},
{
"id": 3,
"text": "entry 3 body",
"importance": 0.52,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 0.8,
"last_accessed": "2026-05-01T10:00:00"
},
{
"id": 4,
"text": "entry 4 body",
"importance": 0.53,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.6,
"temperature": 1.2,
"last_accessed": null
}
],
"dense": [
[
1,
0.8
],
[
2,
0.7
],
[
3,
0.6
]
],
"bm25": [
[
2,
10.0
],
[
4,
5.0
],
[
1,
2.0
]
],
"budget": 3,
"min_score": 0.3,
"now": "2026-10-07T18:58:00"
},
"expected": {
"scored": [
{
"id": 1,
"text": "entry 1 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-10-07T18:00:00",
"rrf": 0.12,
"confidence": 0.9,
"temperature": 1.2,
"relevance": 0.1241,
"mode": "hybrid"
},
{
"id": 2,
"text": "entry 2 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-09-01T10:00:00",
"rrf": 0.11,
"confidence": 0.6,
"temperature": 0.8,
"relevance": 0.0691,
"mode": "hybrid"
},
{
"id": 3,
"text": "entry 3 body",
"importance": 0.52,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-05-01T10:00:00",
"rrf": 0.1,
"confidence": 0.9,
"temperature": 0.8,
"relevance": 0.0739,
"mode": "hybrid"
}
]
}
},
{
"fn": "score",
"name": "dense_only_high_conf",
"input": {
"fusion": {
"ranks": [
[
1,
0.06
],
[
2,
0.055
],
[
3,
0.05
]
],
"best_dense": 0.8,
"mode": "dense-only"
},
"rows": [
{
"id": 1,
"text": "entry 1 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 1.2,
"last_accessed": "2026-10-07T18:00:00"
},
{
"id": 2,
"text": "entry 2 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.6,
"temperature": 0.8,
"last_accessed": "2026-09-01T10:00:00"
},
{
"id": 3,
"text": "entry 3 body",
"importance": 0.52,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 0.8,
"last_accessed": "2026-05-01T10:00:00"
}
],
"dense": [
[
1,
0.8
],
[
2,
0.7
],
[
3,
0.6
]
],
"bm25": [],
"budget": 5,
"min_score": 0.3,
"now": "2026-10-07T18:58:00"
},
"expected": {
"scored": [
{
"id": 1,
"text": "entry 1 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-10-07T18:00:00",
"rrf": 0.06,
"confidence": 0.9,
"temperature": 1.2,
"relevance": 0.062,
"mode": "dense-only"
},
{
"id": 2,
"text": "entry 2 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-09-01T10:00:00",
"rrf": 0.055,
"confidence": 0.6,
"temperature": 0.8,
"relevance": 0.0345,
"mode": "dense-only"
},
{
"id": 3,
"text": "entry 3 body",
"importance": 0.52,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-05-01T10:00:00",
"rrf": 0.05,
"confidence": 0.9,
"temperature": 0.8,
"relevance": 0.037,
"mode": "dense-only"
}
]
}
},
{
"fn": "score",
"name": "dense_only_gap_abstain",
"input": {
"fusion": {
"ranks": [
[
1,
0.06
],
[
2,
0.055
],
[
3,
0.05
]
],
"best_dense": 0.8,
"mode": "dense-only"
},
"rows": [
{
"id": 1,
"text": "entry 1 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 1.2,
"last_accessed": "2026-10-07T18:00:00"
},
{
"id": 2,
"text": "entry 2 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.6,
"temperature": 0.8,
"last_accessed": "2026-09-01T10:00:00"
},
{
"id": 3,
"text": "entry 3 body",
"importance": 0.52,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 0.8,
"last_accessed": "2026-05-01T10:00:00"
}
],
"dense": [
[
1,
0.8
],
[
2,
0.75
]
],
"bm25": [],
"budget": 5,
"min_score": 0.3,
"now": "2026-10-07T18:58:00"
},
"expected": {
"scored": [
{
"id": 1,
"text": "entry 1 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-10-07T18:00:00",
"rrf": 0.06,
"confidence": 0.9,
"temperature": 1.2,
"relevance": 0.062,
"mode": "dense-only"
},
{
"id": 2,
"text": "entry 2 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-09-01T10:00:00",
"rrf": 0.055,
"confidence": 0.6,
"temperature": 0.8,
"relevance": 0.0345,
"mode": "dense-only"
},
{
"id": 3,
"text": "entry 3 body",
"importance": 0.52,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-05-01T10:00:00",
"rrf": 0.05,
"confidence": 0.9,
"temperature": 0.8,
"relevance": 0.037,
"mode": "dense-only"
}
]
}
},
{
"fn": "score",
"name": "dense_only_min_score",
"input": {
"fusion": {
"ranks": [
[
1,
0.06
],
[
2,
0.055
],
[
3,
0.05
]
],
"best_dense": 0.8,
"mode": "dense-only"
},
"rows": [
{
"id": 1,
"text": "entry 1 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 1.2,
"last_accessed": "2026-10-07T18:00:00"
},
{
"id": 2,
"text": "entry 2 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.6,
"temperature": 0.8,
"last_accessed": "2026-09-01T10:00:00"
},
{
"id": 3,
"text": "entry 3 body",
"importance": 0.52,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 0.8,
"last_accessed": "2026-05-01T10:00:00"
}
],
"dense": [
[
1,
0.8
],
[
2,
0.7
],
[
3,
0.6
]
],
"bm25": [],
"budget": 5,
"min_score": 0.9,
"now": "2026-10-07T18:58:00"
},
"expected": {
"scored": []
}
},
{
"fn": "score",
"name": "lexical_only_gate",
"input": {
"fusion": {
"ranks": [
[
2,
0.9
],
[
4,
0.7
]
],
"best_dense": 0.0,
"mode": "lexical-only"
},
"rows": [
{
"id": 2,
"text": "entry 2 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 1.2,
"last_accessed": "2026-10-07T18:00:00"
},
{
"id": 4,
"text": "entry 4 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.6,
"temperature": 0.8,
"last_accessed": "2026-09-01T10:00:00"
}
],
"dense": [],
"bm25": [
[
2,
10.0
],
[
4,
5.0
],
[
1,
2.0
]
],
"budget": 5,
"min_score": 1.0,
"now": "2026-10-07T18:58:00"
},
"expected": {
"scored": [
{
"id": 2,
"text": "entry 2 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-10-07T18:00:00",
"rrf": 0.9,
"confidence": 0.9,
"temperature": 1.2,
"relevance": 6.0994,
"mode": "lexical-only"
},
{
"id": 4,
"text": "entry 4 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"last_accessed": "2026-09-01T10:00:00",
"rrf": 0.7,
"confidence": 0.6,
"temperature": 0.8,
"relevance": 3.5783,
"mode": "lexical-only"
}
]
}
},
{
"fn": "score",
"name": "neither",
"input": {
"fusion": {
"ranks": [
[
2,
0.9
],
[
4,
0.7
]
],
"best_dense": 0.0,
"mode": "lexical-only"
},
"rows": [
{
"id": 2,
"text": "entry 2 body",
"importance": 0.5,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.9,
"temperature": 1.2,
"last_accessed": "2026-10-07T18:00:00"
},
{
"id": 4,
"text": "entry 4 body",
"importance": 0.51,
"topic": "project",
"entities": [
"a"
],
"source": "fixture",
"confidence": 0.6,
"temperature": 0.8,
"last_accessed": "2026-09-01T10:00:00"
}
],
"dense": [],
"bm25": [],
"budget": 5,
"min_score": 0.3,
"now": "2026-10-07T18:58:00"
},
"expected": {
"scored": []
}
}
]
}
@@ -0,0 +1,57 @@
package main
// truth_score_test.go — memory-store batch 3 parity gate: the scoring
// kernel replays truth_score.json (live _py_score_recall_rows — contract
// BUILDER-2026-10-07T18:57:06Z-c2429c).
import (
"encoding/json"
"fmt"
"os"
"testing"
)
func TestScoreParity(t *testing.T) {
b, err := os.ReadFile("truth_score.json")
if err != nil {
t.Fatalf("truth_score.json missing: %v", err)
}
var doc struct {
Cases []struct {
Fn string `json:"fn"`
Name string `json:"name"`
Input map[string]interface{} `json:"input"`
Expected map[string]interface{} `json:"expected"`
} `json:"cases"`
}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("unparseable: %v", err)
}
for _, c := range doc.Cases {
fusion, _ := c.Input["fusion"].(map[string]interface{})
rows := objList(c.Input["rows"])
dense := pairList(c.Input["dense"])
bm25 := pairList(c.Input["bm25"])
budget := int(c.Input["budget"].(float64))
minScore := c.Input["min_score"].(float64)
nowStr, _ := c.Input["now"].(string)
got := ScoreRecallRows(fusion, rows, dense, bm25, budget, minScore, nowStr)
wantArr, _ := c.Expected["scored"].([]interface{})
if len(got) != len(wantArr) {
gb, _ := json.Marshal(got)
wb, _ := json.Marshal(wantArr)
t.Errorf("%s: scored = %d, want %d\n got %s\nwant %s",
c.Name, len(got), len(wantArr), gb, wb)
continue
}
for i, w := range wantArr {
want, _ := w.(map[string]interface{})
jsonEq(t, c.Name, field("scored[%d]", i), got[i], want)
}
}
}
// field — formatted comparison label.
func field(format string, i int) string {
return fmt.Sprintf(format, i)
}
+297
View File
@@ -0,0 +1,297 @@
package main
// close.go — batch 3: the closure mechanics of scaffold.py +
// structural_store.py (contract BUILDER-2026-10-07T18:42:38Z-52829e).
// CloseQuality (the pure bucket math — the parity oracle's shape),
// RecordObservedImpact (independent observation — never re-derives the
// prediction), CloseContract (phase gate, inputs assembly, stamping).
import (
"fmt"
"sort"
)
// CloseQualityInputs — the input shape (R2 Wave 1 parity: the Rust
// scaffold_core.close_quality computes from the SAME gathered inputs).
type CloseQualityInputs struct {
ContractID string `json:"contract_id"`
Phase string `json:"phase"`
AffectedEntities []string `json:"affected_entities"`
ExpectedNewEntities []string `json:"expected_new_entities"`
PredictedExistingAffected []string `json:"predicted_existing_affected"`
PredictedFrontier map[string]interface{} `json:"predicted_frontier"`
ExpectedRuntimeEffects []string `json:"expected_runtime_effects"`
ObservedEvidence []map[string]interface{} `json:"observed_evidence"`
Now string `json:"now"`
}
// strSet — helpers.
func strSet(list []string) map[string]bool {
out := map[string]bool{}
for _, s := range list {
out[s] = true
}
return out
}
func sortedSet(m map[string]bool) []string {
out := make([]string, 0, len(m))
for k := range m {
out = append(out, k)
}
sort.Strings(out)
if out == nil {
return []string{}
}
return out
}
func unionSets(ms ...map[string]bool) map[string]bool {
out := map[string]bool{}
for _, m := range ms {
for k := range m {
out[k] = true
}
}
return out
}
func intersect(a, b map[string]bool) map[string]bool {
out := map[string]bool{}
for k := range a {
if b[k] {
out[k] = true
}
}
return out
}
func difference(a, b map[string]bool) map[string]bool {
out := map[string]bool{}
for k := range a {
if !b[k] {
out[k] = true
}
}
return out
}
// CloseQuality — the pure bucket math (Python _py_close_quality verbatim).
func CloseQuality(inputs CloseQualityInputs) map[string]interface{} {
affected := strSet(inputs.AffectedEntities)
expectedNew := strSet(inputs.ExpectedNewEntities)
expectedRuntime := strSet(inputs.ExpectedRuntimeEffects)
obsSet := map[string]bool{}
for _, item := range inputs.ObservedEvidence {
eid, _ := item["entity"].(string)
if eid != "" {
obsSet[eid] = true
}
}
predExisting := strSet(inputs.PredictedExistingAffected)
for k := range affected {
predExisting[k] = true
}
if inputs.PredictedFrontier != nil {
for _, key := range []string{"level0_direct", "level1_obligations", "contracts", "level2_verification"} {
if arr, ok := inputs.PredictedFrontier[key].([]interface{}); ok {
for _, raw := range arr {
if s, ok := raw.(string); ok {
predExisting[s] = true
}
}
}
}
}
correctlyPredicted := intersect(predExisting, obsSet)
predictedButUnaffected := difference(predExisting, obsSet)
expectedNewObserved := intersect(expectedNew, obsSet)
expectedNewMissing := difference(expectedNew, obsSet)
// matched_runtime: observed entities for which SOME expected effect
// STARTSWITH the observed entity.
matchedRuntime := map[string]bool{}
for o := range obsSet {
for eff := range expectedRuntime {
if len(eff) >= len(o) && eff[:len(o)] == o {
matchedRuntime[o] = true
break
}
}
}
// expected_runtime_observed: effects for which SOME matched observed
// entity is a prefix of the effect.
expectedRuntimeObserved := map[string]bool{}
for eff := range expectedRuntime {
for o := range matchedRuntime {
if len(eff) >= len(o) && eff[:len(o)] == o {
expectedRuntimeObserved[eff] = true
break
}
}
}
genuinelyUnexpectedNew := difference(difference(difference(obsSet, predExisting), expectedNew), matchedRuntime)
// evidence_sources: sorted unique sources (default "unattributed").
srcSet := map[string]bool{}
for _, item := range inputs.ObservedEvidence {
src, _ := item["source"].(string)
if src == "" {
src = "unattributed"
}
srcSet[src] = true
}
var candidates []map[string]interface{}
for _, x := range sortedSet(genuinelyUnexpectedNew) {
candidates = append(candidates, map[string]interface{}{
"entity": x,
"status": "CANDIDATE",
"note": "genuinely unexpected new surface — evidence required before store update",
})
}
if candidates == nil {
candidates = []map[string]interface{}{}
}
return map[string]interface{}{
"predicted_existing_affected": sortedSet(predExisting),
"expected_new_entities": sortedSet(expectedNew),
"observed": sortedSet(obsSet),
"observed_existing": sortedSet(correctlyPredicted),
"observed_new": sortedSet(intersect(obsSet, unionSets(expectedNew, difference(obsSet, predExisting)))),
"correctly_predicted": sortedSet(correctlyPredicted),
"predicted_but_unaffected": sortedSet(predictedButUnaffected),
"expected_new_observed": sortedSet(expectedNewObserved),
"expected_new_missing": sortedSet(expectedNewMissing),
"expected_runtime_effects": sortedSet(expectedRuntime),
"expected_runtime_observed": sortedSet(expectedRuntimeObserved),
"expected_runtime_missing": sortedSet(difference(expectedRuntime, obsSet)),
"genuinely_unexpected_new": sortedSet(genuinelyUnexpectedNew),
"missed": sortedSet(genuinelyUnexpectedNew),
"needless": sortedSet(predictedButUnaffected),
"candidate_corrections": candidates,
"evidence_sources": sortedSet(srcSet),
}
}
// RecordObservedImpact — independent observed impact: derive what was
// ACTUALLY affected from external evidence; nothing auto-promotes.
func RecordObservedImpact(doc map[string]interface{}, taskID string, evidenceItems []map[string]interface{}) map[string]interface{} {
implicated := map[string]bool{}
observations, _ := doc["observations"].([]interface{})
for _, item := range evidenceItems {
eid, _ := item["entity"].(string)
if eid == "" {
continue
}
implicated[eid] = true
detail, _ := item["detail"].(string)
if len(detail) > 300 {
detail = detail[:300]
}
authority, _ := item["authority"].(string)
source, _ := item["source"].(string)
if source == "" {
source = "unattributed"
}
observations = append(observations, map[string]interface{}{
"kind": "observed_consequence",
"task": taskID,
"entity": eid,
"source": source,
"detail": detail,
"authority": authority,
"observed_at": NowStr,
})
}
doc["observations"] = observations
outList := sortedSet(implicated)
return map[string]interface{}{
"task": taskID,
"observed_entities": outList,
"evidence_count": len(evidenceItems),
}
}
// NowStr — the frozen clock binding (the generator/test sets it; the CLI
// sets it per-invocation). Date-time-bomb seam.
var NowStr = ""
// CloseContract — close a contract: record observed impact, run the
// predicted-vs-observed comparison, persist quality. Requires
// superseding/verifying. Mutates the entity (phase/status/next_action/
// observed_at/checkpoints/ext.contract_quality).
func CloseContract(doc map[string]interface{}, contractID string, observedEvidence []map[string]interface{}, scopeFiles []string) (map[string]interface{}, error) {
e := docEntity(doc, "contract:"+contractID)
if e == nil {
return nil, fmt.Errorf("contract not found: %s", contractID)
}
phase, _ := e["phase"].(string)
if phase != "superseding" && phase != "verifying" {
return nil, fmt.Errorf("close requires superseding/verifying phase, got %s", phase)
}
obs := RecordObservedImpact(doc, contractID, observedEvidence)
ident, _ := e["identities"].(map[string]interface{})
ext, _ := e["ext"].(map[string]interface{})
strListFrom := func(v interface{}) []string {
arr, ok := v.([]interface{})
if !ok {
return []string{}
}
out := make([]string, 0, len(arr))
for _, x := range arr {
s, _ := x.(string)
out = append(out, s)
}
return out
}
var predictedFrontier map[string]interface{}
if pf, ok := ext["predicted_frontier"].(map[string]interface{}); ok {
predictedFrontier = pf
}
inputs := CloseQualityInputs{
ContractID: contractID,
Phase: phase,
AffectedEntities: strListFrom(ident["affected_entities"]),
ExpectedNewEntities: strListFrom(ident["expected_new_entities"]),
PredictedExistingAffected: strListFrom(ext["predicted_existing_affected"]),
PredictedFrontier: predictedFrontier,
ExpectedRuntimeEffects: strListFrom(ext["expected_runtime_effects"]),
ObservedEvidence: observedEvidence,
Now: NowStr,
}
quality := CloseQuality(inputs)
quality["contract"] = contractID
quality["captured_at"] = inputs.Now
quality["observed"] = obs["observed_entities"]
if scopeFiles != nil {
ce := &ContractEntity{Identities: ident, Phase: phase, Status: "open"}
quality["scope_check"] = CheckScope(ce, scopeFiles)
}
if e["ext"] == nil {
e["ext"] = map[string]interface{}{}
}
e["ext"].(map[string]interface{})["contract_quality"] = quality
cps, _ := e["checkpoints"].([]interface{})
cps = append(cps, map[string]interface{}{
"phase": "closed",
"at": NowStr,
"evidence": "closure-record",
"note": "predicted-vs-observed captured",
})
e["checkpoints"] = cps
e["phase"] = "closed"
e["status"] = "closed"
ident["next_action"] = NextAction["closed"]
e["observed_at"] = NowStr
return e, nil
}
Binary file not shown.
+1
View File
@@ -118,6 +118,7 @@ type ContractEntity struct {
Status string `json:"status"`
Checkpoints []map[string]interface{} `json:"checkpoints"`
ObservedAt string `json:"observed_at"`
Ext map[string]interface{} `json:"ext,omitempty"`
}
// NewContract — new_contract: the identity dict (sorted lists), draft/open,
+291
View File
@@ -0,0 +1,291 @@
{
"oracle": "src/rune/scaffold.py (live, now frozen at both namespaces)",
"generated": "2026-10-07",
"frozen_now": "2026-10-07T18:46:00",
"cases": [
{
"fn": "close_quality",
"name": "buckets",
"input": {
"inputs": {
"contract_id": "q1",
"phase": "superseding",
"affected_entities": [
"module:a",
"module:b"
],
"expected_new_entities": [
"module:new1",
"module:new2"
],
"predicted_existing_affected": [
"module:c"
],
"predicted_frontier": {
"level0_direct": [
"module:a"
],
"level1_obligations": [
"module:d"
],
"contracts": [
"contract:x"
],
"level2_verification": [
"canary:v"
]
},
"expected_runtime_effects": [
"module:a/ctl",
"module:zz/never"
],
"observed_evidence": [
{
"entity": "module:a",
"source": "tests",
"detail": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"authority": "pytest"
},
{
"entity": "module:new1",
"source": "build",
"detail": "created"
},
{
"entity": "module:surprise",
"source": "runtime",
"detail": "unplanned"
},
{
"entity": "",
"source": "runtime",
"detail": "no entity — ignored"
}
],
"now": "2026-10-07T18:46:00"
}
},
"expected": {
"predicted_existing_affected": [
"canary:v",
"contract:x",
"module:a",
"module:b",
"module:c",
"module:d"
],
"expected_new_entities": [
"module:new1",
"module:new2"
],
"observed": [
"module:a",
"module:new1",
"module:surprise"
],
"observed_existing": [
"module:a"
],
"observed_new": [
"module:new1",
"module:surprise"
],
"correctly_predicted": [
"module:a"
],
"predicted_but_unaffected": [
"canary:v",
"contract:x",
"module:b",
"module:c",
"module:d"
],
"expected_new_observed": [
"module:new1"
],
"expected_new_missing": [
"module:new2"
],
"expected_runtime_effects": [
"module:a/ctl",
"module:zz/never"
],
"expected_runtime_observed": [
"module:a/ctl"
],
"expected_runtime_missing": [
"module:a/ctl",
"module:zz/never"
],
"genuinely_unexpected_new": [
"module:surprise"
],
"missed": [
"module:surprise"
],
"needless": [
"canary:v",
"contract:x",
"module:b",
"module:c",
"module:d"
],
"candidate_corrections": [
{
"entity": "module:surprise",
"status": "CANDIDATE",
"note": "genuinely unexpected new surface — evidence required before store update"
}
],
"evidence_sources": [
"build",
"runtime",
"tests"
]
}
},
{
"fn": "close_contract",
"name": "full_lifecycle",
"input": {},
"expected": {
"entity": {
"id": "contract:c1",
"kind": "construction_contract",
"maturity": "DECLARED",
"tags": [],
"identities": {
"need": "n",
"origin": "user",
"scope": [
"src/go/x/"
],
"requirement": "",
"gap_evidence": "",
"research_refs": [],
"resolution": "",
"toolchain": {},
"affected_entities": [
"module:a"
],
"expected_consumers": [],
"expected_new_entities": [
"module:new1"
],
"regression_obligations": [],
"verification_obligations": [],
"migration_obligations": [],
"rollback_ref": "",
"acceptance": [],
"non_goals": [],
"next_action": "observe real outcome; capture lessons"
},
"evidence_refs": [
"contract-created:c1"
],
"observed_at": "2026-10-07T18:46:00",
"phase": "closed",
"status": "closed",
"checkpoints": [
{
"phase": "approved",
"at": "2026-10-07T18:46:00",
"evidence": "",
"note": ""
},
{
"phase": "building",
"at": "2026-10-07T18:46:00",
"evidence": "",
"note": ""
},
{
"phase": "verifying",
"at": "2026-10-07T18:46:00",
"evidence": "",
"note": ""
},
{
"phase": "closed",
"at": "2026-10-07T18:46:00",
"evidence": "closure-record",
"note": "predicted-vs-observed captured"
}
],
"ext": {
"predicted_frontier": {
"level0_direct": [
"module:a"
],
"level1_obligations": [],
"contracts": [],
"level2_verification": []
},
"contract_quality": {
"predicted_existing_affected": [
"module:a"
],
"expected_new_entities": [
"module:new1"
],
"observed": [
"module:a"
],
"observed_existing": [
"module:a"
],
"observed_new": [],
"correctly_predicted": [
"module:a"
],
"predicted_but_unaffected": [],
"expected_new_observed": [],
"expected_new_missing": [
"module:new1"
],
"expected_runtime_effects": [],
"expected_runtime_observed": [],
"expected_runtime_missing": [],
"genuinely_unexpected_new": [],
"missed": [],
"needless": [],
"candidate_corrections": [],
"evidence_sources": [
"tests"
],
"contract": "c1",
"captured_at": "2026-10-07T18:46:00",
"scope_check": {
"verdict": "red",
"in_scope": [
"src/go/x/main.go"
],
"out_of_scope": [
"src/other/rogue.py"
]
}
}
}
}
}
},
{
"fn": "close_gate",
"name": "phase_guard",
"input": {},
"expected": {
"ok": false,
"error": "close requires superseding/verifying phase, got draft"
}
},
{
"fn": "close_gate",
"name": "missing_contract",
"input": {},
"expected": {
"ok": false,
"error": "contract not found: ghost"
}
}
]
}
+146
View File
@@ -0,0 +1,146 @@
package main
// truth_close_test.go — scaffold batch 3 parity gate: the closure
// mechanics replay truth_close.json (live Python oracle, now frozen —
// contract BUILDER-2026-10-07T18:42:38Z-52829e).
import (
"encoding/json"
"os"
"strings"
"testing"
)
func TestCloseParity(t *testing.T) {
b, err := os.ReadFile("truth_close.json")
if err != nil {
t.Fatalf("truth_close.json missing: %v", err)
}
var doc struct {
FrozenNow string `json:"frozen_now"`
Cases []struct {
Fn string `json:"fn"`
Name string `json:"name"`
Input map[string]interface{} `json:"input"`
Expected map[string]interface{} `json:"expected"`
} `json:"cases"`
}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("unparseable: %v", err)
}
NowStr = doc.FrozenNow
defer func() { NowStr = "" }()
for _, c := range doc.Cases {
switch c.Fn {
case "close_quality":
inputsAny, _ := c.Input["inputs"].(map[string]interface{})
ib, _ := json.Marshal(inputsAny)
var inputs CloseQualityInputs
if err := json.Unmarshal(ib, &inputs); err != nil {
t.Fatalf("%s: inputs: %v", c.Name, err)
}
got := CloseQuality(inputs)
jsonEq(t, c.Name, "quality", got, c.Expected)
case "close_contract":
// Replay the lifecycle: doc → new_contract → transitions →
// predicted_frontier → close_contract. The doc ships IN THE
// EXPECTED ENTITY (the oracle mutated the live doc), so the
// replay rebuilds from the case's recorded inputs and compares
// the lifecycle fields.
want, _ := c.Expected["entity"].(map[string]interface{})
docMap := map[string]interface{}{"entities": []interface{}{}, "observations": []interface{}{}}
ident := map[string]interface{}{
"need": "n",
"scope": []string{"src/go/x/"},
"affected_entities": []string{"module:a"},
"expected_new_entities": []string{"module:new1"},
}
e, err := NewContract(docMap, "c1", "n", "user", ident)
if err != nil {
t.Fatalf("%s: new contract: %v", c.Name, err)
}
docMap["entities"] = append(docMap["entities"].([]interface{}), mustMap(e))
for _, step := range []string{"approved", "building", "verifying"} {
if err := TransitionContract(e, step, "", "", NowStr); err != nil {
t.Fatalf("%s: %s: %v", c.Name, step, err)
}
}
e.Ext = map[string]interface{}{
"predicted_frontier": map[string]interface{}{
"level0_direct": []interface{}{"module:a"},
"level1_obligations": []interface{}{},
"contracts": []interface{}{},
"level2_verification": []interface{}{},
},
}
ev := []map[string]interface{}{{
"entity": "module:a", "source": "tests", "detail": "passed",
}}
// docEntity needs the STORED form; sync it
docMap["entities"].([]interface{})[0] = mustMap(e)
got, err := CloseContract(docMap, "c1", ev, []string{"src/go/x/main.go", "src/other/rogue.py"})
if err != nil {
t.Fatalf("%s: close: %v", c.Name, err)
}
jsonEq(t, c.Name, "phase", got["phase"], want["phase"])
jsonEq(t, c.Name, "status", got["status"], want["status"])
// next_action lives in the STORED identities (CloseContract
// mutates the store's copy).
gotIdent, _ := got["identities"].(map[string]interface{})
jsonEq(t, c.Name, "next_action", gotIdent["next_action"],
want["identities"].(map[string]interface{})["next_action"])
wantQ, _ := want["ext"].(map[string]interface{})["contract_quality"].(map[string]interface{})
gotQ, _ := got["ext"].(map[string]interface{})["contract_quality"].(map[string]interface{})
jsonEq(t, c.Name, "contract_quality", gotQ, wantQ)
// observations recorded
obs := docMap["observations"].([]interface{})
if len(obs) != 1 {
t.Errorf("%s: observations = %d, want 1", c.Name, len(obs))
}
case "close_gate":
if c.Name == "phase_guard" {
docMap := map[string]interface{}{
"entities": []interface{}{mustMap(&ContractEntity{
ID: "contract:early", Kind: "construction_contract",
Identities: map[string]interface{}{"need": "n"},
Phase: "draft", Status: "open",
})},
"observations": []interface{}{},
}
_, err := CloseContract(docMap, "early", nil, nil)
if err == nil {
t.Errorf("%s: draft-phase close must fail", c.Name)
continue
}
want, _ := c.Expected["error"].(string)
if err.Error() != want {
t.Errorf("%s: error\n got %q\nwant %q", c.Name, err.Error(), want)
}
}
if c.Name == "missing_contract" {
docMap := map[string]interface{}{"entities": []interface{}{}, "observations": []interface{}{}}
_, err := CloseContract(docMap, "ghost", nil, nil)
if err == nil {
t.Errorf("%s: missing contract must fail", c.Name)
continue
}
want, _ := c.Expected["error"].(string)
if err.Error() != want {
t.Errorf("%s: error\n got %q\nwant %q", c.Name, err.Error(), want)
}
}
}
}
}
// mustMap — entity → map (the stored form docEntity needs).
func mustMap(e *ContractEntity) map[string]interface{} {
b, _ := json.Marshal(e)
var m map[string]interface{}
_ = json.Unmarshal(b, &m)
return m
}
// silence unused import when tests trim
var _ = strings.HasPrefix
+63 -2
View File
@@ -9,6 +9,7 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"time"
)
@@ -203,7 +204,67 @@ func BackupFile(path string) string {
return backup
}
// UndoDir — PARITY with UNDO_DIR (~/.rune/undo).
func UndoDir() string {
// undoDirFn — the undo-dir seam (tests redirect; prod returns the default).
var undoDirFn = func() string {
return filepath.Join(expandHome("~"), ".rune", "undo")
}
// UndoDir — PARITY with UNDO_DIR (~/.rune/undo).
func UndoDir() string {
return undoDirFn()
}
// UndoLast — PARITY port of undo_last: restore the NEWEST backup from the
// undo dir, delete it after restore. Quirk preserved: the safe-name
// _-mangling is lossy (nested underscores in the original path are
// ambiguous on restore — substring-semantics law: flagged, not fixed).
func UndoLast(undoDir string) (string, string) {
entries, err := os.ReadDir(undoDir)
if err != nil {
return "", "No backups to undo"
}
var backups []string
for _, e := range entries {
if !e.IsDir() && strings.HasSuffix(e.Name(), ".bak") {
backups = append(backups, filepath.Join(undoDir, e.Name()))
}
}
if len(backups) == 0 {
return "", "No backups to undo"
}
// newest first (mtime desc; ties broken by name desc — Python's
// sorted(key=mtime, reverse=True) is stable, input order is ReadDir's
// sorted-by-name here).
sort.SliceStable(backups, func(i, j int) bool {
ib, jb := mtimeOf(backups[i]), mtimeOf(backups[j])
if ib != jb {
return ib > jb
}
return backups[i] > backups[j]
})
backup := backups[0]
name := strings.TrimSuffix(filepath.Base(backup), ".bak")
// parts = name.split("_", 4); original = parts[4].replace("_", "/")
parts := strings.SplitN(name, "_", 5)
if len(parts) >= 5 {
original := strings.ReplaceAll(parts[4], "_", "/")
if _, err := os.Stat(original); err == nil {
data, rerr := os.ReadFile(backup)
if rerr == nil {
if werr := os.WriteFile(original, data, 0o644); werr == nil {
_ = os.Remove(backup)
return original, fmt.Sprintf("Restored %s", original)
}
}
}
}
return "", "Could not determine original path"
}
func mtimeOf(path string) int64 {
info, err := os.Stat(path)
if err != nil {
return 0
}
return info.ModTime().UnixNano()
}
+10 -2
View File
@@ -32,9 +32,17 @@ type PreparedTool struct {
}
// Read-only tools execute immediately; everything else is prepared.
// readOnlyTools — PARITY with tool_executor.py READ_ONLY_TOOLS (the exact
// 12-tool set; contract BUILDER-2026-10-07T19:10:38Z-cc6be2). The prior
// port wrongly ADDED run_command (a mutating tool the oracle routes
// through approval — the dangerous direction) and MISSED 8 tools. The
// frozen truth battery asserts set equality so CI catches divergence.
var readOnlyTools = map[string]bool{
"read_file": true, "list_directory": true, "glob_files": true,
"grep_files": true, "run_command": true,
"read_file": true, "glob_files": true, "grep_files": true,
"list_directory": true, "git_diff": true, "git_log": true,
"repo_map": true, "read_persona": true, "query_memory": true,
"check_growth": true, "diagnose_behavior": true,
"find_capability": true,
}
// DefaultApprovalTTL — seconds (parity with DEFAULT_APPROVAL_TTL).
Binary file not shown.
+53
View File
@@ -0,0 +1,53 @@
{
"oracle": "src/rune/tool_executor.py READ_ONLY_TOOLS + routing",
"generated": "2026-10-07",
"cases": [
{
"fn": "read_only_tools",
"name": "exact_set",
"input": {},
"expected": {
"tools": [
"check_growth",
"diagnose_behavior",
"find_capability",
"git_diff",
"git_log",
"glob_files",
"grep_files",
"list_directory",
"query_memory",
"read_file",
"read_persona",
"repo_map"
]
}
},
{
"fn": "prepare_routing",
"name": "run_command_requires_approval",
"input": {
"tool": "run_command",
"args": {
"command": "ls -la"
}
},
"expected": {
"read_only": false
}
},
{
"fn": "prepare_routing",
"name": "read_file_executes_now",
"input": {
"tool": "read_file",
"args": {
"path": "/tmp"
}
},
"expected": {
"read_only": true
}
}
]
}
+92
View File
@@ -0,0 +1,92 @@
package main
// truth_auth_test.go — the tool-executor AUTHORITY parity gate: the Go
// readOnlyTools set must EQUAL the Python READ_ONLY_TOOLS set (truth_auth.json,
// live oracle — contract BUILDER-2026-10-07T19:10:38Z-cc6be2).
//
// The run_command wrong-add this test pins was a security-adjacent
// divergence: a mutating tool treated as read-only bypasses operator
// approval. If this test fails, STOP: the approval boundary has drifted.
import (
"encoding/json"
"os"
"sort"
"strings"
"testing"
)
func TestReadOnlyToolsExactParity(t *testing.T) {
b, err := os.ReadFile("truth_auth.json")
if err != nil {
t.Fatalf("truth_auth.json missing: %v", err)
}
var doc struct {
Cases []struct {
Fn string `json:"fn"`
Name string `json:"name"`
Input map[string]interface{} `json:"input"`
Expected map[string]interface{} `json:"expected"`
} `json:"cases"`
}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("unparseable: %v", err)
}
for _, c := range doc.Cases {
switch c.Name {
case "exact_set":
wantArr, _ := c.Expected["tools"].([]interface{})
if len(readOnlyTools) != len(wantArr) {
t.Errorf("readOnlyTools = %d tools, want %d — THE APPROVAL BOUNDARY HAS DRIFTED",
len(readOnlyTools), len(wantArr))
}
for _, w := range wantArr {
tool, _ := w.(string)
if !readOnlyTools[tool] {
t.Errorf("readOnlyTools MISSING oracle read-only tool %q", tool)
}
}
// and the reverse: no tool in Go that the oracle excludes
for tool := range readOnlyTools {
found := false
for _, w := range wantArr {
s, _ := w.(string)
if s == tool {
found = true
break
}
}
if !found {
t.Errorf("readOnlyTools has EXTRA tool %q not in the oracle set (run_command class — CHECK THE APPROVAL BOUNDARY)", tool)
}
}
case "run_command_requires_approval":
// run_command MUST NOT be read-only (the dangerous direction).
if readOnlyTools["run_command"] {
t.Error("run_command is read-only in Go but NOT in the oracle — mutating tool bypasses approval")
}
wantRO, _ := c.Expected["read_only"].(bool)
if wantRO != readOnlyTools["run_command"] {
t.Errorf("routing parity broken for run_command")
}
case "read_file_executes_now":
if !readOnlyTools["read_file"] {
t.Error("read_file must be read-only (executes now)")
}
}
}
}
// TestReadOnlySetSortedStable — the set renders deterministically (for
// diagnostics) and never grows silently.
func TestReadOnlySetSortedStable(t *testing.T) {
var names []string
for tool := range readOnlyTools {
names = append(names, tool)
}
sort.Strings(names)
joined := strings.Join(names, ",")
if len(names) != 12 {
t.Errorf("read-only set = %d tools, want 12: %s", len(names), joined)
}
}
+73
View File
@@ -0,0 +1,73 @@
package main
// truth_undo_test.go — the undo round-trip parity gate (live Python
// oracle flow — contract BUILDER-2026-10-07T19:20:10Z-af954d).
import (
"os"
"path/filepath"
"testing"
)
// TestUndoLastRoundTrip — the LIVE ORACLE TRUTH: undo_last can NEVER
// restore absolute paths. The safe-name mangling (slash → _) plus
// split("_", 4) puts the first path segment in parts[3]; parts[4]
// reconstructs a path MISSING its first segment, which never exists.
// The port reproduces this verbatim (dead-function parity — a product
// defect filed upstream; the FIX belongs in the Python oracle first).
func TestUndoLastRoundTrip(t *testing.T) {
undoDir := t.TempDir()
origDir := t.TempDir()
orig := filepath.Join(origDir, "target.txt")
if err := os.WriteFile(orig, []byte("original content\n"), 0o644); err != nil {
t.Fatal(err)
}
savedUndo := undoDirFn
undoDirFn = func() string { return undoDir }
t.Cleanup(func() { undoDirFn = savedUndo })
if BackupFile(orig) == "" {
t.Fatal("backup failed")
}
if err := os.WriteFile(orig, []byte("MUTATED\n"), 0o644); err != nil {
t.Fatal(err)
}
// Parity with the live oracle: (None, "Could not determine original
// path") — the mutation is NOT undone. Pinned so a future "fix" in
// one language without the other cannot silently diverge.
gotPath, msg := UndoLast(undoDir)
if gotPath != "" || msg != "Could not determine original path" {
t.Errorf("oracle parity: got (%q, %q), want (\"\", \"Could not determine original path\")", gotPath, msg)
}
data, err := os.ReadFile(orig)
if err != nil {
t.Fatal(err)
}
if string(data) != "MUTATED\n" {
t.Errorf("oracle never restores; content changed to %q — DIVERGENCE", data)
}
}
// TestUndoLastEmpty — no backups → exact message.
func TestUndoLastEmpty(t *testing.T) {
gotPath, msg := UndoLast(t.TempDir())
if gotPath != "" || msg != "No backups to undo" {
t.Errorf("empty undo: got (%q, %q)", gotPath, msg)
}
}
// TestUndoLastUndeterminable — a backup name with <5 underscore-parts
// cannot resolve → exact message.
func TestUndoLastUndeterminable(t *testing.T) {
undoDir := t.TempDir()
name := filepath.Join(undoDir, "20261007_101010_nodirectory.bak")
if err := os.WriteFile(name, []byte("x"), 0o644); err != nil {
t.Fatal(err)
}
gotPath, msg := UndoLast(undoDir)
if gotPath != "" || msg != "Could not determine original path" {
t.Errorf("undeterminable: got (%q, %q)", gotPath, msg)
}
}
+256
View File
@@ -0,0 +1,256 @@
package main
// digest.go — the always-on digest selection core of warm_router.py
// (contract BUILDER-2026-10-07T19:35:07Z-4d6b4c). LexicalSignal /
// LexicalOverlap / Universality / DigestSelect. DB I/O stays reactive.
import (
"regexp"
"sort"
"strings"
)
// AlwaysDigestTokens — fixed low per-turn cost of the always-on layer.
const AlwaysDigestTokens = 220
// DigestStop — _DIGEST_STOP extracted verbatim from the live module.
var DigestStop = map[string]bool{
"a": true, "about": true, "after": true, "also": true, "an": true,
"and": true, "are": true, "as": true, "at": true, "be": true,
"been": true, "but": true, "by": true, "do": true, "does": true,
"each": true, "for": true, "from": true, "have": true, "her": true,
"him": true, "his": true, "how": true, "in": true, "into": true,
"is": true, "it": true, "its": true, "just": true, "more": true,
"not": true, "of": true, "on": true, "only": true, "or": true,
"over": true, "some": true, "such": true, "than": true, "that": true,
"the": true, "them": true, "then": true, "there": true, "they": true,
"this": true, "to": true, "under": true, "very": true, "was": true,
"were": true, "what": true, "when": true, "where": true, "which": true,
"while": true, "who": true, "why": true, "will": true, "with": true,
"you": true, "your": true,
}
// LexicalSignal — distinctive content words (lowercase, >3 chars after
// stripping edge punctuation, not stop).
func LexicalSignal(body string) map[string]bool {
words := map[string]bool{}
for _, w := range strings.Fields(strings.ToLower(body)) {
w = strings.Trim(w, ".,;:!?()[]{}\"'")
if len(w) > 3 && !DigestStop[w] {
words[w] = true
}
}
return words
}
// LexicalOverlap — Jaccard of two bodies' distinctive words (0.0 on empty).
func LexicalOverlap(a, b string) float64 {
wa, wb := LexicalSignal(a), LexicalSignal(b)
if len(wa) == 0 || len(wb) == 0 {
return 0.0
}
inter := 0
for w := range wa {
if wb[w] {
inter++
}
}
union := len(wa) + len(wb) - inter
return float64(inter) / float64(union)
}
// DedupThreshold — Jaccard above this = near-duplicate, skip.
const DedupThreshold = 0.45
var dateRe = regexp.MustCompile(`\b(19|20)\d{2}[-/]\d{1,2}[-/]\d{1,2}\b|\b\d{1,2}[-/]\d{1,2}[-/](19|20)\d{2}\b`)
var datedMarkers = []string{
"session record", "research + session", "session note", "2026-",
"2025-", "fixed", "fix:", "issue:", "bug", "incident", "workaround",
"cause",
}
var directiveMarkers = []string{
"never", "always", "must", "should", "shall", "do not", "use", "keep",
"prefer", "when", "if", "before", "after", "the only", "required",
"forbidden", "authoritative",
}
func countMarkers(low string, markers []string) int {
hits := 0
for _, m := range markers {
if strings.Contains(low, m) {
hits++
}
}
return hits
}
// Universality — how rule-like a body is (0-1). Dated records: 0.
func Universality(body string) float64 {
low := strings.ToLower(body)
if dateRe.MatchString(body) {
return 0.0
}
hits := countMarkers(low, datedMarkers)
if hits >= 2 {
return 0.0
}
if hits == 1 {
return 0.25
}
directive := countMarkers(low, directiveMarkers)
words := len(strings.Fields(body))
base := 0.5
add := float64(directive) * 0.05
if add > 0.25 {
add = 0.25
}
base += add
switch {
case words <= 40:
base += 0.15
case words <= 90:
// no change
default:
base -= 0.2
}
if base < 0.0 {
base = 0.0
}
if base > 1.0 {
base = 1.0
}
return base
}
// TopicOrder — the slug-prefix topic ranking.
var TopicOrder = []string{"operating", "constitution", "persona", "project", "human", "general"}
// TopicRank — the first matching topic prefix, else 6.
func TopicRank(slug string) int {
for i, t := range TopicOrder {
if strings.HasPrefix(slug, t+"-") || slug == t {
return i
}
}
return 6
}
// DigestRow — one candidate row (the reactive layer's DB projection).
type DigestRow struct {
Text string
Slug string
Triggers string
Importance float64
Summary string
AlwaysOn bool
LastAccessed string
}
// DigestSelect — the pure selection core: sort, gates, dedup, budget.
func DigestSelect(rows []DigestRow, maxTokens int) []map[string]interface{} {
// The 5-key sort: topic rank, -universality, always_on first,
// -importance, -lexical density. Python's sort is STABLE; Go's
// SliceStable preserves the input order on full-key ties.
sortedRows := make([]DigestRow, len(rows))
copy(sortedRows, rows)
sort.SliceStable(sortedRows, func(i, j int) bool {
a, b := sortedRows[i], sortedRows[j]
ra, rb := TopicRank(a.Slug), TopicRank(b.Slug)
if ra != rb {
return ra < rb
}
ua, ub := Universality(a.SummaryOrText()), Universality(b.SummaryOrText())
if ua != ub {
return ua > ub
}
if a.AlwaysOn != b.AlwaysOn {
return a.AlwaysOn
}
if a.Importance != b.Importance {
return a.Importance > b.Importance
}
da := len(LexicalSignal(a.SummaryOrText()))
db := len(LexicalSignal(b.SummaryOrText()))
return da > db
})
out := []map[string]interface{}{}
var selectedBodies []string
used := 0
for _, r := range sortedRows {
if used >= maxTokens {
break
}
// junk: no triggers or trivial body
if strings.TrimSpace(r.Triggers) == "" || len(strings.TrimSpace(r.Text)) < 12 {
continue
}
body := strings.TrimSpace(r.Summary)
if body == "" {
body = r.Text
}
if body == "" {
continue
}
// universality gate
if Universality(body) <= 0.0 {
continue
}
// lexical gate
if len(LexicalSignal(body)) == 0 {
continue
}
// dedup
dup := false
for _, prev := range selectedBodies {
if LexicalOverlap(body, prev) >= DedupThreshold {
dup = true
break
}
}
if dup {
continue
}
tok := len(body) / 4
if tok < 1 {
tok = 1
}
// oversized
if tok > maxTokens {
continue
}
// budget-fit skip (out non-empty and doesn't fit)
if len(out) > 0 && used+tok > maxTokens {
continue
}
importance := r.Importance
if importance == 0 {
importance = 0.5
}
out = append(out, map[string]interface{}{
"slug": r.Slug,
"body": body,
"score": round2W(importance),
"tokens": tok,
"always": true,
"compressed": strings.TrimSpace(r.Summary) != "",
})
selectedBodies = append(selectedBodies, body)
used += tok
}
return out
}
// SummaryOrText — the summary-or-text body used by the sort keys.
func (r DigestRow) SummaryOrText() string {
if s := strings.TrimSpace(r.Summary); s != "" {
return s
}
return r.Text
}
func round2W(f float64) float64 {
return float64(int64(f*100+0.5)) / 100
}
+182
View File
@@ -0,0 +1,182 @@
{
"oracle": "src/rune/warm_router.py _py surfaces + always_digest (DB monkeypatched)",
"generated": "2026-10-07",
"cases": [
{
"fn": "lexical",
"name": "signal_strips_punct",
"input": {
"body": "The curator gates memory writes (always)."
},
"expected": {
"words": [
"always",
"curator",
"gates",
"memory",
"writes"
]
}
},
{
"fn": "lexical",
"name": "overlap_jaccard",
"input": {
"a": "the curator gates memory writes",
"b": "the curator gates memory recall"
},
"expected": {
"ov": 0.6
}
},
{
"fn": "lexical",
"name": "overlap_empty",
"input": {
"a": "the and was",
"b": "curator gates writes"
},
"expected": {
"ov": 0.0
}
},
{
"fn": "universality",
"name": "dated_zero",
"input": {
"body": "Fixed the parser on 2026-10-07 after the incident."
},
"expected": {
"u": 0.0
}
},
{
"fn": "universality",
"name": "incident_markers_zero",
"input": {
"body": "Session record: bug cause was the stale kernel; workaround applied."
},
"expected": {
"u": 0.0
}
},
{
"fn": "universality",
"name": "one_marker_quarter",
"input": {
"body": "This addresses the issue: streaming recovery."
},
"expected": {
"u": 0.25
}
},
{
"fn": "universality",
"name": "directive_rule_high",
"input": {
"body": "Never pipe gate commands through tail; always check the exit code before continuing work."
},
"expected": {
"u": 0.8
}
},
{
"fn": "universality",
"name": "rambling_penalty",
"input": {
"body": "word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word never always must keep"
},
"expected": {
"u": 0.49999999999999994
}
},
{
"fn": "digest",
"name": "selection_full",
"input": {
"rows": [
[
"2026-10-07 fixed the parser bug after the incident report",
"project-parser",
"parser",
0.9,
"",
1,
0.8,
"2026-10-07"
],
[
"Never pipe gate commands through tail; always check the exit code before continuing any work in the repository.",
"operating-gates",
"gate",
0.7,
"",
1,
0.9,
"2026-10-07"
],
[
"the and was with that this from into",
"general-soup",
"soup",
0.5,
"",
0,
0.5,
"2026-10-06"
],
[
"Always check the exit code before continuing any work; never pipe gate commands through tail in the repo.",
"operating-gates-copy",
"gate2",
0.8,
"",
1,
0.7,
"2026-10-05"
],
[
"Prefer coconut milk in coffee; you do not drink eggs at breakfast time.",
"human-prefs",
"coffee",
0.6,
"",
0,
0.6,
"2026-10-04"
],
[
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"operating-huge",
"huge",
1.0,
"",
1,
1.0,
"2026-10-03"
]
]
},
"expected": {
"digest": [
{
"slug": "operating-gates-copy",
"body": "Always check the exit code before continuing any work; never pipe gate commands through tail in the repo.",
"score": 0.8,
"tokens": 26,
"always": true,
"compressed": false
},
{
"slug": "human-prefs",
"body": "Prefer coconut milk in coffee; you do not drink eggs at breakfast time.",
"score": 0.6,
"tokens": 17,
"always": true,
"compressed": false
}
]
}
}
]
}
+101
View File
@@ -0,0 +1,101 @@
package main
// truth_digest_test.go — warm-router deep parity gate: the digest core
// replays truth_digest.json (live Python oracle, DB monkeypatched —
// contract BUILDER-2026-10-07T19:35:07Z-4d6b4c).
import (
"encoding/json"
"os"
"testing"
)
func TestDigestParity(t *testing.T) {
b, err := os.ReadFile("truth_digest.json")
if err != nil {
t.Fatalf("truth_digest.json missing: %v", err)
}
var doc struct {
Cases []struct {
Fn string `json:"fn"`
Name string `json:"name"`
Input map[string]interface{} `json:"input"`
Expected map[string]interface{} `json:"expected"`
} `json:"cases"`
}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("unparseable: %v", err)
}
for _, c := range doc.Cases {
switch c.Fn {
case "lexical":
if c.Name == "signal_strips_punct" {
body, _ := c.Input["body"].(string)
got := LexicalSignal(body)
wantArr, _ := c.Expected["words"].([]interface{})
if len(got) != len(wantArr) {
t.Errorf("%s: words = %d, want %d", c.Name, len(got), len(wantArr))
continue
}
for _, w := range wantArr {
s, _ := w.(string)
if !got[s] {
t.Errorf("%s: missing word %q", c.Name, s)
}
}
}
if c.Name == "overlap_jaccard" || c.Name == "overlap_empty" {
a, _ := c.Input["a"].(string)
bb, _ := c.Input["b"].(string)
got := LexicalOverlap(a, bb)
want, _ := c.Expected["ov"].(float64)
if diff := got - want; diff > 1e-9 || diff < -1e-9 {
t.Errorf("%s: overlap got %f want %f", c.Name, got, want)
}
}
case "universality":
body, _ := c.Input["body"].(string)
got := Universality(body)
want, _ := c.Expected["u"].(float64)
if diff := got - want; diff > 1e-9 || diff < -1e-9 {
t.Errorf("%s: universality got %f want %f", c.Name, got, want)
}
case "digest":
rowsAny, _ := c.Input["rows"].([]interface{})
var rows []DigestRow
for _, raw := range rowsAny {
arr, ok := raw.([]interface{})
if !ok || len(arr) < 7 {
continue
}
imp, _ := arr[3].(float64)
alwaysOn, _ := arr[5].(float64)
rows = append(rows, DigestRow{
Text: strW(arr[0]),
Slug: strW(arr[1]),
Triggers: strW(arr[2]),
Importance: imp,
Summary: strW(arr[4]),
AlwaysOn: alwaysOn != 0,
})
}
got := DigestSelect(rows, 220)
wantArr, _ := c.Expected["digest"].([]interface{})
jsonEqW(t, c.Name, "digest", got, wantArr)
}
}
}
func strW(v interface{}) string {
s, _ := v.(string)
return s
}
func jsonEqW(t *testing.T, name, field string, got, want interface{}) {
t.Helper()
gb, _ := json.Marshal(got)
wb, _ := json.Marshal(want)
if string(gb) != string(wb) {
t.Errorf("%s: %s divergence:\n got %s\nwant %s", name, field, gb, wb)
}
}
Binary file not shown.
+1 -1
View File
@@ -6,7 +6,7 @@ This is the main entry point for the Rune program.
import json
from pathlib import Path
__version__ = "0.121.0"
__version__ = "0.128.0"
# One build identity (handoff 2026-09-10 §4): the semantic version above is
# the repo-level truth (auto-bumped at merge); the DEPLOYED revision (exact
+1 -1
View File
@@ -233,7 +233,7 @@ def main() -> int:
)
check(
"Rune minor version advertises provisioning and restore verification",
'__version__ = "0.121.0"' in rune_version,
'__version__ = "0.128.0"' in rune_version,
failures,
)
# #169 policy update: auto-bump on merge is sanctioned (Nick directive:
+2 -2
View File
@@ -8,7 +8,7 @@ mode system, subject header, shared memory and identity.
This is not an interface. This is how I see, speak, and interact with the world.
Version: v0.121.0
Version: v0.128.0
Features: 41 (24 original + 17 new native commands)
Usage:
@@ -1948,7 +1948,7 @@ class RuneApp(App):
# Show version info
self.chat_channel.add_message(
"system",
f"[dim]Rune v0.121.0 | Textual TUI | {len(loaded)} native modules[/dim]",
f"[dim]Rune v0.128.0 | Textual TUI | {len(loaded)} native modules[/dim]",
)
# Auto-show night mode suggestion if evening/night hours
File diff suppressed because it is too large. Load diff
+364 -292
View File
File diff suppressed because it is too large. Load diff