lockwire 0.1.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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +327 -0
  3. package/dist/actions.d.ts +67 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/actions.js +430 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/actor.d.ts +4 -0
  8. package/dist/actor.d.ts.map +1 -0
  9. package/dist/actor.js +14 -0
  10. package/dist/actor.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +192 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config.d.ts +5 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +27 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/extract.d.ts +16 -0
  20. package/dist/extract.d.ts.map +1 -0
  21. package/dist/extract.js +349 -0
  22. package/dist/extract.js.map +1 -0
  23. package/dist/format.d.ts +5 -0
  24. package/dist/format.d.ts.map +1 -0
  25. package/dist/format.js +65 -0
  26. package/dist/format.js.map +1 -0
  27. package/dist/grammar.d.ts +6 -0
  28. package/dist/grammar.d.ts.map +1 -0
  29. package/dist/grammar.js +45 -0
  30. package/dist/grammar.js.map +1 -0
  31. package/dist/hash.d.ts +12 -0
  32. package/dist/hash.d.ts.map +1 -0
  33. package/dist/hash.js +34 -0
  34. package/dist/hash.js.map +1 -0
  35. package/dist/hook-claude.d.ts +6 -0
  36. package/dist/hook-claude.d.ts.map +1 -0
  37. package/dist/hook-claude.js +50 -0
  38. package/dist/hook-claude.js.map +1 -0
  39. package/dist/hook-codex.d.ts +8 -0
  40. package/dist/hook-codex.d.ts.map +1 -0
  41. package/dist/hook-codex.js +52 -0
  42. package/dist/hook-codex.js.map +1 -0
  43. package/dist/hook-common.d.ts +23 -0
  44. package/dist/hook-common.d.ts.map +1 -0
  45. package/dist/hook-common.js +72 -0
  46. package/dist/hook-common.js.map +1 -0
  47. package/dist/index.d.ts +12 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +12 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/ledger.d.ts +13 -0
  52. package/dist/ledger.d.ts.map +1 -0
  53. package/dist/ledger.js +69 -0
  54. package/dist/ledger.js.map +1 -0
  55. package/dist/lockfile.d.ts +9 -0
  56. package/dist/lockfile.d.ts.map +1 -0
  57. package/dist/lockfile.js +40 -0
  58. package/dist/lockfile.js.map +1 -0
  59. package/dist/markers.d.ts +18 -0
  60. package/dist/markers.d.ts.map +1 -0
  61. package/dist/markers.js +89 -0
  62. package/dist/markers.js.map +1 -0
  63. package/dist/mcp-server.d.ts +2 -0
  64. package/dist/mcp-server.d.ts.map +1 -0
  65. package/dist/mcp-server.js +69 -0
  66. package/dist/mcp-server.js.map +1 -0
  67. package/dist/repo.d.ts +14 -0
  68. package/dist/repo.d.ts.map +1 -0
  69. package/dist/repo.js +75 -0
  70. package/dist/repo.js.map +1 -0
  71. package/dist/types.d.ts +100 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +11 -0
  74. package/dist/types.js.map +1 -0
  75. package/grammars/tree-sitter-javascript.wasm +0 -0
  76. package/grammars/tree-sitter-python.wasm +0 -0
  77. package/grammars/tree-sitter-tsx.wasm +0 -0
  78. package/grammars/tree-sitter-typescript.wasm +0 -0
  79. package/package.json +75 -0
