omkit 0.1.7 → 0.1.8

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.
@@ -70,7 +70,13 @@ export declare class ExecutionTree {
70
70
  private drive;
71
71
  private finalize;
72
72
  private finalizeOnce;
73
- /** The end-of-run links + assert summary, to the terminal (files are already written). */
73
+ /**
74
+ * The end-of-run recap: the run folder, sibling log paths, and the assert tally.
75
+ * Shared verbatim between the terminal (via {@link printSummary}) and the tail of
76
+ * `main.log` (as the footer passed to `writeNodeLogs`), so both close the same way.
77
+ */
78
+ private summaryLines;
79
+ /** The recap to the terminal (files are already written). */
74
80
  private printSummary;
75
81
  private verdictOk;
76
82
  private nodeView;
@@ -243,7 +243,8 @@ export class ExecutionTree {
243
243
  const entries = this.store.entries();
244
244
  const at = (name) => path.join(this.folder.path(), name);
245
245
  const assertSummary = `⊨ ${this.assertionsPassed} passed · ⊭ ${this.assertionsFailed} failed`;
246
- await writeNodeLogs(flat, entries);
246
+ const summary = this.summaryLines(at, assertSummary);
247
+ await writeNodeLogs(flat, entries, summary);
247
248
  await writeRollup(at("events.log"), flat, entries, (e) => e.level === "event");
248
249
  await writeRollup(at("asserts.log"), flat, entries, (e) => e.level === "assert", assertSummary);
249
250
  await writeRollup(at("snapshots.log"), flat, entries, (e) => e.level === "snapshot");
@@ -255,19 +256,30 @@ export class ExecutionTree {
255
256
  process.off("unhandledRejection", this.onUnhandled);
256
257
  this.consoleCapture.uninstall();
257
258
  ExecutionTree.current = null;
258
- this.printSummary(at, assertSummary);
259
+ this.printSummary(summary);
259
260
  if (!this.verdictOk())
260
261
  process.exitCode = 1;
261
262
  }
262
- /** The end-of-run links + assert summary, to the terminal (files are already written). */
263
- printSummary(at, assertSummary) {
263
+ /**
264
+ * The end-of-run recap: the run folder, sibling log paths, and the assert tally.
265
+ * Shared verbatim between the terminal (via {@link printSummary}) and the tail of
266
+ * `main.log` (as the footer passed to `writeNodeLogs`), so both close the same way.
267
+ */
268
+ summaryLines(at, assertSummary) {
269
+ return [
270
+ `om → ${this.folder.path()}`,
271
+ ` main log → ${at("main.log")}`,
272
+ ` events → ${at("events.log")}`,
273
+ ` asserts → ${at("asserts.log")} ${assertSummary}`,
274
+ ` snapshots → ${at("snapshots.log")}`,
275
+ ];
276
+ }
277
+ /** The recap to the terminal (files are already written). */
278
+ printSummary(lines) {
264
279
  const term = this.originalLog;
265
280
  term("");
266
- term(`om → ${this.folder.path()}`);
267
- term(` main log → ${at("main.log")}`);
268
- term(` events → ${at("events.log")}`);
269
- term(` asserts → ${at("asserts.log")} ${assertSummary}`);
270
- term(` snapshots → ${at("snapshots.log")}`);
281
+ for (const line of lines)
282
+ term(line);
271
283
  }
272
284
  verdictOk() {
273
285
  return this.faults.length === 0;
@@ -3,6 +3,8 @@ import type { NodeView } from "./views.ts";
3
3
  /**
4
4
  * Writes each node's own human `.log`: a one-time `ActionRef` header, then that
5
5
  * node's entries (by `nodeId`) prefixed `[seq iso-ts path]`. Rows never repeat
6
- * name/tags — the header carries them.
6
+ * name/tags — the header carries them. The optional `footer` (the run's end-of-run
7
+ * recap — assert tally + sibling log paths) is appended to the **root** log only,
8
+ * so `main.log` closes with the same snippet shown live on the terminal.
7
9
  */
8
- export declare function writeNodeLogs(nodes: readonly NodeView[], entries: readonly LogEntry[]): Promise<void>;
10
+ export declare function writeNodeLogs(nodes: readonly NodeView[], entries: readonly LogEntry[], footer?: readonly string[]): Promise<void>;
@@ -5,19 +5,24 @@ import { entryLine, groupByNode } from "./entryLine.js";
5
5
  /**
6
6
  * Writes each node's own human `.log`: a one-time `ActionRef` header, then that
7
7
  * node's entries (by `nodeId`) prefixed `[seq iso-ts path]`. Rows never repeat
8
- * name/tags — the header carries them.
8
+ * name/tags — the header carries them. The optional `footer` (the run's end-of-run
9
+ * recap — assert tally + sibling log paths) is appended to the **root** log only,
10
+ * so `main.log` closes with the same snippet shown live on the terminal.
9
11
  */
10
- export async function writeNodeLogs(nodes, entries) {
12
+ export async function writeNodeLogs(nodes, entries, footer = []) {
11
13
  const byNode = groupByNode(entries, () => true);
12
14
  const refByNode = new Map(nodes.map((n) => [n.id, n]));
13
15
  const refOf = (id) => refByNode.get(id);
14
16
  await Promise.all(nodes.map(async (node) => {
15
17
  const lines = (byNode.get(node.id) ?? []).map((e) => entryLine(e, refOf));
16
- const body = [...header(node), "", ...lines, ""].join("\n");
18
+ const foot = node.parentId === null && footer.length ? ["", summaryRule, ...footer] : [];
19
+ const body = [...header(node), "", ...lines, ...foot, ""].join("\n");
17
20
  await mkdir(path.dirname(node.logFile), { recursive: true });
18
21
  await writeFile(node.logFile, body, "utf8");
19
22
  }));
20
23
  }
24
+ /** The divider that opens the root log's end-of-run recap (mirrors the header's `── legend ──`). */
25
+ const summaryRule = "── summary ──────────────────────────────────────────────────────────";
21
26
  /** The per-file metadata header: ref, defining script, args, start/finish times, status. */
22
27
  const header = (node) => [
23
28
  `# ${renderRef(node)}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omkit",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A tiny runtime for developer workflows: typed actions that pass runtime capabilities and emit typed events, under one run and one shared log. The operational/runtime layer to tskb's knowledge layer.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",