living-ai-documentation 1.0.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.
Files changed (203) hide show
  1. package/LICENSE +661 -0
  2. package/README.fr.md +344 -0
  3. package/README.md +344 -0
  4. package/dist/bin/cli.d.ts +3 -0
  5. package/dist/bin/cli.d.ts.map +1 -0
  6. package/dist/bin/cli.js +262 -0
  7. package/dist/bin/cli.js.map +1 -0
  8. package/dist/src/frontend/accuracy-gauge.js +70 -0
  9. package/dist/src/frontend/admin.html +1532 -0
  10. package/dist/src/frontend/annotations.js +585 -0
  11. package/dist/src/frontend/boot.js +101 -0
  12. package/dist/src/frontend/config.js +29 -0
  13. package/dist/src/frontend/confirm-modal.js +82 -0
  14. package/dist/src/frontend/context.html +1252 -0
  15. package/dist/src/frontend/dark-mode.js +20 -0
  16. package/dist/src/frontend/diagram/alignment.js +161 -0
  17. package/dist/src/frontend/diagram/clipboard.js +187 -0
  18. package/dist/src/frontend/diagram/constants.js +109 -0
  19. package/dist/src/frontend/diagram/custom-shapes.js +104 -0
  20. package/dist/src/frontend/diagram/debug.js +43 -0
  21. package/dist/src/frontend/diagram/drawio-export.js +649 -0
  22. package/dist/src/frontend/diagram/edge-panel.js +293 -0
  23. package/dist/src/frontend/diagram/edge-rendering.js +12 -0
  24. package/dist/src/frontend/diagram/evidence.js +146 -0
  25. package/dist/src/frontend/diagram/grid.js +78 -0
  26. package/dist/src/frontend/diagram/groups.js +102 -0
  27. package/dist/src/frontend/diagram/history.js +157 -0
  28. package/dist/src/frontend/diagram/image-name-modal.js +48 -0
  29. package/dist/src/frontend/diagram/image-upload.js +36 -0
  30. package/dist/src/frontend/diagram/label-editor.js +115 -0
  31. package/dist/src/frontend/diagram/link-panel.js +144 -0
  32. package/dist/src/frontend/diagram/main.js +364 -0
  33. package/dist/src/frontend/diagram/network.js +2214 -0
  34. package/dist/src/frontend/diagram/node-panel.js +389 -0
  35. package/dist/src/frontend/diagram/node-rendering.js +964 -0
  36. package/dist/src/frontend/diagram/persistence.js +168 -0
  37. package/dist/src/frontend/diagram/ports.js +421 -0
  38. package/dist/src/frontend/diagram/selection-overlay.js +387 -0
  39. package/dist/src/frontend/diagram/state.js +43 -0
  40. package/dist/src/frontend/diagram/t.js +3 -0
  41. package/dist/src/frontend/diagram/toast.js +21 -0
  42. package/dist/src/frontend/diagram/unlock-hold.js +206 -0
  43. package/dist/src/frontend/diagram/zoom.js +20 -0
  44. package/dist/src/frontend/diagram-link-modal.js +137 -0
  45. package/dist/src/frontend/diagram.html +1494 -0
  46. package/dist/src/frontend/documents.js +479 -0
  47. package/dist/src/frontend/export.js +338 -0
  48. package/dist/src/frontend/file-attach.js +178 -0
  49. package/dist/src/frontend/files-modal.js +243 -0
  50. package/dist/src/frontend/i18n/en.json +624 -0
  51. package/dist/src/frontend/i18n/fr.json +624 -0
  52. package/dist/src/frontend/i18n.js +32 -0
  53. package/dist/src/frontend/image-paste.js +126 -0
  54. package/dist/src/frontend/index.html +2806 -0
  55. package/dist/src/frontend/local-search.js +476 -0
  56. package/dist/src/frontend/metadata.js +318 -0
  57. package/dist/src/frontend/misc.js +92 -0
  58. package/dist/src/frontend/new-doc-modal.js +285 -0
  59. package/dist/src/frontend/new-folder-modal.js +169 -0
  60. package/dist/src/frontend/search.js +194 -0
  61. package/dist/src/frontend/shape-editor.html +685 -0
  62. package/dist/src/frontend/sidebar-helpers.js +96 -0
  63. package/dist/src/frontend/sidebar-resize.js +98 -0
  64. package/dist/src/frontend/sidebar.js +351 -0
  65. package/dist/src/frontend/snippet-detect.js +25 -0
  66. package/dist/src/frontend/snippet-table.js +85 -0
  67. package/dist/src/frontend/snippet-tree.js +94 -0
  68. package/dist/src/frontend/snippets.js +1146 -0
  69. package/dist/src/frontend/state.js +46 -0
  70. package/dist/src/frontend/utils.js +21 -0
  71. package/dist/src/frontend/validate.js +107 -0
  72. package/dist/src/frontend/vendor/wordcloud2.js +1187 -0
  73. package/dist/src/frontend/wordcloud.js +693 -0
  74. package/dist/src/lib/config.d.ts +26 -0
  75. package/dist/src/lib/config.d.ts.map +1 -0
  76. package/dist/src/lib/config.js +195 -0
  77. package/dist/src/lib/config.js.map +1 -0
  78. package/dist/src/lib/hash.d.ts +2 -0
  79. package/dist/src/lib/hash.d.ts.map +1 -0
  80. package/dist/src/lib/hash.js +18 -0
  81. package/dist/src/lib/hash.js.map +1 -0
  82. package/dist/src/lib/metadata.d.ts +31 -0
  83. package/dist/src/lib/metadata.d.ts.map +1 -0
  84. package/dist/src/lib/metadata.js +128 -0
  85. package/dist/src/lib/metadata.js.map +1 -0
  86. package/dist/src/lib/parser.d.ts +11 -0
  87. package/dist/src/lib/parser.d.ts.map +1 -0
  88. package/dist/src/lib/parser.js +111 -0
  89. package/dist/src/lib/parser.js.map +1 -0
  90. package/dist/src/lib/status.d.ts +9 -0
  91. package/dist/src/lib/status.d.ts.map +1 -0
  92. package/dist/src/lib/status.js +72 -0
  93. package/dist/src/lib/status.js.map +1 -0
  94. package/dist/src/mcp/server.d.ts +3 -0
  95. package/dist/src/mcp/server.d.ts.map +1 -0
  96. package/dist/src/mcp/server.js +2046 -0
  97. package/dist/src/mcp/server.js.map +1 -0
  98. package/dist/src/mcp/tools/diagrams.d.ts +82 -0
  99. package/dist/src/mcp/tools/diagrams.d.ts.map +1 -0
  100. package/dist/src/mcp/tools/diagrams.js +594 -0
  101. package/dist/src/mcp/tools/diagrams.js.map +1 -0
  102. package/dist/src/mcp/tools/documents.d.ts +44 -0
  103. package/dist/src/mcp/tools/documents.d.ts.map +1 -0
  104. package/dist/src/mcp/tools/documents.js +186 -0
  105. package/dist/src/mcp/tools/documents.js.map +1 -0
  106. package/dist/src/mcp/tools/git.d.ts +10 -0
  107. package/dist/src/mcp/tools/git.d.ts.map +1 -0
  108. package/dist/src/mcp/tools/git.js +217 -0
  109. package/dist/src/mcp/tools/git.js.map +1 -0
  110. package/dist/src/mcp/tools/metadata.d.ts +57 -0
  111. package/dist/src/mcp/tools/metadata.d.ts.map +1 -0
  112. package/dist/src/mcp/tools/metadata.js +222 -0
  113. package/dist/src/mcp/tools/metadata.js.map +1 -0
  114. package/dist/src/mcp/tools/source.d.ts +29 -0
  115. package/dist/src/mcp/tools/source.d.ts.map +1 -0
  116. package/dist/src/mcp/tools/source.js +196 -0
  117. package/dist/src/mcp/tools/source.js.map +1 -0
  118. package/dist/src/routes/annotations.d.ts +3 -0
  119. package/dist/src/routes/annotations.d.ts.map +1 -0
  120. package/dist/src/routes/annotations.js +83 -0
  121. package/dist/src/routes/annotations.js.map +1 -0
  122. package/dist/src/routes/browse-source.d.ts +3 -0
  123. package/dist/src/routes/browse-source.d.ts.map +1 -0
  124. package/dist/src/routes/browse-source.js +79 -0
  125. package/dist/src/routes/browse-source.js.map +1 -0
  126. package/dist/src/routes/browse.d.ts +3 -0
  127. package/dist/src/routes/browse.d.ts.map +1 -0
  128. package/dist/src/routes/browse.js +91 -0
  129. package/dist/src/routes/browse.js.map +1 -0
  130. package/dist/src/routes/config.d.ts +3 -0
  131. package/dist/src/routes/config.d.ts.map +1 -0
  132. package/dist/src/routes/config.js +145 -0
  133. package/dist/src/routes/config.js.map +1 -0
  134. package/dist/src/routes/context.d.ts +3 -0
  135. package/dist/src/routes/context.d.ts.map +1 -0
  136. package/dist/src/routes/context.js +287 -0
  137. package/dist/src/routes/context.js.map +1 -0
  138. package/dist/src/routes/diagrams.d.ts +3 -0
  139. package/dist/src/routes/diagrams.d.ts.map +1 -0
  140. package/dist/src/routes/diagrams.js +69 -0
  141. package/dist/src/routes/diagrams.js.map +1 -0
  142. package/dist/src/routes/documents.d.ts +11 -0
  143. package/dist/src/routes/documents.d.ts.map +1 -0
  144. package/dist/src/routes/documents.js +450 -0
  145. package/dist/src/routes/documents.js.map +1 -0
  146. package/dist/src/routes/export.d.ts +3 -0
  147. package/dist/src/routes/export.d.ts.map +1 -0
  148. package/dist/src/routes/export.js +280 -0
  149. package/dist/src/routes/export.js.map +1 -0
  150. package/dist/src/routes/files.d.ts +3 -0
  151. package/dist/src/routes/files.d.ts.map +1 -0
  152. package/dist/src/routes/files.js +180 -0
  153. package/dist/src/routes/files.js.map +1 -0
  154. package/dist/src/routes/images.d.ts +3 -0
  155. package/dist/src/routes/images.d.ts.map +1 -0
  156. package/dist/src/routes/images.js +49 -0
  157. package/dist/src/routes/images.js.map +1 -0
  158. package/dist/src/routes/metadata.d.ts +3 -0
  159. package/dist/src/routes/metadata.d.ts.map +1 -0
  160. package/dist/src/routes/metadata.js +131 -0
  161. package/dist/src/routes/metadata.js.map +1 -0
  162. package/dist/src/routes/shape-libraries.d.ts +3 -0
  163. package/dist/src/routes/shape-libraries.d.ts.map +1 -0
  164. package/dist/src/routes/shape-libraries.js +118 -0
  165. package/dist/src/routes/shape-libraries.js.map +1 -0
  166. package/dist/src/routes/wordcloud.d.ts +3 -0
  167. package/dist/src/routes/wordcloud.d.ts.map +1 -0
  168. package/dist/src/routes/wordcloud.js +95 -0
  169. package/dist/src/routes/wordcloud.js.map +1 -0
  170. package/dist/src/server.d.ts +7 -0
  171. package/dist/src/server.d.ts.map +1 -0
  172. package/dist/src/server.js +93 -0
  173. package/dist/src/server.js.map +1 -0
  174. package/dist/starter-doc/.living-doc.json +52 -0
  175. package/dist/starter-doc/ADRS/2026_01_01_[ADR]_example_architecture_decision.md +59 -0
  176. package/dist/starter-doc/AI/2026_01_01_how_to.md +112 -0
  177. package/dist/starter-doc/AI/PROJECT-INSTRUCTIONS.md +172 -0
  178. package/dist/starter-doc/AI/PROJECT-STACK.md +77 -0
  179. package/dist/starter-doc/AI/PROJECT-USEFUL-COMMANDS.md +80 -0
  180. package/dist/starter-doc/AI/default/AGENTS.md +31 -0
  181. package/dist/starter-doc/AI/default/CLAUDE.md +31 -0
  182. package/dist/starter-doc/AI/default/MEMORY.md +24 -0
  183. package/dist/starter-doc/AI/rules/no-magic-numbers.md +18 -0
  184. package/dist/starter-doc/AI/rules/track-current-work.md +23 -0
  185. package/dist/starter-doc/WORKLOG/current-task.md +57 -0
  186. package/dist/starter-doc-fr/.living-doc.json +52 -0
  187. package/dist/starter-doc-fr/ADRS/2026_01_01_[ADR]_example_architecture_decision.md +59 -0
  188. package/dist/starter-doc-fr/AI/2026_01_01_how_to.md +100 -0
  189. package/dist/starter-doc-fr/AI/PROJECT-INSTRUCTIONS.md +172 -0
  190. package/dist/starter-doc-fr/AI/PROJECT-STACK.md +77 -0
  191. package/dist/starter-doc-fr/AI/PROJECT-USEFUL-COMMANDS.md +80 -0
  192. package/dist/starter-doc-fr/AI/default/AGENTS.md +31 -0
  193. package/dist/starter-doc-fr/AI/default/CLAUDE.md +31 -0
  194. package/dist/starter-doc-fr/AI/default/MEMORY.md +24 -0
  195. package/dist/starter-doc-fr/AI/rules/no-magic-numbers.md +18 -0
  196. package/dist/starter-doc-fr/AI/rules/track-current-work.md +23 -0
  197. package/dist/starter-doc-fr/WORKLOG/current-task.md +57 -0
  198. package/images/living_documentation.jpg +0 -0
  199. package/images/readme-extra-files.png +0 -0
  200. package/images/readme-filename-pattern.png +0 -0
  201. package/images/readme-intelligent-search-demo.jpg +0 -0
  202. package/images/readme-sidebar.png +0 -0
  203. package/package.json +72 -0
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.metadataRouter = metadataRouter;
7
+ const express_1 = require("express");
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const metadata_1 = require("../lib/metadata");
11
+ const hash_1 = require("../lib/hash");
12
+ const status_1 = require("../lib/status");
13
+ // SuperSeeded documents are read-only as far as metadata is concerned: an ADR
14
+ // that has been replaced should keep the source bindings that prove what the
15
+ // original decision described, frozen at the moment of supersession. The guard
16
+ // itself lives in `lib/status.ts` so MCP tools share the same check.
17
+ function rejectIfSuperSeeded(docsPath, docId, res) {
18
+ try {
19
+ (0, status_1.assertNotSuperSeeded)(docsPath, docId);
20
+ return false;
21
+ }
22
+ catch (err) {
23
+ if (err instanceof status_1.DocumentSuperSeededError) {
24
+ res.status(403).json({ error: err.message });
25
+ return true;
26
+ }
27
+ throw err;
28
+ }
29
+ }
30
+ function metadataRouter(docsPath) {
31
+ const router = (0, express_1.Router)();
32
+ // GET /api/metadata/:docId → { items, total, unchanged, modified, missing, accuracy }
33
+ router.get("/:docId", (req, res) => {
34
+ const docId = decodeURIComponent(req.params.docId);
35
+ try {
36
+ const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
37
+ const entries = (0, metadata_1.getDocEntries)(docsPath, docId);
38
+ const report = (0, metadata_1.buildReport)(entries, sourceRoot);
39
+ res.json(report);
40
+ }
41
+ catch (err) {
42
+ res
43
+ .status(500)
44
+ .json({ error: err instanceof Error ? err.message : String(err) });
45
+ }
46
+ });
47
+ // POST /api/metadata/:docId body: { path }
48
+ router.post("/:docId", (req, res) => {
49
+ const docId = decodeURIComponent(req.params.docId);
50
+ if (rejectIfSuperSeeded(docsPath, docId, res))
51
+ return;
52
+ const { path: rawPath } = req.body;
53
+ if (!rawPath || typeof rawPath !== "string") {
54
+ return res.status(400).json({ error: "path is required" });
55
+ }
56
+ try {
57
+ const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
58
+ const rel = (0, metadata_1.assertUnderSourceRoot)(rawPath, sourceRoot);
59
+ const abs = path_1.default.resolve(sourceRoot, rel);
60
+ if (!fs_1.default.existsSync(abs) || !fs_1.default.statSync(abs).isFile()) {
61
+ return res.status(400).json({ error: "Not a readable file" });
62
+ }
63
+ const hash = (0, hash_1.sha256File)(abs);
64
+ if (!hash)
65
+ return res.status(500).json({ error: "Failed to hash file" });
66
+ const entries = (0, metadata_1.getDocEntries)(docsPath, docId);
67
+ // replace if path already exists, else append
68
+ const idx = entries.findIndex((e) => e.path === rel);
69
+ const entry = { path: rel, hash };
70
+ if (idx >= 0)
71
+ entries[idx] = entry;
72
+ else
73
+ entries.push(entry);
74
+ (0, metadata_1.setDocEntries)(docsPath, docId, entries);
75
+ const report = (0, metadata_1.buildReport)(entries, sourceRoot);
76
+ res.json(report);
77
+ }
78
+ catch (err) {
79
+ res
80
+ .status(400)
81
+ .json({ error: err instanceof Error ? err.message : String(err) });
82
+ }
83
+ });
84
+ // DELETE /api/metadata/:docId body: { path }
85
+ router.delete("/:docId", (req, res) => {
86
+ const docId = decodeURIComponent(req.params.docId);
87
+ if (rejectIfSuperSeeded(docsPath, docId, res))
88
+ return;
89
+ const { path: rel } = req.body;
90
+ if (!rel)
91
+ return res.status(400).json({ error: "path is required" });
92
+ try {
93
+ const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
94
+ const entries = (0, metadata_1.getDocEntries)(docsPath, docId).filter((e) => e.path !== rel);
95
+ (0, metadata_1.setDocEntries)(docsPath, docId, entries);
96
+ const report = (0, metadata_1.buildReport)(entries, sourceRoot);
97
+ res.json(report);
98
+ }
99
+ catch (err) {
100
+ res
101
+ .status(500)
102
+ .json({ error: err instanceof Error ? err.message : String(err) });
103
+ }
104
+ });
105
+ // POST /api/metadata/:docId/refresh → recompute stored hashes from current file state
106
+ router.post("/:docId/refresh", (req, res) => {
107
+ const docId = decodeURIComponent(req.params.docId);
108
+ if (rejectIfSuperSeeded(docsPath, docId, res))
109
+ return;
110
+ try {
111
+ const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
112
+ const entries = (0, metadata_1.getDocEntries)(docsPath, docId).map((e) => {
113
+ const abs = path_1.default.resolve(sourceRoot, e.path);
114
+ if (!fs_1.default.existsSync(abs))
115
+ return e; // keep stored hash, still "missing"
116
+ const fresh = (0, hash_1.sha256File)(abs);
117
+ return fresh ? { path: e.path, hash: fresh } : e;
118
+ });
119
+ (0, metadata_1.setDocEntries)(docsPath, docId, entries);
120
+ const report = (0, metadata_1.buildReport)(entries, sourceRoot);
121
+ res.json(report);
122
+ }
123
+ catch (err) {
124
+ res
125
+ .status(500)
126
+ .json({ error: err instanceof Error ? err.message : String(err) });
127
+ }
128
+ });
129
+ return router;
130
+ }
131
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/routes/metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Router } from "express";
2
+ export declare function shapeLibrariesRouter(docsPath: string): Router;
3
+ //# sourceMappingURL=shape-libraries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape-libraries.d.ts","sourceRoot":"","sources":["../../../src/routes/shape-libraries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAoJjC,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAc7D"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.shapeLibrariesRouter = shapeLibrariesRouter;
7
+ const express_1 = require("express");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const FILE_NAME = ".shape-libraries.json";
11
+ const CUSTOM_SHAPE_DEFAULT_SIZE = 65;
12
+ const CUSTOM_SHAPE_MIN_SIZE = 16;
13
+ const CUSTOM_SHAPE_MAX_SIZE = 1200;
14
+ function filePath(docsPath) {
15
+ return path_1.default.join(docsPath, FILE_NAME);
16
+ }
17
+ function loadStore(docsPath) {
18
+ const fp = filePath(docsPath);
19
+ if (!fs_1.default.existsSync(fp))
20
+ return { libraries: [] };
21
+ try {
22
+ const raw = JSON.parse(fs_1.default.readFileSync(fp, "utf-8"));
23
+ return sanitizeStore(raw);
24
+ }
25
+ catch {
26
+ return { libraries: [] };
27
+ }
28
+ }
29
+ function saveStore(docsPath, store) {
30
+ fs_1.default.writeFileSync(filePath(docsPath), JSON.stringify(sanitizeStore(store), null, 2), "utf-8");
31
+ }
32
+ function clamp01(n) {
33
+ return Math.max(0, Math.min(1, typeof n === "number" && Number.isFinite(n) ? n : 0));
34
+ }
35
+ function safeId(value, fallback) {
36
+ if (typeof value !== "string")
37
+ return fallback;
38
+ const clean = value
39
+ .trim()
40
+ .replace(/[^a-zA-Z0-9_-]/g, "-")
41
+ .slice(0, 80);
42
+ return clean || fallback;
43
+ }
44
+ function safeName(value, fallback) {
45
+ if (typeof value !== "string")
46
+ return fallback;
47
+ const clean = value.trim().slice(0, 120);
48
+ return clean || fallback;
49
+ }
50
+ function safeLabelPlacement(value) {
51
+ return ["center", "below", "above", "right", "left"].includes(String(value))
52
+ ? value
53
+ : "below";
54
+ }
55
+ function safeDimension(value) {
56
+ return typeof value === "number" && Number.isFinite(value)
57
+ ? Math.max(CUSTOM_SHAPE_MIN_SIZE, Math.min(CUSTOM_SHAPE_MAX_SIZE, Math.round(value)))
58
+ : CUSTOM_SHAPE_DEFAULT_SIZE;
59
+ }
60
+ function sanitizeStore(raw) {
61
+ const obj = raw && typeof raw === "object" ? raw : {};
62
+ const rawLibraries = Array.isArray(obj.libraries) ? obj.libraries : [];
63
+ const libraries = rawLibraries.map((lib, libIndex) => {
64
+ const libObj = lib && typeof lib === "object" ? lib : {};
65
+ const shapesRaw = Array.isArray(libObj.shapes) ? libObj.shapes : [];
66
+ return {
67
+ id: safeId(libObj.id, `lib-${libIndex + 1}`),
68
+ name: safeName(libObj.name, `Library ${libIndex + 1}`),
69
+ shapes: shapesRaw
70
+ .map((shape, shapeIndex) => {
71
+ const shapeObj = shape && typeof shape === "object"
72
+ ? shape
73
+ : {};
74
+ const anchorsRaw = Array.isArray(shapeObj.anchors)
75
+ ? shapeObj.anchors
76
+ : [];
77
+ const width = safeDimension(shapeObj.width);
78
+ const height = safeDimension(shapeObj.height);
79
+ return {
80
+ id: safeId(shapeObj.id, `shape-${shapeIndex + 1}`),
81
+ name: safeName(shapeObj.name, `Shape ${shapeIndex + 1}`),
82
+ imageSrc: typeof shapeObj.imageSrc === "string" ? shapeObj.imageSrc : "",
83
+ width,
84
+ height,
85
+ labelPlacement: safeLabelPlacement(shapeObj.labelPlacement),
86
+ showInDiagram: shapeObj.showInDiagram !== false,
87
+ anchors: anchorsRaw
88
+ .map((anchor, anchorIndex) => {
89
+ const anchorObj = anchor && typeof anchor === "object"
90
+ ? anchor
91
+ : {};
92
+ return {
93
+ id: safeId(anchorObj.id, `p${anchorIndex + 1}`),
94
+ x: clamp01(anchorObj.x),
95
+ y: clamp01(anchorObj.y),
96
+ };
97
+ })
98
+ .filter((anchor) => anchor.id),
99
+ };
100
+ })
101
+ .filter((shape) => shape.imageSrc),
102
+ };
103
+ });
104
+ return { libraries };
105
+ }
106
+ function shapeLibrariesRouter(docsPath) {
107
+ const router = (0, express_1.Router)();
108
+ router.get("/", (_req, res) => {
109
+ res.json(loadStore(docsPath));
110
+ });
111
+ router.put("/", (req, res) => {
112
+ const store = sanitizeStore(req.body);
113
+ saveStore(docsPath, store);
114
+ res.json(store);
115
+ });
116
+ return router;
117
+ }
118
+ //# sourceMappingURL=shape-libraries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape-libraries.js","sourceRoot":"","sources":["../../../src/routes/shape-libraries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Router } from 'express';
2
+ export declare function wordcloudRouter(): Router;
3
+ //# sourceMappingURL=wordcloud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordcloud.d.ts","sourceRoot":"","sources":["../../../src/routes/wordcloud.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAoCpD,wBAAgB,eAAe,IAAI,MAAM,CAiDxC"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.wordcloudRouter = wordcloudRouter;
7
+ const express_1 = require("express");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const SKIP_DIRS = new Set([
11
+ 'node_modules', '.git', '.idea', '.vscode', '__pycache__',
12
+ 'target', 'build', 'dist', '.next', 'vendor', '.gradle',
13
+ 'out', 'coverage', '.cache', 'tmp', '.tmp', '.turbo',
14
+ '.svelte-kit', '.nuxt', '.output', 'storybook-static',
15
+ 'public', 'static', '.vercel', '.netlify',
16
+ ]);
17
+ function collectFiles(dir, exts, excludeDirs, rootDir, out = []) {
18
+ let entries;
19
+ try {
20
+ entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
21
+ }
22
+ catch {
23
+ return out;
24
+ }
25
+ for (const e of entries) {
26
+ if (e.isDirectory()) {
27
+ if (e.name.startsWith('.') || SKIP_DIRS.has(e.name))
28
+ continue;
29
+ const relPath = path_1.default.relative(rootDir, path_1.default.join(dir, e.name));
30
+ if (excludeDirs.has(e.name) || excludeDirs.has(relPath))
31
+ continue;
32
+ collectFiles(path_1.default.join(dir, e.name), exts, excludeDirs, rootDir, out);
33
+ }
34
+ else if (e.isFile()) {
35
+ const ext = path_1.default.extname(e.name).slice(1).toLowerCase();
36
+ if (!exts.includes(ext))
37
+ continue;
38
+ const relPath = path_1.default.relative(rootDir, path_1.default.join(dir, e.name));
39
+ if (excludeDirs.has(e.name) || excludeDirs.has(relPath))
40
+ continue;
41
+ out.push(path_1.default.join(dir, e.name));
42
+ }
43
+ }
44
+ return out;
45
+ }
46
+ function wordcloudRouter() {
47
+ const router = (0, express_1.Router)();
48
+ // GET /api/wordcloud?path=<absolute_path>&ext=md&ext=ts&ext=java
49
+ // Returns { files: number, fileTexts: [{path, text}] }
50
+ router.get('/', (req, res) => {
51
+ const rawPath = req.query.path || '/';
52
+ const target = path_1.default.resolve(rawPath);
53
+ // Parse params directly from the raw query string to avoid qs object coercion.
54
+ const rawQuery = req.url.split('?')[1] || '';
55
+ const qp = new URLSearchParams(rawQuery);
56
+ const exts = qp.getAll('ext')
57
+ .map((e) => e.toLowerCase().replace(/^\./, ''))
58
+ .filter(Boolean);
59
+ if (!exts.length)
60
+ exts.push('md');
61
+ const excludeDirs = new Set(qp.getAll('exclude').map((d) => d.replace(/\/$/, '')).filter(Boolean));
62
+ let stat;
63
+ try {
64
+ stat = fs_1.default.statSync(target);
65
+ }
66
+ catch {
67
+ res.status(400).json({ error: 'Path not found' });
68
+ return;
69
+ }
70
+ let files;
71
+ if (stat.isFile()) {
72
+ const ext = path_1.default.extname(target).slice(1).toLowerCase();
73
+ files = exts.includes(ext) ? [target] : [];
74
+ }
75
+ else if (stat.isDirectory()) {
76
+ files = collectFiles(target, exts, excludeDirs, target);
77
+ }
78
+ else {
79
+ res.status(400).json({ error: 'Path must be a directory or a file' });
80
+ return;
81
+ }
82
+ const fileTexts = files.map((f) => ({
83
+ path: path_1.default.relative(target, f),
84
+ text: (() => { try {
85
+ return fs_1.default.readFileSync(f, 'utf-8');
86
+ }
87
+ catch {
88
+ return '';
89
+ } })(),
90
+ }));
91
+ res.json({ files: files.length, fileTexts });
92
+ });
93
+ return router;
94
+ }
95
+ //# sourceMappingURL=wordcloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wordcloud.js","sourceRoot":"","sources":["../../../src/routes/wordcloud.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface ServerOptions {
2
+ docsPath: string;
3
+ port: number;
4
+ openBrowser?: boolean;
5
+ }
6
+ export declare function startServer({ docsPath, port, openBrowser, }: ServerOptions): Promise<void>;
7
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,EAChC,QAAQ,EACR,IAAI,EACJ,WAAmB,GACpB,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E/B"}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startServer = startServer;
7
+ const express_1 = __importDefault(require("express"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const child_process_1 = require("child_process");
10
+ const documents_1 = require("./routes/documents");
11
+ const config_1 = require("./routes/config");
12
+ const browse_1 = require("./routes/browse");
13
+ const images_1 = require("./routes/images");
14
+ const files_1 = require("./routes/files");
15
+ const diagrams_1 = require("./routes/diagrams");
16
+ const shape_libraries_1 = require("./routes/shape-libraries");
17
+ const wordcloud_1 = require("./routes/wordcloud");
18
+ const annotations_1 = require("./routes/annotations");
19
+ const metadata_1 = require("./routes/metadata");
20
+ const browse_source_1 = require("./routes/browse-source");
21
+ const export_1 = require("./routes/export");
22
+ const context_1 = require("./routes/context");
23
+ const server_1 = require("./mcp/server");
24
+ const config_2 = require("./lib/config");
25
+ const activeServers = new Set();
26
+ async function startServer({ docsPath, port, openBrowser = false, }) {
27
+ const app = (0, express_1.default)();
28
+ app.use(express_1.default.json({ limit: '20mb' }));
29
+ // Persist port to .living-doc.json; readAndMigrate runs here and strips any legacy absolute paths.
30
+ (0, config_2.writeConfig)(docsPath, { port });
31
+ // API
32
+ app.use('/api/documents', (0, documents_1.documentsRouter)(docsPath));
33
+ app.use('/api/config', (0, config_1.configRouter)(docsPath));
34
+ app.use('/api/browse', (0, browse_1.browseRouter)(docsPath));
35
+ app.use('/api/images', (0, images_1.imagesRouter)(docsPath));
36
+ app.use('/api/files', (0, files_1.filesRouter)(docsPath));
37
+ app.use('/api/diagrams', (0, diagrams_1.diagramsRouter)(docsPath));
38
+ app.use('/api/shape-libraries', (0, shape_libraries_1.shapeLibrariesRouter)(docsPath));
39
+ app.use('/api/wordcloud', (0, wordcloud_1.wordcloudRouter)());
40
+ app.use('/api/annotations', (0, annotations_1.annotationsRouter)(docsPath));
41
+ app.use('/api/metadata', (0, metadata_1.metadataRouter)(docsPath));
42
+ app.use('/api/browse-source', (0, browse_source_1.browseSourceRouter)(docsPath));
43
+ app.use('/api/export', (0, export_1.exportRouter)(docsPath));
44
+ app.use('/api/context', (0, context_1.contextRouter)(docsPath));
45
+ app.use('/mcp', (0, server_1.mcpRouter)(docsPath));
46
+ // Static frontend assets
47
+ // dotfiles: 'allow' so the npx cache (~/.npm/_npx/...) doesn't trip send's
48
+ // dotfile guard on the .npm path segment and 404 every asset.
49
+ const frontendPath = path_1.default.join(__dirname, 'frontend');
50
+ app.use(express_1.default.static(frontendPath, { dotfiles: 'allow' }));
51
+ // Static assets from docs folder (images, etc.)
52
+ app.use('/images', express_1.default.static(path_1.default.join(docsPath, 'images'), { dotfiles: 'allow' }));
53
+ app.use('/files', express_1.default.static(path_1.default.join(docsPath, 'files'), { dotfiles: 'allow' }));
54
+ app.get('/', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'index.html'), { dotfiles: 'allow' }));
55
+ app.get('/admin', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'admin.html'), { dotfiles: 'allow' }));
56
+ app.get('/diagram', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'diagram.html'), { dotfiles: 'allow' }));
57
+ app.get('/shape-editor', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'shape-editor.html'), { dotfiles: 'allow' }));
58
+ app.get('/context', (_req, res) => res.sendFile(path_1.default.join(frontendPath, 'context.html'), { dotfiles: 'allow' }));
59
+ return new Promise((resolve, reject) => {
60
+ const server = app.listen(port);
61
+ server.once('error', (error) => {
62
+ reject(error);
63
+ });
64
+ server.once('listening', () => {
65
+ activeServers.add(server);
66
+ server.once('close', () => activeServers.delete(server));
67
+ const url = `http://localhost:${port}`;
68
+ console.log('');
69
+ console.log(' Living Documentation');
70
+ console.log(' ─────────────────────────────────');
71
+ console.log(` Local: ${url}`);
72
+ console.log(` Admin: ${url}/admin`);
73
+ console.log(` Docs: ${docsPath}`);
74
+ console.log('');
75
+ console.log(' Press Ctrl+C to stop.');
76
+ console.log('');
77
+ if (openBrowser) {
78
+ openUrl(url);
79
+ }
80
+ resolve();
81
+ });
82
+ });
83
+ }
84
+ function openUrl(url) {
85
+ const platform = process.platform;
86
+ if (platform === 'darwin')
87
+ (0, child_process_1.exec)(`open "${url}"`);
88
+ else if (platform === 'win32')
89
+ (0, child_process_1.exec)(`start "" "${url}"`);
90
+ else
91
+ (0, child_process_1.exec)(`xdg-open "${url}"`);
92
+ }
93
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ {
2
+ "filenamePattern": "YYYY_MM_DD_HH_mm_[Category]_title",
3
+ "title": "Living Documentation",
4
+ "theme": "system",
5
+ "language": "en",
6
+ "port": 4321,
7
+ "extraFiles": [],
8
+ "showDiagramDebug": false,
9
+ "diagramNodePalette": [
10
+ "#ffffff",
11
+ "#f5f5f4",
12
+ "#f1f5f9",
13
+ "#dbeafe",
14
+ "#e0f2fe",
15
+ "#cffafe",
16
+ "#ccfbf1",
17
+ "#dcfce7",
18
+ "#ecfccb",
19
+ "#fef9c3",
20
+ "#ffedd5",
21
+ "#fee2e2",
22
+ "#ffe4e6",
23
+ "#fce7f3",
24
+ "#ede9fe"
25
+ ],
26
+ "diagramEdgePalette": [
27
+ "#ffffff",
28
+ "#a8a29e",
29
+ "#374151",
30
+ "#3b82f6",
31
+ "#14b8a6",
32
+ "#22c55e",
33
+ "#f97316",
34
+ "#ef4444",
35
+ "#a855f7"
36
+ ],
37
+ "sourceRoot": "..",
38
+ "blockedFileExtensions": [
39
+ "exe",
40
+ "sh",
41
+ "bat",
42
+ "cmd",
43
+ "com",
44
+ "scr",
45
+ "ps1",
46
+ "msi"
47
+ ],
48
+ "exclusiveFolderExpansion": true,
49
+ "exclusiveCategoryExpansion": true,
50
+ "codeBlockMaxHeight": 400,
51
+ "markdownSoftBreaks": true
52
+ }
@@ -0,0 +1,59 @@
1
+ ---
2
+ **date:** 2026-01-01
3
+ **status:** Example
4
+ **description:** Example ADR template showing how to record a project decision with enough context, consequences, and tags for an AI assistant to discover and reuse it later.
5
+ **tags:** adr, template, architecture-decision, ai-context, documentation
6
+ ---
7
+
8
+ # Example Architecture Decision
9
+
10
+ ## Context
11
+
12
+ Replace this section with the situation that led to the decision.
13
+
14
+ Explain the problem in concrete terms:
15
+
16
+ - what was hard to understand, maintain, scale, test, or operate;
17
+ - which existing constraints mattered;
18
+ - which alternatives were considered;
19
+ - which user or developer workflow was affected.
20
+
21
+ An ADR should capture the reason behind the change, not only the final code shape. This is what makes it useful later for humans and for AI assistants that need to understand why the project works this way.
22
+
23
+ ## Decision
24
+
25
+ Replace this section with the decision that was made.
26
+
27
+ Be specific enough that another developer or AI assistant can apply the same rule later. Mention the files, modules, data contracts, commands, or conventions that carry the decision when they are relevant.
28
+
29
+ Example:
30
+
31
+ - store project-level AI instructions in `AI/PROJECT-INSTRUCTIONS.md`;
32
+ - document the stack and commands in `AI/PROJECT-STACK.md` and `AI/PROJECT-USEFUL-COMMANDS.md`;
33
+ - expose tool-specific entry points through `AGENTS.md` and `CLAUDE.md`;
34
+ - keep reusable AI rules in `AI/rules/*.md`;
35
+ - use symbolic links when a document must appear in Living Documentation without duplicating the source of truth.
36
+
37
+ ## Consequences
38
+
39
+ ### PROS
40
+
41
+ - The decision is discoverable from the documentation, not only from code.
42
+ - AI assistants can read the ADR frontmatter first, then load the full ADR only when it matches the current task.
43
+ - Future changes can preserve the original intent instead of re-discovering it from implementation details.
44
+
45
+ ### CONS
46
+
47
+ - The ADR must be maintained when the decision changes.
48
+ - A vague ADR is worse than no ADR because it gives future readers false confidence.
49
+ - If the same rule is repeated in too many places, the project can drift. Prefer one source of truth and link to it.
50
+
51
+ ## Follow-up
52
+
53
+ When turning this example into a real ADR:
54
+
55
+ - rename the file with the actual date, category, and decision title;
56
+ - set `status` to `To be validated`, `Accepted`, `SuperSeeded`, `Partially SuperSeeded`, or the status convention used by the project;
57
+ - replace `description` with a one-sentence summary that is useful during ADR discovery;
58
+ - replace `tags` with searchable themes;
59
+ - remove this follow-up section if it is no longer useful.