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:
+25
-9
@@ -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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user