linkedin-studio/docs/second-brain/brief-sb-s3a.md
Kjell Tore Guttormsen d2ec7482be docs(linkedin-studio): SB-S3b brief + plan — supersede arm (light-Voyage hardened)
Second sub-slice of SB-S3 (after S3a's reader landed). Adds an operator-gated,
explicitly-signalled supersede op to the consolidation engine: a temporal-update
candidate retires a stale fact (status: superseded, re-minted to an archival id,
replaced in place, retained as audit) and installs the new winner under the
canonical key-id. Bounded to scripts/brain/ — pure, deterministic, fully
unit-testable.

Operator-confirmed scope: temporal-update→supersede ONLY · winner→dynamic
(re-earn) · minimal `supersedes?: string` · retain superseded as audit.

Light-Voyage-hardened:
- brief-reviewer APPROVE-WITH-FIXES — 8 FIX folded (the load-bearing one: id
  lifecycle → winner-takes-key-id, retired fact re-minted, so mintEntityId(key)
  always points at the live fact).
- plan-critic REVISE → 2 BLOCK + 6 FIX folded: applyDiff must REPLACE-IN-PLACE
  (not copy → would dup the canonical key-id); proposeDiff must value-guard the
  supersede fork (a re-sent stale signal would self-supersede every run); plus
  --gather active-only filter + decay excludes superseded (else retired facts
  leak back as live context / spam stale flags).
- scope-guardian ALIGNED (0 creep / 0 gap).

Also reconciles brief-sb-s3a.md's stale DRAFT status (S3a landed 4fa411f).
No code yet — awaiting go-before-code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RigJBiRFNtFZKCz21qNbQ4
2026-06-23 18:51:25 +02:00

9.1 KiB
Raw Permalink Blame History

Brief — SB-S3a: the first profile.md READER

Slice: SB-S3a (first sub-slice of SB-S3, the cross-silo + ops-centre arc step). Status: LANDED 4fa411f (2026-06-23) — gate 95/0/0, ASSERT_BASELINE_FLOOR 80. Light-Voyage-hardened (brief-review APPROVE · scope-guardian ALIGNED · plan-critic REVISE→folded). SC1/2/3/6 gate-proven; SC4 inspection-pass; SC5 (read-back) deferred to a reloaded session. Predecessors: SB-S0 (id/profile substrate) · SB-S1 (published-gold ingest) · SB-S2 (consolidation motor — motor-only, no reader).

1. Operator decision (2026-06-23)

SB-S3 is the arc's largest slice and was decomposed into four sub-slices (value-first / risk-managed): S3a reader · S3b supersede · S3c cross-silo id-threading · S3d hygiene+ops. The operator picked S3a — the profile.md reader — first, and within S3a the first reader is one agent: strategy-advisor, wired READ-only.

2. Why a reader, and why first

The whole arc was built "so S3's reader inherits rich data" (consolidation-loop.md:67). S2 grows brain/profile.md but no agent or command consumes it today — verified: 0 references to brain/profile.md in agents//commands/; every "profile" hit points at the legacy flat profile/user-profile.md, not the SB-S0 two-layer brain profile. The reader is the deferred payoff of S0→S2: it turns a motor-only system into one that feeds content generation — the first end-to-end proof of capture → consolidate → read-back-into-generation.

It is first because it has no dependency on id-threading (it reads the profile facts, not the cross-silo graph), it is additive / non-breaking, and it is the lowest-risk of the four (read-only consumption of an existing file).

3. Scope — what is IN (S3a)

  1. Wire strategy-advisor to read brain/profile.md. Add the brain profile to the agent's existing Step 0: Load Context list: ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/brain/profile.md The agent reads the markdown in-context and reasons over it — no parser, consistent with the arc thesis (Claude is the retrieval engine; architecture.md:14).

  2. Consumption contract (how the agent uses it). A short subsection in the agent prompt that tells it:

    • The profile has two layers — ## Static (stable, high-confidence) and ## Dynamic (emerging) — and each fact line carries evidence_count + last_seen. Higher evidence_count / more recent last_seen = stronger/fresher signal; weight accordingly.
    • Anti-sycophancy (binding, architecture.md:58): treat every profile fact as evidence to TEST, not flatter. Counter-pressure it against analytics/state each time it is used (e.g. "the profile says you lean X, but your last imports show Y — test that"). The profile informs, it never dictates or flatters.
  3. Graceful absence. brain/profile.md does not exist until brain init runs (fresh installs have no brain). The agent must degrade silently when the file is missing or empty — no error, no "I couldn't find your profile" noise; it simply proceeds on its other context sources.

  4. A deterministic wiring test in the structure-lint / test-runner.sh gate: two UNCONDITIONAL assertions — (a) strategy-advisor.md's context-load declares brain/profile.md; (b) the agent carries the anti-sycophancy sentinel literal evidence to TEST (exact-literal grep + a non-vacuity self-test, per the repo lint idiom in test-runner.sh Sections 13/16c — loose patterns match vacuously). This is the TDD anchor (see §6) and protects the wiring against future agent-file edits.

    • Assertion-floor lockstep (binding): the two new checks are UNCONDITIONAL, so ASSERT_BASELINE_FLOOR in test-runner.sh (Section 18; currently 78 — verify at plan time) must be bumped by exactly +2 → 80 in the same change, per the assertion-erosion guard. Do NOT pin to a deps-present TOTAL.
  5. Doc/count reconciliation. Update the binding counts/docs touched (CLAUDE.md agent table note if needed, STATE telling, consolidation-loop.md reader-status line: "S3a wires the first reader — strategy-advisor").

4. Non-goals — what is OUT (deferred to later S3 sub-slices)

  • More than one reader. content-optimizer is the obvious second reader and the pattern generalizes trivially, but S3a wires exactly one agent — the smallest valuable proof. Follow-on readers are separate work.
  • A hook-level / user-prompt-context.mjs digest reader. A broad "inject a profile digest into every prompt" reader is attractive but carries a twin .mjs parser (twin-sync with profile.ts) + per-prompt context cost — not a good first proof. Deferred.
  • Cross-silo id-threading (S3c). The reader consumes profile facts, not the post↔specific↔trend↔analytics graph. No mintEntityId threading here.
  • Supersede arm (S3b), content-history retirement / triple-post reconciliation + operations.md (S3d) — separate sub-slices.
  • Any WRITE to brain/profile.md. The profile is mutated ONLY via brain consolidate --apply --confirm (operator-gated). S3a is strictly read-only; it adds no write path.
  • A new parser or new .mjs. S3a is markdown-agent edits + a lint assertion only.

5. Boundaries / invariants (must hold)

  • READ-only — S3a never writes the profile; the --apply --confirm gate stays the sole writer.
  • Anti-sycophancy is a built-in default, not a toggle (architecture.md:58).
  • Provenance spine intact — the profile already encodes provenance; the reader must not undermine the published-only learning guard.
  • No tributary schema changes (that's S3c).
  • Fresh-clone safe — missing brain → silent degrade, no crash, no nag from the agent.
  • TDD iron law — the failing wiring test lands before the agent edit.

6. Success criteria (testable)

  • SC1 — wired: strategy-advisor.md Step 0 context-load includes brain/profile.md. (lint assertion, deterministic)
  • SC2 — anti-sycophancy framed: strategy-advisor.md's profile-consumption subsection contains the exact durable sentinel literal evidence to TEST, asserted by an exact-literal grep + a non-vacuity self-test (repo idiom, test-runner.sh §§13/16c). (lint assertion)
  • SC3 — gate green: scripts/test-runner.sh (the structure lint) stays green with the new assertions; its BRAIN_TESTS_FLOOR (82) is unchanged — no brain TS is touched. The hook suite (~136) runs under the separate node --test hooks/scripts/__tests__/*.test.mjs runner (NOT part of test-runner.sh) and is untouched because no hook code path changes.
  • SC6 — assertion floor honoured: ASSERT_BASELINE_FLOOR bumped by exactly the number of new unconditional checks (+2 → 80); the gate's self-count check passes.
  • SC4 — graceful absence (manual/behavioural): running strategy-advisor with no brain/profile.md produces normal output, no error/noise about the missing file.
  • SC5 — read-back works (manual/behavioural): running strategy-advisor with a populated brain/profile.md surfaces ≥1 profile fact as evidence-to-test in its recommendation, counter-pressured against analytics/state — not parroted.

7. Verification

  • Deterministic (gate): SC1SC3 via the structure-lint assertion in test-runner.sh. cd scripts/brain not required — this is an agent-file + lint change; brain TS is untouched.
  • Behavioural (manual, documented): SC4 + SC5 — the honest limit. Agent-prompt behaviour is not unit-testable (the plugin's command-testing workstream is still open). The plan must include a documented manual run: (a) empty-brain run → clean output; (b) populated-brain run (seed via brain init + a --apply --confirm cycle, or a fixture profile) → confirm a profile fact appears as tested evidence. Record the result in STATE/changelog at land.

8. Open questions for brief-review / the operator

  1. Agent choice: strategy-advisor recommended; operator may redirect to content-optimizer (post-level grounding) — confirm at the brief gate.
  2. Lint location: which existing lint file in the test-runner.sh gate hosts the SC1/SC2 assertion (plan resolves precisely).
  3. Behavioural test honesty: is the documented manual verification (SC4/SC5) acceptable for S3a's land, given agent-behaviour is not unit-testable — or does the operator want a fixture-driven harness scoped in (larger)?

9. Brief-review (light-Voyage) — folded

voyage:brief-reviewer verdict: APPROVE (scope crisp, non-goals correct, invariants inherited, deterministic-vs-behavioural split honest). Three [FIX]es folded above:

  • SC3 no longer conflates two runners (brain-82 floor in test-runner.sh vs the separate hook runner).
  • ASSERT_BASELINE_FLOOR lockstep bump (+2 → 80) made binding in §3.4 + SC6.
  • SC2 pinned to the exact literal evidence to TEST + non-vacuity self-test (anti-vacuity idiom).

Reviewer confirmed: strategy-advisor is the better first reader than content-optimizer; SC4/SC5 manual split is correct; do NOT scope a behavioural harness into S3a (keeps "smallest valuable proof").