Skip to content

feat: SessionWeaver Phase 2 retrofit (B-OS → B5) [integration] - #18

Closed
NetDevAutomate wants to merge 31 commits into
mainfrom
feat/sessionweaver-phase2-retrofit
Closed

NetDevAutomate wants to merge 31 commits into
mainfrom
feat/sessionweaver-phase2-retrofit

Conversation

@NetDevAutomate

Copy link
Copy Markdown
Owner

Draft integration PR for the SessionWeaver Phase 2 retrofit into StudyLoop. It exists so CI runs on every merge into feat/sessionweaver-phase2-retrofit; it is not ready for review or merge until B5 and Council B complete.

Tracking: openspec/changes/sessionweaver-phase2-retrofit/ (proposal, design, tasks). Stages land here as reviewed task branches: B1 fresh-install scope, B2 tier-1 ontology (migration v48), B3 concept lifecycle + replication (v49), B4 memory_recall + planner + MCP registration, B5 real-corpus validation, BL-1..BL-4, docs and ADRs.

🤖 Generated with Claude Code

NetDevAutomate and others added 30 commits September 7, 2026 21:51
Freeze the SessionWeaver Phase 2 retrofit's spec and design ahead of any
Phase B code, per EXECUTION-ERRATA.md correction #3 and council ruling R2
("acceptance is not spec-check alone"). The design document normatively
fixes the cross-machine standing order for replicated concept lifecycle
events and its two-copy test matrix, the v48/v49 migration contracts and
their rollback strategy, the non-fatal ontology refresh-failure seam, seed
sanitization, the byte-for-byte memory_recall contract, the fresh-install
scope diagnostic, and the ConceptService compatibility seam -- so B1-B6 can
implement against a reviewed contract instead of inventing one under
implementation pressure.

Delta specs add Gherkin-scenario requirements to six existing capabilities
(harness-session-memory, data-store-and-sync, mcp-server, session-export,
health-and-diagnostics, configuration-and-secrets); no capability is newly
created. openspec validate --specs --all: 25 passed, 0 failed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ange

- proposal.md: the request_scope() call-site list has eight entries; the
  source plan mislabels it "seven" (design.md and tasks.md already said
  eight).
- design.md: B3 must test whether the reference allocator's table-wide
  MAX(logical_time) already satisfies two-copy matrix item 4 before adding
  an explicit advance-on-import step.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…and diagnostics

