linkedin-studio/scripts/brain/tests/consolidate.test.ts
Kjell Tore Guttormsen 585f972a05 feat(linkedin-studio): SB-S3b — supersede arm in the consolidation engine [skip-docs]
The engine can now RETIRE a fact via an operator-gated, explicitly-signalled
temporal-update supersede — completing the consolidation motor's one S2 TODO
("no supersede in S2 — that's S3"). A `supersedes` signal on a candidate retires
the stale fact (re-minted to an archival id, status: superseded, REPLACED IN
PLACE, retained as audit) and installs the new winner under the canonical key-id,
so mintEntityId(key) always points at the live fact.

- consolidate.ts: Candidate.supersedes? + ProfileDiff.supersedes (SupersedeOp
  carries the full winner fact, so applyDiff stays a pure projector). proposeDiff
  value-guarded routing fork (routes only when the target holds a DIFFERENT value —
  else a re-sent signal would self-supersede every run) + intra-batch
  first-supersede-wins guard. applyDiff replace-in-place + value-matched state-check
  (oldId present, active, value===oldValue) → idempotent re-apply + stale-diff safe;
  superseded facts never bumped/promoted (supersede wins). Decay excludes superseded.
  archivalId seeded with the pre-archival id (collision-free).
- cli.ts: renderDiffMd `## Supersessions (old → new)` (rendered last, only when
  present → zero-supersession diffs stay byte-identical); validateCandidates optional
  single-line `supersedes`; `--gather` profileFacts filtered to active (superseded
  archival facts never re-presented as live context).
- Tests: +12 brain (consolidate 10 + consolidate-cli 2). TDD: RED (6 fail) → GREEN
  (94/94). BRAIN_TESTS_FLOOR 82->94; ASSERT_BASELINE_FLOOR unchanged at 80 (no new
  test-runner.sh section). Gate 95/0/0.
- Docs: consolidation-loop.md rule table + honest-limit reconciled (the operator
  gate is the only classification net); engine docstring updated.

All 13 success criteria deterministically tested (unlike S3a, no behavioural-only
SC). READ-only gate unchanged — brain consolidate --apply --confirm stays the sole
profile.md writer. Scope held: scripts/brain/ only; temporal-update only
(condition-dependent/distractor deferred).

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

