loom-spec 0.4.0 → 0.5.0
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.
- package/dist/cli/exportHtml.d.ts +1 -4
- package/dist/cli/exportHtml.js +2 -21
- package/dist/cli/exportHtml.js.map +1 -1
- package/dist/cli/index.js +10 -46
- package/dist/cli/index.js.map +1 -1
- package/dist/mcp/server.js +3 -207
- package/dist/mcp/server.js.map +1 -1
- package/dist/server/app.js +2 -50
- package/dist/server/app.js.map +1 -1
- package/dist/server/exportConfig.d.ts +0 -2
- package/dist/server/exportConfig.js +0 -10
- package/dist/server/exportConfig.js.map +1 -1
- package/dist/server/exportFilter.d.ts +0 -7
- package/dist/server/exportFilter.js +2 -36
- package/dist/server/exportFilter.js.map +1 -1
- package/dist/server/fileOps.d.ts +0 -12
- package/dist/server/fileOps.js +0 -51
- package/dist/server/fileOps.js.map +1 -1
- package/dist/server/watch.d.ts +1 -1
- package/dist/server/watch.js +0 -5
- package/dist/server/watch.js.map +1 -1
- package/dist/validate.d.ts +1 -3
- package/dist/validate.js +0 -15
- package/dist/validate.js.map +1 -1
- package/dist/view/assets/{index-CvyHnPjR.css → index-D8qr-jiw.css} +1 -1
- package/dist/view/assets/index-DI0VS0HQ.js +205 -0
- package/dist/view/index.html +2 -2
- package/dist/view-export/assets/bundle.css +1 -1
- package/dist/view-export/assets/bundle.js +46 -66
- package/package.json +1 -1
- package/templates/.claude/skills/loom-spec/SKILL.md +3 -99
- package/templates/.loom/README.md +1 -1
- package/dist/cli/importTrace.d.ts +0 -15
- package/dist/cli/importTrace.js +0 -188
- package/dist/cli/importTrace.js.map +0 -1
- package/dist/server/otel.d.ts +0 -32
- package/dist/server/otel.js +0 -98
- package/dist/server/otel.js.map +0 -1
- package/dist/types/timeline.d.ts +0 -97
- package/dist/types/timeline.js +0 -7
- package/dist/types/timeline.js.map +0 -1
- package/dist/view/assets/TimelineView-CsYV15RD.js +0 -16
- package/dist/view/assets/index-CqF2JC9l.js +0 -210
- package/schema/timeline.schema.json +0 -135
package/package.json
CHANGED
|
@@ -99,8 +99,6 @@ If a `loom-spec` MCP server is registered with the host (e.g. via
|
|
|
99
99
|
- `loom_list_diagrams`, `loom_read_diagram`, `loom_read_node_types`
|
|
100
100
|
- `loom_add_node`, `loom_update_node`, `loom_mark_stale`, `loom_delete_node`
|
|
101
101
|
- `loom_add_edge`, `loom_delete_edge`
|
|
102
|
-
- `loom_list_timelines`, `loom_read_timeline`
|
|
103
|
-
- `loom_add_event`, `loom_update_event`, `loom_delete_event`
|
|
104
102
|
- `loom_validate` (schema + code-ref drift across every diagram)
|
|
105
103
|
|
|
106
104
|
They validate against the schema before writing, so invalid edits fail fast
|
|
@@ -115,10 +113,10 @@ docs sites, GitHub Pages, embed-in-Notion, etc.), use the CLI:
|
|
|
115
113
|
|
|
116
114
|
- `loom-spec export-html` (full export)
|
|
117
115
|
- `loom-spec export-html <bundle-name>` (from `.loom/exports.json`)
|
|
118
|
-
- `loom-spec export-html --include-tag public --
|
|
116
|
+
- `loom-spec export-html --include-tag public --out manual.html`
|
|
119
117
|
(ad-hoc filter)
|
|
120
118
|
|
|
121
|
-
See Example
|
|
119
|
+
See Example 6 for the full workflow.
|
|
122
120
|
|
|
123
121
|
---
|
|
124
122
|
|
|
@@ -294,93 +292,7 @@ loom_add_node({
|
|
|
294
292
|
})
|
|
295
293
|
```
|
|
296
294
|
|
|
297
|
-
### 6. User wants to
|
|
298
|
-
|
|
299
|
-
> User: "Document the checkout flow on a timeline so I can see the latency
|
|
300
|
-
> breakdown."
|
|
301
|
-
|
|
302
|
-
A timeline is a horizontal time-axis overlay on a specific diagram. Each
|
|
303
|
-
event references a node in that diagram and a `[start_ms, duration_ms]`
|
|
304
|
-
interval. The view plays the events back like a DAW edit, lighting up the
|
|
305
|
-
referenced nodes in a mini graph beside the timeline.
|
|
306
|
-
|
|
307
|
-
```
|
|
308
|
-
# Step 1: Pick the diagram this sequence belongs to.
|
|
309
|
-
loom_list_diagrams()
|
|
310
|
-
loom_read_diagram("overview")
|
|
311
|
-
|
|
312
|
-
# Step 2: Create the timeline file. There's no MCP tool for creating one
|
|
313
|
-
# from scratch — write the empty shell directly:
|
|
314
|
-
#
|
|
315
|
-
# .loom/timelines/checkout.timeline.json
|
|
316
|
-
{
|
|
317
|
-
"version": "1",
|
|
318
|
-
"id": "checkout",
|
|
319
|
-
"title": "Checkout — happy path",
|
|
320
|
-
"description": "Click 'pay' → Stripe charge → confirmation render.",
|
|
321
|
-
"diagram": "overview",
|
|
322
|
-
"tracks": [
|
|
323
|
-
{ "id": "client", "label": "Browser", "color": "#dbeafe" },
|
|
324
|
-
{ "id": "server", "label": "API", "color": "#dcfce7" },
|
|
325
|
-
{ "id": "data", "label": "Postgres", "color": "#ede9fe" }
|
|
326
|
-
],
|
|
327
|
-
"events": []
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
# Step 3: Append events with the MCP tool — it validates that each `node`
|
|
331
|
-
# actually exists in the referenced diagram, so typos fail fast.
|
|
332
|
-
loom_add_event({
|
|
333
|
-
timeline: "checkout",
|
|
334
|
-
node: "checkout-page",
|
|
335
|
-
track: "client",
|
|
336
|
-
start_ms: 0,
|
|
337
|
-
duration_ms: 8,
|
|
338
|
-
kind: "compute",
|
|
339
|
-
label: "click pay",
|
|
340
|
-
code_refs: [{ path: "src/views/Checkout.tsx", symbol: "handlePay" }],
|
|
341
|
-
tags: ["critical-path", "user-input"]
|
|
342
|
-
})
|
|
343
|
-
# → { ok: true, id: "ev1" }
|
|
344
|
-
|
|
345
|
-
loom_add_event({
|
|
346
|
-
timeline: "checkout",
|
|
347
|
-
node: "payments-api",
|
|
348
|
-
track: "server",
|
|
349
|
-
start_ms: 12,
|
|
350
|
-
duration_ms: 320,
|
|
351
|
-
kind: "io",
|
|
352
|
-
label: "POST /checkout (Stripe)",
|
|
353
|
-
triggered_by: "ev1", # explicit causation arrow
|
|
354
|
-
tags: ["critical-path", "external-io"]
|
|
355
|
-
})
|
|
356
|
-
# → { ok: true, id: "ev2" }
|
|
357
|
-
|
|
358
|
-
# Step 4: Adjust if you got something wrong.
|
|
359
|
-
loom_update_event({
|
|
360
|
-
timeline: "checkout",
|
|
361
|
-
id: "ev2",
|
|
362
|
-
patch: { duration_ms: 280 }
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
# Step 5: Validate.
|
|
366
|
-
loom_validate()
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
**When to reach for a timeline rather than extra diagram detail:**
|
|
370
|
-
|
|
371
|
-
- The *order* and *latency* matter (perf review, race conditions, end-to-end
|
|
372
|
-
flow). The diagram alone shows topology, not sequencing.
|
|
373
|
-
- You want one node referenced multiple times because it does different
|
|
374
|
-
things at different moments (e.g. an auth-service that validates *then
|
|
375
|
-
later* re-issues a JWT). Use `code_refs` on each event for function-level
|
|
376
|
-
granularity inside the same node.
|
|
377
|
-
- The user describes a *trace*, a *user journey*, or a *failure case* that
|
|
378
|
-
has a clock.
|
|
379
|
-
|
|
380
|
-
**Don't create a timeline for static structure** — that's what diagrams are
|
|
381
|
-
for. A timeline of "the app boots, then runs forever" adds noise.
|
|
382
|
-
|
|
383
|
-
### 7. User wants to publish architecture docs to a manual
|
|
295
|
+
### 6. User wants to publish architecture docs to a manual
|
|
384
296
|
|
|
385
297
|
> User: "We need to ship the checkout flow as an interactive diagram in
|
|
386
298
|
> our public user manual. Don't expose anything internal."
|
|
@@ -414,7 +326,6 @@ loom_update_node({ diagram: "overview", id: "payments-service",
|
|
|
414
326
|
"user-manual": {
|
|
415
327
|
"include-tags": ["public"],
|
|
416
328
|
"exclude-tags": ["wip"],
|
|
417
|
-
"no-timelines": true,
|
|
418
329
|
"out": "docs/architecture.html"
|
|
419
330
|
}
|
|
420
331
|
}
|
|
@@ -430,13 +341,6 @@ $ loom-spec export-html user-manual
|
|
|
430
341
|
# standalone visualisation.
|
|
431
342
|
```
|
|
432
343
|
|
|
433
|
-
**When to use timelines vs not in an export:**
|
|
434
|
-
|
|
435
|
-
- Static manual / API reference → `--no-timelines` (the topology is the
|
|
436
|
-
story). Smaller file, less to digest.
|
|
437
|
-
- Onboarding / "how does the checkout actually run" → keep timelines so
|
|
438
|
-
the reader can hit Play.
|
|
439
|
-
|
|
440
344
|
**Don't auto-publish** — the export is intentional. A `git add` of the
|
|
441
345
|
generated `.html` belongs in the change that updates the architecture,
|
|
442
346
|
not in an automated commit triggered by every `.loom/` edit.
|
|
@@ -6,7 +6,7 @@ This directory contains the node-based architecture spec for the project. It is
|
|
|
6
6
|
|
|
7
7
|
- `node-types.json` — defines the available node types for this project. Customize freely; add types specific to your domain.
|
|
8
8
|
- `diagrams/*.flow.json` — one file per subsystem. Each is a self-contained graph.
|
|
9
|
-
- `
|
|
9
|
+
- `exports.json` — (optional) named export bundles for `loom-spec export-html` (e.g. a `user-manual` bundle that filters to `tags: ["public"]`).
|
|
10
10
|
|
|
11
11
|
## Viewing and editing
|
|
12
12
|
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export interface ImportTraceArgs {
|
|
2
|
-
/** Path to the OTLP JSON trace file. */
|
|
3
|
-
trace: string;
|
|
4
|
-
/** Timeline id to create or append into. */
|
|
5
|
-
asId: string;
|
|
6
|
-
/** Diagram id the new timeline overlays. */
|
|
7
|
-
diagramId: string;
|
|
8
|
-
/** Optional path to a mapping file (see MappingFile shape below). */
|
|
9
|
-
map?: string;
|
|
10
|
-
/** Append to an existing timeline instead of overwriting. */
|
|
11
|
-
append: boolean;
|
|
12
|
-
/** Working directory root (walked up to find .loom/). */
|
|
13
|
-
root: string;
|
|
14
|
-
}
|
|
15
|
-
export declare function runImportTrace(args: ImportTraceArgs): Promise<void>;
|
package/dist/cli/importTrace.js
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
import { findLoomRoot } from "../server/findLoomRoot.js";
|
|
4
|
-
import { readDiagram, readTimeline, writeTimeline } from "../server/fileOps.js";
|
|
5
|
-
import { parseOtlpJson } from "../server/otel.js";
|
|
6
|
-
import { validateTimeline } from "../validate.js";
|
|
7
|
-
const KIND_TO_EVENT_KIND = {
|
|
8
|
-
internal: "compute",
|
|
9
|
-
server: "io",
|
|
10
|
-
client: "io",
|
|
11
|
-
producer: "io",
|
|
12
|
-
consumer: "io",
|
|
13
|
-
unknown: undefined,
|
|
14
|
-
};
|
|
15
|
-
async function loadMapping(path) {
|
|
16
|
-
const raw = await readFile(path, "utf8");
|
|
17
|
-
const parsed = JSON.parse(raw);
|
|
18
|
-
return {
|
|
19
|
-
serviceMap: new Map(Object.entries(parsed.services ?? {})),
|
|
20
|
-
spanMap: new Map(Object.entries(parsed.spans ?? {})),
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Decide which node a span belongs to.
|
|
25
|
-
* Precedence: explicit span map > explicit service map > heuristic match.
|
|
26
|
-
*/
|
|
27
|
-
function resolveNode(span, mapping, nodes) {
|
|
28
|
-
if (mapping) {
|
|
29
|
-
const direct = mapping.spanMap.get(span.name);
|
|
30
|
-
if (direct)
|
|
31
|
-
return direct;
|
|
32
|
-
if (span.serviceName) {
|
|
33
|
-
const svc = mapping.serviceMap.get(span.serviceName);
|
|
34
|
-
if (svc)
|
|
35
|
-
return svc;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Heuristic: try matching span.name first (it's most specific — for
|
|
39
|
-
// CLIENT/PRODUCER spans it names the *downstream* target, which is the
|
|
40
|
-
// node we want), then fall back to service.name.
|
|
41
|
-
const candidates = [];
|
|
42
|
-
candidates.push(span.name.toLowerCase());
|
|
43
|
-
if (span.serviceName)
|
|
44
|
-
candidates.push(span.serviceName.toLowerCase());
|
|
45
|
-
for (const c of candidates) {
|
|
46
|
-
// 1. exact id match
|
|
47
|
-
const idHit = nodes.find((n) => n.id.toLowerCase() === c);
|
|
48
|
-
if (idHit)
|
|
49
|
-
return idHit.id;
|
|
50
|
-
// 2. node id appears as a token inside the candidate
|
|
51
|
-
// (e.g. "todo-store update" → finds id "todo-store")
|
|
52
|
-
const idInCandidate = nodes.find((n) => c.includes(n.id.toLowerCase()));
|
|
53
|
-
if (idInCandidate)
|
|
54
|
-
return idInCandidate.id;
|
|
55
|
-
// 3. candidate appears in a node label
|
|
56
|
-
// (e.g. "todo-api" → finds label "Todo API")
|
|
57
|
-
const labelHit = nodes.find((n) => n.label.toLowerCase().includes(c));
|
|
58
|
-
if (labelHit)
|
|
59
|
-
return labelHit.id;
|
|
60
|
-
// 4. code-ref path includes the candidate
|
|
61
|
-
const refHit = nodes.find((n) => (n.code_refs ?? []).some((r) => r.path.toLowerCase().includes(c)));
|
|
62
|
-
if (refHit)
|
|
63
|
-
return refHit.id;
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
function eventIdFor(spanId, existingIds) {
|
|
68
|
-
// Stable: take the first 8 hex chars of the span id, prefix with "ev".
|
|
69
|
-
// Fall back to a sequence if collision (shouldn't happen in practice).
|
|
70
|
-
const base = `ev-${spanId.slice(0, 8) || "span"}`.toLowerCase();
|
|
71
|
-
if (!existingIds.has(base))
|
|
72
|
-
return base;
|
|
73
|
-
let i = 2;
|
|
74
|
-
while (existingIds.has(`${base}-${i}`))
|
|
75
|
-
i++;
|
|
76
|
-
return `${base}-${i}`;
|
|
77
|
-
}
|
|
78
|
-
export async function runImportTrace(args) {
|
|
79
|
-
// 1. Locate the .loom/ root and load the diagram we're overlaying.
|
|
80
|
-
const loomRoot = await findLoomRoot(args.root);
|
|
81
|
-
const diagram = await readDiagram(loomRoot.loomPath, args.diagramId);
|
|
82
|
-
// 2. Load and parse the trace.
|
|
83
|
-
const traceRaw = await readFile(resolve(args.trace), "utf8");
|
|
84
|
-
const traceJson = JSON.parse(traceRaw);
|
|
85
|
-
const spans = parseOtlpJson(traceJson);
|
|
86
|
-
if (spans.length === 0) {
|
|
87
|
-
console.error("Trace contained 0 spans — nothing to import.");
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
// 3. Optional mapping file.
|
|
91
|
-
const mapping = args.map ? await loadMapping(resolve(args.map)) : null;
|
|
92
|
-
// 4. Compute t=0 (earliest span start) so the timeline is repo-portable.
|
|
93
|
-
const minStartNs = spans.reduce((m, s) => (s.startNs < m ? s.startNs : m), spans[0].startNs);
|
|
94
|
-
// 5. If appending, load existing timeline; otherwise start fresh.
|
|
95
|
-
let existing = null;
|
|
96
|
-
if (args.append) {
|
|
97
|
-
try {
|
|
98
|
-
existing = await readTimeline(loomRoot.loomPath, args.asId);
|
|
99
|
-
if (existing.diagram !== args.diagramId) {
|
|
100
|
-
console.error(`Refusing to append: existing timeline '${args.asId}' references diagram ` +
|
|
101
|
-
`'${existing.diagram}', not '${args.diagramId}'.`);
|
|
102
|
-
process.exit(1);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
catch (e) {
|
|
106
|
-
if (e.code !== "ENOENT")
|
|
107
|
-
throw e;
|
|
108
|
-
// Fall through: --append on a missing file behaves like create.
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const existingIds = new Set(existing?.events.map((e) => e.id) ?? []);
|
|
112
|
-
const spanIdToEventId = new Map();
|
|
113
|
-
const events = [];
|
|
114
|
-
const skipped = [];
|
|
115
|
-
// 6. First pass: pick node + event id for each span.
|
|
116
|
-
for (const s of spans) {
|
|
117
|
-
const node = resolveNode(s, mapping, diagram.nodes);
|
|
118
|
-
if (!node) {
|
|
119
|
-
skipped.push({ span: s, reason: "no matching node" });
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
const id = eventIdFor(s.spanId, existingIds);
|
|
123
|
-
existingIds.add(id);
|
|
124
|
-
spanIdToEventId.set(s.spanId, id);
|
|
125
|
-
const start_ms = Number((s.startNs - minStartNs) / 1000000n);
|
|
126
|
-
const duration_ms = Number((s.endNs - s.startNs) / 1000000n);
|
|
127
|
-
events.push({
|
|
128
|
-
id,
|
|
129
|
-
node,
|
|
130
|
-
start_ms: Math.max(0, start_ms),
|
|
131
|
-
duration_ms: Math.max(0, duration_ms),
|
|
132
|
-
label: s.name.length > 60 ? s.name.slice(0, 57) + "…" : s.name,
|
|
133
|
-
kind: KIND_TO_EVENT_KIND[s.kind] ?? "compute",
|
|
134
|
-
track: s.serviceName ?? undefined,
|
|
135
|
-
tags: [`otel-import`, `kind:${s.kind}`],
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
// 7. Second pass: wire triggered_by from span parent.
|
|
139
|
-
for (let i = 0; i < spans.length; i++) {
|
|
140
|
-
const s = spans[i];
|
|
141
|
-
const ev = events.find((e) => e.id === spanIdToEventId.get(s.spanId));
|
|
142
|
-
if (!ev)
|
|
143
|
-
continue;
|
|
144
|
-
if (s.parentSpanId) {
|
|
145
|
-
const parentEventId = spanIdToEventId.get(s.parentSpanId);
|
|
146
|
-
if (parentEventId)
|
|
147
|
-
ev.triggered_by = parentEventId;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
// 8. Build the timeline. Auto-derive tracks from distinct services.
|
|
151
|
-
const trackIds = new Set((existing?.tracks?.map((t) => t.id) ?? []).concat(events.map((e) => e.track).filter((t) => !!t)));
|
|
152
|
-
const tracks = Array.from(trackIds).map((id) => ({ id, label: id }));
|
|
153
|
-
const timeline = {
|
|
154
|
-
version: "1",
|
|
155
|
-
id: args.asId,
|
|
156
|
-
title: existing?.title ?? `Imported: ${args.asId}`,
|
|
157
|
-
description: existing?.description ??
|
|
158
|
-
`Generated by 'loom-spec import-trace' from ${args.trace}.`,
|
|
159
|
-
diagram: args.diagramId,
|
|
160
|
-
events: existing ? [...existing.events, ...events] : events,
|
|
161
|
-
tracks,
|
|
162
|
-
};
|
|
163
|
-
// 9. Validate before writing.
|
|
164
|
-
const v = await validateTimeline(timeline);
|
|
165
|
-
if (!v.ok) {
|
|
166
|
-
console.error("Generated timeline failed schema validation:");
|
|
167
|
-
for (const e of v.errors)
|
|
168
|
-
console.error(` - ${e}`);
|
|
169
|
-
process.exit(1);
|
|
170
|
-
}
|
|
171
|
-
await writeTimeline(loomRoot.loomPath, args.asId, timeline);
|
|
172
|
-
// 10. Report.
|
|
173
|
-
console.log(`Wrote ${events.length} event${events.length === 1 ? "" : "s"} to ` +
|
|
174
|
-
`${loomRoot.loomPath}/timelines/${args.asId}.timeline.json` +
|
|
175
|
-
(existing ? ` (appended; total ${timeline.events.length})` : ""));
|
|
176
|
-
if (skipped.length > 0) {
|
|
177
|
-
console.log(`Skipped ${skipped.length} span${skipped.length === 1 ? "" : "s"} ` +
|
|
178
|
-
`with no matching node. Pass --map mapping.json to override.`);
|
|
179
|
-
const sample = skipped.slice(0, 5);
|
|
180
|
-
for (const { span, reason } of sample) {
|
|
181
|
-
console.log(` • ${span.name} (service=${span.serviceName ?? "—"}) ${reason}`);
|
|
182
|
-
}
|
|
183
|
-
if (skipped.length > sample.length) {
|
|
184
|
-
console.log(` … and ${skipped.length - sample.length} more.`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
//# sourceMappingURL=importTrace.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"importTrace.js","sourceRoot":"","sources":["../../src/cli/importTrace.ts"],"names":[],"mappings":"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"}
|
package/dist/server/otel.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal OTLP JSON parser. Reads the standard OpenTelemetry resource/scope/
|
|
3
|
-
* spans shape (`resourceSpans[].scopeSpans[].spans[]`) and projects it down
|
|
4
|
-
* to a flat list of normalized spans suitable for translating into a
|
|
5
|
-
* loom-spec timeline.
|
|
6
|
-
*
|
|
7
|
-
* Scope: just enough of the OTLP JSON shape for the import-trace CLI.
|
|
8
|
-
* Does NOT validate exhaustively, does NOT handle protobuf binary, does NOT
|
|
9
|
-
* walk Jaeger or Zipkin formats — those can be follow-ons.
|
|
10
|
-
*/
|
|
11
|
-
export interface ParsedSpan {
|
|
12
|
-
spanId: string;
|
|
13
|
-
parentSpanId: string | null;
|
|
14
|
-
/** Service that emitted the span (from resource attribute). */
|
|
15
|
-
serviceName: string | null;
|
|
16
|
-
/** Span name (often the operation or route). */
|
|
17
|
-
name: string;
|
|
18
|
-
/** "server" | "client" | "internal" | "producer" | "consumer" | "unknown". */
|
|
19
|
-
kind: SpanKind;
|
|
20
|
-
/** Start time in nanoseconds since UNIX epoch. */
|
|
21
|
-
startNs: bigint;
|
|
22
|
-
/** End time in nanoseconds since UNIX epoch. */
|
|
23
|
-
endNs: bigint;
|
|
24
|
-
/** Flattened key→value of attributes (resource + span merged; span wins). */
|
|
25
|
-
attributes: Record<string, string | number | boolean>;
|
|
26
|
-
}
|
|
27
|
-
export type SpanKind = "internal" | "server" | "client" | "producer" | "consumer" | "unknown";
|
|
28
|
-
/**
|
|
29
|
-
* Parse an OTLP JSON object (already JSON.parsed) into normalized spans.
|
|
30
|
-
* Throws if `resourceSpans` is missing — we don't try to recover or guess.
|
|
31
|
-
*/
|
|
32
|
-
export declare function parseOtlpJson(raw: unknown): ParsedSpan[];
|
package/dist/server/otel.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal OTLP JSON parser. Reads the standard OpenTelemetry resource/scope/
|
|
3
|
-
* spans shape (`resourceSpans[].scopeSpans[].spans[]`) and projects it down
|
|
4
|
-
* to a flat list of normalized spans suitable for translating into a
|
|
5
|
-
* loom-spec timeline.
|
|
6
|
-
*
|
|
7
|
-
* Scope: just enough of the OTLP JSON shape for the import-trace CLI.
|
|
8
|
-
* Does NOT validate exhaustively, does NOT handle protobuf binary, does NOT
|
|
9
|
-
* walk Jaeger or Zipkin formats — those can be follow-ons.
|
|
10
|
-
*/
|
|
11
|
-
const KIND_MAP = {
|
|
12
|
-
0: "unknown",
|
|
13
|
-
1: "internal",
|
|
14
|
-
2: "server",
|
|
15
|
-
3: "client",
|
|
16
|
-
4: "producer",
|
|
17
|
-
5: "consumer",
|
|
18
|
-
};
|
|
19
|
-
function attrValue(a) {
|
|
20
|
-
const v = a.value;
|
|
21
|
-
if (!v)
|
|
22
|
-
return undefined;
|
|
23
|
-
if (v.stringValue !== undefined)
|
|
24
|
-
return v.stringValue;
|
|
25
|
-
if (v.boolValue !== undefined)
|
|
26
|
-
return v.boolValue;
|
|
27
|
-
if (v.intValue !== undefined)
|
|
28
|
-
return Number(v.intValue);
|
|
29
|
-
if (v.doubleValue !== undefined)
|
|
30
|
-
return v.doubleValue;
|
|
31
|
-
return undefined;
|
|
32
|
-
}
|
|
33
|
-
function flattenAttrs(attrs) {
|
|
34
|
-
const out = {};
|
|
35
|
-
for (const a of attrs ?? []) {
|
|
36
|
-
const v = attrValue(a);
|
|
37
|
-
if (v !== undefined)
|
|
38
|
-
out[a.key] = v;
|
|
39
|
-
}
|
|
40
|
-
return out;
|
|
41
|
-
}
|
|
42
|
-
function toBigInt(t) {
|
|
43
|
-
if (t === undefined)
|
|
44
|
-
return 0n;
|
|
45
|
-
if (typeof t === "number")
|
|
46
|
-
return BigInt(t);
|
|
47
|
-
return BigInt(t);
|
|
48
|
-
}
|
|
49
|
-
function normalizeKind(k) {
|
|
50
|
-
if (typeof k === "number")
|
|
51
|
-
return KIND_MAP[k] ?? "unknown";
|
|
52
|
-
if (typeof k === "string") {
|
|
53
|
-
// OTLP exporters sometimes emit "SPAN_KIND_SERVER" etc.
|
|
54
|
-
const lower = k.replace(/^SPAN_KIND_/i, "").toLowerCase();
|
|
55
|
-
if (lower in { internal: 1, server: 1, client: 1, producer: 1, consumer: 1 }) {
|
|
56
|
-
return lower;
|
|
57
|
-
}
|
|
58
|
-
return "unknown";
|
|
59
|
-
}
|
|
60
|
-
return "unknown";
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Parse an OTLP JSON object (already JSON.parsed) into normalized spans.
|
|
64
|
-
* Throws if `resourceSpans` is missing — we don't try to recover or guess.
|
|
65
|
-
*/
|
|
66
|
-
export function parseOtlpJson(raw) {
|
|
67
|
-
if (!raw || typeof raw !== "object") {
|
|
68
|
-
throw new Error("Trace file is not a JSON object");
|
|
69
|
-
}
|
|
70
|
-
const root = raw;
|
|
71
|
-
if (!Array.isArray(root.resourceSpans)) {
|
|
72
|
-
throw new Error("Not an OTLP JSON trace — expected top-level 'resourceSpans' array. " +
|
|
73
|
-
"Jaeger/Zipkin formats are not yet supported.");
|
|
74
|
-
}
|
|
75
|
-
const out = [];
|
|
76
|
-
for (const rs of root.resourceSpans) {
|
|
77
|
-
const resourceAttrs = flattenAttrs(rs.resource?.attributes);
|
|
78
|
-
const serviceName = resourceAttrs["service.name"] ?? null;
|
|
79
|
-
for (const ss of rs.scopeSpans ?? []) {
|
|
80
|
-
for (const s of ss.spans ?? []) {
|
|
81
|
-
const spanAttrs = flattenAttrs(s.attributes);
|
|
82
|
-
const attributes = { ...resourceAttrs, ...spanAttrs };
|
|
83
|
-
out.push({
|
|
84
|
-
spanId: s.spanId ?? "",
|
|
85
|
-
parentSpanId: s.parentSpanId && s.parentSpanId.length > 0 ? s.parentSpanId : null,
|
|
86
|
-
serviceName,
|
|
87
|
-
name: s.name ?? "(unnamed)",
|
|
88
|
-
kind: normalizeKind(s.kind),
|
|
89
|
-
startNs: toBigInt(s.startTimeUnixNano),
|
|
90
|
-
endNs: toBigInt(s.endTimeUnixNano),
|
|
91
|
-
attributes,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return out;
|
|
97
|
-
}
|
|
98
|
-
//# sourceMappingURL=otel.js.map
|
package/dist/server/otel.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"otel.js","sourceRoot":"","sources":["../../src/server/otel.ts"],"names":[],"mappings":"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"}
|
package/dist/types/timeline.d.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AUTOGENERATED — do not edit.
|
|
3
|
-
* Source: schema/timeline.schema.json
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* A time-axis overlay describing when events happen on the nodes of a diagram. Same node universe, different render.
|
|
7
|
-
*/
|
|
8
|
-
export interface LoomTimeline {
|
|
9
|
-
$schema?: string;
|
|
10
|
-
version: "1";
|
|
11
|
-
/**
|
|
12
|
-
* Timeline identifier. Should match the filename without extension.
|
|
13
|
-
*/
|
|
14
|
-
id: string;
|
|
15
|
-
title: string;
|
|
16
|
-
description?: string;
|
|
17
|
-
/**
|
|
18
|
-
* Id of the diagram whose nodes this timeline overlays.
|
|
19
|
-
*/
|
|
20
|
-
diagram: string;
|
|
21
|
-
events: TimelineEvent[];
|
|
22
|
-
/**
|
|
23
|
-
* Optional explicit track definitions (label, color). If omitted, tracks are inferred from events[].track values.
|
|
24
|
-
*/
|
|
25
|
-
tracks?: TimelineTrack[];
|
|
26
|
-
}
|
|
27
|
-
export interface TimelineEvent {
|
|
28
|
-
/**
|
|
29
|
-
* Unique within this timeline.
|
|
30
|
-
*/
|
|
31
|
-
id: string;
|
|
32
|
-
/**
|
|
33
|
-
* Node id from the referenced diagram.
|
|
34
|
-
*/
|
|
35
|
-
node: string;
|
|
36
|
-
/**
|
|
37
|
-
* Track label. Events on the same track are interpreted as sequential; events on different tracks at overlapping times are concurrent. If omitted, the renderer auto-assigns one track per node.
|
|
38
|
-
*/
|
|
39
|
-
track?: string;
|
|
40
|
-
/**
|
|
41
|
-
* Start time in milliseconds from t=0.
|
|
42
|
-
*/
|
|
43
|
-
start_ms: number;
|
|
44
|
-
/**
|
|
45
|
-
* Duration in milliseconds. May be 0 for instantaneous events.
|
|
46
|
-
*/
|
|
47
|
-
duration_ms: number;
|
|
48
|
-
/**
|
|
49
|
-
* Short text rendered inside the clip.
|
|
50
|
-
*/
|
|
51
|
-
label?: string;
|
|
52
|
-
description?: string;
|
|
53
|
-
/**
|
|
54
|
-
* Optional category for clip styling. Distinct from edge.kind in the diagram — this describes what the node is doing during this clip, not what flows between nodes.
|
|
55
|
-
*/
|
|
56
|
-
kind?: "compute" | "io" | "wait" | "error";
|
|
57
|
-
/**
|
|
58
|
-
* Optional anchors to the specific function(s) running during this clip. Like node-level code_refs but scoped to a moment in time. Drift detection checks these too. Use for function-level granularity inside a node (e.g. 'validate' vs. 'issue jwt' both happen on the auth-service node).
|
|
59
|
-
*/
|
|
60
|
-
code_refs?: CodeRef[];
|
|
61
|
-
/**
|
|
62
|
-
* Optional id of another event that caused this one. Used for explicit causation chains and to preserve OTel span.parent_id when importing traces. The renderer can draw a connecting arrow between the two clips.
|
|
63
|
-
*/
|
|
64
|
-
triggered_by?: string;
|
|
65
|
-
/**
|
|
66
|
-
* Free-form labels for filtering or grouping clips. Examples: 'critical-path', 'billable-time', 'background'.
|
|
67
|
-
*/
|
|
68
|
-
tags?: string[];
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Same shape as the CodeRef in diagram.schema.json. Inlined here to keep the schema self-contained — no cross-file $ref required to validate.
|
|
72
|
-
*/
|
|
73
|
-
export interface CodeRef {
|
|
74
|
-
/**
|
|
75
|
-
* Repo-relative file path.
|
|
76
|
-
*/
|
|
77
|
-
path: string;
|
|
78
|
-
/**
|
|
79
|
-
* Function, class, or component name. Preferred over lines because it survives refactors.
|
|
80
|
-
*/
|
|
81
|
-
symbol?: string;
|
|
82
|
-
/**
|
|
83
|
-
* Line range(s) like '1-80' or '12,45-50'. Use only when no symbol applies.
|
|
84
|
-
*/
|
|
85
|
-
lines?: string;
|
|
86
|
-
}
|
|
87
|
-
export interface TimelineTrack {
|
|
88
|
-
/**
|
|
89
|
-
* Track id, matches event.track values.
|
|
90
|
-
*/
|
|
91
|
-
id: string;
|
|
92
|
-
label: string;
|
|
93
|
-
/**
|
|
94
|
-
* Optional background tint for the track lane.
|
|
95
|
-
*/
|
|
96
|
-
color?: string;
|
|
97
|
-
}
|
package/dist/types/timeline.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/types/timeline.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;GAGG"}
|