lockwire 0.1.32 → 0.1.34

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 (53) hide show
  1. package/README.md +11 -0
  2. package/dist/actions.d.ts +11 -1
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +65 -9
  5. package/dist/actions.js.map +1 -1
  6. package/dist/blake3.d.ts +9 -0
  7. package/dist/blake3.d.ts.map +1 -0
  8. package/dist/blake3.js +128 -0
  9. package/dist/blake3.js.map +1 -0
  10. package/dist/cli.js +27 -3
  11. package/dist/cli.js.map +1 -1
  12. package/dist/compat.d.ts +21 -0
  13. package/dist/compat.d.ts.map +1 -0
  14. package/dist/compat.js +59 -0
  15. package/dist/compat.js.map +1 -0
  16. package/dist/format.d.ts +1 -1
  17. package/dist/format.d.ts.map +1 -1
  18. package/dist/format.js +6 -0
  19. package/dist/format.js.map +1 -1
  20. package/dist/hash.d.ts.map +1 -1
  21. package/dist/hash.js +2 -4
  22. package/dist/hash.js.map +1 -1
  23. package/dist/hook-claude.d.ts +6 -0
  24. package/dist/hook-claude.d.ts.map +1 -1
  25. package/dist/hook-claude.js +26 -0
  26. package/dist/hook-claude.js.map +1 -1
  27. package/dist/lockfile.d.ts +2 -0
  28. package/dist/lockfile.d.ts.map +1 -1
  29. package/dist/lockfile.js +13 -2
  30. package/dist/lockfile.js.map +1 -1
  31. package/dist/mcp-protocol.d.ts +118 -0
  32. package/dist/mcp-protocol.d.ts.map +1 -0
  33. package/dist/mcp-protocol.js +231 -0
  34. package/dist/mcp-protocol.js.map +1 -0
  35. package/dist/mcp-server.d.ts +1 -1
  36. package/dist/mcp-server.d.ts.map +1 -1
  37. package/dist/mcp-server.js +28 -23
  38. package/dist/mcp-server.js.map +1 -1
  39. package/dist/moves.d.ts +12 -4
  40. package/dist/moves.d.ts.map +1 -1
  41. package/dist/moves.js +80 -21
  42. package/dist/moves.js.map +1 -1
  43. package/dist/schema.d.ts +44 -0
  44. package/dist/schema.d.ts.map +1 -0
  45. package/dist/schema.js +68 -0
  46. package/dist/schema.js.map +1 -0
  47. package/dist/tasks.d.ts.map +1 -1
  48. package/dist/tasks.js +5 -0
  49. package/dist/tasks.js.map +1 -1
  50. package/dist/types.d.ts +5 -0
  51. package/dist/types.d.ts.map +1 -1
  52. package/dist/types.js.map +1 -1
  53. package/package.json +4 -5
