Skip to content

rotate: merge wip/2026-08-07 (109 commits — #724 recovery wave, gate fixes, tracking) - #738

Merged
rodaddy merged 111 commits into
mainfrom
wip/2026-08-07
Aug 18, 2026
Merged

rotate: merge wip/2026-08-07 (109 commits — #724 recovery wave, gate fixes, tracking)#738
rodaddy merged 111 commits into
mainfrom
wip/2026-08-07

Conversation

@rodaddy

@rodaddy rodaddy commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Summary

Verification

  • Done-means: scripts/done-means/724-wrap-lane-adoption.sh
  • Relevant Open Brain tests/typecheck/migrations passed
  • Python package checks passed or are not applicable
  • Live Open Brain smoke passed or is not applicable

Every lane PR in this range merged behind an independent verify-lane receipt bound to its head SHA plus the enforced harvest gate; per-PR receipts live on PRs #727-#732 and #737. The wave is RUNNING on the local dogfood runtime: revision bf5e4d3 deployed with revision-proof, 3110/health serving the embed_watermark block from the live DB, live manual wrap saved+durable against a hook-owned lane, window-content recall verified in both search arms.

Critical Self-Review

Review Gate

  • Critical self-review fields above are filled with specific, non-placeholder content
  • MEDIUM+ review findings were captured in docs/sme/ or explicitly marked not applicable
  • Live Open Brain checks: [x] linked below or [ ] not applicable because:

Contract Parity

Downstream Rollout

  • I checked docs/downstream-rollout.md
  • rtech-mcps handoff is complete or not applicable
  • mcp2cli cache/skill refresh is complete or not applicable
  • rtech-hermes Python runtime/plugin changes are complete or not applicable
  • Hermes live rollout/canaries are complete or not applicable

Notes/evidence:

rodaddy added 30 commits August 7, 2026 22:54
…mode adopted, SME per-entry files, PR-body template+pr-scribe, lane-bootstrap), 3 rejections recorded
… with dated Tightenings changelog (ledger item 19)

Operator directive 2026-08-08. First harvest: 11 entries from the
2026-08-07/08 lane rounds (PRs 615-621), incl. the validator env trap,
the h3 section-parser bug, bun pass-count proof, rg -e, sed portability,
guard workarounds, gates-read-the-database, clean-clone finish.
…ctive 2026-08-08)

docs/sop-rlvr-lanes.md: the head-session loop, the parts table, measured
why-it-works evidence from the first two runs, and the staged expansion
path (repo norm -> second-repo pilot -> _DOCS/_ob canon). AGENTS.md gains
an Operating Mode section so every future session meets it at the door.
…-stash trap, absolute-path CI death, control clauses for live checks, total-loss hypothesis, production-composition coverage
…ane report format, controller obligations with enforcement states (operator directive 2026-08-08)
…, deviations flagged, broken steps fail hard, hooks as last-ditch enforcement
…cwd trap, gitignore-by-outcome, no premature citations, done-means field live, canon on main
…t keeps round-3 harvest, graph/sop take the post-628 union
…sence defect (prove absence by the variable the code reads; re-run, never re-quote)
…eed runs on Sol, non-negotiable floor kept, loud one-way escalation
…ate removed, terra medium proven live; fast lanes may route Terra medium
…leness receipts, wall-clock flake class, gate word-match defect, effort-tiers-are-policy
…on, wrong-layer pattern, named-env residual risk
…ed reply + pointers, never whole-corpus single-shot)
…ydration stamp, recall telemetry, drain-first outage)
…rsion pr-body-gate (#641), Sol runtime deaths, residual-risk flag
…rove RED after check edits, envelope-before-payload, #641 three-lane confirmation
…on-check negative matches, enum-before-dimension, closed-port outage pattern
rodaddy and others added 22 commits August 10, 2026 09:50
…anding lane

Two genuinely new lessons from _plans/worklog/land-artifacts-2026-08-10.md:

- `rg -qF "$line"` parsed a diff-derived leading "-" as a flag and reported
  seven false MISSING lines during the pre-rebase superset check. Third
  spelling of the round-19 `rg -r` / `rg -E` family, so it is recorded as a
  standing class: `--` before any pattern that came from data, and `-F` does
  not imply it. The same reflex bit again during this harvest (`rg -h` is
  `--help`). Adds the corollary that a one-directional check whose verdict
  authorizes a drop or overwrite needs a positive control, because here the
  broken answer pointed at restoring stale graph content over newer root.

- #710 and #712 were closed from the CLI, so their artifacts render "Closed
  without a pull request". That is the renderer being honest and it is the live
  argument that controller-contract obligation 2b is load-bearing: this repo's
  squash-into-wip flow frequently never creates GitHub's closing linkage, so
  the rationale has to live in a closure comment that the discussion mirror
  captures unconditionally.

The #715/#712 lane's lessons (stderr not stdout, the reflex fix passing review,
the deliberately unpinned bun byte threshold) were checked against round 29's
#712 block and are already harvested there — not repeated.

Review-facing half as an SME entry (lane gotcha-agent, order 71); lane files
rebuilt via scripts/build-sme-indexes.ts. sme-per-entry-files.sh count pin
234 -> 235 with the reason inline; clause 1 remains RED for #707, which is not
this harvest's file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… read (#714) (#718)