Lift SessionWeaver's frozen tier-1 ontology extraction/rebuild/status
module (extraction version tier1-v2-canonical-messages, same
logical-hash algorithm, so A2's baseline stays comparable). Migration
v48 installs the six schema objects additively; install_schema is
tolerant of a pre-existing ad hoc ontology schema (found on the real
sessions.db) so a real upgrade converges instead of crashing -- the
first rebuild replaces it regardless of its prior shape.

Wire an incremental ontology refresh into
export_sessions._run_export, behind a named, monkeypatchable seam
(refresh_ontology_after_export) called after the capture commit: a
refresh failure is caught, logged as a structured
ontology_refresh_failed warning, surfaced in the export summary, and
never rolls back captured sessions (EXECUTION-ERRATA.md #7). Add
`session-maint ontology-rebuild [--incremental]` and `ontology-status`
for manual/maintenance recovery.

Add the sync boundary: ontology tables never join SYNC_TABLES or
GLOBAL_SYNC_TABLES (positive-control tested), and
sync._seed_remote_db strips every ontology row from a seed snapshot
before scp so a freshly seeded remote derives its own ontology rather
than inheriting the source's.

Add a report-only "harness" doctor check (present/coverage/freshness/
extraction-version), never fatal, with a fixture-inserted red-path
test.

Add the ontology_live safety harness (Online Backup only, real DB
never touched, new opt-in live_ontology pytest marker) and R7
migration-safety tests: fresh creation, interrupted-migration
recovery, downgrade, and idempotent re-migration. Retains real
acceptance receipts (docs/data/) from a live Online Backup run:
coverage 100%, zero integrity violations, identical hash across two
full rebuilds and one incremental no-op, cold rebuild 3.47s.

Fixes a v47-pinned assertion in test_replica_coordinator.py that this
version bump would otherwise break, and regenerates .secrets.baseline
(detect-secrets 1.5.0) for the two evidence files' SHA-256 hashes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ed scope

A virgin install crashed or leaked ad-hoc errors the moment any scope-dependent
path ran: `studyloop study` propagated a bare ScopeError as a generic exit-1
ClickException, each of the seven unguarded request_scope() MCP tool sites let
FastMCP wrap it in ad-hoc text, and session-db-mcp's open_context()/
_get_connection() let sqlite3's "unable to open database file" leak through a
distinct, unhelpful error shape on a database that simply doesn't exist yet.

Add ScopeUnconfiguredError (a ScopeError subclass identifying exactly the
"nothing configured" case) and scope_setup_diagnostic(), one shared
{code: "scope_unconfigured", message, remediation} shape. Every entry point
that can hit it now reports that same payload instead of a traceback: the
CLI exits 2, both MCP servers' tool-call boundaries return isError with the
JSON payload embedded in the text content, and a missing database is treated
identically to a missing scope rather than as its own error class.

Both packages' config writers (generate_default_config(), ensure_config_dir())
now write memory.default_scope: unclassified explicitly for a brand-new
config.yaml, so a fresh install is immediately usable. The runtime default for
an absent file or a file that omits the key stays unset (errata #9) -- this
changes only what a *generated* file contains, not what an absent setting means.

Tests: packages/studyloop/tests/test_fresh_install_scope.py drives a virgin
HOME (no STUDYLOOP_CONFIG, no SESSION_CONTEXT_SCOPE) as a real subprocess
against the source tree -- the CLI, all seven MCP tool sites, and
session-db-mcp's session_search/memory_search -- so this suite's own
config-isolation fixtures cannot hide the defect the way the existing fixture
already did. test_fresh_install_scope_installed.py (marked integration)
repeats every check against a real `uv build` wheel install per plan ruling
R10. Unit tests cover scope_setup_diagnostic, ScopeUnconfiguredError, the two
config writers' round trip, and open_context()/_get_connection() on a missing
database.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add a "Tier-1 ontology (derived, never synced)" section to
docs/session-memory.md covering what it captures, why it never syncs,
the automatic export-time refresh, and session-maint
ontology-rebuild/ontology-status for manual recovery. Record the
feature under CHANGELOG.md's [Unreleased] Added.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Mark tasks.md's B2 tasks 2.1 (migration v48 + lift), 2.2 (refresh
hook + session-maint ontology-rebuild), and 2.3 (sync boundary +
seed sanitization) complete. Leave 2.4 unchecked with an inline note:
its tests/hash/timing/count verification and a green preflight are
done, but code/build-ontology.py's retirement is explicitly B6's
(task-B2-brief.md) and the independent review is the reviewer's step.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Task B1 of openspec/changes/sessionweaver-phase2-retrofit: generated config
writes memory.default_scope: unclassified; one structured ScopeError
diagnostic at the CLI and every MCP tool in both servers; missing-database
path covered; virgin-HOME tests on source-tree and installed-package paths.
Review: .superpowers/sdd/sessionweaver-phase2/task-B1-review.md (0 findings).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d agents

CI run 34167164262 (jobs test (3.12) and test (3.13)) failed
test_fresh_install_scope.py::test_studyloop_study_exits_2_with_the_diagnostic_on_a_virgin_home
because on the GitHub runner `studyloop study 'Test Topic'` exits 1 with
"No AI agent found. Install one of: Kiro CLI, Codex, Claude Code,
OpenCode, or pi" before the scope check ever runs. session/start.py calls
detect_agents() (studyloop.agent_launcher) before start_study_session()
raises ScopeUnconfiguredError, so the expected exit 2 + structured scope
diagnostic is unreachable unless some agent binary is resolvable via
shutil.which on the subprocess's PATH. Locally the test only passed
because this machine has agent CLIs installed.

Fix the test, not production code: add a `_fake_agent_bin()` helper that
writes a no-op executable named `claude` (matching
studyloop.adapters.claude.ADAPTER.binary) into a throwaway bin dir and
prepends it to the subprocess PATH via `_usable_path()`/`_virgin_env()`'s
new `agent_bin` parameter. detect_agents() only calls shutil.which(), so
the script is never actually executed -- start_study_session() still
raises ScopeUnconfiguredError immediately after agent selection, well
before any launch command is built. Applied to both
test_studyloop_study_exits_2_with_the_diagnostic_on_a_virgin_home and its
installed-wheel sibling in test_fresh_install_scope_installed.py, which
had the same dependency.

Reproduced RED locally by running both files with a PATH stripped of
every real agent CLI (venv bin + tmux + /usr/bin:/bin only), then
confirmed GREEN with that same stripped PATH after the fix.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Replace permission-bit failure injection with the backup helper's real None failure contract. This keeps the abort-before-stream invariant reliable under both ordinary users and root CI containers.
Preserve direct coverage that a nonzero SSH/sqlite command result is translated into None after the push-contract test moved to the orchestration seam.
Bring the independently reviewed migration v48, deterministic ontology evidence, and CI-parity sync test correction into the SessionWeaver Phase 2 integration branch.

# Conflicts:
#	.secrets.baseline
#	docs/session-memory.md
Lift SessionWeaver's concept_schema.py unchanged (SCHEMA_VERSION = 2,
SCHEMA_FINGERPRINT byte-identical to the reference,
af95685e6e39e166148006519862bee3be1a15219d76772236a82890fe11011d) and
add migrate_v49, which installs exactly that DDL: context_concepts,
context_concept_events, context_concept_clock, context_concept_fts and
context_concept_schema, plus their indexes/triggers and the two
context_citations guard triggers. UPSTREAM_SCHEMA_VERSION is pinned to
49, the migration number that installs the sidecar.

Why: tasks.md 3.1 -- B3 owns v49 (v48 stays B2's); the sidecar must be
additive-only, with context_assertions.proposed_state left as execution
state (errata #3), and adopt a byte-identical pre-existing PoC sidecar
while refusing drift, because sidecar rows are authored data.

Migration-safety per B2's R7 pattern: fresh create to v49, additive-only
shape check on context_assertions, exact-adopt, drift refusal,
interrupted-migration recovery, repeated-open idempotence, downgrade
contract, and a real Online Backup v47->v49 upgrade retained as
docs/data/concept-sidecar-migration-v49-receipt.json (aggregates only;
source sentinels asserted unchanged; live DB still v47, 5813 sessions).
The detect-secrets baseline is regenerated for the receipt's hex-hash
false positives, matching B2's precedent.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ection

Lift SessionWeaver v0.2.0's concepts.py, winddown.py, okf.py (as
okf_import.py), projection.py (A3b2's fixed Publisher with its
identity-guarded rollback), authorization.py and safe_fs.py into
agent_session_tools.context, adapting only import paths to the package
(relative imports; okf -> okf_import). All frozen contracts are kept
byte-identical: the sessionweaver://session/ source-URI prefix, the
session_weaver_projection frontmatter key, the projection marker and
manifest filenames, and ConceptService's public surface (project,
winddown, transition, bind_legacy, import_okf).

Why: tasks.md 3.1 -- B4 consumes ConceptService as a caller, never a
second implementation, and B6 deletes the SessionWeaver copies, so the
lifted behaviour must be the reference behaviour, provable by the
reference's own tests.

Tests: the reference suites lifted with the same import rewrites
(223 tests: schema exactness/adoption, wind-down parsing, lifecycle
transitions, bind closure, OKF scan/classification precedence,
projection publish/rollback, adversarial SQL integrity). Two
adaptations, both consequences of v49 installing the sidecar up front:
the upstream-version pin asserts 49, and a rejected import call now
asserts zero sidecar rows instead of no sidecar table. One targeted
nosec B506 documents that _StrictSafeLoader narrows yaml.SafeLoader.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Concept roots and their complete append-only event history join the
context replication protocol: snapshot selection follows the
authorization seam's two visibility shapes (bound roots travel with
their assertion's citation closure, legacy roots with their claimed
session), the apply path inserts only rows it does not already have,
and the receiving side's own schema triggers re-validate every root.
The local clock, the FTS read model and the schema marker never travel.

Standing is exactly the frozen order (design.md, ruling R2):
standing = max(events, key=(lamport, machine_id, event_id)) with
machine_id = context_access_state.instance and lamport = logical_time.
The three read-model sites drop the reference's standing-kind
precedence, which contradicted the frozen pure-triple order under
replication ties while being locally unobservable (local lamports are
strictly increasing); the lifted total-order test is adapted to the
frozen order with the reasoning recorded inline.

Duplicate machine_id is diagnosed and refused, never merged:
negotiate() already refuses two live peers with one instance, and the
new ConceptReplicaIdentityError refuses incoming events that claim the
receiver's own instance for history it never wrote, or that bind one
(origin_instance, origin_seq) slot to two different events.

Lamport advance on import (design.md's B3 verification note): matrix
item 4 was run against the unmodified reference allocator first, and
passes -- _allocate's table-wide MAX(logical_time) already advances the
next local event past every imported lamport, so no explicit
advance-on-import step was added.

Also wired: v49 adds the three replica-content-generation triggers for
the two replicated tables (v46 froze its own list); staged transport
indexes both tables by id; the legacy-sync guard treats the sidecar's
seeded singletons and FTS shadow tables as bookkeeping, not populated
context; tiering's archive-completeness proof excludes the per-database
clock and concept-FTS shadow tables while keeping roots/events in the
retention proof; compaction seeds a fresh clock/marker and copies roots
after their citation closure so the sidecar triggers re-validate.

Tests: the normative two-copy matrix (7 scenarios) on fixtures in both
replication orders, replay idempotence, post-convergence Lamport
advance, read-model hash equivalence, concurrent accept/retire resolved
to the computed winner in either order, causal accept-then-retire, and
three duplicate-identity refusals; plus the same matrix once on two
real Online Backup copies (live_concepts marker, copy B honestly
re-identified before any concept history exists, source sentinels
asserted unchanged). Full package suite: 1999 passed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…MCP tool

session-context gains winddown --session ID --from FILE|--stdin and
concept accept|retire ID --reason, concept bind LEGACY_ID --from FILE
--reason, concept import-okf DIR [--dry-run] [--report PATH], and
concept project --out DIR [--project ID] [--json], all thin wrappers
over the frozen ConceptService seam with the reference CLI's bounded
input reading (wind-down byte limit, descriptor-anchored non-symlink
files), atomic report writes, deterministic JSON payloads, and the
reference exit-code contract (2 validation, 1 runtime/write failure).
mcp_server.py gains memory_winddown with the same validation: a
field-level error list raises a structured ToolError and writes
nothing; a valid batch commits atomically.

Why: tasks.md 3.2 -- one seam, one validation surface, no second
implementation of concept transitions; context_assertions keeps its
execution-state vocabulary (verified in the round-trip test).

Also frozen (tasks.md 3.4): ConceptService's public API is pinned by an
exact-signature regression test (method set, every signature string,
and the four result shapes), so B4 consumes a checked contract.

This commit also carries the live_concepts harness extensions and their
opt-in tests (they type-check as one unit with the CLI): the live
two-copy matrix on two real Online Backup copies, and the full
2,033-record legacy OKF import runner whose sanitized report feeds the
OpenSpec evidence attachment.

Tests: lossless round trip, stdin input, field-level failures for
malformed documents/invalid JSON/symlinked input, lifecycle verbs with
retired-terminal diagnostics, legacy bind, OKF dry-run/write/report,
projection output, MCP happy path and loud structured failure with
zero partial writes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…evidence

docs/context-memory.md gains the wind-down/concept command reference,
the two trust labels (model-proposed vs legacy-unbound, never blended),
the frozen cross-machine standing order in one paragraph, and the
frozen ConceptService surface table. CHANGELOG records the concept
sidecar under [Unreleased] Added. OpenSpec tasks 3.1-3.5 are checked
with their evidence pointers (3.5's independent review remains the
reviewer's step). The evidence file is added with -f: openspec/ is
gitignored for new files, but this change's artifacts are tracked and
the brief requires the report attached to the change directory.

Evidence: openspec/changes/sessionweaver-phase2-retrofit/evidence/
legacy-okf-import-report.json -- the full legacy OKF import on a real
Online Backup (live_concepts marker): 2,035 scanned, 2,033 parseable
records imported legacy-unbound with zero write failures and the exact
A3b1 baseline FTS content hash (0c036eae...); the two extra files are
post-baseline non-records classified invalid_schema (reported, never
dropped); dry-run/write classification identical; idempotent re-import
already_present=2,033 with zero writes; OKF tree sentinel and source
database sentinels unchanged. The visibility sub-classification split
differs from the baseline because this run retains every project
unclassified on a newer corpus (5,813 sessions vs 5,678); the report
retains the split (no_exact_match 1559, no_visible_evidence 429,
oversized_evidence 45) for the reviewer.

The detect-secrets baseline is regenerated for the evidence hashes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ence

Completes the previous docs commit: the gitignore advice for openspec/
aborted the add chain, so the evidence attachment missed it. openspec/
ignores only new untracked files -- this change's artifacts are
tracked, and the brief requires the sanitized legacy OKF import report
attached to the change directory, so the evidence file is added with
-f. The detect-secrets baseline is regenerated for the report's hex
hashes, matching the established false-positive handling.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
pytest resolves rootdir (and its configfile) from the paths it is given,
so any package-scoped invocation reads this package's pyproject.toml and
never the workspace root's -m exclusions. Round 0 shipped the package
config without them, so a plain 'pytest packages/agent-session-tools/...'
silently ran the live_concepts suites: two 1 GB SQLite Online Backups of
the owner's real sessions.db, a 140-second OKF import, and two committed
evidence files rewritten -- the same trap fired during the independent
review (B3 review round 1, Important #2).

Add the -m exclusion for every opt-in marker this package declares
(integration, live_ontology, live_concepts), matching the workspace-root
convention and packages/studyloop's MUST-duplicate precedent, and pin it
with a subprocess regression that proves package-scoped collection
deselects every live-marked test by default while an explicit -m opt-in
still selects them and ordinary tests stay selected.

Co-Authored-By: Kiro <noreply@kiro.dev>
Round 0's committed migration receipt was captured at commit 1, before
migrate_v49 gained its six replica_content_context_concept* triggers, so
its whole-database schema_sha256 (5c2f2c56...) no longer described the
shipped migration -- and nothing deterministic could catch that, because
that hash covers every sqlite_master row and is therefore a property of
the source corpus, not the migration (a fresh schema.sql install yields
81f3310a..., the real backup 6dfb4027...) (B3 review round 1,
Important #1).

Give the receipt a source-independent fingerprint instead:
sidecar_migration_fingerprint() hashes the DDL of exactly the objects
migrate_v49 installs (context_concept* objects, the two
context_citations_bound_* guard triggers, the six replica_content_*
triggers; FTS5 shadow tables excluded -- library-generated from the
fingerprinted virtual-table declaration), emitted as
sidecar_objects_sha256 (evidence_version 1 -> 2). Two always-on fixture
regressions pin it: the name selection equals the complete non-shadow
v49 delta (so a future migration edit cannot slip an object past the
receipt check), and a fresh install of the shipped migration must
reproduce the committed receipt's hash byte-for-byte.

Receipt regenerated at HEAD on a fresh SQLite Online Backup (live DB
untouched: v47, 5,813 sessions); its schema_sha256 is now 6dfb4027...,
byte-identical to the review's independently reproduced value. Secrets
baseline regenerated for the receipt's changed hex strings only.

Co-Authored-By: Kiro <noreply@kiro.dev>
Bring the independently reviewed migration v49, lifted concept lifecycle/wind-down/import/projection, replication proofs, CLI/MCP surface, and full-corpus import evidence into the SessionWeaver Phase 2 integration branch.
Capture the existing public search contract before introducing the shared AND-to-OR planner. The fixture freezes row keys, deterministic ordering, null/default values, phrase/operator behavior, and the 300-character preview boundary.
Reuse the released SessionWeaver planner behind session_search while keeping its public row schema, SQL ranking, filters, and 300-character previews unchanged. Black-box tests prove the frozen cases remain identical and only the previously empty implicit-AND query widens through OR fallback.
Port SessionWeaver v0.2.0 concept-first recall onto StudyLoop's B3 authorization seam and shared query planner. The public MCP tool validates strict bounds, preserves the frozen report schema, deduplicates concept source sessions, and proves through behavioral traces that embeddings and ontology are not consulted.
Have studyloop install agents merge session-db and studyloop into Claude Code, Kiro, and Codex configuration without touching the real HOME. Format-preserving temp-HOME tests prove unrelated entries survive, repeated installation is byte-identical, missing configs are created, and doctor reports registration without mutation.
Repair an incorrect StudyLoop-owned JSON MCP entry by replacing only that value object, then append any missing owned entry. This avoids reserializing unrelated MCP entries while retaining byte-idempotence on subsequent installs.
Retain the exact 25-question corpus, aggregate-only v47 Online Backup evidence, and a reproducible released-reference acceptance runner. Document the frozen recall contract and MCP registration, add positive work/personal scope coverage, and mark OpenSpec B4 complete after a green 5,964-test preflight.
Route explicit phrase and boolean queries through the historical FTS escaping path so the shared recall planner remains frozen. Restrict AND-to-OR widening to empty implicit plain-text searches and pin compatibility with negative controls.
Replace owned JSON values and TOML subtrees by parser-validated byte spans rather than canonical-only regexes. This preserves unrelated configuration, prevents duplicate keys, handles CRLF and nested tables, and converges byte-identically on rerun.
Track TOML lexical state before recognizing candidate MCP table headers. This prevents owned-looking text inside multiline values from truncating unrelated config while retaining byte-preserving subtree repair.
Bring the independently reviewed shared planner, frozen-contract memory_recall, 25-question identity proof, and idempotent Claude/Kiro/Codex MCP registration into the SessionWeaver Phase 2 integration branch.
@NetDevAutomate

Copy link
Copy Markdown
Owner Author

Closing without merging this branch as a whole.

Its non-OKF half (11 of 31 commits: capture/scope safety, MCP-server registration and installer fixes, the shared AND-to-OR query planner, sync-test hardening) was landed on main locally by named cherry-pick (e71f3537..4ab13499, fast-forwarded as 48900c3d), with every conflict resolution and the OKF residue proof recorded in docs/architecture/session-memory/receipts/stage4-pr18-keep-half-2026-09-10.md.

The ontology/OKF half (13 commits: migrations v48/v49, concept sidecar, OKF import, memory_winddown/memory_recall) is dropped: the owner ruled 2026-09-10 that OKF is not part of the solution and is being removed entirely in preparation for a semantic layer (okf-removal-inventory-2026-09-10.md). Two openspec proposal commits and one OKF-only test-marker commit were skipped.

Attribution correction recorded in the receipt: the +0.142 recall@5 established on DEV belongs to replacing this branch's AND-first planner with the learning-memory phrase-token OR planner (ADR-0011:311, F-B0-1), not to fb33e2ce itself. Measured on the scoped corpus with both arms under identical visibility: main before 0.000 (42/91 questions crash on FTS syntax, 49 return nothing), after 0.1066, lift +0.107 CI95 [+0.043, +0.182], non-inferior on every stratum. Landed as a non-inferior integration by owner directive; the 42-question FTS crash remains open on main.

main is not pushed by agents; the owner pushes. The branch tip 031dbab9 stays reachable and will be tagged archive/feat-sessionweaver-phase2-retrofit-2026-09-10 before any branch deletion.

NetDevAutomate added a commit that referenced this pull request Sep 10, 2026
…tory and work order

Andy asked (2026-09-10) whether OKF is used and, if the data says it serves no
purpose, for it to be removed ahead of a semantic layer. This receipt is the
verification, not the removal.

Verified from source and the live database: main has no OKF/ontology code; on
the three feature branches (PR #18's tree is byte-identical to
origin/feat/b4-recall-surfaces) it is ~5,300 source lines that no serving path
reads -- every consumer is a writer, a diagnostic or a snapshot-stripper, and
mcp_server.py's own docstring says "No embedding or ontology store". The value
gate written for it (G3b) was never reached; the claim-centric layer it fed
scored 0.129 against a 0.64 bar and 0 of 2,033 imported OKF concepts were ever
citation-bound. All 66,324 live ontology_* rows were produced by a deterministic
builder (hashlib/re/sqlite3 only) and are rebuildable at $0.

Two things the removal must respect: PR #18 splits 13 drop / 14 keep, and the
keep-half contains fb33e2c -- the AND-to-OR query planner, the programme's one
established win -- so the resolution is merge the keep-half, drop the OKF half;
and context_concepts holds one non-derived row (a wind-down Finding) that must be
exported as prose before any DROP. The DROP list is recorded but gated on Andy's
explicit confirmation with a verified .bak first: this database is the only
surviving copy of ~89% of session history.
NetDevAutomate added a commit that referenced this pull request Sep 10, 2026
… proof, DEV re-score, corrected attribution

Eleven of PR #18's 31 commits cherry-picked by name onto main; three
skipped with reasons (two openspec proposals, and e1560f2 whose whole
content is OKF live-marker hygiene for files main never had); thirteen
dropped. Every pick followed by an OKF/ontology/DDL grep; the tree is
clean (two pre-existing benign hits on main: a minified vendor identifier
and a learner topic string). Suite +1 red vs the Stage 3 pin, diagnosed
from the artefact as the mise tmux shim failing under a virgin HOME -- an
owner-machine environment red, proven by passing with the real binary.

The re-score corrects the plan: fb33e2c is NOT the +0.142 win. ADR-0011
and the look-2 arm show that figure comes from REPLACING its AND-first
planner with the learning-memory phrase-token OR planner (F-B0-1 is a
measured defect in the shipped path). Measured with B0 re-pinned at
today's scoped main so both arms see the same corpus: B0 0.000, B1 0.1066
(identical to the pinned PR receipt to 17 digits), lift +0.107 CI95
[+0.043, +0.182], non-inferior everywhere, not "established" (lower bound
under +0.05). Both arms crash on 42/91 questions (fts5 syntax on
backticks, ?, digits) -- live on main today, not fixed by the keep-half.
NetDevAutomate added a commit that referenced this pull request Sep 10, 2026
…lf; PR #18 closed; zero OKF remnants proven tree-wide

Andy's 22:57 directive ("OKF should be fully removed - leaving no
remittance as part of the merge") resolves the council's BLOCKING item:
the keep-half lands as a non-inferior integration by owner directive,
with the lift stated as measured (+0.107, CI95 [+0.043, +0.182]) and no
retrieval win claimed. main fast-forwarded 9235ab7 -> 48900c3, tree
byte-identical to the tested integration tree; PR #18 closed with the
corrected reason. The zero-remnant condition is proven over the whole
tree: the OKF/ontology grep matches the same six pre-existing files before
and after the merge -- nothing introduced -- and those six are Stage 5's
scope. grok-4.6 failed to deliver a verdict for the second stage of three
(finish_reason=length on investigation narration) and is replaced by
kimi-k2-thinking for the remaining councils.
NetDevAutomate added a commit that referenced this pull request Sep 10, 2026
…s pre-planner and planner code alike

score.py builds the shipped arm from mcp_server._session_search_queries,
which only exists after PR #18's 4fe2e4c; a B0 pinned at today's main has
no such helper. This wrapper mirrors whichever query shape the imported
package ships (single escape_fts_query AND query, or the planner's
sequence) and purges the module cache on EVERY arm build -- the harness
only purged when a pin was given, so the second arm silently reused the
first arm's modules and both arms scored one code (caught when both arms
printed the same shape). Used for the Stage 4 receipt on main.
NetDevAutomate added a commit that referenced this pull request Sep 10, 2026
…ecar -- code, tests, migrations, registrations

Owner ruling 2026-09-10 (ADR-0011 on main): OKF is not part of the solution
and is removed entirely, leaving no remnant, in preparation for a semantic
layer. Evidence in receipts/okf-removal-inventory-2026-09-10.md: no serving
path read any of it, 0/2,033 imported concepts citation-bound, the ontology
moved fused recall by +0.00, value gates never reached.

agent-session-tools: 12 modules deleted (concept_cli, concept_live,
concept_schema, concepts, okf_import, ontology, ontology_live, plus the
sidecar-only authorization, projection, safe_fs, winddown and recall
seams) and 18 test files; migrations v48/v49 and their registration
removed, CURRENT_VERSION back to 47 (what main ships); the
memory_winddown and memory_recall MCP tools removed so the tool set equals
main's; live_ontology/live_concepts markers removed from both pyproject
files. Ten files whose whole branch diff was OKF were restored to the
MERGE BASE (not main's current version -- restoring to main would have
imported main's newer work; caught and corrected during the lane's own
audit). recall.py was memory_recall's engine (PR #18 drop-half, d573133):
deleted rather than kept as a second session_search.

studyloop: check_ontology_freshness and its doctor registration removed
(_doctor.py and doctor/harness.py now match main); test_doctor_ontology.py
deleted. scripts/b4_recall_acceptance.py deleted (existed only to run the
v49 migration and import_okf); pin_poc_set.py docstring retargeted.

Kept, because they are not OKF: the learning-memory package and its
claims/evidence store; studyloop's learning tier (history/concepts.py,
learning/concept_quality.py, get_concept_context -- identical on main).

Gates on the worktree: ruff check clean, 727 files formatted, pyright
0/0/0; agent-session-tools 1,691 passed / 0 failed; studyloop reds equal
the pinned environment set plus two expected on a branch that predates
main's Stage 3 fix. Finish line: git grep for
okf|ontolog|concept_sidecar|context_concept|memory_winddown|memory_recall
over packages/ returns nothing.
@NetDevAutomate
NetDevAutomate deleted the feat/sessionweaver-phase2-retrofit branch September 10, 2026 22:58
NetDevAutomate added a commit that referenced this pull request Sep 11, 2026
…nce lanes, baselines

The owner named the missing function: query without exact phrasing, with
the embeddings aligned to the sessions DB through every prune/hide path and
the semantic layer as the agent's interface. Four read-only lanes mapped
the substrate (dead but tested embeddings code, empty migration-7 tables,
sqlite-vec importable under the wrong extra), the lifecycle (deletes
covered; in-place content rewrites, scrub and dedup leave vectors stale;
prune_hot would silently stop evicting the day vectors exist), the rulers
(gold DEV 91 and a census with no arm seam) and the agent interface (MCP
tolerant, CLI strict-phrase 0/5).

Three seats approved the plan with changes. Two BLOCKING findings and one
MAJOR were closed by measurement in-session: sqlite-vec honours ROLLBACK, a
connection without the extension still runs every write path when triggers
touch only the plain table, and the 91-question crash count through the
real MCP tool is 42/91 (every one contains "or"/"and"/"not"), macro
recall@5 0.1066 -- reproducing PR #18's pinned number through the real
interface for the first time. The remaining findings are folded into the
amended Stages 11-15 and their acceptance rules. Two owner decisions are
recorded as open: what R3 means if the semantic arm fails to establish
lift, and whether fresh sub-agent lanes may be used.
NetDevAutomate added a commit that referenced this pull request Sep 11, 2026
…ensus on sessions.db

Read-only runs of the harness against the live database (mtime unchanged).

Gold DEV, 91 questions: the real MCP tool scores macro recall@5 0.1066
(K 0.182, P 0.034, R 0.103), MRR 0.084, 42/91 crashes -- backtick 31,
question-mark 8, no-such-column 2, comma 1 -- reproducing PR #18's pinned
number through the agent's interface. The frozen replica is identical on
all 91 items (paired delta 0, CI [0, 0]). The CLI the skill calls the
"deterministic fallback" scores 0.000: the same 42 crashes and no rows for
the other 49, because it wraps every multi-word question in one adjacency
phrase.

Census, 5,434 eligible learner turns in visible sessions (397 unwinnable
by construction, ceiling 0.927): hit@5 0.526, 0.551 of the winnable
ceiling; 129 vocabulary-gap misses against 2,228 winnable ranking misses;
2,349 turns (43.2%) crash the shipped search, led by syntax:< (803, XML-ish
prompt content), comma (379), no-such-column (368), syntax:. (269). The
paraphrase gap is real but the crash class and ranking are the larger
levers, which is the Stage 2-before-Stage 4 order the council approved.
Per source: claude_code 0.611, kiro_cli 0.483, codex 0.469, grok 0.457.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant