@chipschat/conformance 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +34 -2
  3. package/dist/checks.d.ts +29 -0
  4. package/dist/checks.d.ts.map +1 -0
  5. package/dist/checks.js +133 -0
  6. package/dist/checks.js.map +1 -0
  7. package/dist/exchange.d.ts +30 -0
  8. package/dist/exchange.d.ts.map +1 -0
  9. package/dist/exchange.js +102 -0
  10. package/dist/exchange.js.map +1 -0
  11. package/dist/fake-chips.d.ts +130 -0
  12. package/dist/fake-chips.d.ts.map +1 -0
  13. package/dist/fake-chips.js +1642 -0
  14. package/dist/fake-chips.js.map +1 -0
  15. package/dist/fake-join.d.ts +56 -0
  16. package/dist/fake-join.d.ts.map +1 -0
  17. package/dist/fake-join.js +181 -0
  18. package/dist/fake-join.js.map +1 -0
  19. package/dist/index.d.ts +20 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +14 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/project.d.ts +39 -0
  24. package/dist/project.d.ts.map +1 -0
  25. package/dist/project.js +254 -0
  26. package/dist/project.js.map +1 -0
  27. package/dist/report.d.ts +65 -0
  28. package/dist/report.d.ts.map +1 -0
  29. package/dist/report.js +142 -0
  30. package/dist/report.js.map +1 -0
  31. package/dist/room-files.d.ts +54 -0
  32. package/dist/room-files.d.ts.map +1 -0
  33. package/dist/room-files.js +144 -0
  34. package/dist/room-files.js.map +1 -0
  35. package/dist/scenario.d.ts +41 -0
  36. package/dist/scenario.d.ts.map +1 -0
  37. package/dist/scenario.js +414 -0
  38. package/dist/scenario.js.map +1 -0
  39. package/dist/settings.d.ts +60 -0
  40. package/dist/settings.d.ts.map +1 -0
  41. package/dist/settings.js +142 -0
  42. package/dist/settings.js.map +1 -0
  43. package/dist/spend.d.ts +20 -0
  44. package/dist/spend.d.ts.map +1 -0
  45. package/dist/spend.js +50 -0
  46. package/dist/spend.js.map +1 -0
  47. package/dist/subject.d.ts +55 -0
  48. package/dist/subject.d.ts.map +1 -0
  49. package/dist/subject.js +22 -0
  50. package/dist/subject.js.map +1 -0
  51. package/dist/waiting.d.ts +12 -0
  52. package/dist/waiting.d.ts.map +1 -0
  53. package/dist/waiting.js +30 -0
  54. package/dist/waiting.js.map +1 -0
  55. package/dist/workspace.d.ts +893 -0
  56. package/dist/workspace.d.ts.map +1 -0
  57. package/dist/workspace.js +3160 -0
  58. package/dist/workspace.js.map +1 -0
  59. package/package.json +39 -3
@@ -0,0 +1,254 @@
1
+ /**
2
+ * A room's project in the fake (ADR 0220): one bare git repository per room, in a folder of the
3
+ * fake's own, served by git's `http-backend` as the server serves it, behind the harness's token
4
+ * and the agent it names in `chips-actor`. A push that moves `main` is recorded as
5
+ * `project.changed`, before git's answer ends, as the server records it.
6
+ *
7
+ * It keeps git's own refusals, no rewriting or deleting `main`, and pushes to a room are taken one
8
+ * at a time. It does not check each push for secrets, sizes or other branches, as the server's
9
+ * hook does: the SDK makes the same check before it commits (ADR 0221), and that is what a bridge
10
+ * is tested on. A machine with no git answers 503, in words, as the server does.
11
+ */
12
+ import { execFile, spawn } from "node:child_process";
13
+ import { existsSync, mkdtempSync, rmSync } from "node:fs";
14
+ import { tmpdir } from "node:os";
15
+ import { join } from "node:path";
16
+ import { PROJECT_ACTOR_HEADER, PROJECT_BRANCH, PROJECT_CHANGED_FILES } from "@chipschat/protocol";
17
+ /** git told what a room's project may take, through its environment, as the server tells it. */
18
+ const POLICY = [
19
+ ["receive.denyNonFastForwards", "true"],
20
+ ["receive.denyDeletes", "true"],
21
+ ["receive.fsckObjects", "true"],
22
+ ["http.receivepack", "true"],
23
+ ];
24
+ function environment() {
25
+ const env = {
26
+ PATH: "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin",
27
+ GIT_CONFIG_NOSYSTEM: "1",
28
+ GIT_CONFIG_GLOBAL: "/dev/null",
29
+ GIT_CONFIG_COUNT: String(POLICY.length),
30
+ };
31
+ POLICY.forEach(([key, value], at) => {
32
+ env[`GIT_CONFIG_KEY_${at}`] = key;
33
+ env[`GIT_CONFIG_VALUE_${at}`] = value;
34
+ });
35
+ return env;
36
+ }
37
+ function git(args, cwd) {
38
+ return new Promise((resolve, reject) => {
39
+ execFile("git", [...args], { cwd, env: environment(), encoding: "utf8" }, (error, stdout) => error === null ? resolve(stdout) : reject(error));
40
+ });
41
+ }
42
+ function words(response, status, message) {
43
+ response.writeHead(status, {
44
+ "content-type": "text/plain; charset=utf-8",
45
+ ...(status === 401 ? { "www-authenticate": 'Basic realm="Chips"' } : {}),
46
+ });
47
+ response.end(`${message}\n`);
48
+ }
49
+ /** A CGI answer's head, `Status:` and its headers to the empty line; nothing until that has come. */
50
+ function cgiHead(bytes) {
51
+ const end = bytes.indexOf("\r\n\r\n");
52
+ if (end < 0)
53
+ return undefined;
54
+ let status = 200;
55
+ const headers = {};
56
+ for (const line of bytes.subarray(0, end).toString("latin1").split("\r\n")) {
57
+ const colon = line.indexOf(":");
58
+ if (colon < 0)
59
+ continue;
60
+ const name = line.slice(0, colon).trim();
61
+ const value = line.slice(colon + 1).trim();
62
+ if (name.toLowerCase() === "status")
63
+ status = Number.parseInt(value, 10) || 500;
64
+ else
65
+ headers[name] = value;
66
+ }
67
+ return { status, headers, rest: bytes.subarray(end + 4) };
68
+ }
69
+ export class FakeProjects {
70
+ workspace;
71
+ root = mkdtempSync(join(tmpdir(), "chips-fake-projects-"));
72
+ /** The push going on in each room, which the next one waits for. */
73
+ pushing = new Map();
74
+ constructor(workspace) {
75
+ this.workspace = workspace;
76
+ }
77
+ /** One of git's requests to a room's project, from a harness whose token has been checked. */
78
+ async serve(request, response, asked) {
79
+ const admitted = this.admit(request, asked);
80
+ if (typeof admitted !== "string")
81
+ return words(response, admitted.status, admitted.message);
82
+ try {
83
+ await this.ensure(asked.spaceId);
84
+ }
85
+ catch {
86
+ return words(response, 503, "Projects are off on this server: git was not found on this machine.");
87
+ }
88
+ if (request.method === "POST" && asked.rest === "/git-receive-pack") {
89
+ return this.push(request, response, asked, admitted);
90
+ }
91
+ return this.backend(request, response, asked, admitted);
92
+ }
93
+ /** The agent a request is for, or the words it is refused with. */
94
+ admit(request, asked) {
95
+ const method = request.method ?? "GET";
96
+ const reads = method === "GET" && asked.rest === "/info/refs";
97
+ const posts = method === "POST" &&
98
+ (asked.rest === "/git-upload-pack" || asked.rest === "/git-receive-pack");
99
+ if (!reads && !posts) {
100
+ return {
101
+ status: 404,
102
+ message: "A space's project answers git's smart HTTP, and nothing else.",
103
+ };
104
+ }
105
+ const actor = request.headers[PROJECT_ACTOR_HEADER];
106
+ const agentId = typeof actor === "string" ? actor : undefined;
107
+ const refused = this.workspace.refuseOnProject(agentId, asked.spaceId);
108
+ if (refused !== undefined) {
109
+ return { status: refused.endsWith("with that id.") ? 404 : 403, message: refused };
110
+ }
111
+ return agentId ?? "";
112
+ }
113
+ /** A push, in the room's turn, recorded before git's answer ends when it moved `main`. */
114
+ async push(request, response, asked, agentId) {
115
+ const release = await this.turnIn(asked.spaceId);
116
+ try {
117
+ const before = await this.head(asked.spaceId);
118
+ await this.backend(request, response, asked, agentId, async () => {
119
+ const after = await this.head(asked.spaceId);
120
+ if (after === null || after === before)
121
+ return;
122
+ const change = await this.changes(asked.spaceId, before, after);
123
+ this.workspace.recordProjectChange(asked.spaceId, agentId, change);
124
+ });
125
+ }
126
+ finally {
127
+ release();
128
+ }
129
+ }
130
+ close() {
131
+ rmSync(this.root, { recursive: true, force: true });
132
+ }
133
+ directoryOf(spaceId) {
134
+ if (!/^spc_[0-9A-Z]{26}$/.test(spaceId))
135
+ throw new Error(`not a space: ${spaceId}`);
136
+ return join(this.root, `${spaceId}.git`);
137
+ }
138
+ async ensure(spaceId) {
139
+ const directory = this.directoryOf(spaceId);
140
+ if (existsSync(join(directory, "HEAD")))
141
+ return;
142
+ await git([
143
+ "init",
144
+ "--quiet",
145
+ "--bare",
146
+ "--template=",
147
+ `--initial-branch=${PROJECT_BRANCH}`,
148
+ directory,
149
+ ]);
150
+ }
151
+ async head(spaceId) {
152
+ try {
153
+ return ((await git(["rev-parse", "--verify", "--quiet", `refs/heads/${PROJECT_BRANCH}`], this.directoryOf(spaceId))).trim() || null);
154
+ }
155
+ catch {
156
+ return null;
157
+ }
158
+ }
159
+ async changes(spaceId, before, after) {
160
+ const directory = this.directoryOf(spaceId);
161
+ const from = before ?? (await git(["hash-object", "-t", "tree", "/dev/null"], directory)).trim();
162
+ const range = before === null ? [after] : [after, `^${before}`];
163
+ const count = await git(["rev-list", "--count", ...range], directory);
164
+ const subject = await git(["log", "-1", "--format=%s", after], directory);
165
+ const files = (await git(["diff", "--numstat", "-z", "--no-renames", from, after], directory))
166
+ .split("\0")
167
+ .filter((entry) => entry !== "")
168
+ .map((entry) => {
169
+ const [added = "-", removed = "-", ...path] = entry.split("\t");
170
+ return {
171
+ path: path.join("\t"),
172
+ added: added === "-" ? null : Number(added),
173
+ removed: removed === "-" ? null : Number(removed),
174
+ };
175
+ })
176
+ .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
177
+ return {
178
+ before,
179
+ after,
180
+ commits: Number(count.trim()),
181
+ message: subject.trim().slice(0, 300),
182
+ files: files.slice(0, PROJECT_CHANGED_FILES),
183
+ ...(files.length > PROJECT_CHANGED_FILES
184
+ ? { more_files: files.length - PROJECT_CHANGED_FILES }
185
+ : {}),
186
+ };
187
+ }
188
+ async turnIn(spaceId) {
189
+ const before = this.pushing.get(spaceId) ?? Promise.resolve();
190
+ let release = () => { };
191
+ const mine = new Promise((resolve) => {
192
+ release = resolve;
193
+ });
194
+ const chained = before.then(() => mine);
195
+ this.pushing.set(spaceId, chained);
196
+ await before;
197
+ return () => {
198
+ release();
199
+ if (this.pushing.get(spaceId) === chained)
200
+ this.pushing.delete(spaceId);
201
+ };
202
+ }
203
+ /** git's answer, streamed back; `after` runs once git is done, before the answer ends. */
204
+ backend(request, response, asked, who, after) {
205
+ return new Promise((resolve) => {
206
+ const child = spawn("git", ["http-backend"], {
207
+ env: {
208
+ ...environment(),
209
+ GIT_PROJECT_ROOT: this.root,
210
+ GIT_HTTP_EXPORT_ALL: "1",
211
+ REMOTE_USER: who,
212
+ REQUEST_METHOD: request.method ?? "GET",
213
+ PATH_INFO: `/${asked.spaceId}.git${asked.rest}`,
214
+ QUERY_STRING: asked.query,
215
+ CONTENT_TYPE: request.headers["content-type"] ?? "",
216
+ HTTP_CONTENT_ENCODING: request.headers["content-encoding"] ?? "",
217
+ GIT_PROTOCOL: String(request.headers["git-protocol"] ?? ""),
218
+ },
219
+ });
220
+ request.pipe(child.stdin);
221
+ child.stdin.on("error", () => child.kill());
222
+ let head = Buffer.alloc(0);
223
+ let answered = false;
224
+ const held = [];
225
+ child.stdout.on("data", (chunk) => {
226
+ if (answered) {
227
+ held.push(chunk);
228
+ return;
229
+ }
230
+ head = Buffer.concat([head, chunk]);
231
+ const parsed = cgiHead(head);
232
+ if (parsed === undefined)
233
+ return;
234
+ answered = true;
235
+ response.writeHead(parsed.status, parsed.headers);
236
+ held.push(parsed.rest);
237
+ });
238
+ child.on("close", () => {
239
+ void (async () => {
240
+ if (!answered) {
241
+ words(response, 500, "git could not answer for this project.");
242
+ resolve();
243
+ return;
244
+ }
245
+ // Written once git is done, the record first: what the answer says has been recorded.
246
+ await after?.().catch(() => undefined);
247
+ response.end(Buffer.concat(held));
248
+ resolve();
249
+ })();
250
+ });
251
+ });
252
+ }
253
+ }
254
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The report: the connection checklist the app shows, lit by what the harness sent, and the
3
+ * notes underneath it. The rows are the protocol's own list, so `chips conformance` and the
4
+ * Harnesses tab cannot disagree about what an adapter has earned.
5
+ *
6
+ * Passing means the rows the plan's M2.5 names — and the two a run cannot do without. Messages,
7
+ * Runs, Steps, Approvals, Cost and Finished must be lit, and nothing the harness sent may have
8
+ * been refused. Questions and Context are reported and not required: a harness with no
9
+ * questions to ask and no window size to report is complete without them.
10
+ */
11
+ export interface RowResult {
12
+ readonly label: string;
13
+ readonly types: readonly string[];
14
+ readonly gives: string;
15
+ readonly lit: boolean;
16
+ /** How many events of the row's types the harness sent. */
17
+ readonly count: number;
18
+ readonly required: boolean;
19
+ }
20
+ export type Severity = "error" | "warn" | "note";
21
+ export interface Finding {
22
+ readonly severity: Severity;
23
+ readonly message: string;
24
+ }
25
+ /** What became of a capability the harness declared: its check passed or failed, or none sees it. */
26
+ export type Outcome = "passed" | "failed" | "declared";
27
+ export interface CapabilityResult {
28
+ readonly capability: string;
29
+ readonly outcome: Outcome;
30
+ }
31
+ /**
32
+ * How far the harness got, by the plan's four levels (open-source harnesses plan, §2): it talks,
33
+ * it is supervised, it lives in Chips, it is managed from Chips. The first two are rows of the
34
+ * checklist; the last two count the capabilities whose checks passed, or that no check can see.
35
+ */
36
+ export interface LevelResult {
37
+ readonly label: string;
38
+ readonly has: number;
39
+ readonly of: number;
40
+ /** For the two levels made of capabilities: each one the harness declared, and how it did. */
41
+ readonly capabilities?: readonly CapabilityResult[];
42
+ }
43
+ export interface Report {
44
+ readonly adapter: string;
45
+ readonly rows: readonly RowResult[];
46
+ readonly levels: readonly LevelResult[];
47
+ readonly findings: readonly Finding[];
48
+ /** How many events the harness sent that the log took. */
49
+ readonly events: number;
50
+ readonly durationMs: number;
51
+ readonly passed: boolean;
52
+ }
53
+ export declare const REQUIRED_ROWS: ReadonlySet<string>;
54
+ /** The rows, lit by the types the harness sent. */
55
+ export declare function rowsOf(sent: readonly string[]): RowResult[];
56
+ /** The capabilities each of the upper two levels is made of, in the order the report says them. */
57
+ export declare const LEVEL_CAPABILITIES: Readonly<Record<string, readonly string[]>>;
58
+ /** The four levels, from the rows lit and what became of each capability declared. */
59
+ export declare function levelsOf(rows: readonly RowResult[], outcomes: ReadonlyMap<string, Outcome>): LevelResult[];
60
+ export declare function passes(rows: readonly RowResult[], findings: readonly Finding[]): boolean;
61
+ /** The reference page for an event type: the one an unlit row in the app links to. */
62
+ export declare function docsFor(type: string): string;
63
+ /** The report as lines, ready for a console. */
64
+ export declare function formatReport(report: Report): string[];
65
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,qGAAqG;AACrG,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,CAO5C,CAAC;AAEH,mDAAmD;AACnD,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,CAY3D;AAED,mGAAmG;AACnG,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAiB1E,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,QAAQ,CACtB,IAAI,EAAE,SAAS,SAAS,EAAE,EAC1B,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GACrC,WAAW,EAAE,CAcf;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAKxF;AAED,sFAAsF;AACtF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AA+CD,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBrD"}
package/dist/report.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The report: the connection checklist the app shows, lit by what the harness sent, and the
3
+ * notes underneath it. The rows are the protocol's own list, so `chips conformance` and the
4
+ * Harnesses tab cannot disagree about what an adapter has earned.
5
+ *
6
+ * Passing means the rows the plan's M2.5 names — and the two a run cannot do without. Messages,
7
+ * Runs, Steps, Approvals, Cost and Finished must be lit, and nothing the harness sent may have
8
+ * been refused. Questions and Context are reported and not required: a harness with no
9
+ * questions to ask and no window size to report is complete without them.
10
+ */
11
+ import { CONNECTION_CHECKLIST, HARNESS_CAPABILITIES } from "@chipschat/protocol";
12
+ export const REQUIRED_ROWS = new Set([
13
+ "Messages",
14
+ "Runs",
15
+ "Steps",
16
+ "Approvals",
17
+ "Cost",
18
+ "Finished",
19
+ ]);
20
+ /** The rows, lit by the types the harness sent. */
21
+ export function rowsOf(sent) {
22
+ return CONNECTION_CHECKLIST.map((row) => {
23
+ const count = sent.filter((type) => row.types.includes(type)).length;
24
+ return {
25
+ label: row.label,
26
+ types: row.types,
27
+ gives: row.gives,
28
+ lit: count > 0,
29
+ count,
30
+ required: REQUIRED_ROWS.has(row.label),
31
+ };
32
+ });
33
+ }
34
+ /** The capabilities each of the upper two levels is made of, in the order the report says them. */
35
+ export const LEVEL_CAPABILITIES = {
36
+ "Lives in Chips": [
37
+ HARNESS_CAPABILITIES.agents,
38
+ HARNESS_CAPABILITIES.newSpaces,
39
+ HARNESS_CAPABILITIES.forks,
40
+ HARNESS_CAPABILITIES.newAgents,
41
+ HARNESS_CAPABILITIES.followsRooms,
42
+ HARNESS_CAPABILITIES.restarts,
43
+ ],
44
+ "Managed from Chips": [
45
+ HARNESS_CAPABILITIES.contextFiles,
46
+ HARNESS_CAPABILITIES.models,
47
+ HARNESS_CAPABILITIES.heartbeats,
48
+ HARNESS_CAPABILITIES.contextWindows,
49
+ HARNESS_CAPABILITIES.jobs,
50
+ HARNESS_CAPABILITIES.autonomy,
51
+ ],
52
+ };
53
+ /** The four levels, from the rows lit and what became of each capability declared. */
54
+ export function levelsOf(rows, outcomes) {
55
+ const lit = (label) => rows.some((row) => row.label === label && row.lit);
56
+ const supervised = rows.every((row) => row.lit || !row.required);
57
+ return [
58
+ { label: "Talks", has: lit("Messages") ? 1 : 0, of: 1 },
59
+ { label: "Supervised", has: supervised ? 1 : 0, of: 1 },
60
+ ...Object.entries(LEVEL_CAPABILITIES).map(([label, all]) => {
61
+ const capabilities = all
62
+ .filter((capability) => outcomes.has(capability))
63
+ .map((capability) => ({ capability, outcome: outcomes.get(capability) ?? "failed" }));
64
+ const has = capabilities.filter((each) => each.outcome !== "failed").length;
65
+ return { label, has, of: all.length, capabilities };
66
+ }),
67
+ ];
68
+ }
69
+ export function passes(rows, findings) {
70
+ return (rows.every((row) => row.lit || !row.required) &&
71
+ findings.every((finding) => finding.severity !== "error"));
72
+ }
73
+ /** The reference page for an event type: the one an unlit row in the app links to. */
74
+ export function docsFor(type) {
75
+ return `https://chipschat.ai/reference/events/${type.replace(/\./g, "-")}/`;
76
+ }
77
+ const MARK = { error: "x", warn: "!", note: "·" };
78
+ /** One row, as the app draws it: a mark, the label, and what was sent or what to send. */
79
+ function rowLine(row, width) {
80
+ const mark = row.lit ? "●" : "○";
81
+ const first = row.types[0] ?? "";
82
+ const times = row.count > 1 ? ` ×${row.count}` : "";
83
+ const detail = row.lit ? `sent ${first}${times}` : `send ${first} for ${row.gives}`;
84
+ return ` ${mark} ${row.label.padEnd(width)} ${detail}`;
85
+ }
86
+ /** What is missing, in a sentence. */
87
+ function verdict(report) {
88
+ if (report.passed)
89
+ return " Passed. Every required row is lit and nothing was refused.";
90
+ const dark = report.rows.filter((row) => row.required && !row.lit).map((row) => row.label);
91
+ const errors = report.findings.filter((finding) => finding.severity === "error").length;
92
+ const parts = [
93
+ ...(dark.length === 0 ? [] : [`${listOf(dark)} ${dark.length === 1 ? "is" : "are"} not lit`]),
94
+ ...(errors === 0 ? [] : [`${errors} thing${errors === 1 ? "" : "s"} to fix below`]),
95
+ ];
96
+ return ` Not passed: ${parts.join("; ")}.`;
97
+ }
98
+ function listOf(words) {
99
+ if (words.length <= 1)
100
+ return words.join("");
101
+ return `${words.slice(0, -1).join(", ")} and ${words.at(-1)}`;
102
+ }
103
+ const MARKS = {
104
+ passed: "✓",
105
+ failed: "✗",
106
+ declared: "· not checked",
107
+ };
108
+ /** A level as one line: lit or not for the first two, a count and each capability for the rest. */
109
+ function levelLine(level, width) {
110
+ if (level.capabilities === undefined)
111
+ return ` ${level.has === 1 ? "●" : "○"} ${level.label}`;
112
+ const label = level.label.padEnd(width);
113
+ const each = level.capabilities
114
+ .map(({ capability, outcome }) => `${capability.replace(/_/g, " ")} ${MARKS[outcome]}`)
115
+ .join(", ");
116
+ const mark = level.has === level.of ? "●" : level.has > 0 ? "◐" : "○";
117
+ return ` ${mark} ${label} ${level.has} of ${level.of}${each === "" ? "" : `: ${each}`}`;
118
+ }
119
+ /** The report as lines, ready for a console. */
120
+ export function formatReport(report) {
121
+ const width = Math.max(...report.rows.map((row) => row.label.length));
122
+ const lines = report.rows.map((row) => rowLine(row, width));
123
+ const levelWidth = Math.max(...report.levels.map((level) => level.label.length));
124
+ lines.push("", ...report.levels.map((level) => levelLine(level, levelWidth)));
125
+ lines.push("");
126
+ lines.push(` ${report.events} event${report.events === 1 ? "" : "s"} in ${(report.durationMs / 1000).toFixed(1)} s`);
127
+ if (report.findings.length > 0) {
128
+ lines.push("", " Notes");
129
+ for (const finding of report.findings) {
130
+ lines.push(` ${MARK[finding.severity]} ${finding.message}`);
131
+ }
132
+ }
133
+ const unlit = report.rows.filter((row) => !row.lit);
134
+ if (unlit.length > 0) {
135
+ lines.push("", " Each unlit row links to the page that lights it:");
136
+ for (const row of unlit)
137
+ lines.push(` ${row.label.padEnd(width)} ${docsFor(row.types[0] ?? "")}`);
138
+ }
139
+ lines.push("", verdict(report));
140
+ return lines;
141
+ }
142
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The room's files (ADR 0099), as the fake plays them: the real server's reads and door over the
3
+ * fake's log rather than its projections. The files posted in a room, in order, none from a message
4
+ * taken back; what each file of a post was made from, copied onto it from the post's `replaces`;
5
+ * and the refusal of one made from a version no longer current. Which file is which version, and
6
+ * the refusal's words, are the protocol's, so the two cannot differ.
7
+ */
8
+ import { type PostedFile, type RoomFile, type StaleRefusal } from "@chipschat/protocol";
9
+ /** An event as the fake's log holds it, as far as these reads need it (the workspace's own). */
10
+ interface StoredEvent {
11
+ readonly seq: number;
12
+ readonly id: string;
13
+ readonly type: string;
14
+ readonly ts: string;
15
+ readonly space_id: string | null;
16
+ readonly actor: {
17
+ readonly kind: string;
18
+ readonly id: string;
19
+ };
20
+ readonly payload: Readonly<Record<string, unknown>>;
21
+ }
22
+ /** The files posted in a room, oldest first, up to the event at `upto` and with it. */
23
+ export declare function postedFilesInLog(log: readonly StoredEvent[], spaceId: string, upto?: number): PostedFile[];
24
+ /** How a room's files are read out: for whom, how many, and who each was posted by now. */
25
+ interface Reading {
26
+ readonly spaceId: string;
27
+ readonly most: number;
28
+ /** Who a participant is now, as a line's `from` says it. */
29
+ readonly by: (participantId: string) => RoomFile["by"];
30
+ readonly sign?: ((attachmentId: string) => {
31
+ url: string;
32
+ url_expires_at: string;
33
+ }) | undefined;
34
+ }
35
+ /** A room's files at their current version, newest first, as the real server hands them over. */
36
+ export declare function roomFilesInLog(log: readonly StoredEvent[], room: Reading & {
37
+ readonly upto?: number | undefined;
38
+ }): RoomFile[];
39
+ /** One name's versions, newest first, each with what it was made from (ADR 0100). */
40
+ export declare function fileVersionsInLog(log: readonly StoredEvent[], room: Reading & {
41
+ readonly name: string;
42
+ }): RoomFile[];
43
+ /**
44
+ * The real door's `fillMadeFrom` and the store's `fileGate`, at once, since the fake has one writer
45
+ * and nothing between them: each file's `replaces` copied onto it when it names a version of that
46
+ * file in this room, the map not kept; a key that is none of the post's files refused; a file made
47
+ * from a version no longer current refused `stale_file`.
48
+ */
49
+ export declare function madeFromInLog(log: readonly StoredEvent[], event: Record<string, unknown>, nameOf: (participantId: string) => string): {
50
+ kind: "invalid";
51
+ message: string;
52
+ } | StaleRefusal | undefined;
53
+ export {};
54
+ //# sourceMappingURL=room-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-files.d.ts","sourceRoot":"","sources":["../src/room-files.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,YAAY,EAKlB,MAAM,qBAAqB,CAAC;AAE7B,gGAAgG;AAChG,UAAU,WAAW;IACnB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACrD;AAYD,uFAAuF;AACvF,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,SAAS,WAAW,EAAE,EAC3B,OAAO,EAAE,MAAM,EACf,IAAI,SAA2B,GAC9B,UAAU,EAAE,CAuBd;AAcD,2FAA2F;AAC3F,UAAU,OAAO;IACf,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,YAAY,EAAE,MAAM,KAAK;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CAAC;CACjG;AAsBD,iGAAiG;AACjG,wBAAgB,cAAc,CAC5B,GAAG,EAAE,SAAS,WAAW,EAAE,EAC3B,IAAI,EAAE,OAAO,GAAG;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACrD,QAAQ,EAAE,CAGZ;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,WAAW,EAAE,EAC3B,IAAI,EAAE,OAAO,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxC,QAAQ,EAAE,CAaZ;AAkBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,SAAS,WAAW,EAAE,EAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GACxC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,GAAG,SAAS,CAkCjE"}