loom-spec 0.1.1 → 0.3.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/README.md +124 -20
- package/dist/cli/importTrace.d.ts +15 -0
- package/dist/cli/importTrace.js +188 -0
- package/dist/cli/importTrace.js.map +1 -0
- package/dist/cli/index.js +37 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/mcp/server.js +207 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/server/app.js +50 -2
- package/dist/server/app.js.map +1 -1
- package/dist/server/fileOps.d.ts +12 -0
- package/dist/server/fileOps.js +51 -0
- package/dist/server/fileOps.js.map +1 -1
- package/dist/server/otel.d.ts +32 -0
- package/dist/server/otel.js +98 -0
- package/dist/server/otel.js.map +1 -0
- package/dist/server/watch.d.ts +1 -1
- package/dist/server/watch.js +5 -0
- package/dist/server/watch.js.map +1 -1
- package/dist/types/timeline.d.ts +97 -0
- package/dist/types/timeline.js +7 -0
- package/dist/types/timeline.js.map +1 -0
- package/dist/validate.d.ts +3 -1
- package/dist/validate.js +15 -0
- package/dist/validate.js.map +1 -1
- package/dist/view/assets/TimelineView-DEfpV9mL.js +16 -0
- package/dist/view/assets/{index-Cst6HUW5.css → index-CvyHnPjR.css} +1 -1
- package/dist/view/assets/index-Du05xzao.js +210 -0
- package/dist/view/index.html +2 -2
- package/package.json +1 -1
- package/schema/timeline.schema.json +135 -0
- package/templates/.claude/skills/loom-spec/SKILL.md +88 -0
- package/dist/view/assets/index-Cdrw4Ya7.js +0 -205
package/README.md
CHANGED
|
@@ -2,34 +2,72 @@
|
|
|
2
2
|
|
|
3
3
|
> A node-based architecture spec that lives in your repo. AI-readable, AI-writable, git-diffable.
|
|
4
4
|
|
|
5
|
-
`loom-spec` keeps a structured visual spec of your application's architecture **inside your repo**, designed to be edited by both humans (in a browser-based node editor) and AI coding agents (directly via JSON files).
|
|
5
|
+
`loom-spec` keeps a structured visual spec of your application's architecture **inside your repo**, designed to be edited by both humans (in a browser-based node editor) and AI coding agents (directly via JSON files or MCP tool calls).
|
|
6
6
|
|
|
7
|
-
It's a spec layer, not an execution layer. The nodes don't run
|
|
7
|
+
It's a spec layer, not an execution layer. The nodes describe; they don't run.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Why
|
|
10
|
+
|
|
11
|
+
- **Architecture drift.** Mermaid diagrams in `docs/` go stale the moment you refactor.
|
|
12
|
+
- **Agents losing the forest for the trees.** An agent grepping through `src/` doesn't see the system. Every session rebuilds the mental model from scratch.
|
|
13
|
+
- **The mental-model gap.** People who think in signal flow but don't read code well get cut out.
|
|
14
|
+
|
|
15
|
+
`loom-spec` is one canonical, machine-readable file-set under `.loom/` that says what exists and how it connects. Humans edit it visually. The agent reads it before implementing and updates it when code changes. `code_refs` anchor each node to actual source, so [`loom-spec validate`](#loom-spec-validate---root-dir---json) catches drift instead of letting it accumulate.
|
|
16
|
+
|
|
17
|
+
## Install + first run
|
|
10
18
|
|
|
11
19
|
```bash
|
|
12
|
-
|
|
13
|
-
npx loom-spec init
|
|
14
|
-
npx loom-spec view
|
|
20
|
+
cd your-project
|
|
21
|
+
npx loom-spec init --mcp # scaffolds .loom/, the agent skill, and .mcp.json
|
|
22
|
+
npx loom-spec view # opens the editor on http://localhost:7777
|
|
15
23
|
```
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
`--mcp` is optional but recommended — it auto-registers the MCP server for Claude Code (and other MCP-capable agents). Skip it if you want to wire that up manually later via `npx loom-spec install-mcp`.
|
|
26
|
+
|
|
27
|
+
If you prefer it as a dev dependency:
|
|
18
28
|
|
|
19
29
|
```bash
|
|
20
30
|
npm install --save-dev loom-spec
|
|
21
31
|
```
|
|
22
32
|
|
|
23
|
-
Then in `package.json`:
|
|
24
|
-
|
|
25
33
|
```json
|
|
26
34
|
{
|
|
27
35
|
"scripts": {
|
|
28
|
-
"loom": "loom-spec view"
|
|
36
|
+
"loom": "loom-spec view",
|
|
37
|
+
"loom:check": "loom-spec validate"
|
|
29
38
|
}
|
|
30
39
|
}
|
|
31
40
|
```
|
|
32
41
|
|
|
42
|
+
## A typical workflow
|
|
43
|
+
|
|
44
|
+
1. **Sketch the high-level architecture once.** Open `loom-spec view`, click **+ Add** to drop services, data stores, and UI components onto the canvas. Connect them with edges. Mark nodes as `planned` if you haven't built them yet, `implemented` once the code exists.
|
|
45
|
+
2. **Let the agent grow it.** With Claude Code (or any MCP-capable agent) in the same repo, tell it what to build: *"add a payments service that the checkout flow calls"*. The agent calls `loom_add_node` and `loom_add_edge`, then writes the actual code. Your open editor updates live via SSE.
|
|
46
|
+
3. **Anchor nodes to code.** When a feature is done, the agent (or you) adds `code_refs`: `{ "path": "src/server/payments.ts", "symbol": "chargeCard" }`. This is what makes drift detection work.
|
|
47
|
+
4. **Catch drift in CI.** Add `loom-spec validate` as a pre-commit hook or CI step. It exits non-zero if any `code_refs` point at missing files or unresolved symbols.
|
|
48
|
+
5. **Stale, don't delete.** When the underlying code goes away, the agent marks the node `status: stale` instead of deleting it. Humans review staleness — the architectural history stays.
|
|
49
|
+
|
|
50
|
+
## What lives in your repo
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
.loom/
|
|
54
|
+
├── README.md Why this directory exists; for humans.
|
|
55
|
+
├── node-types.json The vocabulary: ui, service, data, event, external (plus your customs).
|
|
56
|
+
└── diagrams/
|
|
57
|
+
└── overview.flow.json { nodes, edges, groups }
|
|
58
|
+
|
|
59
|
+
.claude/
|
|
60
|
+
└── skills/
|
|
61
|
+
└── loom-spec/
|
|
62
|
+
└── SKILL.md Tells Claude Code (or any Agent-Skills-aware tool)
|
|
63
|
+
when and how to maintain the spec, with five
|
|
64
|
+
worked examples.
|
|
65
|
+
|
|
66
|
+
.mcp.json Registers the MCP server, if you ran init --mcp.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Nothing of the `loom-spec` package itself is committed — the npm install lives in `node_modules/`. Only the spec and the skill are tracked.
|
|
70
|
+
|
|
33
71
|
## Commands
|
|
34
72
|
|
|
35
73
|
### `loom-spec init [--path <dir>] [--force]`
|
|
@@ -51,6 +89,18 @@ Add `--mcp` to also register the MCP server in `.mcp.json` (idempotent merge —
|
|
|
51
89
|
|
|
52
90
|
Starts a local browser editor. Walks up from `--root` (default: cwd) to find the nearest `.loom/`. Opens on port 7777 by default.
|
|
53
91
|
|
|
92
|
+
In the editor you can:
|
|
93
|
+
|
|
94
|
+
- Drag nodes; edits debounce and write to disk within ~500ms
|
|
95
|
+
- Click a node or edge to inspect and edit fields, code refs, tags, type-specific properties
|
|
96
|
+
- Drag from a node's right handle to another node to create an edge
|
|
97
|
+
- Use the **+ Add** menu in the top bar to add a new node by type
|
|
98
|
+
- Use the diagram switcher (top-left dropdown) to navigate between diagrams or create new ones
|
|
99
|
+
- Use the "Drill into" chevron on any node or group with `drill_down` set to jump to a sub-diagram
|
|
100
|
+
- Toggle light/dark theme; preference is persisted
|
|
101
|
+
|
|
102
|
+
External edits to the JSON files (e.g. by an AI agent) propagate to the open UI live via Server-Sent Events — no reload needed.
|
|
103
|
+
|
|
54
104
|
### `loom-spec validate [--root <dir>] [--json]`
|
|
55
105
|
|
|
56
106
|
Checks every diagram for schema validity plus **code-ref drift**: missing files, missing symbols, out-of-range line ranges. Skips nodes marked `planned` or `deprecated` (their code may legitimately not exist). Exit code is non-zero if any issue is found — useful as a CI step or pre-commit hook.
|
|
@@ -86,17 +136,9 @@ The server exposes semantic tools that validate against the schema before writin
|
|
|
86
136
|
- `loom_add_edge`, `loom_delete_edge`
|
|
87
137
|
- `loom_validate` (same drift check as the CLI)
|
|
88
138
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- Drag nodes; edits debounce and write to disk within ~500ms
|
|
92
|
-
- Click a node or edge to inspect and edit fields, code refs, tags, type-specific properties
|
|
93
|
-
- Drag from a node's right handle to another node to create an edge
|
|
94
|
-
- Use the "+ Add" menu in the top bar to add a new node by type
|
|
95
|
-
- Use the diagram switcher (top-left dropdown) to navigate between diagrams or create new ones
|
|
96
|
-
- Use the "Drill into" chevron on any node or group with `drill_down` set to jump to a sub-diagram
|
|
97
|
-
- Toggle light/dark theme; preference is persisted
|
|
139
|
+
### `loom-spec install-mcp [--path <dir>]`
|
|
98
140
|
|
|
99
|
-
|
|
141
|
+
Writes the MCP-server entry into `.mcp.json` without touching anything else. Idempotent (safe to run repeatedly) and non-destructive (other MCP servers and unrelated top-level keys are preserved).
|
|
100
142
|
|
|
101
143
|
## File format
|
|
102
144
|
|
|
@@ -157,6 +199,68 @@ Edge kinds: `request`, `event`, `data-read`, `data-write`, `signal`, `dependency
|
|
|
157
199
|
|
|
158
200
|
Full JSON Schemas ship with the package — see `schema/diagram.schema.json` and `schema/node-types.schema.json`.
|
|
159
201
|
|
|
202
|
+
### Adding custom node types
|
|
203
|
+
|
|
204
|
+
`node-types.json` is yours to edit. Add a type for whatever domain you're modelling. A worker with typed ports:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"types": {
|
|
209
|
+
"worker": {
|
|
210
|
+
"label": "Worker",
|
|
211
|
+
"color": "#fb923c",
|
|
212
|
+
"icon": "server",
|
|
213
|
+
"fields": [
|
|
214
|
+
{ "name": "queue", "type": "string", "required": true },
|
|
215
|
+
{ "name": "concurrency", "type": "number" }
|
|
216
|
+
],
|
|
217
|
+
"ports": {
|
|
218
|
+
"in": [{ "name": "jobs", "signal": "data" }],
|
|
219
|
+
"out": [{ "name": "results", "signal": "data" }, { "name": "errors", "signal": "data" }]
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Once that's saved, the **+ Add** menu shows "Worker"; new worker nodes render with three labeled handles instead of one generic one. Edges can target a specific port via `from: "worker-1:results"`.
|
|
227
|
+
|
|
228
|
+
### Drill-down between diagrams
|
|
229
|
+
|
|
230
|
+
For LangGraph-style multi-step agents or anything with non-trivial internal flow: one node in the overview, plus a sub-diagram with the steps inside.
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
// overview.flow.json
|
|
234
|
+
{
|
|
235
|
+
"id": "agent",
|
|
236
|
+
"type": "service",
|
|
237
|
+
"label": "Agent",
|
|
238
|
+
"drill_down": "agent-internals",
|
|
239
|
+
"code_refs": [{ "path": "agent.py" }]
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
// agent-internals.flow.json
|
|
245
|
+
{
|
|
246
|
+
"nodes": [
|
|
247
|
+
{ "id": "decide", "type": "service", "label": "decide_next_step",
|
|
248
|
+
"code_refs": [{ "path": "agent.py", "symbol": "decide_next_step" }] },
|
|
249
|
+
{ "id": "call-tool", "type": "service", "label": "call_tool",
|
|
250
|
+
"code_refs": [{ "path": "agent.py", "symbol": "call_tool" }] },
|
|
251
|
+
{ "id": "format", "type": "service", "label": "format_response",
|
|
252
|
+
"code_refs": [{ "path": "agent.py", "symbol": "format_response" }] }
|
|
253
|
+
],
|
|
254
|
+
"edges": [
|
|
255
|
+
{ "id": "e1", "from": "decide", "to": "call-tool", "kind": "control", "label": "if tool needed" },
|
|
256
|
+
{ "id": "e2", "from": "call-tool", "to": "format", "kind": "control" },
|
|
257
|
+
{ "id": "e3", "from": "decide", "to": "format", "kind": "control", "label": "if final" }
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Click the chevron on the overview's `agent` node to navigate in.
|
|
263
|
+
|
|
160
264
|
## How AI agents use it
|
|
161
265
|
|
|
162
266
|
`loom-spec init` writes a `SKILL.md` to `.claude/skills/loom-spec/` following the [Agent Skills open standard](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview). Claude Code (and other tools that adopt the convention) auto-discovers it.
|
|
@@ -0,0 +1,15 @@
|
|
|
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>;
|
|
@@ -0,0 +1,188 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"importTrace.js","sourceRoot":"","sources":["../../src/cli/importTrace.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { runView } from "./view.js";
|
|
|
4
4
|
import { runValidate } from "./validate.js";
|
|
5
5
|
import { runMcp } from "./mcp.js";
|
|
6
6
|
import { runInstallMcp } from "./installMcp.js";
|
|
7
|
+
import { runImportTrace } from "./importTrace.js";
|
|
7
8
|
const HELP = `loom-spec — node-based architecture spec for your repo
|
|
8
9
|
|
|
9
10
|
Usage:
|
|
@@ -27,11 +28,18 @@ Usage:
|
|
|
27
28
|
pre-commit hook.
|
|
28
29
|
|
|
29
30
|
loom-spec mcp [--root <dir>]
|
|
30
|
-
Start a Model Context Protocol server on stdio. Exposes
|
|
31
|
-
loom_list_diagrams,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
Start a Model Context Protocol server on stdio. Exposes 15 tools
|
|
32
|
+
for diagrams (loom_list_diagrams, loom_add_node, loom_add_edge, …)
|
|
33
|
+
and timelines (loom_list_timelines, loom_add_event, …) — wire it
|
|
34
|
+
into Claude Code's mcp.json (or any MCP-capable client).
|
|
35
|
+
|
|
36
|
+
loom-spec import-trace <trace.json> --as <timeline-id> --diagram <diagram-id>
|
|
37
|
+
[--map <mapping.json>] [--append] [--root <dir>]
|
|
38
|
+
Read an OpenTelemetry OTLP-JSON trace and generate a timeline that
|
|
39
|
+
mirrors the actual spans on the named diagram. Each span becomes
|
|
40
|
+
an event; parent/child relationships preserve as triggered_by;
|
|
41
|
+
service.name becomes the track. Spans whose service or name can't
|
|
42
|
+
be matched to a node are skipped — pass --map to override.
|
|
35
43
|
|
|
36
44
|
loom-spec --help
|
|
37
45
|
Print this help.
|
|
@@ -98,6 +106,30 @@ async function main() {
|
|
|
98
106
|
});
|
|
99
107
|
return;
|
|
100
108
|
}
|
|
109
|
+
if (subcommand === "import-trace") {
|
|
110
|
+
// Positional arg: the trace file path (first non-flag in rest).
|
|
111
|
+
const trace = rest.find((a) => a && !a.startsWith("--"));
|
|
112
|
+
if (!trace) {
|
|
113
|
+
console.error("import-trace: missing trace file path");
|
|
114
|
+
console.log(HELP);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
const asId = flags.as;
|
|
118
|
+
const diagramId = flags.diagram;
|
|
119
|
+
if (!asId || !diagramId) {
|
|
120
|
+
console.error("import-trace: --as <timeline-id> and --diagram <diagram-id> are required");
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
await runImportTrace({
|
|
124
|
+
trace,
|
|
125
|
+
asId,
|
|
126
|
+
diagramId,
|
|
127
|
+
map: typeof flags.map === "string" ? flags.map : undefined,
|
|
128
|
+
append: Boolean(flags.append),
|
|
129
|
+
root: flags.root ?? process.cwd(),
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
101
133
|
console.error(`unknown subcommand: ${subcommand}\n`);
|
|
102
134
|
console.log(HELP);
|
|
103
135
|
process.exit(1);
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|