#714's filed premise was stale: PR #713 (issue #709) already made the hook parse
--head and set PR_HEAD_REF, so the branch tier is fed. Re-verifying it found a
narrower residue that does reproduce.

A branch NAME is not a ref until something can resolve it. `gh pr create --head
<branch>` names a branch on the REMOTE, and run from a root checkout that has
fetched but never created a local branch of that name -- no cd, no worktree --
the bare name resolves to nothing, so the tier was handed a dead string:

  git cat-file -e lane/x:scripts/done-means/check.sh   -> fatal, exit 128
  git cat-file -e origin/lane/x:...                    -> exit 0

The refusal then printed "; and in ref lane/x", which reads as "your check is
not on the branch" when the truth is "that name means nothing here". A refusal
that misdirects is worse than one that admits it looked nowhere: the cheapest
way past it is a false receipt, which is the reflex the gate exists to prevent.

resolvableRef() now tries the name as given first (so a correct ref, a SHA, or a
local-only checkout is never mangled), then <remote>/<name> for each configured
remote with origin first. Every candidate is asserted on POSITIVELY via
rev-parse --verify (round 28), so a name resolving nowhere skips the branch tier
rather than feeding it garbage, and the announcement names both what --head said
and what actually resolved (AGENTS.md: nothing is adjusted silently).

existsInRef's containment guard on the PATH is untouched: this widens WHERE a
check may resolve, never WHAT may be named.