287 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, test } from "node:test";
import assert from "node:assert/strict";
import { proposeDiff, applyDiff, type Candidate, type ProfileDiff } from "../src/consolidate.js";
import { mintEntityId } from "../src/id.js";
import { parseProfile, serializeProfile } from "../src/profile.js";
import type { ProfileDoc, ProfileFact } from "../src/types.js";
const TODAY = "2026-06-23";
const observedId = (key: string) => mintEntityId({ kind: "observed", key });
const fact = (over: Partial<ProfileFact>): ProfileFact => ({
id: "000000000000",
value: "v",
first_seen: "2026-01-01",
last_seen: TODAY,
evidence_count: 1,
provenance: "published",
status: "active",
...over,
});
const doc = (staticF: ProfileFact[], dynamicF: ProfileFact[]): ProfileDoc => ({
schemaVersion: 1,
static: staticF,
dynamic: dynamicF,
});
const cand = (over: Partial<Candidate>): Candidate => ({
key: "k",
value: "v",
provenance: "published",
source: "manual",
observed_date: TODAY,
...over,
});
describe("proposeDiff classification (SC1ag)", () => {
test("SC1a — add: a published candidate with no match becomes a new dynamic fact", () => {
const diff = proposeDiff({ current: doc([], []), candidates: [cand({ key: "topic", value: "AI safety" })], today: TODAY });
assert.equal(diff.additions.length, 1);
assert.equal(diff.additions[0].value, "AI safety");
assert.equal(diff.additions[0].id, observedId("topic"));
assert.equal(diff.additions[0].evidence_count, 1);
assert.equal(diff.additions[0].status, "active");
});
test("SC1b — reject: an ai-draft candidate produces an empty diff", () => {
const diff = proposeDiff({ current: doc([], []), candidates: [cand({ provenance: "ai-draft" })], today: TODAY });
assert.deepEqual(diff.additions, []);
assert.deepEqual(diff.evidenceBumps, []);
assert.deepEqual(diff.promotions, []);
assert.deepEqual(diff.conflicts, []);
});
test("SC1c — evidence-bump: same key+value bumps the existing fact, no addition", () => {
const id = observedId("topic");
const cur = doc([], [fact({ id, value: "AI safety", evidence_count: 1 })]);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "topic", value: "AI safety" })], today: TODAY });
assert.equal(diff.additions.length, 0);
assert.equal(diff.evidenceBumps.length, 1);
assert.deepEqual(diff.evidenceBumps[0], { id, newCount: 2, last_seen: TODAY });
});
test("SC1d — promote: a dynamic fact reaching N=3 is promoted", () => {
const id = observedId("topic");
const cur = doc([], [fact({ id, value: "AI safety", evidence_count: 2 })]);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "topic", value: "AI safety" })], today: TODAY });
assert.equal(diff.evidenceBumps[0].newCount, 3);
assert.deepEqual(diff.promotions, [{ id }]);
});
test("SC1d — no promote below N", () => {
const id = observedId("topic");
const cur = doc([], [fact({ id, value: "x", evidence_count: 1 })]);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "topic", value: "x" })], today: TODAY });
assert.deepEqual(diff.promotions, []);
});
test("SC1e — conflict: different value keeps BOTH with DISTINCT ids, old fact untouched", () => {
const primaryId = observedId("role");
const cur = doc([], [fact({ id: primaryId, value: "advisor", evidence_count: 2 })]);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect" })], today: TODAY });
assert.equal(diff.conflicts.length, 1);
assert.equal(diff.conflicts[0].primaryId, primaryId);
assert.equal(diff.conflicts[0].primaryValue, "advisor");
assert.notEqual(diff.conflicts[0].altId, primaryId, "alt id must differ from primary id (no duplicate-id corruption)");
// the alt fact is added; the old fact is NOT bumped
assert.equal(diff.additions.length, 1);
assert.equal(diff.additions[0].value, "architect");
assert.equal(diff.additions[0].id, diff.conflicts[0].altId);
assert.deepEqual(diff.evidenceBumps, []);
});
test("SC1f — decay: a dynamic fact older than 90d is flagged; a static fact is decay-exempt", () => {
const old = "2026-03-01"; // ~114 days before TODAY
const dyn = fact({ id: observedId("stale-topic"), value: "old", last_seen: old });
const stat = fact({ id: observedId("settled"), value: "stable", last_seen: old });
const cur = doc([stat], [dyn]);
const diff = proposeDiff({ current: cur, candidates: [], today: TODAY });
assert.equal(diff.staleFlags.length, 1, "only the dynamic stale fact is flagged");
assert.equal(diff.staleFlags[0].id, dyn.id);
assert.ok(diff.staleFlags[0].daysStale > 90);
});
test("SC1f — a fresh dynamic fact is not flagged", () => {
const cur = doc([], [fact({ id: observedId("fresh"), last_seen: "2026-06-20" })]);
const diff = proposeDiff({ current: cur, candidates: [], today: TODAY });
assert.deepEqual(diff.staleFlags, []);
});
test("SC1g — folded immutable: a candidate overlapping a profile-field seed adds a new observed fact, seed untouched", () => {
const foldedId = mintEntityId({ kind: "profile-field", key: "role" });
const folded = fact({ id: foldedId, value: "advisor", provenance: "human" });
const cur = doc([folded], []);
const before = serializeProfile(cur);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect" })], today: TODAY });
// candidate keys to observed:role (≠ profile-field:role) → no match → ADD, no conflict on the folded seed
assert.equal(diff.additions.length, 1);
assert.equal(diff.additions[0].id, observedId("role"));
assert.equal(diff.conflicts.length, 0);
assert.equal(serializeProfile(cur), before, "input doc not mutated; folded seed untouched");
});
});
describe("proposeDiff purity + applyDiff round-trip (SC2, SC3, SC4)", () => {
test("SC2 — proposeDiff does not mutate its inputs", () => {
const cur = doc([], [fact({ id: observedId("topic"), value: "x" })]);
const candidates = [cand({ key: "topic", value: "x" }), cand({ key: "new", value: "y" })];
const snapCur = JSON.stringify(cur);
const snapCand = JSON.stringify(candidates);
proposeDiff({ current: cur, candidates, today: TODAY });
assert.equal(JSON.stringify(cur), snapCur, "current unchanged");
assert.equal(JSON.stringify(candidates), snapCand, "candidates unchanged");
});
test("SC3 — applyDiff(current, proposeDiff(...)) round-trips through parse/serialize", () => {
const cur = doc([fact({ id: mintEntityId({ kind: "profile-field", key: "name" }), value: "KTG", provenance: "human" })], [fact({ id: observedId("topic"), value: "AI safety", evidence_count: 2 })]);
const candidates = [
cand({ key: "topic", value: "AI safety" }), // bump→promote
cand({ key: "new-topic", value: "governance" }), // add
cand({ key: "topic", value: "alignment" }), // conflict on topic → alt
];
const diff = proposeDiff({ current: cur, candidates, today: TODAY });
const next = applyDiff(cur, diff);
const round = parseProfile(serializeProfile(next));
assert.deepEqual(round, next, "applied doc round-trips exactly");
// every fact id is unique (no duplicate-id corruption)
const ids = [...round.static, ...round.dynamic].map((f) => f.id);
assert.equal(new Set(ids).size, ids.length, "all fact ids unique");
});
test("SC4 — idempotent: re-running propose→apply with the same candidates adds no duplicate facts", () => {
const cur = doc([], []);
const candidates = [cand({ key: "topic", value: "AI safety" })];
const once = applyDiff(cur, proposeDiff({ current: cur, candidates, today: TODAY }));
const twice = applyDiff(once, proposeDiff({ current: once, candidates, today: TODAY }));
const factsOnce = [...once.static, ...once.dynamic].length;
const factsTwice = [...twice.static, ...twice.dynamic].length;
assert.equal(factsTwice, factsOnce, "no duplicate fact on re-run (bump only)");
});
});
describe("supersede arm (SB-S3b)", () => {
test("S3b-SC1 — routing: a supersede candidate retires the active prior, no keep-both", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2 })]);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect", supersedes: "role" })], today: TODAY });
assert.equal(diff.supersedes.length, 1, "one supersede op");
assert.equal(diff.conflicts.length, 0, "supersede routes away from keep-both");
assert.equal(diff.supersedes[0].oldId, id);
assert.equal(diff.supersedes[0].oldValue, "advisor");
assert.equal(diff.supersedes[0].winner.value, "architect");
assert.equal(diff.supersedes[0].winner.id, observedId("role"), "winner takes the canonical key-id");
assert.equal(diff.additions.length, 0, "winner is carried in the op, not additions");
});
test("S3b-SC2 — apply: retired fact superseded+re-minted, winner at key-id, both retained", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2, first_seen: "2026-01-01" })]);
const next = applyDiff(cur, proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect", supersedes: "role" })], today: TODAY }));
const all = [...next.static, ...next.dynamic];
const winner = all.find((f) => f.value === "architect")!;
const retired = all.find((f) => f.value === "advisor")!;
assert.ok(winner && retired, "both winner + retired present");
assert.equal(winner.id, id, "winner takes the canonical key-id");
assert.equal(winner.status, "active");
assert.equal(winner.evidence_count, 1, "winner re-earns evidence");
assert.equal(retired.status, "superseded");
assert.notEqual(retired.id, id, "retired fact re-minted off the key-id (archival)");
assert.equal(retired.first_seen, "2026-01-01", "retired fact keeps its OWN first_seen (audit)");
const ids = all.map((f) => f.id);
assert.equal(new Set(ids).size, ids.length, "no duplicate id");
});
test("S3b-SC3a — propose-idempotent: a re-sent supersede whose target already holds the new value bumps, no new supersession", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2 })]);
const once = applyDiff(cur, proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect", supersedes: "role" })], today: TODAY }));
// re-extract the same candidate (value now matches the winner) WITH the stale signal still set
const diff2 = proposeDiff({ current: once, candidates: [cand({ key: "role", value: "architect", supersedes: "role" })], today: TODAY });
assert.equal(diff2.supersedes.length, 0, "no self-supersede when the target already holds the value");
assert.equal(diff2.evidenceBumps.length, 1, "it bumps the winner instead");
});
test("S3b-SC3b — apply-idempotent: re-applying the same supersede diff is a no-op (value-matched skip)", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2 })]);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect", supersedes: "role" })], today: TODAY });
const once = applyDiff(cur, diff);
const twice = applyDiff(once, diff);
assert.deepEqual(twice, once, "re-applying the same supersede diff changes nothing");
});
test("S3b-SC4 — graceful no-target: a supersede signal with no active prior degrades to a plain add", () => {
const cur = doc([], []);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect", supersedes: "role" })], today: TODAY });
assert.equal(diff.supersedes.length, 0);
assert.equal(diff.additions.length, 1, "degrades to a plain add");
assert.equal(diff.additions[0].value, "architect");
assert.equal(diff.additions[0].id, observedId("role"));
});
test("S3b-SC5 — round-trip: a superseded fact produced by applyDiff parses/serializes identically", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2 })]);
const next = applyDiff(cur, proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect", supersedes: "role" })], today: TODAY }));
const round = parseProfile(serializeProfile(next));
assert.deepEqual(round, next, "superseded fact round-trips through the grammar");
const ids = [...round.static, ...round.dynamic].map((f) => f.id);
assert.equal(new Set(ids).size, ids.length, "all ids unique");
});
test("S3b-SC7 — no regression: a candidate WITHOUT the signal still keeps-both (no supersede)", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2 })]);
const diff = proposeDiff({ current: cur, candidates: [cand({ key: "role", value: "architect" })], today: TODAY });
assert.equal(diff.supersedes.length, 0);
assert.equal(diff.conflicts.length, 1, "keep-both unchanged when no signal");
});
test("S3b-SC8 — intra-batch: two supersede candidates for the same key resolve deterministically (first wins)", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2 })]);
const diff = proposeDiff({
current: cur,
candidates: [
cand({ key: "role", value: "architect", supersedes: "role" }),
cand({ key: "role", value: "principal", supersedes: "role" }),
],
today: TODAY,
});
assert.equal(diff.supersedes.length, 1, "only the first supersede for the key is taken");
assert.equal(diff.supersedes[0].winner.value, "architect");
const next = applyDiff(cur, diff);
const ids = [...next.static, ...next.dynamic].map((f) => f.id);
assert.equal(new Set(ids).size, ids.length, "no duplicate id after intra-batch supersede");
});
test("S3b-SC11 — decay excludes superseded: a retained superseded dynamic fact is not stale-flagged", () => {
const old = "2026-03-01"; // ~114 days before TODAY
const superseded = fact({ id: observedId("old-role"), value: "advisor", last_seen: old, status: "superseded" });
const active = fact({ id: observedId("topic"), value: "x", last_seen: old, status: "active" });
const cur = doc([], [superseded, active]);
const diff = proposeDiff({ current: cur, candidates: [], today: TODAY });
assert.equal(diff.staleFlags.length, 1, "only the active stale fact is flagged");
assert.equal(diff.staleFlags[0].id, active.id);
});
test("S3b-SC12 — supersede wins over a same-id bump in one diff", () => {
const id = observedId("role");
const cur = doc([], [fact({ id, value: "advisor", evidence_count: 2 })]);
const winner = fact({ id, value: "architect", evidence_count: 1, status: "active" });
const diff: ProfileDiff = {
additions: [],
promotions: [],
conflicts: [],
staleFlags: [],
evidenceBumps: [{ id, newCount: 3, last_seen: TODAY }], // a stale bump targeting the same id
supersedes: [{ oldId: id, oldValue: "advisor", winner }],
};
const next = applyDiff(cur, diff);
const all = [...next.static, ...next.dynamic];
const w = all.find((f) => f.value === "architect")!;
const r = all.find((f) => f.value === "advisor")!;
assert.equal(r.status, "superseded", "the old fact is superseded, not bumped");
assert.equal(w.evidence_count, 1, "winner unaffected by the stale bump");
});
});