Splits the old S3d charter: S3d = ops centre ONLY (operations.md becomes a read tributary; strategy-advisor honours the dated frozen-past-self anchor that deprecates older inferences — advisory/reader-side). The hygiene + triple-post reconciliation half (dead content-history.md retirement + post-tracking↔published↔analytics) moves to a new SB-S3e (the last S3 slice). Light-Voyage hardening: scope-guardian ALIGNED (0 creep/gap); brief-reviewer REVISE (5 FIX folded); plan-critic 3 major + 3 minor folded. Baselines verified live: gate 95→97, brain 113→114, ASSERT floor 80→82. The RED-bearing brain-test literal is pinned to the dated-anchor convention (_As of YYYY-MM-DD:_, verified absent) — NOT 'deprecates older inferences', which already ships in the seed comment and would make the RED gate vacuous. Go-before-code gate pending (forks: Option B enrich seed · advisory deprecation · one reader · doc home). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RigJBiRFNtFZKCz21qNbQ4
16 KiB
Plan — SB-S3d: wire the operations centre (operations.md READER + dated anchor)
Brief:
docs/second-brain/brief-sb-s3d.md. Slice: SB-S3d (ops centre only; hygiene+reconciliation → SB-S3e). Operator confirmed (2026-06-23): Split, ops-centre first. Recommendations pending the go-gate: Option B (enrich seed) + advisory deprecation + one reader (strategy-advisor). Order is TDD: the failing lint/seed checks land BEFORE the agent/seed edits (iron law).
Goal
strategy-advisor reads brain/operations.md and honours the dated frozen-past-self anchor — preferring it over older/contradicting profile facts (the guard, advisory) — guarded by a deterministic wiring lint, with an enriched seed that ships the dated-anchor convention. No engine write, no post-silo contact, no parser.
Files touched (exhaustive — for scope-guardian)
| File | Change | Why |
|---|---|---|
scripts/test-runner.sh |
NEW Section 16e (2 unconditional checks) + bump ASSERT_BASELINE_FLOOR 80→82 + extend the Section-18 history comment + header enumeration (:33-36) |
SC1/SC2/SC5 — the TDD anchor |
scripts/brain/tests/scaffold.test.ts |
NEW test() asserting the dated-anchor seed convention (Option B) | SC3 — fails first (RED) |
scripts/brain/src/scaffold.ts |
enrich operationsSeed() (:52-64): dated-anchor convention + light Plans/Ideas guidance |
SC3 — makes the guard operational |
agents/strategy-advisor.md |
add brain/operations.md to Step 0 Load-Context (:41-48) + a consumption subsection after :63 (anchor authoritative + deprecates older inferences literal + graceful absence) |
SC1/SC2/SC6/SC7 — the wiring |
docs/second-brain/architecture.md |
edit the SB-S3 build-row (:80) to the post-split truth (S3d ✅ ops · S3e remains hygiene+reconciliation) |
doc reconciliation |
Not touched (scope fence): any post silo (hooks/scripts/state-updater.mjs, ## Recent Posts, content-history*, analytics, tributary JSON) — that is S3e · consolidate.ts/assemble.ts/ingest.ts/cli.ts (no engine/graph change; advisory guard only) · consolidation-loop.md (profile-motor contract, not this loop) · content-planner.md (second reader, not S3d) · CLAUDE.md agent table (count/model lint unaffected — no new agent, frontmatter unchanged) · Section 16d (the profile reader stays exactly as-is).
Step 1 — (RED) Lint: Section 16e + floor bump
Insert a new section after Section 16d (test-runner.sh:833, before Section 17 at :834), modelled byte-for-byte on 16d's idiom (two exact literals + *_wired() + non-vacuity self-test + real-file grep with grep -qF):
- Literals:
OPS_LIT='brain/operations.md',ANCHOR_LIT='deprecates older inferences'. ops_reader_wired()— wired iff BOTH literals present. Pin the body VERBATIM from 16d (test-runner.sh:802),grep -qF(fixed-string —OPS_LITcontains.//, so-Fis mandatory or the.is a regex wildcard):echo "$1" | grep -qF "$OPS_LIT" && echo "$1" | grep -qF "$ANCHOR_LIT"(echo twice — grep consumes stdin).- Check A (self-test, unconditional): a fully-wired probe (
"reads brain/operations.md; the anchor deprecates older inferences") MUST be detected; three under-wired probes MUST be rejected:reads brain/operations.md but never says the anchor outranks anything(file lit, missing anchor lit)the anchor deprecates older inferences but names no source file(anchor lit, missing file lit)reads brain/profile.md and tests the evidence(sibling-file decoy — names the OTHER brain file + no anchor lit; must NOT match either operations literal) →pass/fail"ops-reader self-test: full wiring detected; 3 under-wired forms rejected (incl. sibling-filebrain/profile.mddecoy)".
- Check B (real-file grep, unconditional):
grep -qF "$OPS_LIT" agents/strategy-advisor.md && grep -qF "$ANCHOR_LIT" agents/strategy-advisor.md→pass"strategy-advisor.md wired to brain operations reader (names '…operations.md', frames 'deprecates older inferences')" elsefail. - Header enumeration (
:33-37): insert the 16e clause immediately after "…with a non-vacuity self-test) in Section 16d;" (mid-:36), BEFORE the "the assertion-count anti-erosion floor (SC6) in Section 18. All are live below (Sections 8–18)." tail — preserving the 16d → 16e → 18 ordering. Clause: "the brain operations-reader guard (SB-S3d:strategy-advisornamesbrain/operations.mdAND carries the frozen-past-self literaldeprecates older inferences, with a non-vacuity self-test) in Section 16e;". The "Sections 8–18" range is unchanged (16e is in range). - Floor (
:905-913):ASSERT_BASELINE_FLOOR=80→82; extend the history comment: "+2 for SB-S3d's two UNCONDITIONAL Section-16e checks (ops-reader self-test + strategy-advisor ops-wiring grep) = 82." Both new checks are deps-free → they lift the deps-absent minimum, so +2 is correct (NOT pinned to deps-present TOTAL).
Non-collisions (verify with plan-critic): new prose carries no algorithm-magnitude token (Section 8 stat-consistency safe) and no Significant?( column (Section 11 render-chain safe); the edit uses the exempt ${LINKEDIN_STUDIO_DATA:-…} external form → Section 13 data-dir guard safe; agent count (19) + strategy-advisor model/frontmatter unchanged → Sections 2/9/10 unaffected; Section 16d's two literals remain present in the (unchanged) profile subsection.
Step 2 — (RED) Brain seed test (Option B)
In scripts/brain/tests/scaffold.test.ts, add ONE new test() (bumps the suite count → floor +1) asserting the enriched seed — e.g. test("operations.md ships a dated frozen-past-self anchor convention", ...):
initBrain(), readbrain/operations.md.- The single RED-bearing assertion is the date convention, which is verified ABSENT from the current seed (
grep "As of" scaffold.ts= 0 → the test fails first):assert.match(ops, /_As of YYYY-MM-DD:_/)(or/As of/— but the underscore form is the exact seed literal). - Do NOT assert
deprecates older inferencesas the failing literal — it ALREADY ships in the current seed comment (scaffold.ts:58, verifiedgrep -c= 1), so it passes pre-enrichment and would make the RED gate vacuous. It may be asserted only as an explicit non-RED companion (documented as such), or omitted. - Keep matching the existing
Who I am now/## Plans/## Ideasanchors so the new case is a strict superset of the old guarantee. - Leave the existing 5 tests untouched (the no-clobber test at
:70-77already proves idempotency of the new seed). - Baseline (verified live, 2026-06-23): brain suite reports
tests 113and the gate reports 95 checks — so the floor becomes recorded + 1 = 114 (not a hardcoded guess) and the gate goes 95→97.
RED proof (recorded): (cd scripts/brain && npm test) against the un-enriched seed → the new test FAILS (no _As of in the seed yet). bash scripts/test-runner.sh → Section 16e Check A passes, Check B FAILS (agent not yet wired), floor self-count passes (TOTAL 96 ≥ 82). Capture this failing output in STATE/changelog as the iron-law artifact. This is the required failing state.
Step 3 — (GREEN) Enrich the seed
In scripts/brain/src/scaffold.ts, rewrite operationsSeed() (:52-64, the full function incl. the closing brace at :64 — body string is :53-63) to ship the dated-anchor convention + light guidance. Load-bearing: the rewrite MUST retain ## Who I am now, ## Plans, and ## Ideas verbatim — the existing anchor test scaffold.test.ts:48-58 asserts all three, so dropping one regresses that test. Idempotency is untouched: initBrain existence-skips (writes a seed only when the file is absent, scaffold.ts:105-113), so the new seed string never reaches an already-created operations.md. Sketch:
function operationsSeed(): string {
return `# Operations
> The operations centre — where you're headed now, what you're working on, what you might do next.
> User-authored: the brain motor never writes here (a \`brain init\` re-run never clobbers your edits).
## Who I am now (anchor)
<!-- Frozen-past-self guard: a DATED, user-authored "where I'm headed now" statement.
It DEPRECATES older inferences — when a profile.md fact predates or contradicts this
anchor, the anchor wins. Re-date it when your direction shifts. -->
_As of YYYY-MM-DD:_ <one or two sentences on your current direction>
## Plans
<!-- Active commitments — what you're working toward now. One per line. -->
## Ideas
<!-- Parking lot — possible content/strategy ideas, not yet commitments. One per line. -->
`;
}
GREEN gate (brain): (cd scripts/brain && npm test) → new test passes; suite reports tests 114 (verified baseline 113 + 1); bump BRAIN_TESTS_FLOOR 113→114 (test-runner.sh:716) + extend its inline breakdown comment ("+ SB-S3d 1 [scaffold dated-anchor seed]"). The no-clobber test (scaffold.test.ts:70-77) runs in this same gate and must stay green.
Step 4 — (GREEN) Wire strategy-advisor.md
- Step 0 Load Context (
strategy-advisor.md:41-48): insert one line INSIDE the fenced block, immediately before the closing ``` fence (:48), after the profile line (:47):${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/brain/operations.md → the operations centre: dated "who I am now" anchor + plans + ideas (user-authored) - New subsection immediately after the profile subsection's graceful-absence line (
:63), e.g.### Consuming the operations centre (brain/operations.md):- Anchor is authoritative: "The
## Who I am nowanchor is the user's own dated declaration of current direction. It is authoritative and deprecates older inferences: when abrain/profile.mdDynamic fact predates the anchor's date or contradicts its stated direction, prefer the anchor and flag the older fact as possibly-stale — do not parrot it." ← carries the exact literaldeprecates older inferences. - Inversion (make the contrast explicit): "Unlike profile facts, which you treat as evidence to TEST, the anchor is user-declared direction, not an inference to challenge — honour it. (It is direction, not praise; honouring it never licenses flattery.)"
- Plans / Ideas: "
## Plansare active commitments (current intent);## Ideasare a parking lot (suggestions, not commitments) — weigh accordingly." - Graceful absence: "If
brain/operations.md(or its anchor) is missing or empty, proceed silently on the other context sources — no error, no note about a missing ops centre."
- Anchor is authoritative: "The
GREEN gate (lint): bash scripts/test-runner.sh → Section 16e Check A + Check B pass, FAIL=0, 97/0/0, ASSERT floor 82 honoured. (16d still green — profile literals untouched.)
Step 5 — Doc reconciliation
Edit architecture.md:80 (the SB-S3 build-row) so the post-split status is true: S3a/b/c ✅ as today, then "S3d ✅ ops centre — operations.md is a read tributary; strategy-advisor honours the dated anchor that deprecates older inferences (advisory). S3e remains — dead content-history.md retirement + triple-post (post-tracking↔published↔analytics) reconciliation." No other architecture edit (the §59 guard spec already stands; the §80 row was the stale claim).
Step 6 — Behavioural verification (manual, recorded — SC6/SC7)
Agent-prompt behaviour is not unit-testable (operator-accepted). Honest procedure, result recorded in STATE/changelog at land:
- SC6 (graceful absence): with no
brain/operations.mdat the data-root, the wiring degrades silently — inspect the subsection's graceful-absence clause + (best-effort) astrategy-advisorrun on an empty root → no missing-file noise. - SC7 (guard fires): seed a temp root (
LINKEDIN_STUDIO_DATA=<tmp> brain init), write a dated anchor (_As of 2026-06-20:_ pivoting from X to Z) and a contradicting older profile fact (leans toward X,last_seen< 2026-06-20) → run the agent → confirm it prefers the anchor (Z) and flags the older X fact as deprecated, not parroted. If the harness cannot exercise a per-call data-root, record that honestly and fall back to inspection of the wiring + framing (no overclaim).
Step 7 — Land
STATE "Telling" + "👉 NESTE" updated (S3d done → S3e is the new last slice); commit. Mixed change: the seed/agent/lint are code → [skip-docs] judged per the repo convention; brief+plan+architecture are docs. Push only inside the window (date '+%u %H:%M' first; origin = PUBLIC open/ → confirm before push). No version bump (S3d additive within v0.5.2 dev; release is a separate decision).
Verification (testable)
| SC | Check | Command | Expected |
|---|---|---|---|
| SC1+SC2 | ops reader wired + literal | bash scripts/test-runner.sh |
Section 16e Check B passes |
| SC3 | seed convention | (cd scripts/brain && npm test) |
new test passes; floor 114 |
| SC4 | gate green | bash scripts/test-runner.sh |
97/0/0; 16d still green; hook suite (separate runner) untouched |
| SC5 | assertion floor | same run | "anti-erosion: 97 … >= floor 82" passes |
| (red proof) | failing-test-first | gate run BETWEEN Step 1/2 and Step 3/4 | exit 1: scaffold test fails (Step 2), 16e Check B fails (Step 1) |
| SC6 | graceful absence | manual, empty root | clean output, no missing-file noise |
| SC7 | guard fires | manual, seeded anchor+stale fact | anchor wins, older fact flagged (or honest fallback recorded) |
Risks
- R1 — vacuous lint. Mitigated by the 16d-style non-vacuity self-test with the sibling-file (
brain/profile.md) + "outranks anything" decoys. - R2 — floor false-fail on fresh clone. Both new lint checks are deps-free (lift the deps-absent minimum) → +2 → 82 correct, not pinned to deps-present TOTAL. The brain floor (114) only checked when the brain suite runs (deps-present); a fresh clone warn-skips it (unchanged mechanism).
- R3 — behavioural overclaim. Step 6 honest-fallback clause (verifiseringsplikt): never report a guard-fires pass not actually run.
- R4 — anti-sycophancy weakening. The anchor's "authoritative" stance must not read as "flatter the user." Mitigated by the explicit "direction, not praise" clause + the profile
evidence to TESTstance staying verbatim (Section 16d unchanged, still grepped). - R5 — seed breaks idempotency. Mitigated: the enriched seed is still a static string;
scaffold.test.ts:70-77(no-clobber) stays green and is run in Step 3's GREEN gate. - R6 — stale §80 doc. The build-row claim "S3d remains (ops + hygiene + reconciliation)" becomes false at land; mitigated by EDITING
:80to the split truth (no automated guard coversarchitecture.md; Section 11 scans non-docs dirs only).
Plan-critic — folded
voyage:plan-critic (no blockers; 3 major + 3 minor) folded above:
- Major-1 — vacuous brain RED: the seed already ships
deprecates older inferences(scaffold.ts:58), so the RED-bearing literal must be the date convention_As of YYYY-MM-DD:_(verified absent). Folded into Step 2. ✅ - Major-2 — unverified brain floor: recorded the live count (
tests 113) → floor = recorded + 1 = 114, not a hardcoded guess. Folded into Step 2/3. ✅ - Major-3 —
grep -qFfixed-string: pinned theops_reader_wired()body verbatim fromtest-runner.sh:802(-Fmandatory —OPS_LIThas.//). Folded into Step 1. ✅ - Minor-1 — header range: corrected to
:33-37; the 16e clause inserts after "…in Section 16d;", before the SC6/Section-18 tail. Folded into Step 1. ✅ - Minor-2 — function range: cite
operationsSeed()as:52-64incl. the closing brace (body:53-63). Folded into Step 3. ✅ - Minor-3 — retained anchors: the three
##anchors are load-bearing forscaffold.test.ts:48-58; the rewrite retains them verbatim. Folded into Step 3. ✅
Cross-checks the critic confirmed sound: floor arithmetic (ASSERT 80→82, BRAIN 113→114), the 3 decoys each miss ≥1 literal, the sibling-file decoy brain/profile.md cannot match OPS_LIT, Section 16d stays green (profile literals untouched; the new subsection adds a second evidence to TEST occurrence, harmless), and no collision with Sections 8/11/13.