Done-means: scripts/done-means/714-head-ref-resolves-remote.sh, 6 clauses
driving the real hook with synthetic PreToolUse payloads against a GENUINE bare
remote -- the defect is invisible in any fixture where the lane branch also
exists locally, which is why 709-hook-feeds-head-ref.sh clause 3 passed
throughout (round 28's false-green family). RED 3/6 before, GREEN 6/6 after;
clauses 2/3/6 are controls that fail a bad fix and were green from the start.
…oks (#711) (#717)

This clone's core.hooksPath was the ABSOLUTE path
/Volumes/ThunderBolt/Development/open-brain/_githooks, while
_githooks/install.sh:24 writes the relative "_githooks" under a comment written
against this exact trap. The config had diverged from its own installer and
nothing detected it: the installer reports "already set" only on an exact
match, and no check asserted the value.

.git/config is shared by every linked worktree, so an absolute value points
every lane worktree at the PRIMARY checkout's hooks. That is the root of the
#705-#714 family -- a lane fixing a git hook could not exercise its own fix on
push, and a lane BREAKING one pushed green.

Proven with a throwaway worktree and a marker line in each tree's copy:
absolute + worktree -> primary's hook; relative + worktree -> its own hook;
relative + primary -> unchanged. A relative hooksPath does resolve per-worktree.

The config flip is per-clone state and cannot be committed (it was applied on
this machine via ./_githooks/install.sh and is recorded in the journal). What
ships is the detection:

- _githooks/pre-push asserts the effective core.hooksPath matches the
  installer's value, before any validation and before the --explain exit, and
  fails the push naming the configured value, the expected value, and the
  install.sh command. Unset stays legal: git then uses .git/hooks and this file
  is not running at all.
- _githooks/install.sh names the specific damage when the value it corrects was
  absolute.
- scripts/lane-bootstrap.ts states which hooks the new worktree will run.
- scripts/install-hooks.sh became a refusing stub: it set core.hooksPath to
  .githooks, which does not exist here, silently disabling every tracked hook.

Done-means: scripts/done-means/711-hookspath-relative.sh (5/5 green; red before
the fix was b/c failing with a/d passing as the mutation control).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Audited every gate/check that judges work in this repo against the #705-#714
family's two shapes (A: judging from the wrong tree; B: letting the environment
decide the verdict). Ran each gate rather than reading it, on the untouched
primary at 183d066.

The five filed members are fixed and hold. Four new members are live:

- #719 (B) core.hooksPath displaces the global gitleaks + protected-branch
  hook and _githooks/ ships no pre-commit, so secret scanning is silently off.
  The .git/hooks shim written to repair this is unreachable by construction.
- #720 (A) validate-pr-body's OWN_TREE fallback passes a Done-means check that
  is absent from the branch under review, on the primary checkout's copy.
- #721 (B) merge-gate-and-verify-lane.sh records its only live clause as PASS
  on any non-empty inherited MGVL_IN_VERIFY_LANE — exit 0, verify-lane unrun.
- #722 (B) both pre-push done-means checks (705, 712) are RED on untouched
  main: fixtures inherit the global core.hooksPath and trip #711's assertion,
  then report it as substantive regressions that have not occurred.

#722 is the one that matters most: the gate with the most family history
currently has no working done-means coverage, and both blinded checks emit
confident false regression text.

Report carries the per-gate table, reproductions with positive and negative
controls, and an explicit SOUND list (9 negative results) so the next audit
does not re-litigate them. No fixes in this lane, per charter.
…ay not answer for it (#720) (#723)

`OWN_TREE` was consulted as a plain second tree, BEFORE the branch under
review was ever asked. The pr-body-gate hook runs the PRIMARY checkout's
copy of the validator, so that tree is the integration branch — which has
accumulated every done-means check ever merged. A check deleted from,
renamed on, or never committed to the branch under review therefore PASSED
on the strength of a same-named file in a tree that is not being merged,
and the fallback fired most readily in exactly the case it should have
caught. Family A (#706's own defect) one layer deeper, in the fallback.

The rule now: the tree under review answers first, then the head ref. When
a head ref is known those two are AUTHORITATIVE — their combined "no" is
the answer, the own tree is not consulted, and the refusal says so. The
own tree may answer only when no head ref exists at all (a human running
the validator by hand), and that note names its weaker basis rather than
reading identically to a branch-backed pass.

Done-means: scripts/done-means/720-validator-rejects-foreign-tree.sh
7 clauses. Clause 5 drives the REAL path — a PreToolUse payload through
.claude/hooks/pr-body-gate.ts with a genuine `gh pr create --head`, which
the check's own RED run showed ALLOWING the foreign-tree citation
end-to-end. Clauses 3/4/6 are the positive and regression controls; 7 is
the mutant control. RED 4/7 pre-fix, GREEN 7/7 post-fix.

706 (5/5), 709 (5/5), and 714 (6/6) re-run green. 709 clause 4 asserts on
the `looked in:` marker, so the new refusal keeps it verbatim rather than
the assertion being moved to fit new wording.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…placed (#719) (#727)

`core.hooksPath = _githooks` REPLACES the operator's global hooks directory.
Git consults exactly one directory; it never chains and never overlays. So
`_githooks/` shipping only `pre-push` meant this repo had NO pre-commit hook,
and the two controls the displaced global hook carried were silently OFF for
every commit made here:

  - gitleaks staged secret scanning
  - LAW #8 — no commits on main/master/develop/production/staging

Measured before the fix, in this lane's own worktree:

    $ git hook run pre-commit
    error: cannot find a hook named pre-commit

    # positive control, same tree, same command, the displaced path:
    $ git -c core.hooksPath=~/.config/git/hooks hook run pre-commit
    INF no leaks found

The control is the finding: gitleaks was installed and working the whole time,
and this repo's own config was the only thing stopping it. The
`.git/hooks/pre-commit` shim whose docstring said it restored exactly this was
unreachable — git ignores `.git/hooks` once core.hooksPath is set — so that
repair was written and never once ran.

Sweeping the WHOLE displaced set, as an override demands, found a SECOND live
gap the issue did not name: the global `pre-push` also carried a gitleaks range
scan and a default-branch push guard, and this repo's own `pre-push` replaced
it carrying neither. Secret scanning was absent from BOTH ends of the commit
path, not one.

Changes:

  - `_githooks/pre-commit` (new): LAW #8 branch block, then a gitleaks
    `--staged --redact=100` scan. Fails CLOSED when gitleaks is absent, per
    _DOCS/STANDARDS-git.md. Announces every stage, because #719's failure mode
    is that an ABSENT gate and a PASSED gate look identical.
  - `_githooks/pre-push`: restores the displaced range scan and default-branch
    guard (keeping the global hook's ALLOW_DEFAULT_PUSH human escape hatch, so
    this does not silently become stricter than the rule it restores), placed
    BEFORE typecheck and the suite.
  - `_githooks/pre-push`: extends the #711 drift assertion so "hooksPath value
    correct, directory INCOMPLETE" warns and names the missing hook. #711 was
    5/5 GREEN throughout this defect because it asserted the VALUE only. It
    warns rather than refuses: a wrong value corrupts this hook's own verdict,
    a missing sibling hook means a DIFFERENT gate is missing, and refusing a
    push over a defect it cannot cause is what trains `--no-verify`.
  - `_githooks/displaced-hooks-allowlist.txt` (new): dropping a displaced
    control becomes a decision someone wrote down, with a reason.
  - `scripts/done-means/719-hooks-dir-complete.sh` (new): 10 clauses driving
    REAL `git commit` and `git push` in fixtures configured exactly like this
    repo, with a fake canary (Stripe's published test value; never a real
    credential) and a paired control for every refusal.

The controls are reimplemented in tracked files rather than delegated to the
global hook: that path is absolute and machine-specific (#711's root enabler),
untracked and unreviewable, and absent in CI and every fresh clone — so a
delegating hook would degrade to no gate exactly where oversight is thinnest.

Verification (all RUNNING this session):
  - 719 check: 10/10 GREEN post-fix; 7 of 8 clauses RED pre-fix.
  - 711 check: 5/5 GREEN, no regression.
  - Six mutants, applied and reverted one at a time: deleting pre-commit kills
    a/b/d/h; neutering only the commit-side scan kills b alone (while the hook
    still prints a green tick — the sharpest result); removing only the branch
    block kills d alone; neutering the push scan kills f alone; making the hook
    fail OPEN on a missing gitleaks lets the canary commit; removing the new
    completeness assertion kills i alone. Every control clause survived its
    siblings' mutants.

Scope: this restores what the override displaced. It is deliberately not the
full seven-check gate docs/CI_CD_REQUIREMENTS.md specifies as the eventual
required state; that is separate work with its own cost budget.
…ited (#721) (#730)

merge-gate-and-verify-lane.sh clause 9 is the ONLY clause that exercises
verify-lane end to end. It skipped on the mere PRESENCE of
MGVL_IN_VERIFY_LANE and recorded that skip as PASS, so

    MGVL_IN_VERIFY_LANE=1 bash scripts/done-means/merge-gate-and-verify-lane.sh

exited 0 with every clause green and the live proof never executed. A stale
export or a CI env leak silently disabled the check's only live evidence, and
the transcript was indistinguishable from a genuine run. Family B of the
2026-08-10 gate-layer audit: a gate letting its environment decide the verdict.

The guard itself is right — the recursion it prevents is measured (331
worktrees, 2026-08-08). The defect is that it was ASSERTED rather than EARNED.

verify-lane.ts:479-480 exports both markers together and both are structured
(MGVL_IN_VERIFY_LANE=pr-<n>, MGVL_VERIFY_LANE_PRS=<ancestry including n>), so
the claim is now RE-DERIVED from the values: the marker must parse as pr-<n>
AND <n> must appear in the ancestry. Shape alone is deliberately not enough —
that would only replace one magic word with another.

Also:
- A skip is now recorded SKIP, never PASS, and a skipped live clause exits 4
  (non-zero so it cannot read as proof, distinct from 1 so it cannot read as a
  regression). Follows issue-resolution-artifacts.sh's "skipped is not passed".
- A polluted environment is exit 3 (HARNESS-ERROR), not a clause failure:
  "I cannot trust my inputs" and "the subject regressed" have different owners.
- Sibling sweep: MGVL_LIVE_PR, the other inherited variable steering the live
  clause, was announced but never validated. Now refused when non-numeric or
  when it self-targets the PR containing this check.

Verified this session (7/7 GREEN, and RED-first against the pre-fix subject at
afc5525 where 6/7 clauses failed and the fabricated marker exited 0). Two
negative controls: reintroducing skip-as-PASS is caught by clause 6, and
weakening corroboration alone — invisible to clause 6 — is caught by clause 3.
No CI workflow or sibling check consumes the exit contract, so exit 4 breaks
no caller. Neutrality failures on this branch are pre-existing and identical
on origin/wip/2026-08-07.

Refs #721
…e code (#722) (#731)

* checkpoint(#722): in-progress fixture hooksPath pin, salvaged from parked worktree (WRITTEN, untested)

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

* fix(done-means): 712 clause (d) asserted on a path the fixture cannot pin (#722)

The salvaged checkpoint pinned core.hooksPath in both fixtures and added the
BLIND/HARNESS-ERROR guards, which took 705 from 5-of-6 FAIL to 6-of-6 PASS.
712 still failed clause (d) with the hook fully reached -- a real verdict, not
a blind -- so the pin alone was not the whole defect.

Clause (d) required the announced log path to sit under the fixture's own
OPENBRAIN_TEMP_WORKSPACE ("$SCRATCH/ws"), set on the hook invocation by
run_hook_through_pipe. The fixture cannot win that assertion, for the same
reason #722 exists -- the ambient environment decides the verdict:

  env OPENBRAIN_TEMP_WORKSPACE=/probe/ws zsh  -c 'echo $OPENBRAIN_TEMP_WORKSPACE'
    -> /Volumes/ThunderBolt/_tmp    (the caller's value is discarded)
  env OPENBRAIN_TEMP_WORKSPACE=/probe/ws bash -c 'echo $OPENBRAIN_TEMP_WORKSPACE'
    -> /probe/ws

The hook's shebang is `#!/usr/bin/env zsh`; ~/.zshenv is read by every zsh,
including a non-interactive script, and it sources env-roots.zsh whose line 6
is an unconditional `export OPENBRAIN_TEMP_WORKSPACE=/Volumes/ThunderBolt/_tmp`.
That overwrites what the caller passed, so the hook always logs to the
operator's real temp workspace. Measured with a probe copy of the check:
has_buntest=1, has_ws=0, announced path .../_scratch/pre-push/bun-test-*.log.

So the old assertion tested the operator's shell profile, not the hook. The
clause's stated subject is that the redirect is ANNOUNCED and the log NAMED;
it now checks the announcement plus a concrete bun-test-<pid>-<epoch>.log
filename. Pinning the DIRECTORY is not this check's business and is not
something the fixture can do; pinning the SHAPE is, and it still fails if the
hook stops naming the log.

Mutation-tested: replacing the filename pattern with a sentinel the hook never
emits makes clause (d) FAIL, so the clause is not vacuously green.

Refs #722

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX
…ad (#724) (#729)

* test(done-means): gate the Aug 14-17 embedding backlog on recall, not on storage (#724)

Adds scripts/done-means/724-backlog-recallable.sh, the red-first acceptance
gate for #724 item 1. It is the reward function for the backlog fix, not a
test of the fix's author, and it deliberately does not assert the shape the
lane brief assumed.

The brief located the backlog in ob_session_events. Measured against the live
dogfood database while authoring, it is not there: 55 of 55 window events carry
an embedding, and embedded_at equals created_at to within a millisecond, so
embedding is synchronous on that write path. The gap in the window is in
ob_session_lanes -- 2 of 2 eligible rows unembedded, against 549 all-time.

Rather than hardcode whichever table happens to be short today, clause 1 reads
src/embedding-targets.ts:EMBEDDING_TARGETS at runtime and checks every
embedding-bearing table, using each target's own baseFilterSql for eligibility
and its own namespaceColumn/namespaceVia for isolation. Holding a second copy
of that list is precisely the defect class #433 documents, and the registry's
filters matter: counting lanes with an empty topic would report 7,634 phantom
window rows instead of 2.

Clause 2 drives the real executeSearch from this checkout in BOTH keyword and
semantic mode. Keyword search reads stored text and is structurally blind to a
missing embedding, so a lexical-only probe would pass straight over the defect
under test; the two arms disagreeing is itself the signature of stored-but-not-
indexed rows. Clause 3 is the control: a known-good pre-window row must come
back through the same path, so a dead service, an empty table list, or a broken
embedding provider cannot fake a pass by returning nothing everywhere. A failed
control exits 3, not 0 or 1 -- with the instrument silent the run has no
authority to judge the window either way. Zero candidate rows examined is also
exit 3, never a pass.

Two instrument defects were found and fixed while establishing red, both of
which had made the gate lie about a healthy path:

- The probe subjects were left(content, 60) of the newest rows, which yielded
  boilerplate ("Recorded codex turn checkpoint for Development. 3. Self-host")
  truncated mid-word and shared by thousands of rows. All 25 keyword hits were
  different rows carrying the same prefix. Subjects are now excluded from the
  known boilerplate and cut on a word boundary.
- The window boundaries were resolved in local time by SQL and in UTC by the
  probe. The control row at 2026-08-14T02:55:40Z is Aug 13 21:55 local: SQL
  called it pre-window, the probe called it in-window, and the control reported
  zero hits while nothing was broken. Both halves now take boundaries computed
  by Postgres in one session zone.

Observed this session (RUNNING): exit 1 with clause 1 FAIL on ob_session_lanes,
clause 2 PASS, clause 3 PASS. Exit 3 confirmed against an unreachable database.
Whether the nats-worker outage caused the unembedded lanes is unverified by
this gate; it observes the rows, not the cause. No fix is included.

Refs #724

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

* fix(embeddings): give the repair primitive the bulk caller it never had (#724)

The Aug 14-17 backlog did not drain because nothing enqueues embedding
repair. docs/embedding-repair.md states the boundary outright: the
maintenance bootstrap starts the embedding.repair runner but "invents no
namespace and enqueues no job" -- enqueue is deliberately an explicit,
auth-scoped caller boundary. No caller occupied that position for a bulk
historical backlog: maintenance-sweep enqueues only distill and graph
derivation, and scripts/backfill.ts covers only the five original domain
tables, which excludes ob_session_lanes where the window gap actually was.

Measured on the dogfood database rather than assumed: eligible-but-
unembedded ob_session_lanes held at 549 across four minutes with zero
maintenance_jobs activity, and no embedding.repair job has ever been
recorded. The runner was healthy and correctly idle.

scripts/repair-embeddings.ts occupies the missing caller position and
nothing more. It adds no pipeline, no table, and no SQL: it loops
repairStaleBatch (src/embedding-repair.ts:682), whose own docstring says
it is for script-style bulk runs, over EMBEDDING_TARGET_NAMES read at
runtime so the table list cannot drift into a second copy. Namespace
scope is mandatory and explicit.

Two behaviors are measurement-driven, not preference:

Selection asks for the "missing" reason alone. buildSelection ORs every
reason into one unordered SELECT ... LIMIT n, and the source_drift arm
matches rows that already have an embedding, so an all-reasons batch is
crowded with non-repairable rows and, with no ORDER BY, need never
converge. Restricting to "missing" makes every selected row repairable,
which is what makes repaired == 0 a truthful stop condition.

A per-table failure no longer aborts the run. The first global run died
on a leaked test fixture still live on the dogfood database: a BEFORE
UPDATE trigger on thoughts that RAISEs on every update. That trigger is a
separate defect and is not dropped here; the loop simply refuses to let
it hide the other tables' backlogs, and reports it in the exit code.

Run result: 1,627 rows repaired across five tables; eligible-but-
unembedded ob_session_lanes went 549 to 0. The done-means check moved
from exit 1 (clause 1 FAIL, 2 of 2 window lanes unembedded) to exit 0
with all three clauses passing.

Residual, filed in the worklog and not closed here: the leaked trigger
blocking 1,297 thoughts rows, unique-constraint collisions blocking the
sessions drain, and the fact that nothing yet schedules this CLI.

Refs #724

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

---------

Co-authored-by: Rodaddy <rico@rtech-consulting.com>
…#724) (#728)

* test(nats-worker): red done-means for embed watermark on worker health (#724)

Nothing alarms when the maintenance producer ticks with no consumer. Raw
rows keep arriving, embedded rows stop, and every liveness surface stays
green -- observed as three silent days. A watermark comparison (newest
embedded-row age vs newest raw-row age, with fresh raw rows present as
the guard) would have caught it in about an hour.

This is the RED half only. It asserts the desired `embed_watermark` block
on the NATS worker's own /health (port 3110), composed by
startHealthServer in scripts/run-nats-worker.ts:83-113. The surface
belongs there and not on 3100:
docs/core01-nats-worker-runbook.md ("What /health on 3100 does and does
NOT show") records that the HTTP service derives its blocks from its own
process environment and deliberately never observes the worker process,
and forbids putting the worker back into the HTTP service's business.

Naming matches the existing convention rather than inventing one:
server/transport/health.ts:14-33 and :35-79 establish the snake_case
liveness block with a boolean `stale` verdict, raw counters beside it, an
explicit `*_threshold_*`, and a content-free `reason`;
src/operator-doctor.ts:111 establishes `*_age_seconds` for an age.
Absence-is-not-staleness is asserted too, matching the optional
`maintenance_producer` and `capture` blocks at
server/transport/health.ts:93-105.

All ages are fixture data and the clock is injected; no wall-clock
sleeps or comparisons (docs/lane-contract.md, Tightenings round 5).

RED (observed this session, bun run test:isolated on this file): 4 fail,
1 pass. The single pass is the absence control, which is correct on
current code -- no observer is composed, so no block appears and the
worker stays healthy. The four failures are the missing fields and the
missing verdict:
  - carries the embed watermark ages ... -> Received: undefined
  - CONTROL current watermark healthy ... -> body.embed_watermark undefined
  - flips off healthy when lagging ... -> Expected "degraded", got "healthy"
  - stale requires FRESH RAW ROWS ... -> body.embed_watermark undefined

bunx tsc --noEmit: clean. No implementation in this commit.

Refs #724

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

* feat(nats-worker): surface embed watermark liveness on worker /health (#724)

The maintenance producer ticked for three days with no consumer draining
the embed queue. Raw rows kept arriving, embedded rows stopped, and
nothing anywhere COMPARED the two -- every liveness surface stayed green
while the corpus quietly stopped being searchable.

Add an optional `embed_watermark` block to the NATS worker's /health on
3110, composed by startHealthServer. `stale: true` flips status to
degraded/503 even when the bridge is available, so a healthy bridge
cannot mask a stalled embed lane.

The block matches the shape the producer (#625) and capture (#647)
liveness blocks established at server/transport/health.ts:14-33 and
:35-79: snake_case named block, boolean `stale` as THE verdict, raw
counters beside it, an explicit *_threshold_* naming the bound used, and
a content-free `reason`. `*_age_seconds` follows
src/operator-doctor.ts:111. Injection matches the optional-input pattern
at server/transport/health.ts:118-138; degradation matches :185-196.

Absence is not staleness: a worker composing no observer emits no block
and cannot be degraded by one. `stale` additionally requires
`raw_rows_recent > 0` so an idle corpus does not alarm.

Threshold: OPENBRAIN_EMBED_WATERMARK_LAG_THRESHOLD_SECONDS, default
3600. Nothing adjusted silently -- the startup log announces the value,
its source (default/env/invalid_env_default), and whether an observer is
composed.

Sited on 3110 rather than 3100 per
docs/core01-nats-worker-runbook.md ("What /health on 3100 does and does
NOT show"), which forbids putting the HTTP service back in the worker's
business.

Refs #724

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

* test(done-means): bash wrapper so #724's check runs under verify-lane (#728)

scripts/verify-lane.ts:473 executes every Done-means check with `bash`, so
#724's acceptance — a bun test file,
scripts/run-nats-worker-embed-watermark.test.ts — cannot be named directly in
a PR body and the merge gate for #728 could not pass. That runner limitation
is filed separately as #733; this adds the bash-shaped front door rather than
changing the acceptance itself.

The wrapper runs `bun run test:isolated` on that one file and maps outcomes to
the repo exit grammar: 0 green, 1 the thing under test failed (tests red, or
exit 0 with zero tests executed — a silent skip is not a pass), 3 harness error
for bun missing, a missing `test:isolated` entry point, an unreadable .env, or
a database bootstrap that never named a database or reported a tally. A broken
harness is not a red result and must not be reported as one.

It fails loudly at exit 3 when the acceptance FILE is absent from the tree:
zero files examined is the failure mode that would otherwise read as a pass.
.env resolution falls back to the canonical checkout the same way 614 does, so
the check runs from a lane clone or worktree that carries no .env of its own.

Observed this session on this tree: exit 0, 5 pass / 0 fail against isolated
database ob_isolated_80153_msy175db07; and exit 3 with the loud message when
the acceptance file is moved aside.

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

---------

Co-authored-by: Rodaddy <rico@rtech-consulting.com>
* test(runtime): red-first proof that wrap must adopt an existing capture lane's scope (#724)

Reproduces the manual wrap/checkpoint failure exactly: a lane created by the
capture hook (agent='openbrain-capture', all other exact-scope fields NULL) is
wrapped from a runtime scoped as a different agent, and session_start is
refused with 'existing lane exact scope does not match session_start request'.

Asserts the POST-fix behavior per the operator ruling 2026-08-17: wrap adopts
the lane's stored scope, session_start for a wrap binds on session_key +
namespace only, the write verb carries the LANE's scope, and the lane is never
re-pointed. The server-side one-way fill is an isolation boundary and is not
changed by this lane.

RED on this commit: 6 failed, 1 passed. No fix applied.

Refs #724

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

* fix(runtime): manual wrap adopts an existing lane's scope instead of claiming its own (#724)

A manual `openbrain-memory --event wrap` (and `--event checkpoint`) against a
lane the capture hook opened failed with `Existing lane exact scope does not
match session_start request`, losing two Development sessions' wraps. The
capture hook creates the base lane with `agent` set and every other exact-scope
coordinate NULL; the client made `session_start` claim the CALLER's full exact
scope, which trips the server's #646 one-way fill.

Operator ruling 2026-08-17: the wrap adopts the lane's scope. The server's
refusal is an isolation boundary and does not move -- `server/` and `src/` are
untouched here. The client is what stops asserting a scope it does not own.

Claim first, adopt only on that specific refusal:

1. `session_start` claims the caller's own exact scope, exactly as before. On
   success nothing else changes -- same single call, same arguments -- so the
   ordinary path is byte-for-byte unchanged and adoption costs nothing until it
   is needed.
2. Only on the scope refusal, re-issue `session_start` claiming nothing but
   `session_key`. That is the server's `!hasCompleteExactScope` branch, which
   returns the existing lane verbatim instead of attempting a fill.
3. `session_wrap` then carries the coordinates that came back on that lane, not
   the requester's, because the write verb must still satisfy the server's
   lane-scope predicate. Adoption is not "send fewer fields on start".

Discovering unconditionally was tried first and is wrong twice over: on a lane
that does not exist yet it CREATES a bare NULL-scoped lane and strands it, and
it adds a wire call to the sequence the cross-runtime contract fixture pins.

`validate_adopted_lane` binds the adopting start on `session_key` + `namespace`
-- the coordinates the caller genuinely owns -- because there is no requested
exact scope for the response to prove. The namespace refusals (#654/#662) are
extracted into `_require_proven_namespace` and enforced unchanged on both
paths rather than copied. Nothing else is widened: capture
(`append_session_event`) and the context-pack exact-scope proof are untouched,
and the adopting flag is scoped to the single discovery call so a spooled
session_start replay still proves its own parked scope.

Two fidelity gaps in the test fakes are corrected, both toward the real server:
`LaneAwareTransport` now mirrors the `hasCompleteExactScope` gate (it had only
the refusal half, so it refused a request the server accepts), and
`StartThenFailClient` reads exact-scope coordinates with `.get()`, matching the
server schema where all of them are `.optional()`.

DEVIATION, needs a ruling before merge:
`test_checkpoint_first_lane_denies_hostile_same_namespace_claim` now fails. It
is not collateral -- it is the ruling's direct consequence. Verified by driving
both cases through the fake: the client emits an IDENTICAL request sequence
whether the stored lane belongs to the capture hook or to another session in
the same namespace. Only the server's stored lane differs, so no client-side
signal distinguishes them. Adoption and that assertion cannot both hold. The
test is left failing rather than deleted or weakened, because relaxing an
isolation assertion is not an implementer's call.

Refs #724

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

* test(runtime): retire the hostile same-namespace claim test per operator ruling (#724)

Operator ruling (Rico, 2026-08-17): with wrap-adopts-lane-scope (the #724
item-4 fix on this branch), the client provably cannot distinguish the capture
hook's lane from another same-namespace session's lane -- the wire sequences
are identical, which the lane proved. There is nothing observable left for
test_checkpoint_first_lane_denies_hostile_same_namespace_claim to assert on.

Same namespace is the same tenant. The boundary that matters is the server's
namespace predicate, and AGENTS.md Coding Standards already state that
client-side convenience checks are not security controls.

A comment stands at the test's former site naming the ruling date and the
reason, so the next reader knows it was retired rather than lost.
docs/memory-contract.md now says in one sentence that wrap/checkpoint adoption
is namespace-scoped by design.

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

* test(done-means): add a bash front door for the wrap-lane adoption pytest file (#724)

`scripts/verify-lane.ts` runs every Done-means check with bash, so the pytest
acceptance file for wrap-lane adoption cannot be named directly in a PR body.
This wrapper runs it and maps the result onto the repo exit grammar: 0 green,
1 red, 3 harness error. The harness tier explicitly covers uv missing,
dependencies unresolvable, and the test file being absent — zero files
examined is never reported as a pass.

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX
…ark observer (#724) (#737)

* test(nats-worker): red-first proof the LIVE worker composes no watermark observer (#724)

#728 landed the embed-watermark health surface on the NATS worker and proved
every part of it by INJECTING an `embedWatermarkHealth` option. Nothing
constructs one. `startNatsWorkerProcess` only forwards
`options.embedWatermarkHealth` (scripts/run-nats-worker.ts:333-335) and the
live entrypoint calls it with `{ env: process.env }`, so the deployed worker
logs `embed_watermark_observed: false` (:345), publishes no `embed_watermark`
block, and can never alarm — the surface is in the tree and absent from the
serving process (#674 class; #656 caught the identical shape for capture).

Adds the acceptance gate only, not the fix:

- scripts/run-nats-worker-live-watermark.pg.test.ts starts the worker the way
  the deployed process does (NO watermark option) against a real pool on the
  isolated test database, seeds `thoughts` rows at explicit ages, and asserts
  the startup summary reports an observer AND that /health carries a block
  computed from those rows — stale+503 past threshold, healthy within it,
  healthy-with-numbers on an idle corpus.
- scripts/done-means/724-watermark-live-observer.sh is the bash front door
  (verify-lane runs checks with bash, #733), exit grammar 0/1/3, and fails a
  0-pass exit 0 so a silently-skipped dbDescribe cannot read as green.

A real database is load-bearing: the failure mode guarded is an observer
returning plausible numbers not derived from rows, which a fake pool would let
pass. `thoughts` is EMBEDDING_TARGETS' first entry under FULL_PROVENANCE
(src/embedding-targets.ts:181,191), so `created_at` is the raw watermark and
`embedded_at` the embedded one from one table.

RED as written: 4 tests, 4 failures, each on the gap itself
(`embed_watermark_observed` false / block undefined), none on harness noise.

Refs #724

* feat(nats-worker): the deployed worker composes its own embed watermark observer (#724)

PR #728 built the whole embed_watermark health surface and proved it by
INJECTING the reading. Nothing constructed an observer, so the deployed worker
logged embed_watermark_observed: false, published no block, and could never
alarm -- the surface was in the tree and absent from the serving process. Same
class as #656 (capture observer wired).

startNatsWorkerProcess now default-constructs an observer against its own pool
when the caller supplies none; the option stays an override so #728's fixture
test is unchanged. The live entrypoint still passes only { env: process.env }.

The watermark is registry-driven: every EMBEDDING_TARGETS entry whose
provenance.hasEmbeddedAt is true (src/embedding-targets.ts:146-150,326), the
same registry the embedding repair path drives off. ob_entities is skipped on
ENTITY_PROVENANCE (:158-162) rather than queried for a column it lacks.

The health handler is synchronous, so the accessor never queries: it serves a
cached reading and schedules a background refresh past a 30s TTL, announced at
startup as embed_watermark_cache_ttl_seconds beside the threshold. A read
failure composes stale: false with a reason naming the failure and the last
good numbers (-1 when never measured) -- a database the observer cannot reach is
evidence about the observer, not the lane -- and can neither crash /health nor
hold a silent green.

Done-means: bash scripts/done-means/724-watermark-live-observer.sh
  before wiring: 0 pass, 4 fail  after: 4 pass, 0 fail
  38 pass across the worker + registry suites; bunx tsc --noEmit clean.

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX

---------

Co-authored-by: Rodaddy <rico@rtech-consulting.com>
@gitguardian

gitguardian Bot commented Aug 18, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
35895816 Triggered PostgreSQL Credentials 28fe9d9 src/observability/observability.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Two integration lines had advanced in parallel (main: #686-#691/#701/#726;
wip: #708-#737). Resolutions, all announced: lane-contract Tightenings kept
as a UNION with a fork note (rounds <=29 are per-line); sme-per-entry-files
pin re-measured on the merged tree per round 28's own rule, both provenance
trails kept; docs/sme/gotcha-agent.md REGENERATED from entries (never
hand-merged) after renumbering three forked order collisions (72/73/74).

Claude-Session: https://claude.ai/code/session_01U3sT5FabVFHQwwfqKVXFjX
@rodaddy

rodaddy commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

verify-lane receipt: check=scripts/done-means/724-wrap-lane-adoption.sh exit=0 sha=19df06617f8747e16e4dbaf772b0a96a62f56b16 at=2026-08-18T13:04:59.569Z

check output (tail)

=== DONE-MEANS #724: wrap-lane adoption in the Python runtime ===

acceptance file: python/openbrain-memory/tests/test_runtime_wrap_lane_adoption.py
runner:          uv run pytest tests/test_runtime_wrap_lane_adoption.py -q
tally:           7 passed, 0 failed, 0 error(s) (runner exit 0)

PASS — 7 tests executed, 0 failures, exit 0

transcript: /Volumes/ThunderBolt/_tmp/open-brain/_scratch/done-means-724-wrap-b3bb4b96f089.log.done.done

VERDICT: PASS

Posted by scripts/verify-lane.ts. The SHA above is the PR head observed at run time;
.claude/hooks/merge-gate.ts refuses the merge if the PR has moved since.

@rodaddy

rodaddy commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

harvested: 7d79165 docs/lane-contract.md — the rotation merge's own lessons are IN this PR (the round-numbering fork note, union resolution, and the re-measured sme pin per round 28's rule); also 19df066 for the #707 heading fix the merged check surfaced.

@rodaddy
rodaddy merged commit c7bf1b9 into main Aug 18, 2026
15 of 16 checks passed
@rodaddy
rodaddy deleted the wip/2026-08-07 branch August 18, 2026 13:08
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.

pre-commit gate is silently absent: repo core.hooksPath displaces the global gitleaks + protected-branch hook, and nothing runs in its place

1 participant