feat(linkedin-studio): SB-S3c — cross-silo id-threading + post→analytics assembler [skip-docs]
Hub-side design: the published record now carries the specifics/trends ids it was built from (additive, omit-empty → byte-backward-compatible), and a new pure assembler (scripts/brain/src/assemble.ts + `brain assemble`) joins post↔analytics by normalized title-prefix + date with honest confidence tiers (high/low/none). Answers the arc's north-star query: which raw material actually performs? (specific → post → measured analytics). All four tributaries untouched (analytics READ-only via inlined raw-JSON, no package import); profile.md grammar untouched (the fact→post link stays OUT — C-1). The repeatable --specific/--trend ingest flags collect via a new collectRepeated helper, leaving parseFlags untouched. TDD: 19 new brain tests (ingest 4 + publish 3 + assemble 8 + cli 4), all SC1–SC12. brain 113/113, gate 95/0/0, BRAIN_TESTS_FLOOR 94→113, ASSERT_BASELINE_FLOOR unchanged at 80. Light-Voyage hardened (brief-review 5 FIX · plan-critic 1 BLOCK+4 MAJOR+4 MINOR · scope-guardian ALIGNED). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RigJBiRFNtFZKCz21qNbQ4
This commit is contained in:
parent
016d823f3b
commit
edd3e15ef7
12 changed files with 515 additions and 14 deletions
|
|
@ -77,7 +77,7 @@ describe("ingest IO — writePublished / ingestText / scanInbox / listPublished
|
|||
mkdirSync(publishedDir(root), { recursive: true });
|
||||
const squatter: PublishedRecord = {
|
||||
id, provenance: "published", published_date: CAPTURED, captured_at: CAPTURED,
|
||||
source: "manual", body: "a DIFFERENT body that happens to share the id",
|
||||
source: "manual", specifics: [], trends: [], body: "a DIFFERENT body that happens to share the id",
|
||||
};
|
||||
writeFileSync(join(publishedDir(root), `${id}.md`), serializePublishedRecord(squatter), "utf8");
|
||||
|
||||
|
|
@ -125,4 +125,34 @@ describe("ingest IO — writePublished / ingestText / scanInbox / listPublished
|
|||
assert.equal(res.records[0].provenance, "published");
|
||||
assert.equal(res.skipped, 1, "the malformed file counted as skipped, not a crash");
|
||||
});
|
||||
|
||||
// SC4 — ingestText threads specifics/trends onto the written record; absent → [].
|
||||
test("SC4: ingestText threads specifics/trends; round-trips off disk", () => {
|
||||
const spec = "aaaaaaaaaaaa";
|
||||
const trend = "bbbbbbbbbbbb";
|
||||
const res = ingestText({ body: "tagged post body", captured_at: CAPTURED, specifics: [spec], trends: [trend] });
|
||||
assert.deepEqual(res.record.specifics, [spec]);
|
||||
assert.deepEqual(res.record.trends, [trend]);
|
||||
const onDisk = parsePublishedRecord(readFileSync(res.path, "utf8"));
|
||||
assert.deepEqual(onDisk.specifics, [spec]);
|
||||
assert.deepEqual(onDisk.trends, [trend]);
|
||||
});
|
||||
|
||||
test("SC4: ingestText with no specifics/trends keeps them empty (regression)", () => {
|
||||
const res = ingestText({ body: "plain post", captured_at: CAPTURED });
|
||||
assert.deepEqual(res.record.specifics, []);
|
||||
assert.deepEqual(res.record.trends, []);
|
||||
});
|
||||
|
||||
// SC3 (producer side) — a malformed id thrown fast at the producer boundary.
|
||||
test("SC3: ingestText with a non-12-hex specifics id throws at the producer", () => {
|
||||
assert.throws(
|
||||
() => ingestText({ body: "x", captured_at: CAPTURED, specifics: ["NOTAHEX"] }),
|
||||
/bad specifics id/i,
|
||||
);
|
||||
assert.throws(
|
||||
() => ingestText({ body: "y", captured_at: CAPTURED, trends: ["zzz"] }),
|
||||
/bad trends id/i,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue