G V-8 (TS), A-17, test: the TypeScript writer is generic over the contract's bodies and names its events; findings-asked is mesh-conditions' event

The TypeScript writer holds no FindingBody of its own and works on the wire form (checkFinding, views reader findings laid out by
viewFindingBody); both writers name findings-asked as the seat mesh-conditions' event. The view-waits test waits on the raise,
not on a count of yields.

Builds: design 47 G §686, §640, §687, A-3, A-13, A-17
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 21:45:07 +01:00
parent 43960cc925
commit 58bbc26219
6 changed files with 165 additions and 130 deletions
+25 -9
View File
@@ -861,7 +861,7 @@ test("the finding writer writes, clears and states findings as the Go writer doe
const w = new Writer({
module: "m",
state: st,
subjects: { written: "w", cleared: "c", stated: "s", asked: "a" },
observe: async () => {
if (++observes <= 2) throw new Error("not yet");
return { findings: [{ kind: "k", scope: "module", id: "a", severity: "warning", summary: "now", source: "p", subject: { scope: "module", id: "a" } }], pending: [{ key: "module.wait.k", since: "2026-11-11T11:00:00Z", bound: "5m" }] };
@@ -870,7 +870,7 @@ test("the finding writer writes, clears and states findings as the Go writer doe
if (refuse > 0) { refuse--; throw new Error("no ack"); }
sent.push({ subject, body });
},
listen: async (_s, h) => { consumers++; ask = h; return () => {}; },
listen: async (s, h) => { assert.equal(s, "mesh-conditions.findings-asked"); consumers++; ask = h; return () => {}; },
log: (l) => logs.push(l),
now: () => new Date(clock),
wait: async (ms) => { waits.push(ms); clock += ms; return true; },
@@ -881,11 +881,11 @@ test("the finding writer writes, clears and states findings as the Go writer doe
clock += 3600_000;
await w.write({ ...f, run: "other" }); // nothing it says changed
await w.write({ ...f, summary: "two" });
assert.deepEqual(sent.map((s) => s.subject), ["w", "w"]);
assert.deepEqual(sent.map((s) => s.subject), ["finding-written", "finding-written"]);
assert.equal(sent[1].body.since, first);
assert.equal(sent[1].body.observer, "m");
await w.clear("module", "never", "k", "held by the keeper");
assert.equal(sent[2].subject, "c");
assert.equal(sent[2].subject, "finding-cleared");
assert.equal(sent[2].body.why, "held by the keeper");
// an unacknowledged event is sent again for a minute, then logged naming the finding
refuse = 1000;
@@ -900,7 +900,7 @@ test("the finding writer writes, clears and states findings as the Go writer doe
await w.start();
for (let i = 0; i < 50 && sent.length < 4; i++) await new Promise((r) => setImmediate(r));
const stated = sent[3];
assert.equal(stated.subject, "s");
assert.equal(stated.subject, "findings-stated");
assert.deepEqual(waits.slice(0, 2), [OBSERVE_RETRY_MS, OBSERVE_RETRY_MS]);
assert.equal(stated.body.findings.length, 1);
assert.equal(stated.body.findings[0].since, first);
@@ -921,7 +921,7 @@ test("the finding writer writes, clears and states findings as the Go writer doe
let release!: () => void;
const gate = new Promise<void>((r) => (release = r));
const w2 = new Writer({
module: "m", state: st, subjects: { written: "w", cleared: "c", stated: "s", asked: "a" },
module: "m", state: st,
observe: async () => { await gate; return { findings: [], pending: [] }; },
publish: async () => {}, listen: async () => () => {},
});
@@ -935,7 +935,7 @@ test("the finding writer writes, clears and states findings as the Go writer doe
});
test("the finding writer owns its kinds, keeps a views reader's findings in its statement and refuses an owner of no form", async () => {
const { Writer, VIEW_KINDS } = await import("../dist/views/index.js");
const { Writer, VIEW_KINDS, checkFinding, escapeName, viewFindingBody, writerFindings, viewWaitsFinding } = await import("../dist/views/index.js");
const store = new Map<string, any>();
const st: any = {
get: async (k: string) => (store.has(k) ? { key: k, value: store.get(k), revision: 1 } : null),
@@ -945,7 +945,7 @@ test("the finding writer owns its kinds, keeps a views reader's findings in its
};
const sent: { subject: string; body: any }[] = [];
const w = new Writer({
module: "m", state: st, kinds: ["k"], subjects: { written: "w", cleared: "c", stated: "s", asked: "a" },
module: "m", state: st, kinds: ["k"],
observe: async () => ({ findings: [], pending: [] }),
publish: async (subject, body) => void sent.push({ subject, body }),
listen: async () => () => {},
@@ -954,6 +954,10 @@ test("the finding writer owns its kinds, keeps a views reader's findings in its
await assert.rejects(w.write({ ...f, kind: "other" }), /"other"/);
await assert.rejects(w.clear("module", "a", "other", "why"), /"other"/);
await assert.rejects(w.write({ ...f, owner: "Not A Form" }), /owner/);
// a body whose wire form lacks a field the contract names fails at its first write, naming it (design 47 G A-3)
const { subject: _s, ...noSubject } = f;
await assert.rejects(w.write(noSubject as any), /subject/);
assert.throws(() => checkFinding({ ...f, kind: "a.b" }), /dot/);
await assert.rejects(w.write({ ...f, "waiting-on": "x y" }), /waiting-on/);
await w.write({ ...f, owner: "me@node-1" });
await w.write({ ...f, kind: VIEW_KINDS[0], id: "m.o.s" });
@@ -961,7 +965,19 @@ test("the finding writer owns its kinds, keeps a views reader's findings in its
await w.state();
assert.deepEqual([...store.keys()].sort(), ["module.m.o.s.view-waits", "module.x.other"].sort());
const stated = sent.at(-1)!;
assert.equal(stated.subject, "s");
assert.equal(stated.subject, "findings-stated");
assert.ok(stated.body.kinds.includes("k") && stated.body.kinds.includes("view-waits"));
assert.equal(stated.body.findings.length, 1);
// a views reader's findings are laid out by the writer from the part's plain ones (design 47 G §687)
assert.equal(escapeName("a b.c"), "a=20b=2ec");
const vf = viewWaitsFinding("m", { owner: "o", state: "s", "waiting-since": "2026-11-11T12:00:00Z", "waits-for": "r7", view: "" } as any, new Date("2026-11-11T12:06:00Z"));
const laid = viewFindingBody(vf, "m", "n1");
assert.deepEqual([laid.kind, laid.scope, laid.id, laid.severity, laid.source], ["view-waits", "module", "m=2eo=2es", "warning", "views"]);
assert.deepEqual(laid.subject, { scope: "module", id: "m", machine: "n1" });
assert.equal(viewFindingBody({ ...vf, kind: "view-too-large" }, "m", "n1").severity, "urgent");
const vw = writerFindings(w, "m", "n1");
await vw.put(vf);
assert.equal(store.has("module.m=2eo=2es.view-waits"), true);
await vw.delete(vf);
assert.equal(store.has("module.m=2eo=2es.view-waits"), false);
});