@@ -0,0 +1,40 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ const LOCKFILE_NAME = "lockwire.lock";
4
+ export function lockfilePath(repoRoot) {
5
+ return `${repoRoot}/${LOCKFILE_NAME}`;
6
+ }
7
+ export async function readLockfile(repoRoot) {
8
+ const path = lockfilePath(repoRoot);
9
+ if (!existsSync(path))
10
+ return { version: 1, anchors: [] };
11
+ const raw = await readFile(path, "utf8");
12
+ const parsed = JSON.parse(raw);
13
+ return { version: 1, anchors: parsed.anchors ?? [] };
14
+ }
15
+ export async function writeLockfile(repoRoot, lockfile) {
16
+ const sorted = {
17
+ version: 1,
18
+ anchors: [...lockfile.anchors].sort((a, b) => a.id.localeCompare(b.id)),
19
+ };
20
+ await writeFile(lockfilePath(repoRoot), `${JSON.stringify(sorted, null, 2)}\n`, "utf8");
21
+ }
22
+ export function upsertAnchor(lockfile, anchor) {
23
+ const anchors = lockfile.anchors.filter((a) => a.id !== anchor.id);
24
+ anchors.push(anchor);
25
+ return { version: 1, anchors };
26
+ }
27
+ export function removeAnchor(lockfile, id) {
28
+ return { version: 1, anchors: lockfile.anchors.filter((a) => a.id !== id) };
29
+ }
30
+ export function anchorsForPath(lockfile, repoRelativePath) {
31
+ return lockfile.anchors.filter((a) => a.target.path === repoRelativePath);
32
+ }
33
+ const ID_ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz"; // Crockford base32, lowercase, no i/l/o/u
34
+ export function newAnchorId() {
35
+ let id = "";
36
+ for (let i = 0; i < 8; i++)
37
+ id += ID_ALPHABET[Math.floor(Math.random() * ID_ALPHABET.length)];
38
+ return id;
39
+ }
40
+ //# sourceMappingURL=lockfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGvD,MAAM,aAAa,GAAG,eAAe,CAAC;AAEtC,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,GAAG,QAAQ,IAAI,aAAa,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;IAC3C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,QAAkB;IACtE,MAAM,MAAM,GAAa;QACvB,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;KACxE,CAAC;IACF,MAAM,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,MAAc;IAC7D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;IACnE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,EAAU;IACzD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAkB,EAAE,gBAAwB;IACzE,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,WAAW,GAAG,kCAAkC,CAAC,CAAC,0CAA0C;AAElG,MAAM,UAAU,WAAW;IACzB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9F,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Tier } from "./types.js";
2
+ export interface DocMarker {
3
+ line: number;
4
+ target: {
5
+ path: string;
6
+ symbol?: string;
7
+ };
8
+ tiers: Tier[] | null;
9
+ id: string | null;
10
+ claimLine: number;
11
+ claimHash: string;
12
+ claimExcerpt: string;
13
+ }
14
+ /** Scans a markdown document's text for `<!-- lockwire <target> [tiers] [id=<id>] -->` markers. */
15
+ export declare function scanMarkers(text: string): DocMarker[];
16
+ /** Rewrites a marker line to carry its stamped id, preserving any tier spec already present. */
17
+ export declare function stampMarkerLine(line: string, id: string): string;
18
+ //# sourceMappingURL=markers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../src/markers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACrB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAwCrD;AAwCD,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE"}
@@ -0,0 +1,89 @@
1
+ import { fingerprint } from "./hash.js";
2
+ import { ALL_TIERS } from "./types.js";
3
+ const MARKER_RE = /^<!--\s*lockwire\s+(.+?)\s*-->\s*$/;
4
+ const TIER_SET = new Set(ALL_TIERS);
5
+ /** Scans a markdown document's text for `<!-- lockwire <target> [tiers] [id=<id>] -->` markers. */
6
+ export function scanMarkers(text) {
7
+ const lines = text.split(/\r?\n/);
8
+ const markers = [];
9
+ for (let i = 0; i < lines.length; i++) {
10
+ const line = lines[i] ?? "";
11
+ const m = MARKER_RE.exec(line.trim());
12
+ if (!m)
13
+ continue;
14
+ const tokens = (m[1] ?? "").split(/\s+/).filter(Boolean);
15
+ const targetToken = tokens[0];
16
+ if (!targetToken)
17
+ continue;
18
+ let tiers = null;
19
+ let id = null;
20
+ for (const tok of tokens.slice(1)) {
21
+ if (tok.startsWith("id=")) {
22
+ id = tok.slice(3);
23
+ }
24
+ else if (tok.split(",").every((t) => TIER_SET.has(t))) {
25
+ tiers = tok.split(",");
26
+ }
27
+ }
28
+ const [path, symbol] = targetToken.split("#");
29
+ if (!path)
30
+ continue;
31
+ const { claimLine, text: claimText } = captureFollowingBlock(lines, i + 1);
32
+ if (claimLine === -1)
33
+ continue;
34
+ markers.push({
35
+ line: i + 1,
36
+ target: { path, ...(symbol ? { symbol } : {}) },
37
+ tiers,
38
+ id,
39
+ claimLine,
40
+ claimHash: fingerprint(claimText),
41
+ claimExcerpt: excerpt(claimText),
42
+ });
43
+ }
44
+ return markers;
45
+ }
46
+ /** Consumes blank lines, then the block that follows: a fenced code block in full, or lines up to the next blank line. */
47
+ function captureFollowingBlock(lines, startIdx) {
48
+ let i = startIdx;
49
+ while (i < lines.length && (lines[i] ?? "").trim() === "")
50
+ i++;
51
+ if (i >= lines.length)
52
+ return { claimLine: -1, text: "" };
53
+ const firstLine = lines[i] ?? "";
54
+ const claimLine = i + 1;
55
+ const collected = [];
56
+ if (firstLine.trim().startsWith("```")) {
57
+ const fence = firstLine.trim().slice(0, 3);
58
+ collected.push(firstLine);
59
+ i++;
60
+ while (i < lines.length) {
61
+ const l = lines[i] ?? "";
62
+ collected.push(l);
63
+ i++;
64
+ if (l.trim().startsWith(fence))
65
+ break;
66
+ }
67
+ }
68
+ else {
69
+ while (i < lines.length && (lines[i] ?? "").trim() !== "") {
70
+ collected.push(lines[i] ?? "");
71
+ i++;
72
+ }
73
+ }
74
+ return { claimLine, text: collected.join("\n") };
75
+ }
76
+ function excerpt(text, max = 90) {
77
+ const flat = text.replace(/\s+/g, " ").trim();
78
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
79
+ }
80
+ /** Rewrites a marker line to carry its stamped id, preserving any tier spec already present. */
81
+ export function stampMarkerLine(line, id) {
82
+ const m = MARKER_RE.exec(line.trim());
83
+ if (!m)
84
+ return line;
85
+ const tokens = (m[1] ?? "").split(/\s+/).filter((t) => !t.startsWith("id="));
86
+ tokens.push(`id=${id}`);
87
+ return `<!-- lockwire ${tokens.join(" ")} -->`;
88
+ }
89
+ //# sourceMappingURL=markers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers.js","sourceRoot":"","sources":["../src/markers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function startMcpServer(repoRoot: string): Promise<void>;
2
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAiBA,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmHpE"}
@@ -0,0 +1,69 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { ack, check, history, linkDoc, refs, status, waive } from "./actions.js";
5
+ import { readConfig } from "./config.js";
6
+ function text(payload) {
7
+ return {
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: typeof payload === "string" ? payload : JSON.stringify(payload, null, 2),
12
+ },
13
+ ],
14
+ };
15
+ }
16
+ export async function startMcpServer(repoRoot) {
17
+ const server = new McpServer({ name: "lockwire", version: "0.1.0" });
18
+ server.registerTool("lockwire_claims_for", {
19
+ title: "Claims for code",
20
+ description: "What does the documentation assert about this file or symbol? Call before editing.",
21
+ inputSchema: { path: z.string(), symbol: z.string().optional() },
22
+ }, async ({ path, symbol }) => text(await refs(repoRoot, path, symbol)));
23
+ server.registerTool("lockwire_refs", {
24
+ title: "Reverse lookup",
25
+ description: "Which documentation claims reference this file or symbol.",
26
+ inputSchema: { path: z.string(), symbol: z.string().optional() },
27
+ }, async ({ path, symbol }) => text(await refs(repoRoot, path, symbol)));
28
+ server.registerTool("lockwire_status", {
29
+ title: "Anchor status",
30
+ description: "Current status of every anchor, optionally filtered by a glob scope.",
31
+ inputSchema: { scope: z.string().optional() },
32
+ }, async ({ scope }) => text(await status(repoRoot, scope)));
33
+ server.registerTool("lockwire_verify", {
34
+ title: "Verify a doc",
35
+ description: "Check one document's anchors before committing it.",
36
+ inputSchema: { doc: z.string() },
37
+ }, async ({ doc }) => {
38
+ const config = await readConfig(repoRoot);
39
+ const result = await check(repoRoot, config);
40
+ return text(result.results.filter((r) => r.anchor.doc === doc));
41
+ });
42
+ server.registerTool("lockwire_history", {
43
+ title: "Anchor history",
44
+ description: "Ledger timeline for an anchor id, a path#symbol, or a doc path — how many times has this claim broken, and how was it resolved.",
45
+ inputSchema: { ref: z.string() },
46
+ }, async ({ ref }) => text(await history(repoRoot, ref)));
47
+ server.registerTool("lockwire_link", {
48
+ title: "Create or refresh an anchor",
49
+ description: "Scan a doc for lockwire markers and stamp fresh fingerprints.",
50
+ inputSchema: { doc: z.string(), reviewed: z.boolean().optional() },
51
+ }, async ({ doc, reviewed }) => text(await linkDoc(repoRoot, doc, await readConfig(repoRoot), { type: "ai", tool: { name: "mcp" } }, reviewed === undefined ? {} : { reviewed })));
52
+ server.registerTool("lockwire_ack", {
53
+ title: "Acknowledge drift",
54
+ description: "Record that drift was handled and re-stamp the anchor's fingerprints.",
55
+ inputSchema: {
56
+ anchor: z.string(),
57
+ resolution: z.enum(["updated", "superseded", "false-positive"]),
58
+ note: z.string().optional(),
59
+ },
60
+ }, async ({ anchor, resolution, note }) => text(await ack(repoRoot, anchor, resolution, note, { type: "ai", tool: { name: "mcp" } }, await readConfig(repoRoot))));
61
+ server.registerTool("lockwire_waive", {
62
+ title: "Waive an anchor",
63
+ description: "Time-boxed, logged, expiring waiver. No permanent suppression.",
64
+ inputSchema: { anchor: z.string(), reason: z.string(), expires: z.string() },
65
+ }, async ({ anchor, reason, expires }) => text(await waive(repoRoot, anchor, reason, expires, { type: "ai", tool: { name: "mcp" } })));
66
+ const transport = new StdioServerTransport();
67
+ await server.connect(transport);
68
+ }
69
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
package/dist/repo.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /** Recursively lists repo-relative, posix paths, skipping `.git`/`node_modules`/`.lockwire` and anything matching `exclude`. */
2
+ export declare function walkFiles(repoRoot: string, exclude?: readonly string[]): string[];
3
+ /** Windows delivers hook paths with backslashes even under Git Bash. Normalize before any comparison. */
4
+ export declare function toPosix(p: string): string;
5
+ export declare function toRepoRelative(repoRoot: string, absPath: string): string;
6
+ /** Walk up from `startDir` looking for `lockwire.lock`, falling back to a `.git` directory, falling back to cwd. */
7
+ export declare function findRepoRoot(startDir: string): string;
8
+ /**
9
+ * A small, dependency-free glob matcher: `**` matches across path separators, `*` matches within
10
+ * one segment. Enough for `config.docs`/`config.exclude` defaults; not a full minimatch replacement.
11
+ */
12
+ export declare function globToRegExp(glob: string): RegExp;
13
+ export declare function matchesAny(path: string, globs: readonly string[]): boolean;
14
+ //# sourceMappingURL=repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"AAKA,gIAAgI;AAChI,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,EAAE,CAcrF;AAED,yGAAyG;AACzG,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,oHAAoH;AACpH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBjD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE1E"}
package/dist/repo.js ADDED
@@ -0,0 +1,75 @@
1
+ import { existsSync, readdirSync } from "node:fs";
2
+ import { dirname, join, relative, resolve } from "node:path";
3
+ const ALWAYS_SKIP = new Set([".git", "node_modules", ".lockwire"]);
4
+ /** Recursively lists repo-relative, posix paths, skipping `.git`/`node_modules`/`.lockwire` and anything matching `exclude`. */
5
+ export function walkFiles(repoRoot, exclude = []) {
6
+ const out = [];
7
+ function walk(dir) {
8
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
9
+ if (ALWAYS_SKIP.has(entry.name))
10
+ continue;
11
+ const abs = join(dir, entry.name);
12
+ const rel = toRepoRelative(repoRoot, abs);
13
+ if (matchesAny(rel, exclude))
14
+ continue;
15
+ if (entry.isDirectory())
16
+ walk(abs);
17
+ else
18
+ out.push(rel);
19
+ }
20
+ }
21
+ walk(repoRoot);
22
+ return out;
23
+ }
24
+ /** Windows delivers hook paths with backslashes even under Git Bash. Normalize before any comparison. */
25
+ export function toPosix(p) {
26
+ return p.replace(/\\/g, "/");
27
+ }
28
+ export function toRepoRelative(repoRoot, absPath) {
29
+ return toPosix(relative(repoRoot, absPath));
30
+ }
31
+ /** Walk up from `startDir` looking for `lockwire.lock`, falling back to a `.git` directory, falling back to cwd. */
32
+ export function findRepoRoot(startDir) {
33
+ let dir = resolve(startDir);
34
+ while (true) {
35
+ if (existsSync(join(dir, "lockwire.lock")) || existsSync(join(dir, ".git")))
36
+ return dir;
37
+ const parent = dirname(dir);
38
+ if (parent === dir)
39
+ return resolve(startDir);
40
+ dir = parent;
41
+ }
42
+ }
43
+ /**
44
+ * A small, dependency-free glob matcher: `**` matches across path separators, `*` matches within
45
+ * one segment. Enough for `config.docs`/`config.exclude` defaults; not a full minimatch replacement.
46
+ */
47
+ export function globToRegExp(glob) {
48
+ let out = "";
49
+ for (let i = 0; i < glob.length; i++) {
50
+ const c = glob[i];
51
+ if (c === "*" && glob[i + 1] === "*") {
52
+ out += ".*";
53
+ i++;
54
+ if (glob[i + 1] === "/")
55
+ i++;
56
+ }
57
+ else if (c === "*") {
58
+ out += "[^/]*";
59
+ }
60
+ else if (c === "?") {
61
+ out += "[^/]";
62
+ }
63
+ else if (c && ".+^${}()|[]\\".includes(c)) {
64
+ out += `\\${c}`;
65
+ }
66
+ else {
67
+ out += c;
68
+ }
69
+ }
70
+ return new RegExp(`^${out}$`);
71
+ }
72
+ export function matchesAny(path, globs) {
73
+ return globs.some((g) => globToRegExp(g).test(path));
74
+ }
75
+ //# sourceMappingURL=repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.js","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ export type Tier = "path" | "sig" | "body" | "deps";
2
+ export declare const ALL_TIERS: readonly Tier[];
3
+ export type AnchorStatus = "fresh" | "drifted" | "relocated" | "orphaned" | "waived" | "superseded";
4
+ export interface Fingerprints {
5
+ path: string;
6
+ sig: string;
7
+ body: string;
8
+ deps: string;
9
+ }
10
+ export interface ActorTool {
11
+ name: string;
12
+ version?: string;
13
+ }
14
+ /** An Agent Trace (agent-trace.dev v0.1.0) contributor. Ledger actors reuse this shape rather than inventing one. */
15
+ export interface Actor {
16
+ type: "human" | "ai" | "mixed" | "unknown";
17
+ model_id?: string;
18
+ tool?: ActorTool;
19
+ session?: string;
20
+ }
21
+ export interface AnchorTarget {
22
+ path: string;
23
+ symbol?: string;
24
+ }
25
+ export interface AnchorClaim {
26
+ line: number;
27
+ hash: string;
28
+ excerpt: string;
29
+ }
30
+ export interface Waiver {
31
+ reason: string;
32
+ expires: string;
33
+ by: Actor;
34
+ }
35
+ export interface Anchor {
36
+ id: string;
37
+ doc: string | null;
38
+ claim: AnchorClaim | null;
39
+ target: AnchorTarget;
40
+ tiers: Tier[];
41
+ fingerprints: Fingerprints;
42
+ linked: {
43
+ at: string;
44
+ commit: string | null;
45
+ by: Actor;
46
+ };
47
+ status: AnchorStatus;
48
+ waiver: Waiver | null;
49
+ }
50
+ export interface Lockfile {
51
+ version: 1;
52
+ anchors: Anchor[];
53
+ }
54
+ export type LedgerEvent = "anchor.created" | "anchor.verified" | "anchor.drifted" | "anchor.relocated" | "anchor.resolved" | "anchor.orphaned" | "anchor.superseded" | "anchor.acknowledged" | "waiver.granted" | "waiver.expired";
55
+ export interface LedgerRecord {
56
+ v: 1;
57
+ id: string;
58
+ ts: string;
59
+ event: LedgerEvent;
60
+ anchor: string;
61
+ actor: Actor;
62
+ tier?: Tier;
63
+ from?: string;
64
+ to?: string;
65
+ commit?: string | null;
66
+ note?: string;
67
+ hash: string;
68
+ }
69
+ export interface LockwireConfig {
70
+ version: 1;
71
+ docs: string[];
72
+ exclude: string[];
73
+ normalizeLocals: boolean;
74
+ hook: {
75
+ mode: "advisory" | "ask" | "deny";
76
+ maxClaimsInContext: number;
77
+ };
78
+ noiseBudget: {
79
+ maxStalePercent: number;
80
+ };
81
+ }
82
+ export declare const DEFAULT_CONFIG: LockwireConfig;
83
+ /** A symbol found in a source file, ready for tier extraction. Produced by extract.ts. */
84
+ export interface ResolvedSymbol {
85
+ kind: string;
86
+ name: string;
87
+ exported: boolean;
88
+ sigTokens: string;
89
+ bodyText: string;
90
+ bodyNormalized: string;
91
+ deps: string[];
92
+ }
93
+ export interface FileSymbols {
94
+ /** dotted-path name -> symbol, e.g. "createSession" or "AuthConfig.refresh" */
95
+ bySymbolPath: Map<string, ResolvedSymbol>;
96
+ /** sig-fingerprint of a symbol -> symbol paths that share it, used for relocation matching */
97
+ sigIndex: Map<string, string[]>;
98
+ fileExports: string[];
99
+ }
100
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ // Shared types for the lockwire core. See LOCKWIRE-SPEC.md — this file is the TS mirror of §2, §4, §5.
2
+ export const ALL_TIERS = ["path", "sig", "body", "deps"];
3
+ export const DEFAULT_CONFIG = {
4
+ version: 1,
5
+ docs: ["**/*.md"],
6
+ exclude: ["node_modules/**", "dist/**", "**/CHANGELOG.md"],
7
+ normalizeLocals: true,
8
+ hook: { mode: "advisory", maxClaimsInContext: 8 },
9
+ noiseBudget: { maxStalePercent: 25 },
10
+ };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,uGAAuG;AAGvG,MAAM,CAAC,MAAM,SAAS,GAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAuG1E,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC,SAAS,CAAC;IACjB,OAAO,EAAE,CAAC,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,CAAC;IAC1D,eAAe,EAAE,IAAI;IACrB,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,EAAE;IACjD,WAAW,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE;CACrC,CAAC"}
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "lockwire",
3
+ "version": "0.1.0",
4
+ "description": "Bind documentation claims to code fingerprints. Catch stale CLAUDE.md, AGENTS.md and docs at write time inside Claude Code and Codex, with a tamper-evident history.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "lockwire": "dist/cli.js"
9
+ },
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "grammars",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "engines": {
25
+ "node": ">=20"
26
+ },
27
+ "scripts": {
28
+ "build": "npm run grammars && tsc -p tsconfig.build.json",
29
+ "grammars": "node scripts/grammars.mjs",
30
+ "typecheck": "tsc --noEmit",
31
+ "lint": "biome check .",
32
+ "test": "vitest run",
33
+ "prepack": "npm run build"
34
+ },
35
+ "keywords": [
36
+ "documentation",
37
+ "docs-as-code",
38
+ "documentation-drift",
39
+ "stale-docs",
40
+ "claude-code",
41
+ "claude-code-plugin",
42
+ "codex",
43
+ "mcp",
44
+ "mcp-server",
45
+ "tree-sitter",
46
+ "ai-agents",
47
+ "context-engineering",
48
+ "agents-md",
49
+ "claude-md",
50
+ "developer-tools"
51
+ ],
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/Reality-Ventures/lockwire.git"
55
+ },
56
+ "homepage": "https://github.com/Reality-Ventures/lockwire#readme",
57
+ "bugs": {
58
+ "url": "https://github.com/Reality-Ventures/lockwire/issues"
59
+ },
60
+ "dependencies": {
61
+ "@modelcontextprotocol/sdk": "1.30.1",
62
+ "@noble/hashes": "2.4.0",
63
+ "web-tree-sitter": "0.27.0",
64
+ "zod": "4.6.5"
65
+ },
66
+ "devDependencies": {
67
+ "@biomejs/biome": "2.5.14",
68
+ "@types/node": "22.19.7",
69
+ "tree-sitter-javascript": "0.25.0",
70
+ "tree-sitter-python": "0.25.0",
71
+ "tree-sitter-typescript": "0.23.2",
72
+ "typescript": "5.9.3",
73
+ "vitest": "4.1.11"
74
+ }
75
+ }