@@ -1 +1 @@
1
- {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAInD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAetE;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAIzE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAErE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,CAErF;AAID,wBAAgB,WAAW,IAAI,MAAM,CAIpC;AAED,+GAA+G;AAC/G,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBrF"}
1
+ {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAInD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAetE;AAED,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAOlE;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAIzE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAErE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,CAErF;AAID,wBAAgB,WAAW,IAAI,MAAM,CAIpC;AAED,+GAA+G;AAC/G,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBrF"}
package/dist/lockfile.js CHANGED
@@ -1,5 +1,6 @@
1
- import { existsSync } from "node:fs";
1
+ import { existsSync, readFileSync } from "node:fs";
2
2
  import { readFile, realpath, rename, rm, writeFile } from "node:fs/promises";
3
+ import { withLevel } from "./compat.js";
3
4
  import { stripBom } from "./repo.js";
4
5
  const LOCKFILE_NAME = "lockwire.lock";
5
6
  export function lockfilePath(repoRoot) {
@@ -21,10 +22,20 @@ export async function readLockfile(repoRoot) {
21
22
  }
22
23
  return { version: 1, anchors: parsed.anchors ?? [] };
23
24
  }
25
+ /** The lockfile's anchors read synchronously, or null when there's none or it can't be read. */
26
+ export function readLockfileSync(repoRoot) {
27
+ try {
28
+ const raw = stripBom(readFileSync(lockfilePath(repoRoot), "utf8"));
29
+ return { version: 1, anchors: JSON.parse(raw).anchors ?? [] };
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
24
35
  export async function writeLockfile(repoRoot, lockfile) {
25
36
  const sorted = {
26
37
  version: 1,
27
- anchors: [...lockfile.anchors].sort((a, b) => a.id.localeCompare(b.id)),
38
+ anchors: lockfile.anchors.map(withLevel).sort((a, b) => a.id.localeCompare(b.id)),
28
39
  };
29
40
  await writeFileAtomic(lockfilePath(repoRoot), `${JSON.stringify(sorted, null, 2)}\n`);
30
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * The Model Context Protocol, as much of it as lockwire's server uses: JSON-RPC 2.0 over stdio, the
3
+ * `initialize` handshake, `ping`, and tools and prompts (list, call, get). lockwire implements this
4
+ * itself rather than depend on the MCP SDK, whose package also carries an HTTP stack, OAuth code and
5
+ * demo servers that a stdio-only server never loads but every install downloads and every scanner
6
+ * flags. The tests drive this server with the official SDK client, so it stays compatible with it.
7
+ */
8
+ import { type Output, type Shape } from "./schema.js";
9
+ /** Protocol versions this server speaks, newest first. A client asking for another gets the newest. */
10
+ export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05", "2024-10-07"];
11
+ type Id = string | number;
12
+ export interface JsonRpcMessage {
13
+ jsonrpc: "2.0";
14
+ id?: Id | null;
15
+ method?: string;
16
+ params?: Record<string, unknown>;
17
+ result?: unknown;
18
+ error?: {
19
+ code: number;
20
+ message: string;
21
+ data?: unknown;
22
+ };
23
+ }
24
+ /**
25
+ * A message channel, in the shape MCP transports share: the server sets the callbacks, then calls
26
+ * `start`. The SDK's own transports (its in-memory pair, used by the tests) fit it as they are.
27
+ */
28
+ export interface Transport {
29
+ start(): Promise<void>;
30
+ send(message: JsonRpcMessage): Promise<void>;
31
+ close(): Promise<void>;
32
+ onmessage?: (message: JsonRpcMessage) => void;
33
+ onclose?: () => void;
34
+ onerror?: (error: Error) => void;
35
+ }
36
+ export declare const ErrorCode: {
37
+ readonly ParseError: -32700;
38
+ readonly InvalidRequest: -32600;
39
+ readonly MethodNotFound: -32601;
40
+ readonly InvalidParams: -32602;
41
+ readonly InternalError: -32603;
42
+ };
43
+ export interface ToolResult {
44
+ content: {
45
+ type: "text";
46
+ text: string;
47
+ }[];
48
+ isError?: boolean;
49
+ }
50
+ export interface ToolAnnotations {
51
+ readOnlyHint: boolean;
52
+ destructiveHint: boolean;
53
+ idempotentHint: boolean;
54
+ openWorldHint: boolean;
55
+ }
56
+ interface PromptResult {
57
+ description?: string;
58
+ messages: {
59
+ role: "user" | "assistant";
60
+ content: {
61
+ type: "text";
62
+ text: string;
63
+ };
64
+ }[];
65
+ }
66
+ export declare class McpServer {
67
+ private readonly info;
68
+ /** Told to the client at `initialize`, for its model to read; computed then, so it's current. */
69
+ private readonly instructions?;
70
+ private readonly tools;
71
+ private readonly prompts;
72
+ private transport;
73
+ private clientInfo;
74
+ constructor(info: {
75
+ name: string;
76
+ version: string;
77
+ },
78
+ /** Told to the client at `initialize`, for its model to read; computed then, so it's current. */
79
+ instructions?: (() => string | undefined) | undefined);
80
+ /** The client's own name and version, from its `initialize` request. */
81
+ getClientVersion(): {
82
+ name?: string;
83
+ version?: string;
84
+ } | undefined;
85
+ registerTool<S extends Shape>(name: string, def: {
86
+ title: string;
87
+ description: string;
88
+ inputSchema: S;
89
+ annotations: ToolAnnotations;
90
+ }, handler: (args: Output<S>) => Promise<ToolResult> | ToolResult): void;
91
+ registerPrompt<S extends Shape>(name: string, def: {
92
+ title: string;
93
+ description: string;
94
+ argsSchema: S;
95
+ }, handler: (args: Output<S>) => Promise<PromptResult> | PromptResult): void;
96
+ connect(transport: Transport): Promise<void>;
97
+ close(): Promise<void>;
98
+ private receive;
99
+ private handle;
100
+ /** A tool's failures are results the model can read and act on, not protocol errors. */
101
+ private callTool;
102
+ }
103
+ /** Newline-delimited JSON-RPC on stdin and stdout, as MCP's stdio transport specifies. */
104
+ export declare class StdioServerTransport implements Transport {
105
+ private readonly input;
106
+ private readonly output;
107
+ onmessage?: (message: JsonRpcMessage) => void;
108
+ onclose?: () => void;
109
+ onerror?: (error: Error) => void;
110
+ private buffer;
111
+ constructor(input?: NodeJS.ReadableStream, output?: NodeJS.WritableStream);
112
+ start(): Promise<void>;
113
+ private line;
114
+ send(message: JsonRpcMessage): Promise<void>;
115
+ close(): Promise<void>;
116
+ }
117
+ export {};
118
+ //# sourceMappingURL=mcp-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-protocol.d.ts","sourceRoot":"","sources":["../src/mcp-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * The Model Context Protocol, as much of it as lockwire's server uses: JSON-RPC 2.0 over stdio, the
3
+ * `initialize` handshake, `ping`, and tools and prompts (list, call, get). lockwire implements this
4
+ * itself rather than depend on the MCP SDK, whose package also carries an HTTP stack, OAuth code and
5
+ * demo servers that a stdio-only server never loads but every install downloads and every scanner
6
+ * flags. The tests drive this server with the official SDK client, so it stays compatible with it.
7
+ */
8
+ import { objectJson, parseObject } from "./schema.js";
9
+ /** Protocol versions this server speaks, newest first. A client asking for another gets the newest. */
10
+ export const SUPPORTED_PROTOCOL_VERSIONS = [
11
+ "2025-11-25",
12
+ "2025-06-18",
13
+ "2025-03-26",
14
+ "2024-11-05",
15
+ "2024-10-07",
16
+ ];
17
+ export const ErrorCode = {
18
+ ParseError: -32700,
19
+ InvalidRequest: -32600,
20
+ MethodNotFound: -32601,
21
+ InvalidParams: -32602,
22
+ InternalError: -32603,
23
+ };
24
+ class RpcError extends Error {
25
+ code;
26
+ constructor(code, message) {
27
+ super(message);
28
+ this.code = code;
29
+ }
30
+ }
31
+ export class McpServer {
32
+ info;
33
+ instructions;
34
+ tools = new Map();
35
+ prompts = new Map();
36
+ transport;
37
+ clientInfo;
38
+ constructor(info,
39
+ /** Told to the client at `initialize`, for its model to read; computed then, so it's current. */
40
+ instructions) {
41
+ this.info = info;
42
+ this.instructions = instructions;
43
+ }
44
+ /** The client's own name and version, from its `initialize` request. */
45
+ getClientVersion() {
46
+ return this.clientInfo;
47
+ }
48
+ registerTool(name, def, handler) {
49
+ this.tools.set(name, {
50
+ title: def.title,
51
+ description: def.description,
52
+ input: def.inputSchema,
53
+ annotations: def.annotations,
54
+ handler,
55
+ });
56
+ }
57
+ registerPrompt(name, def, handler) {
58
+ this.prompts.set(name, {
59
+ title: def.title,
60
+ description: def.description,
61
+ args: def.argsSchema,
62
+ handler,
63
+ });
64
+ }
65
+ async connect(transport) {
66
+ this.transport = transport;
67
+ transport.onmessage = (message) => {
68
+ void this.receive(message);
69
+ };
70
+ await transport.start();
71
+ }
72
+ async close() {
73
+ await this.transport?.close();
74
+ }
75
+ async receive(message) {
76
+ // A response to a request (this server sends none) or a notification needs no answer.
77
+ if (message.method === undefined || message.id === undefined || message.id === null)
78
+ return;
79
+ const id = message.id;
80
+ try {
81
+ const result = await this.handle(message.method, message.params ?? {});
82
+ await this.transport?.send({ jsonrpc: "2.0", id, result });
83
+ }
84
+ catch (err) {
85
+ const code = err instanceof RpcError ? err.code : ErrorCode.InternalError;
86
+ const text = err instanceof Error ? err.message : String(err);
87
+ await this.transport?.send({ jsonrpc: "2.0", id, error: { code, message: text } });
88
+ }
89
+ }
90
+ async handle(method, params) {
91
+ switch (method) {
92
+ case "initialize": {
93
+ const asked = params.protocolVersion;
94
+ const info = params.clientInfo;
95
+ if (info && typeof info === "object")
96
+ this.clientInfo = info;
97
+ let instructions;
98
+ try {
99
+ instructions = this.instructions?.();
100
+ }
101
+ catch {
102
+ // instructions are a courtesy: never fail the handshake over them
103
+ }
104
+ return {
105
+ ...(instructions ? { instructions } : {}),
106
+ protocolVersion: SUPPORTED_PROTOCOL_VERSIONS.find((v) => v === asked)
107
+ ? asked
108
+ : SUPPORTED_PROTOCOL_VERSIONS[0],
109
+ capabilities: { tools: { listChanged: false }, prompts: { listChanged: false } },
110
+ serverInfo: this.info,
111
+ };
112
+ }
113
+ case "ping":
114
+ return {};
115
+ case "tools/list":
116
+ return {
117
+ tools: [...this.tools].map(([name, t]) => ({
118
+ name,
119
+ title: t.title,
120
+ description: t.description,
121
+ inputSchema: objectJson(t.input),
122
+ annotations: t.annotations,
123
+ })),
124
+ };
125
+ case "tools/call":
126
+ return this.callTool(params);
127
+ case "prompts/list":
128
+ return {
129
+ prompts: [...this.prompts].map(([name, p]) => ({
130
+ name,
131
+ title: p.title,
132
+ description: p.description,
133
+ arguments: Object.entries(p.args).map(([arg, field]) => ({
134
+ name: arg,
135
+ required: field.required,
136
+ })),
137
+ })),
138
+ };
139
+ case "prompts/get": {
140
+ const name = String(params.name);
141
+ const prompt = this.prompts.get(name);
142
+ if (!prompt)
143
+ throw new RpcError(ErrorCode.InvalidParams, `Prompt ${name} not found`);
144
+ const parsed = parseObject(prompt.args, params.arguments ?? {});
145
+ if ("problem" in parsed)
146
+ throw new RpcError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${name}: ${parsed.problem}`);
147
+ return prompt.handler(parsed.value);
148
+ }
149
+ default:
150
+ throw new RpcError(ErrorCode.MethodNotFound, `Method not found: ${method}`);
151
+ }
152
+ }
153
+ /** A tool's failures are results the model can read and act on, not protocol errors. */
154
+ async callTool(params) {
155
+ const failed = (text) => ({
156
+ content: [{ type: "text", text }],
157
+ isError: true,
158
+ });
159
+ const name = String(params.name);
160
+ const tool = this.tools.get(name);
161
+ if (!tool)
162
+ return failed(`Tool ${name} not found`);
163
+ const parsed = parseObject(tool.input, params.arguments ?? {});
164
+ if ("problem" in parsed)
165
+ return failed(`Invalid arguments for tool ${name}: ${parsed.problem}`);
166
+ try {
167
+ return await tool.handler(parsed.value);
168
+ }
169
+ catch (err) {
170
+ return failed(err instanceof Error ? err.message : String(err));
171
+ }
172
+ }
173
+ }
174
+ /** Newline-delimited JSON-RPC on stdin and stdout, as MCP's stdio transport specifies. */
175
+ export class StdioServerTransport {
176
+ input;
177
+ output;
178
+ onmessage;
179
+ onclose;
180
+ onerror;
181
+ buffer = "";
182
+ constructor(input = process.stdin, output = process.stdout) {
183
+ this.input = input;
184
+ this.output = output;
185
+ }
186
+ async start() {
187
+ this.input.setEncoding("utf8");
188
+ this.input.on("data", (chunk) => {
189
+ this.buffer += chunk;
190
+ for (let nl = this.buffer.indexOf("\n"); nl >= 0; nl = this.buffer.indexOf("\n")) {
191
+ const line = this.buffer.slice(0, nl).replace(/\r$/, "");
192
+ this.buffer = this.buffer.slice(nl + 1);
193
+ if (line.trim())
194
+ this.line(line);
195
+ }
196
+ });
197
+ this.input.on("end", () => this.onclose?.());
198
+ this.input.on("error", (err) => this.onerror?.(err));
199
+ }
200
+ line(line) {
201
+ let message;
202
+ try {
203
+ message = JSON.parse(line);
204
+ }
205
+ catch {
206
+ void this.send({
207
+ jsonrpc: "2.0",
208
+ id: null,
209
+ error: { code: ErrorCode.ParseError, message: "Parse error" },
210
+ });
211
+ return;
212
+ }
213
+ // Batches went out of the protocol in 2025-06-18; an older client's batch is still answered.
214
+ for (const m of Array.isArray(message) ? message : [message])
215
+ if (m && typeof m === "object" && m.jsonrpc === "2.0")
216
+ this.onmessage?.(m);
217
+ }
218
+ send(message) {
219
+ return new Promise((resolve) => {
220
+ if (this.output.write(`${JSON.stringify(message)}\n`))
221
+ resolve();
222
+ else
223
+ this.output.once("drain", () => resolve());
224
+ });
225
+ }
226
+ async close() {
227
+ this.input.removeAllListeners("data");
228
+ this.onclose?.();
229
+ }
230
+ }
231
+ //# sourceMappingURL=mcp-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-protocol.js","sourceRoot":"","sources":["../src/mcp-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAe,UAAU,EAAE,WAAW,EAAc,MAAM,aAAa,CAAC;AAE/E,uGAAuG;AACvG,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;CACJ,CAAC;AA0BX,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU,EAAE,CAAC,KAAK;IAClB,cAAc,EAAE,CAAC,KAAK;IACtB,cAAc,EAAE,CAAC,KAAK;IACtB,aAAa,EAAE,CAAC,KAAK;IACrB,aAAa,EAAE,CAAC,KAAK;CACb,CAAC;AAEX,MAAM,QAAS,SAAQ,KAAK;IAEf;IADX,YACW,IAAY,EACrB,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,SAAI,GAAJ,IAAI,CAAQ;IAIvB,CAAC;CACF;AAoCD,MAAM,OAAO,SAAS;IAOD;IAEA;IARF,KAAK,GAAG,IAAI,GAAG,EAAgB,CAAC;IAChC,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,SAAS,CAAwB;IACjC,UAAU,CAAkD;IAEpE,YACmB,IAAuC;IACxD,iGAAiG;IAChF,YAAuC;QAFvC,SAAI,GAAJ,IAAI,CAAmC;QAEvC,iBAAY,GAAZ,YAAY,CAA2B;IACvD,CAAC;IAEJ,wEAAwE;IACxE,gBAAgB;QACd,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,YAAY,CACV,IAAY,EACZ,GAAyF,EACzF,OAA8D;QAE9D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE;YACnB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,KAAK,EAAE,GAAG,CAAC,WAAW;YACtB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,cAAc,CACZ,IAAY,EACZ,GAA0D,EAC1D,OAAkE;QAElE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE;YACrB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,IAAI,EAAE,GAAG,CAAC,UAAU;YACpB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAoB;QAChC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,SAAS,CAAC,SAAS,GAAG,CAAC,OAAO,EAAE,EAAE;YAChC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC,CAAC;QACF,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC;IAChC,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,OAAuB;QAC3C,sFAAsF;QACtF,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,IAAI;YAAE,OAAO;QAC5F,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACvE,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC;YAC1E,MAAM,IAAI,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9D,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAA+B;QAClE,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC;gBACrC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;gBAC/B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,IAAI,CAAC,UAAU,GAAG,IAA8B,CAAC;gBACvF,IAAI,YAAgC,CAAC;gBACrC,IAAI,CAAC;oBACH,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;gBACvC,CAAC;gBAAC,MAAM,CAAC;oBACP,kEAAkE;gBACpE,CAAC;gBACD,OAAO;oBACL,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACzC,eAAe,EAAE,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC;wBACnE,CAAC,CAAC,KAAK;wBACP,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC;oBAClC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;oBAChF,UAAU,EAAE,IAAI,CAAC,IAAI;iBACtB,CAAC;YACJ,CAAC;YACD,KAAK,MAAM;gBACT,OAAO,EAAE,CAAC;YACZ,KAAK,YAAY;gBACf,OAAO;oBACL,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBACzC,IAAI;wBACJ,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,WAAW,EAAE,CAAC,CAAC,WAAW;wBAC1B,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC;wBAChC,WAAW,EAAE,CAAC,CAAC,WAAW;qBAC3B,CAAC,CAAC;iBACJ,CAAC;YACJ,KAAK,YAAY;gBACf,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC/B,KAAK,cAAc;gBACjB,OAAO;oBACL,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC7C,IAAI;wBACJ,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,WAAW,EAAE,CAAC,CAAC,WAAW;wBAC1B,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;4BACvD,IAAI,EAAE,GAAG;4BACT,QAAQ,EAAE,KAAK,CAAC,QAAQ;yBACzB,CAAC,CAAC;qBACJ,CAAC,CAAC;iBACJ,CAAC;YACJ,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACjC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACtC,IAAI,CAAC,MAAM;oBAAE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,UAAU,IAAI,YAAY,CAAC,CAAC;gBACrF,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;gBAChE,IAAI,SAAS,IAAI,MAAM;oBACrB,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,aAAa,EACvB,gCAAgC,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,CAC1D,CAAC;gBACJ,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtC,CAAC;YACD;gBACE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,qBAAqB,MAAM,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED,wFAAwF;IAChF,KAAK,CAAC,QAAQ,CAAC,MAA+B;QACpD,MAAM,MAAM,GAAG,CAAC,IAAY,EAAc,EAAE,CAAC,CAAC;YAC5C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACjC,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC,QAAQ,IAAI,YAAY,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QAC/D,IAAI,SAAS,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC,8BAA8B,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAChG,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;CACF;AAED,0FAA0F;AAC1F,MAAM,OAAO,oBAAoB;IAOZ;IACA;IAPnB,SAAS,CAAqC;IAC9C,OAAO,CAAc;IACrB,OAAO,CAA0B;IACzB,MAAM,GAAG,EAAE,CAAC;IAEpB,YACmB,QAA+B,OAAO,CAAC,KAAK,EAC5C,SAAgC,OAAO,CAAC,MAAM;QAD9C,UAAK,GAAL,KAAK,CAAuC;QAC5C,WAAM,GAAN,MAAM,CAAwC;IAC9D,CAAC;IAEJ,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACtC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;YACrB,KAAK,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACzD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;gBACxC,IAAI,IAAI,CAAC,IAAI,EAAE;oBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,CAAC;IAEO,IAAI,CAAC,IAAY;QACvB,IAAI,OAAgB,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,IAAI,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,KAAK;gBACd,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE;aAC9D,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,6FAA6F;QAC7F,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1D,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAK,CAAoB,CAAC,OAAO,KAAK,KAAK;gBACvE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAmB,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,OAAuB;QAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;gBAAE,OAAO,EAAE,CAAC;;gBAC5D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;IACnB,CAAC;CACF"}
@@ -1,5 +1,5 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
1
  import type { IndexStats } from "./docindex.js";
2
+ import { McpServer } from "./mcp-protocol.js";
3
3
  /** Builds the configured server without connecting a transport -- split out from startMcpServer so tests can drive it over an in-memory transport instead of real stdio. */
4
4
  export declare function createServer(repoRoot: string, opts?: {
5
5
  onIndexStats?: (stats: IndexStats) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiBpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAuBhD,4KAA4K;AAC5K,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CAAO,GACxD,SAAS,CA2VX;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAwB,MAAM,mBAAmB,CAAC;AAsBpE,4KAA4K;AAC5K,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CAAO,GACxD,SAAS,CAgWX;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE"}
@@ -1,13 +1,13 @@
1
1
  import { existsSync } from "node:fs";
2
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import { z } from "zod";
5
2
  import { ack, check, history, linkDoc, refs, repoint, status, unlinkedFor, waive, } from "./actions.js";
6
3
  import { changedFiles } from "./changed.js";
4
+ import { newerWriterNotice } from "./compat.js";
7
5
  import { readConfig } from "./config.js";
8
6
  import { withRepoLock } from "./lock.js";
9
- import { lockfilePath } from "./lockfile.js";
7
+ import { lockfilePath, readLockfileSync } from "./lockfile.js";
8
+ import { McpServer, StdioServerTransport } from "./mcp-protocol.js";
10
9
  import { toRepoPath } from "./repo.js";
10
+ import { s } from "./schema.js";
11
11
  import { fixDocsPrompt, listTasks, resolveTask, taskContext } from "./tasks.js";
12
12
  function text(payload) {
13
13
  return {
@@ -27,13 +27,18 @@ function missingLockNote(repoRoot) {
27
27
  }
28
28
  /** Builds the configured server without connecting a transport -- split out from startMcpServer so tests can drive it over an in-memory transport instead of real stdio. */
29
29
  export function createServer(repoRoot, opts = {}) {
30
- const server = new McpServer({ name: "lockwire", version: "0.1.0" });
30
+ // An older lockwire than the one that stamped some claims says so up front, so the model can
31
+ // suggest updating instead of trusting results for claims it can't check.
32
+ const server = new McpServer({ name: "lockwire", version: "0.1.0" }, () => {
33
+ const lock = readLockfileSync(repoRoot);
34
+ return lock ? (newerWriterNotice(lock, "agent") ?? undefined) : undefined;
35
+ });
31
36
  // The server outlives many calls, so it keeps the doc index in memory: the first `claims_for`
32
37
  // builds (or loads) it, later ones only re-validate it. Nothing is written to disk.
33
38
  const indexSession = {};
34
39
  /** Who is acting: the MCP client's own name (claude-code, codex, cursor…) when it gave one. */
35
40
  const agentActor = () => {
36
- const client = server.server.getClientVersion();
41
+ const client = server.getClientVersion();
37
42
  return {
38
43
  type: "ai",
39
44
  tool: client?.name
@@ -47,7 +52,7 @@ export function createServer(repoRoot, opts = {}) {
47
52
  server.registerTool("lockwire_claims_for", {
48
53
  title: "Claims for code",
49
54
  description: "What does the documentation assert about this file or symbol? Call before editing. Returns `anchors` (claims lockwire is checking) and `unlinked` (claims written in a doc about this code that nobody has linked yet, so nothing is checking them — treat them as real claims too).",
50
- inputSchema: { path: z.string(), symbol: z.string().optional() },
55
+ inputSchema: { path: s.string(), symbol: s.string().optional() },
51
56
  // Pure read (the lockfile and the docs; the doc index is held in memory, never written to disk) --
52
57
  // repeat calls are trivially idempotent.
53
58
  annotations: {
@@ -69,7 +74,7 @@ export function createServer(repoRoot, opts = {}) {
69
74
  server.registerTool("lockwire_refs", {
70
75
  title: "Reverse lookup",
71
76
  description: "Which documentation claims reference this file or symbol.",
72
- inputSchema: { path: z.string(), symbol: z.string().optional() },
77
+ inputSchema: { path: s.string(), symbol: s.string().optional() },
73
78
  annotations: {
74
79
  readOnlyHint: true,
75
80
  destructiveHint: false,
@@ -81,7 +86,7 @@ export function createServer(repoRoot, opts = {}) {
81
86
  server.registerTool("lockwire_status", {
82
87
  title: "Anchor status",
83
88
  description: "Current status of every anchor, optionally filtered by a glob scope.",
84
- inputSchema: { scope: z.string().optional() },
89
+ inputSchema: { scope: s.string().optional() },
85
90
  annotations: {
86
91
  readOnlyHint: true,
87
92
  destructiveHint: false,
@@ -92,7 +97,7 @@ export function createServer(repoRoot, opts = {}) {
92
97
  server.registerTool("lockwire_verify", {
93
98
  title: "Verify a doc",
94
99
  description: "Check one document's anchors before committing it.",
95
- inputSchema: { doc: z.string() },
100
+ inputSchema: { doc: s.string() },
96
101
  // Not read-only: check() writes the lockfile and appends ledger events on state
97
102
  // transitions. It IS idempotent -- every transition is guarded by the anchor's current
98
103
  // status (e.g. `if (anchor.status !== "drifted")`), so a repeat call with nothing else
@@ -120,7 +125,7 @@ export function createServer(repoRoot, opts = {}) {
120
125
  server.registerTool("lockwire_history", {
121
126
  title: "Anchor history",
122
127
  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.",
123
- inputSchema: { ref: z.string() },
128
+ inputSchema: { ref: s.string() },
124
129
  annotations: {
125
130
  readOnlyHint: true,
126
131
  destructiveHint: false,
@@ -131,7 +136,7 @@ export function createServer(repoRoot, opts = {}) {
131
136
  server.registerTool("lockwire_link", {
132
137
  title: "Create or refresh an anchor",
133
138
  description: "Scan a doc for lockwire markers and stamp fresh fingerprints.",
134
- inputSchema: { doc: z.string(), reviewed: z.boolean().optional() },
139
+ inputSchema: { doc: s.string(), reviewed: s.boolean().optional() },
135
140
  // A second call with nothing changed in between stamps nothing and appends no ledger event.
136
141
  annotations: {
137
142
  readOnlyHint: false,
@@ -144,9 +149,9 @@ export function createServer(repoRoot, opts = {}) {
144
149
  title: "Acknowledge drift",
145
150
  description: "Record that drift was handled and re-stamp the anchor's fingerprints.",
146
151
  inputSchema: {
147
- anchor: z.string(),
148
- resolution: z.enum(["updated", "superseded", "false-positive"]),
149
- note: z.string().optional(),
152
+ anchor: s.string(),
153
+ resolution: s.enum(["updated", "superseded", "false-positive"]),
154
+ note: s.string().optional(),
150
155
  },
151
156
  // ack() unconditionally appends an anchor.acknowledged event every call, same reasoning
152
157
  // as lockwire_link -- each ack is a distinct logged action, so repeat calls are not a
@@ -161,7 +166,7 @@ export function createServer(repoRoot, opts = {}) {
161
166
  server.registerTool("lockwire_waive", {
162
167
  title: "Waive an anchor",
163
168
  description: "Time-boxed, logged, expiring waiver. No permanent suppression.",
164
- inputSchema: { anchor: z.string(), reason: z.string(), expires: z.string() },
169
+ inputSchema: { anchor: s.string(), reason: s.string(), expires: s.string() },
165
170
  // waive() unconditionally appends a waiver.granted event every call -- same reasoning as
166
171
  // lockwire_link and lockwire_ack.
167
172
  annotations: {
@@ -175,9 +180,9 @@ export function createServer(repoRoot, opts = {}) {
175
180
  title: "Re-point moved claims",
176
181
  description: "After moving code to another file: point every claim whose symbol moved there, unchanged, at its new path#symbol and rewrite its doc marker. `anchors` limits it to those ids; `to` (with one id) names the new home when lockwire found the code in several places or it changed on the way. A bound tier that differs at the new place stays drifted. `dryRun` reports what would change without writing.",
177
182
  inputSchema: {
178
- anchors: z.array(z.string()).optional(),
179
- to: z.string().optional(),
180
- dryRun: z.boolean().optional(),
183
+ anchors: s.array(s.string()).optional(),
184
+ to: s.string().optional(),
185
+ dryRun: s.boolean().optional(),
181
186
  },
182
187
  // Re-pointing an anchor that already points at its new home skips it, so a repeat call with
183
188
  // nothing moved in between writes nothing.
@@ -209,7 +214,7 @@ export function createServer(repoRoot, opts = {}) {
209
214
  server.registerTool("lockwire_tasks", {
210
215
  title: "Documentation tasks",
211
216
  description: "Every documentation claim that needs attention, as a task list: claims whose code or value changed, numbers that no longer match their source, claims whose target is gone, and markers nobody has linked. Each task says what is wrong and what to do. Start here when asked to fix or update documentation. `paths` limits it to claims about (or in) those files; `changed` to files this branch touched.",
212
- inputSchema: { paths: z.array(z.string()).optional(), changed: z.boolean().optional() },
217
+ inputSchema: { paths: s.array(s.string()).optional(), changed: s.boolean().optional() },
213
218
  // A dry run of check: computes everything, writes nothing.
214
219
  annotations: {
215
220
  readOnlyHint: true,
@@ -229,7 +234,7 @@ export function createServer(repoRoot, opts = {}) {
229
234
  server.registerTool("lockwire_task_context", {
230
235
  title: "Context for a task",
231
236
  description: "Everything needed to fix one task from lockwire_tasks: the whole claim sentence, the bound code (its declaration) or value as it was when the claim was stamped and as it is now, and the claim's history. `stamped.exact` says whether the stamped side is exactly what the claim was checked against.",
232
- inputSchema: { id: z.string() },
237
+ inputSchema: { id: s.string() },
233
238
  annotations: {
234
239
  readOnlyHint: true,
235
240
  destructiveHint: false,
@@ -240,7 +245,7 @@ export function createServer(repoRoot, opts = {}) {
240
245
  server.registerTool("lockwire_resolve", {
241
246
  title: "Resolve a task",
242
247
  description: "After you have edited the doc so the claim is true, re-stamp that one claim (nothing else in the doc). It is checked first: a sentence whose number still disagrees with its value is refused, as is a marker whose target still doesn't exist. Pass a short `note` saying what you checked or changed; it goes into the claim's history. Returns resolved / already-fresh / refused (with the reason) and the tasks still open on the same doc.",
243
- inputSchema: { id: z.string(), note: z.string().optional() },
248
+ inputSchema: { id: s.string(), note: s.string().optional() },
244
249
  // Writes the lockfile and ledger. Resolving an already-fresh claim is a no-op, so it is idempotent.
245
250
  annotations: {
246
251
  readOnlyHint: false,
@@ -252,7 +257,7 @@ export function createServer(repoRoot, opts = {}) {
252
257
  server.registerPrompt("fix-docs", {
253
258
  title: "Fix documentation drift",
254
259
  description: "Work through lockwire's task list: fix every documentation claim that no longer matches the code or data it describes, and check each fix.",
255
- argsSchema: { scope: z.string().optional() },
260
+ argsSchema: { scope: s.string().optional() },
256
261
  }, ({ scope }) => ({
257
262
  messages: [
258
263
  {