loom-spec 0.2.0 → 0.4.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 +25 -0
- package/dist/cli/exportHtml.js +201 -0
- package/dist/cli/exportHtml.js.map +1 -0
- 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 +81 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/server/exportConfig.d.ts +42 -0
- package/dist/server/exportConfig.js +88 -0
- package/dist/server/exportConfig.js.map +1 -0
- package/dist/server/exportFilter.d.ts +59 -0
- package/dist/server/exportFilter.js +172 -0
- package/dist/server/exportFilter.js.map +1 -0
- 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/view/assets/TimelineView-CsYV15RD.js +16 -0
- package/dist/view/assets/index-CqF2JC9l.js +210 -0
- package/dist/view/assets/index-CvyHnPjR.css +1 -0
- package/dist/view/index.html +2 -2
- package/dist/{view/assets/index-B18EbiQt.css → view-export/assets/bundle.css} +1 -1
- package/dist/view-export/assets/bundle.js +225 -0
- package/dist/view-export/index.html +24 -0
- package/package.json +3 -2
- package/templates/.claude/skills/loom-spec/SKILL.md +111 -0
- package/dist/view/assets/index-DAM9J2qS.js +0 -225
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" data-theme="light">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>loom-spec</title>
|
|
7
|
+
<script>
|
|
8
|
+
// Apply persisted theme before paint to avoid flash.
|
|
9
|
+
try {
|
|
10
|
+
const t = localStorage.getItem("loom-theme");
|
|
11
|
+
if (t === "light" || t === "dark") {
|
|
12
|
+
document.documentElement.setAttribute("data-theme", t);
|
|
13
|
+
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
14
|
+
document.documentElement.setAttribute("data-theme", "dark");
|
|
15
|
+
}
|
|
16
|
+
} catch {}
|
|
17
|
+
</script>
|
|
18
|
+
<script type="module" crossorigin src="/assets/bundle.js"></script>
|
|
19
|
+
<link rel="stylesheet" crossorigin href="/assets/bundle.css">
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<div id="root"></div>
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loom-spec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Node-based architecture spec that lives in your repo. AI-readable, AI-writable, git-diffable.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "René Jesser",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"./node-types-schema": "./schema/node-types.schema.json"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
|
-
"build": "tsc -p tsconfig.json && vite build --config src/view/vite.config.ts",
|
|
50
|
+
"build": "tsc -p tsconfig.json && vite build --config src/view/vite.config.ts && vite build --config src/view/vite.config.export.ts",
|
|
51
|
+
"build:export": "vite build --config src/view/vite.config.export.ts",
|
|
51
52
|
"dev": "concurrently -n server,view -c blue,magenta \"pnpm dev:server\" \"pnpm dev:view\"",
|
|
52
53
|
"dev:server": "tsx src/cli/index.ts view --dev --root ../../examples/todo-app --port 7778",
|
|
53
54
|
"dev:view": "vite --config src/view/vite.config.ts",
|
|
@@ -59,6 +59,38 @@ For any task that touches structure:
|
|
|
59
59
|
`<name>.flow.json` instead of cramming it into an existing diagram.
|
|
60
60
|
- Link from the overview with a `drill_down` reference if appropriate.
|
|
61
61
|
|
|
62
|
+
### Tagging hygiene for exports
|
|
63
|
+
|
|
64
|
+
`loom-spec export-html` filters by node `tags` to produce scoped bundles
|
|
65
|
+
(public manual, ops runbook, internal overview). Tagging is the source
|
|
66
|
+
of truth for what ships where. Conventions:
|
|
67
|
+
|
|
68
|
+
- **`public`** — shows up in user-facing documentation. Default-off
|
|
69
|
+
(untagged nodes are *not* in public exports).
|
|
70
|
+
- **`internal`** — explicitly internal; can be used as `--exclude-tag`
|
|
71
|
+
for public exports, or as `--include-tag` for an internal-only bundle.
|
|
72
|
+
- **`ops`** — for operational runbooks (deploy paths, monitoring,
|
|
73
|
+
on-call docs).
|
|
74
|
+
- **`wip`** — work-in-progress; always exclude from any export.
|
|
75
|
+
|
|
76
|
+
When you set `tags: ["public"]` on a node, remember the cascade:
|
|
77
|
+
|
|
78
|
+
- Edges between two `public` nodes survive. Edges where one endpoint is
|
|
79
|
+
untagged are **dropped** in the public export. If the user-facing
|
|
80
|
+
flow depends on an "internal" node visually, either tag that node
|
|
81
|
+
`public` too or accept the dangling visualisation.
|
|
82
|
+
- A group with no `public` children disappears entirely.
|
|
83
|
+
- A `drill_down` chevron pointing at a diagram that has zero `public`
|
|
84
|
+
nodes is removed (the diagram doesn't ship).
|
|
85
|
+
|
|
86
|
+
**Security check before tagging `public`:** look at the node's
|
|
87
|
+
`code_refs[].path` and `description`. Tags filter nodes, not their
|
|
88
|
+
content. If a `code_ref` points at `src/server/admin/secrets.ts` or
|
|
89
|
+
the description names an internal system, that *text* ships in the
|
|
90
|
+
public export. Either remove the sensitive ref / rewrite the
|
|
91
|
+
description, or split the node into a public surface and an internal
|
|
92
|
+
implementation node and tag accordingly.
|
|
93
|
+
|
|
62
94
|
## Preferred tools (when the MCP server is wired up)
|
|
63
95
|
|
|
64
96
|
If a `loom-spec` MCP server is registered with the host (e.g. via
|
|
@@ -78,6 +110,16 @@ re-reading + re-writing JSON on every mutation.
|
|
|
78
110
|
If the MCP server is not available, edit the JSON files directly using the
|
|
79
111
|
rules above — the format is stable and tools-agnostic by design.
|
|
80
112
|
|
|
113
|
+
For exporting the spec to a self-contained interactive HTML (for manuals,
|
|
114
|
+
docs sites, GitHub Pages, embed-in-Notion, etc.), use the CLI:
|
|
115
|
+
|
|
116
|
+
- `loom-spec export-html` (full export)
|
|
117
|
+
- `loom-spec export-html <bundle-name>` (from `.loom/exports.json`)
|
|
118
|
+
- `loom-spec export-html --include-tag public --no-timelines --out manual.html`
|
|
119
|
+
(ad-hoc filter)
|
|
120
|
+
|
|
121
|
+
See Example 7 for the full workflow.
|
|
122
|
+
|
|
81
123
|
---
|
|
82
124
|
|
|
83
125
|
## Examples
|
|
@@ -338,6 +380,67 @@ loom_validate()
|
|
|
338
380
|
**Don't create a timeline for static structure** — that's what diagrams are
|
|
339
381
|
for. A timeline of "the app boots, then runs forever" adds noise.
|
|
340
382
|
|
|
383
|
+
### 7. User wants to publish architecture docs to a manual
|
|
384
|
+
|
|
385
|
+
> User: "We need to ship the checkout flow as an interactive diagram in
|
|
386
|
+
> our public user manual. Don't expose anything internal."
|
|
387
|
+
|
|
388
|
+
```
|
|
389
|
+
# Step 1: Identify which nodes belong in the public manual.
|
|
390
|
+
loom_read_diagram("overview")
|
|
391
|
+
# → review nodes; confirm with the user if scope is unclear
|
|
392
|
+
|
|
393
|
+
# Step 2: Tag the public-facing surface. Skip anything that exposes
|
|
394
|
+
# internal services, security-sensitive paths, or work-in-progress.
|
|
395
|
+
loom_update_node({ diagram: "overview", id: "checkout-page",
|
|
396
|
+
patch: { tags: ["public"] } })
|
|
397
|
+
loom_update_node({ diagram: "overview", id: "checkout-api",
|
|
398
|
+
patch: { tags: ["public"] } })
|
|
399
|
+
loom_update_node({ diagram: "overview", id: "payments-service",
|
|
400
|
+
patch: { tags: ["public"] } })
|
|
401
|
+
# … but NOT fraud-screening, admin-tools, internal-billing, etc.
|
|
402
|
+
|
|
403
|
+
# Step 3: Verify the tag set covers a connected slice. Edges between
|
|
404
|
+
# two public nodes survive; edges to untagged neighbours get dropped
|
|
405
|
+
# in the export. If the export would have orphans, either tag the
|
|
406
|
+
# missing neighbour or accept that the link disappears.
|
|
407
|
+
|
|
408
|
+
# Step 4: Write a named bundle to .loom/exports.json so the export is
|
|
409
|
+
# reproducible. (No MCP tool for this yet — write the file directly.)
|
|
410
|
+
#
|
|
411
|
+
# .loom/exports.json
|
|
412
|
+
{
|
|
413
|
+
"exports": {
|
|
414
|
+
"user-manual": {
|
|
415
|
+
"include-tags": ["public"],
|
|
416
|
+
"exclude-tags": ["wip"],
|
|
417
|
+
"no-timelines": true,
|
|
418
|
+
"out": "docs/architecture.html"
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
# Step 5: Generate the HTML.
|
|
424
|
+
# (Shell, not MCP — agents can invoke via Bash tool or similar.)
|
|
425
|
+
$ loom-spec export-html user-manual
|
|
426
|
+
|
|
427
|
+
# Step 6: Sanity-check the output. Open docs/architecture.html in a
|
|
428
|
+
# browser and confirm: no internal node names visible, no surprising
|
|
429
|
+
# code_refs paths leaked in the inspector, the flow makes sense as a
|
|
430
|
+
# standalone visualisation.
|
|
431
|
+
```
|
|
432
|
+
|
|
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
|
+
**Don't auto-publish** — the export is intentional. A `git add` of the
|
|
441
|
+
generated `.html` belongs in the change that updates the architecture,
|
|
442
|
+
not in an automated commit triggered by every `.loom/` edit.
|
|
443
|
+
|
|
341
444
|
---
|
|
342
445
|
|
|
343
446
|
## Format reference
|
|
@@ -364,3 +467,11 @@ for. A timeline of "the app boots, then runs forever" adds noise.
|
|
|
364
467
|
**flow**.
|
|
365
468
|
- Don't leave `drill_down` pointing at a non-existent diagram id.
|
|
366
469
|
- Don't `loom_delete_node` for code that was just removed — `mark_stale` it.
|
|
470
|
+
- Don't tag everything `public` "just in case" — the value of a tag is
|
|
471
|
+
that it means something. If `public` is on every node, scoped exports
|
|
472
|
+
stop being scoped.
|
|
473
|
+
- Don't manually edit the generated `.html` from `export-html` — re-run
|
|
474
|
+
the export instead. Edits to the generated file are lost on the next
|
|
475
|
+
run and obscure the source of truth.
|
|
476
|
+
- Don't add `loom-spec export-html` to `init` defaults or auto-run it
|
|
477
|
+
from a hook. Exports are intentional, not background.
|