lockstep-cli 0.0.5 → 0.1.1

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 (80) hide show
  1. package/README.md +29 -0
  2. package/dist/adapters/claude.js +26 -7
  3. package/dist/adapters/claude.js.map +1 -1
  4. package/dist/adapters/install.test.js +53 -2
  5. package/dist/adapters/install.test.js.map +1 -1
  6. package/dist/adapters/merge.d.ts +11 -0
  7. package/dist/adapters/merge.js +41 -0
  8. package/dist/adapters/merge.js.map +1 -1
  9. package/dist/adapters/templates.d.ts +3 -2
  10. package/dist/adapters/templates.js +92 -3
  11. package/dist/adapters/templates.js.map +1 -1
  12. package/dist/capture/classify-edge.test.js +9 -7
  13. package/dist/capture/classify-edge.test.js.map +1 -1
  14. package/dist/capture/classify.d.ts +6 -4
  15. package/dist/capture/classify.js +9 -8
  16. package/dist/capture/classify.js.map +1 -1
  17. package/dist/capture/classify.test.js +7 -2
  18. package/dist/capture/classify.test.js.map +1 -1
  19. package/dist/capture/diff.d.ts +2 -0
  20. package/dist/capture/diff.js +15 -0
  21. package/dist/capture/diff.js.map +1 -1
  22. package/dist/capture/extract.d.ts +5 -0
  23. package/dist/capture/extract.js +17 -0
  24. package/dist/capture/extract.js.map +1 -0
  25. package/dist/capture/feature-context.d.ts +3 -0
  26. package/dist/capture/feature-context.js +43 -0
  27. package/dist/capture/feature-context.js.map +1 -0
  28. package/dist/capture/feature-context.test.d.ts +1 -0
  29. package/dist/capture/feature-context.test.js +45 -0
  30. package/dist/capture/feature-context.test.js.map +1 -0
  31. package/dist/capture/index.d.ts +59 -0
  32. package/dist/capture/index.js +101 -21
  33. package/dist/capture/index.js.map +1 -1
  34. package/dist/capture/manifest.d.ts +26 -0
  35. package/dist/capture/manifest.js +98 -0
  36. package/dist/capture/manifest.js.map +1 -0
  37. package/dist/capture/manifest.test.d.ts +1 -0
  38. package/dist/capture/manifest.test.js +40 -0
  39. package/dist/capture/manifest.test.js.map +1 -0
  40. package/dist/capture/outbound.d.ts +10 -0
  41. package/dist/capture/outbound.js +139 -0
  42. package/dist/capture/outbound.js.map +1 -0
  43. package/dist/capture/outbound.test.d.ts +1 -0
  44. package/dist/capture/outbound.test.js +89 -0
  45. package/dist/capture/outbound.test.js.map +1 -0
  46. package/dist/capture/python.d.ts +5 -0
  47. package/dist/capture/python.js +127 -0
  48. package/dist/capture/python.js.map +1 -0
  49. package/dist/capture/python.test.d.ts +1 -0
  50. package/dist/capture/python.test.js +99 -0
  51. package/dist/capture/python.test.js.map +1 -0
  52. package/dist/capture/replay.test.d.ts +1 -0
  53. package/dist/capture/replay.test.js +101 -0
  54. package/dist/capture/replay.test.js.map +1 -0
  55. package/dist/capture/surface.d.ts +23 -0
  56. package/dist/capture/surface.js +83 -0
  57. package/dist/capture/surface.js.map +1 -0
  58. package/dist/capture/surface.test.d.ts +1 -0
  59. package/dist/capture/surface.test.js +37 -0
  60. package/dist/capture/surface.test.js.map +1 -0
  61. package/dist/connect.d.ts +1 -1
  62. package/dist/connect.js +23 -12
  63. package/dist/connect.js.map +1 -1
  64. package/dist/index.js +25 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/init.js +3 -1
  67. package/dist/init.js.map +1 -1
  68. package/dist/mcp/server.d.ts +1 -1
  69. package/dist/mcp/server.js +26 -3
  70. package/dist/mcp/server.js.map +1 -1
  71. package/dist/scan.d.ts +64 -0
  72. package/dist/scan.js +176 -0
  73. package/dist/scan.js.map +1 -0
  74. package/dist/scan.test.d.ts +1 -0
  75. package/dist/scan.test.js +258 -0
  76. package/dist/scan.test.js.map +1 -0
  77. package/dist/statusline.d.ts +6 -0
  78. package/dist/statusline.js +108 -0
  79. package/dist/statusline.js.map +1 -0
  80. package/package.json +8 -4
@@ -0,0 +1,101 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { formatReplay } from "./index.js";
4
+ const decisions = {
5
+ decisions: [
6
+ { scopeRef: "http:POST /auth/session", status: "binding", ruleText: "Sessions expire in 24h", impact: 3 },
7
+ { scopeRef: "svc:orders", status: "binding", ruleText: "Orders are append-only", impact: 1 },
8
+ { scopeRef: "svc:draft", status: "proposed", ruleText: "not binding — ignored", impact: 9 },
9
+ ],
10
+ };
11
+ // The server pre-renders `line`; formatReplay only prefixes " • " and interleaves by impact.
12
+ const briefing = {
13
+ constraints: [
14
+ { line: "⚠ [ratified · PRD-142] Guest flow must not present OTP before payment (impact 5)", impact: 5, conflictOpen: false },
15
+ { line: "⚠ [ratified · PRD-142] Checkout must accept guest orders (impact 3) · conflict open", impact: 3, conflictOpen: true },
16
+ ],
17
+ overflow: 0,
18
+ };
19
+ test("null briefing → output is byte-identical to the pre-Phase-B format", () => {
20
+ const out = formatReplay(null, decisions, null);
21
+ const expected = [
22
+ "Lockstep:",
23
+ "📌 2 binding decision(s) in effect:",
24
+ " • [impact 3] [http:POST /auth/session] Sessions expire in 24h",
25
+ " • [impact 1] [svc:orders] Orders are append-only",
26
+ ].join("\n");
27
+ assert.equal(out, expected);
28
+ // absent briefing arg behaves the same as explicit null
29
+ assert.equal(formatReplay(null, decisions), expected);
30
+ });
31
+ test("constraints interleave into the binding section, impact-desc", () => {
32
+ const out = formatReplay(null, decisions, briefing);
33
+ const lines = out.split("\n");
34
+ assert.equal(lines[0], "Lockstep:");
35
+ assert.equal(lines[1], "📌 4 binding decision(s) in effect:"); // 2 decisions + 2 constraints
36
+ assert.deepEqual(lines.slice(2), [
37
+ " • ⚠ [ratified · PRD-142] Guest flow must not present OTP before payment (impact 5)", // impact 5
38
+ " • ⚠ [ratified · PRD-142] Checkout must accept guest orders (impact 3) · conflict open", // impact 3, tie → constraint first
39
+ " • [impact 3] [http:POST /auth/session] Sessions expire in 24h", // impact 3 decision, after the constraint
40
+ " • [impact 1] [svc:orders] Orders are append-only",
41
+ ]);
42
+ });
43
+ test("on an impact tie, the constraint leads the plain decision", () => {
44
+ const tied = {
45
+ decisions: [{ scopeRef: "svc:x", status: "binding", ruleText: "plain", impact: 3 }],
46
+ };
47
+ const b = {
48
+ constraints: [{ line: "⚠ [ratified · PRD-9] constraint", impact: 3, conflictOpen: false }],
49
+ overflow: 0,
50
+ };
51
+ const lines = formatReplay(null, tied, b).split("\n");
52
+ assert.equal(lines[2], " • ⚠ [ratified · PRD-9] constraint");
53
+ assert.equal(lines[3], " • [impact 3] [svc:x] plain");
54
+ });
55
+ test("overflow line appears only when overflow > 0", () => {
56
+ const withOverflow = { constraints: briefing.constraints, overflow: 7 };
57
+ const out = formatReplay(null, decisions, withOverflow);
58
+ assert.match(out, /\n {2}• \(\+7 product constraints in scope — get_product_context\)$/);
59
+ // no overflow → no line
60
+ assert.doesNotMatch(formatReplay(null, decisions, briefing), /product constraints in scope/);
61
+ });
62
+ test("constraints render even when there are no binding decisions", () => {
63
+ const out = formatReplay(null, { decisions: [] }, briefing);
64
+ const lines = out.split("\n");
65
+ assert.equal(lines[1], "📌 2 binding decision(s) in effect:");
66
+ assert.ok(lines[2]?.startsWith(" • ⚠ [ratified · PRD-142]"));
67
+ });
68
+ test("empty briefing (no constraints, overflow 0) leaves prior behavior intact", () => {
69
+ const empty = { constraints: [], overflow: 0 };
70
+ assert.equal(formatReplay(null, decisions, empty), formatReplay(null, decisions, null));
71
+ });
72
+ test("drift conflicts from the inbox render their own briefing section", () => {
73
+ const inbox = {
74
+ conflicts: [{ id: "k7", surface: "http:POST /payments/init", constraintRuleText: "no OTP before payment", engRuleText: "OTP on all inits" }],
75
+ };
76
+ const out = formatReplay(inbox, null, null);
77
+ assert.match(out, /⚔️ 1 drift conflict\(s\)/);
78
+ assert.match(out, /\[http:POST \/payments\/init\] your "OTP on all inits" vs constraint "no OTP before payment" — review both/);
79
+ });
80
+ test("project principles lead the briefing, above the binding-decisions section (Phase P)", () => {
81
+ const withPrinciples = {
82
+ constraints: [],
83
+ overflow: 0,
84
+ principles: [
85
+ { line: "◆ [principle] Server-side business logic is Ruby.", impact: 3 },
86
+ { line: "◆ [principle] Prefer boring technology.", impact: 0 },
87
+ ],
88
+ principlesOverflow: 0,
89
+ };
90
+ const out = formatReplay(null, decisions, withPrinciples);
91
+ const lines = out.split("\n");
92
+ assert.equal(lines[1], "◆ 2 project principle(s) — the team's standing decision criteria:");
93
+ assert.ok(lines[2].includes("Server-side business logic is Ruby."));
94
+ assert.ok(out.indexOf("project principle(s)") < out.indexOf("binding decision(s)"), "principles render before binding decisions");
95
+ assert.doesNotMatch(out, /more — query the ledger/);
96
+ const overflowing = { ...withPrinciples, principlesOverflow: 2 };
97
+ assert.match(formatReplay(null, decisions, overflowing), /\(\+2 more — query the ledger\)/);
98
+ // Absent principles (old core) → byte-identical to before.
99
+ assert.equal(formatReplay(null, decisions, { constraints: [], overflow: 0 }), formatReplay(null, decisions, null));
100
+ });
101
+ //# sourceMappingURL=replay.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.test.js","sourceRoot":"","sources":["../../src/capture/replay.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Canonical surface identity — the shared vocabulary that lets a producer and a consumer name the
3
+ * same logical interface as the SAME string, without sharing source. This is the keystone of
4
+ * routing/impact: a change to `http:POST /auth/session` matches a dependency on `http:POST /auth/session`.
5
+ *
6
+ * Format: `<kind>:<normalized-id>`
7
+ * http → http:POST /auth/session (method + normalized path)
8
+ * proto → proto:auth.v1.AuthService/Login (package.Service/Method)
9
+ * gql → gql:Mutation.login
10
+ * pkg → pkg:@scope/name#exportName (published-package export)
11
+ *
12
+ * Pure + testable. HTTP is first-class; proto is parsed; gql/openapi/pkg are light stubs we can
13
+ * deepen later behind this same interface.
14
+ */
15
+ export type SurfaceId = string;
16
+ /** Normalize a route path: ensure a leading slash, `{id}`→`:id`, strip querystring/trailing slash. */
17
+ export declare function normalizePath(p: string): string;
18
+ /**
19
+ * Extract every canonical surface ID a changed file *defines* (i.e. produces). Returns [] for files
20
+ * that expose no public interface — which is most files. This narrowness is intentional: it's what
21
+ * keeps the ledger quiet (a bare `export` is NOT a contract surface).
22
+ */
23
+ export declare function extractSurfaces(path: string, content?: string): SurfaceId[];
@@ -0,0 +1,83 @@
1
+ const HTTP_VERBS = "get|post|put|patch|delete|options|head|all";
2
+ /** Normalize a route path: ensure a leading slash, `{id}`→`:id`, strip querystring/trailing slash. */
3
+ export function normalizePath(p) {
4
+ let s = p.split("?")[0].trim();
5
+ if (!s.startsWith("/"))
6
+ s = "/" + s;
7
+ s = s.replace(/\{([^}]+)\}/g, ":$1"); // OpenAPI/Express-style {id} → :id
8
+ if (s.length > 1)
9
+ s = s.replace(/\/+$/, ""); // drop trailing slash (keep root "/")
10
+ return s;
11
+ }
12
+ const httpId = (method, path) => `http:${method.toUpperCase() === "ALL" ? "ANY" : method.toUpperCase()} ${normalizePath(path)}`;
13
+ /** Express/Fastify-style: `app.get("/x")`, `router.post('/y', ...)`, `fastify.delete(\`/z\`)`. */
14
+ function extractExpressRoutes(content) {
15
+ const re = new RegExp(`\\.(${HTTP_VERBS})\\s*\\(\\s*['"\`]([^'"\`]+)['"\`]`, "gi");
16
+ const out = [];
17
+ for (const m of content.matchAll(re))
18
+ out.push(httpId(m[1], m[2]));
19
+ return out;
20
+ }
21
+ /** Next.js app-router: `app/auth/session/route.ts` + `export async function POST` → http:POST /auth/session. */
22
+ function extractNextRoutes(path, content) {
23
+ const m = path.match(/(?:^|\/)app\/(.*)\/route\.(?:ts|tsx|js|mjs)$/i);
24
+ if (!m)
25
+ return [];
26
+ const segments = m[1]
27
+ .split("/")
28
+ .filter((seg) => !(seg.startsWith("(") && seg.endsWith(")"))) // route groups don't affect the URL
29
+ .map((seg) => seg.replace(/^\[(?:\.\.\.)?([^\]]+)\]$/, ":$1")); // [id] / [...slug] → :id
30
+ const routePath = "/" + segments.join("/");
31
+ const out = [];
32
+ for (const v of content.matchAll(/export\s+(?:async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\b/g)) {
33
+ out.push(httpId(v[1], routePath));
34
+ }
35
+ return out;
36
+ }
37
+ /** Protobuf: `package auth.v1;` + `service AuthService { rpc Login (...) ... }` → proto:auth.v1.AuthService/Login. */
38
+ function extractProto(content) {
39
+ const pkg = content.match(/^\s*package\s+([\w.]+)\s*;/m)?.[1] ?? "";
40
+ const out = [];
41
+ const svcRe = /service\s+(\w+)\s*\{([\s\S]*?)\}/g;
42
+ for (const svc of content.matchAll(svcRe)) {
43
+ const service = svc[1];
44
+ for (const rpc of svc[2].matchAll(/rpc\s+(\w+)\s*\(/g)) {
45
+ out.push(`proto:${pkg ? pkg + "." : ""}${service}/${rpc[1]}`);
46
+ }
47
+ }
48
+ return out;
49
+ }
50
+ /** GraphQL (light stub): top-level Query/Mutation/Subscription fields → gql:Mutation.login. */
51
+ function extractGraphql(content) {
52
+ const out = [];
53
+ const blockRe = /\b(type|extend\s+type)\s+(Query|Mutation|Subscription)\s*\{([\s\S]*?)\}/g;
54
+ for (const block of content.matchAll(blockRe)) {
55
+ const root = block[2];
56
+ for (const field of block[3].matchAll(/^\s*(\w+)\s*[(:]/gm))
57
+ out.push(`gql:${root}.${field[1]}`);
58
+ }
59
+ return out;
60
+ }
61
+ const isHttpRoutey = (path) => /(^|\/)(routes?|controllers?|api|handlers?|endpoints?)(\/|\.)/i.test(path);
62
+ /**
63
+ * Extract every canonical surface ID a changed file *defines* (i.e. produces). Returns [] for files
64
+ * that expose no public interface — which is most files. This narrowness is intentional: it's what
65
+ * keeps the ledger quiet (a bare `export` is NOT a contract surface).
66
+ */
67
+ export function extractSurfaces(path, content) {
68
+ const out = new Set();
69
+ if (/\.proto$/i.test(path) && content)
70
+ extractProto(content).forEach((s) => out.add(s));
71
+ if (/\.(graphql|gql)$/i.test(path) && content)
72
+ extractGraphql(content).forEach((s) => out.add(s));
73
+ if (/\.(ts|tsx|js|mjs|cjs)$/i.test(path) && content) {
74
+ extractNextRoutes(path, content).forEach((s) => out.add(s));
75
+ // Express/Fastify route literals — only trust them in files that look like route/handler code,
76
+ // so an incidental `.get("...")` on some object elsewhere doesn't mint a phantom endpoint.
77
+ if (isHttpRoutey(path) || /\b(express|fastify|router|app)\b/.test(content)) {
78
+ extractExpressRoutes(content).forEach((s) => out.add(s));
79
+ }
80
+ }
81
+ return [...out];
82
+ }
83
+ //# sourceMappingURL=surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.js","sourceRoot":"","sources":["../../src/capture/surface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { extractSurfaces } from "./surface.js";
4
+ test("extracts Express/Fastify routes as canonical http IDs", () => {
5
+ const ids = extractSurfaces("src/routes/auth.ts", `router.post('/auth/session', login)\napp.get("/auth/me", me)`);
6
+ assert.deepEqual(ids.sort(), ["http:GET /auth/me", "http:POST /auth/session"]);
7
+ });
8
+ test("normalizes path params and casing", () => {
9
+ const ids = extractSurfaces("src/routes/users.ts", "router.GET('/users/{id}/', show)");
10
+ assert.deepEqual(ids, ["http:GET /users/:id"]);
11
+ });
12
+ test("producer and consumer derive the SAME id for the same endpoint", () => {
13
+ const producer = extractSurfaces("services/auth/src/routes/session.ts", "app.post('/auth/session', h)");
14
+ // A consumer would declare this exact string in lockstep.yaml — they must match.
15
+ assert.equal(producer[0], "http:POST /auth/session");
16
+ });
17
+ test("Next.js app-router route file", () => {
18
+ const ids = extractSurfaces("app/auth/session/route.ts", "export async function POST(req) {}\nexport function GET() {}");
19
+ assert.deepEqual(ids.sort(), ["http:GET /auth/session", "http:POST /auth/session"]);
20
+ });
21
+ test("Next.js dynamic + route-group segments", () => {
22
+ const ids = extractSurfaces("app/(marketing)/users/[id]/route.ts", "export async function GET() {}");
23
+ assert.deepEqual(ids, ["http:GET /users/:id"]);
24
+ });
25
+ test("protobuf service/rpc with package", () => {
26
+ const ids = extractSurfaces("proto/auth.proto", "package auth.v1;\nservice AuthService {\n rpc Login (Req) returns (Res);\n rpc Logout (Req) returns (Res);\n}");
27
+ assert.deepEqual(ids.sort(), ["proto:auth.v1.AuthService/Login", "proto:auth.v1.AuthService/Logout"]);
28
+ });
29
+ test("graphql root fields", () => {
30
+ const ids = extractSurfaces("schema.graphql", "type Mutation {\n login(x: String): Token\n}");
31
+ assert.deepEqual(ids, ["gql:Mutation.login"]);
32
+ });
33
+ test("a non-interface file yields no surfaces", () => {
34
+ assert.deepEqual(extractSurfaces("src/util.ts", "export function add(a,b){return a+b}"), []);
35
+ assert.deepEqual(extractSurfaces("README.md", "# hi"), []);
36
+ });
37
+ //# sourceMappingURL=surface.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.test.js","sourceRoot":"","sources":["../../src/capture/surface.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACjE,MAAM,GAAG,GAAG,eAAe,CAAC,oBAAoB,EAAE,8DAA8D,CAAC,CAAC;IAClH,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,EAAE,yBAAyB,CAAC,CAAC,CAAC;AACjF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAC7C,MAAM,GAAG,GAAG,eAAe,CAAC,qBAAqB,EAAE,kCAAkC,CAAC,CAAC;IACvF,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gEAAgE,EAAE,GAAG,EAAE;IAC1E,MAAM,QAAQ,GAAG,eAAe,CAAC,qCAAqC,EAAE,8BAA8B,CAAC,CAAC;IACxG,iFAAiF;IACjF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+BAA+B,EAAE,GAAG,EAAE;IACzC,MAAM,GAAG,GAAG,eAAe,CAAC,2BAA2B,EAAE,8DAA8D,CAAC,CAAC;IACzH,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,wBAAwB,EAAE,yBAAyB,CAAC,CAAC,CAAC;AACtF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE;IAClD,MAAM,GAAG,GAAG,eAAe,CAAC,qCAAqC,EAAE,gCAAgC,CAAC,CAAC;IACrG,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAC7C,MAAM,GAAG,GAAG,eAAe,CACzB,kBAAkB,EAClB,iHAAiH,CAClH,CAAC;IACF,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,iCAAiC,EAAE,kCAAkC,CAAC,CAAC,CAAC;AACxG,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE;IAC/B,MAAM,GAAG,GAAG,eAAe,CAAC,gBAAgB,EAAE,+CAA+C,CAAC,CAAC;IAC/F,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACnD,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,aAAa,EAAE,sCAAsC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7F,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;AAC7D,CAAC,CAAC,CAAC"}
package/dist/connect.d.ts CHANGED
@@ -8,5 +8,5 @@ export declare function runConnect(opts: {
8
8
  org?: string;
9
9
  project?: string;
10
10
  }): Promise<void>;
11
- /** Invite a teammate by GitHub handle to this repo's project. */
11
+ /** Invite a teammate by GitHub handle to the project THIS repo is connected to. */
12
12
  export declare function runInvite(handle: string): Promise<void>;
package/dist/connect.js CHANGED
@@ -15,12 +15,19 @@ export async function runConnect(opts) {
15
15
  const r = await cloud.post("/connect", { gitRemote: remote, project: opts.project });
16
16
  const verb = r.status === "created" ? "created and connected" : r.status === "joined" ? "joined" : "already connected to";
17
17
  console.log(`✓ ${verb} project "${r.projectName}" (${remote})`);
18
+ if (r.createdOrg) {
19
+ // The repo landed in a brand-new workspace — likely NOT what you want if a teammate already has
20
+ // this project. Cross-service teammates join via an invite, not by naming the same project.
21
+ console.log(`\n⚠ This created a NEW workspace "${r.projectName}".`);
22
+ console.log(` If you meant to join a teammate's project, ask them to run`);
23
+ console.log(` \`lockstep invite ${process.env.USER ?? "<your-github-handle>"}\` first, then re-run \`lockstep connect\`.`);
24
+ }
18
25
  console.log(`\nOpen this repo in Claude Code — Lockstep registers the session automatically.`);
19
26
  if (r.status === "created") {
20
- console.log(`Teammates with GitHub access can join by running \`lockstep connect\` in their clone.`);
27
+ console.log(`Invite teammates with \`lockstep invite <github-handle>\`.`);
21
28
  }
22
29
  }
23
- /** Invite a teammate by GitHub handle to this repo's project. */
30
+ /** Invite a teammate by GitHub handle to the project THIS repo is connected to. */
24
31
  export async function runInvite(handle) {
25
32
  const remote = gitRemote(process.cwd());
26
33
  if (!remote) {
@@ -28,19 +35,23 @@ export async function runInvite(handle) {
28
35
  process.exit(1);
29
36
  }
30
37
  const me = await cloud.get("/me");
31
- const orgId = me.memberships[0]?.orgId;
32
- if (!orgId) {
38
+ const orgIds = [...new Set(me.memberships.map((m) => m.orgId))];
39
+ if (orgIds.length === 0) {
33
40
  console.error("No workspace yet — run `lockstep connect` first.");
34
41
  process.exit(1);
35
42
  }
36
- const projectName = remote.split("/").pop() ?? "default";
37
- const overview = await cloud.get(`/orgs/${orgId}/overview`);
38
- const projectId = overview?.projects.find((p) => p.name === projectName)?.id;
39
- if (!projectId) {
40
- console.error("This repo isn't connected yet run `lockstep connect` first.");
41
- process.exit(1);
43
+ // Resolve the project by which one this repo's remote is actually connected to — not by guessing
44
+ // the name from the remote (which breaks when `connect --project` used a custom name).
45
+ for (const orgId of orgIds) {
46
+ const overview = await cloud.get(`/orgs/${orgId}/overview`);
47
+ const project = overview?.projects.find((p) => (p.repos ?? []).some((r) => r.gitRemote === remote));
48
+ if (project) {
49
+ await cloud.post(`/orgs/${orgId}/projects/${project.id}/invite`, { githubLogin: handle.replace(/^@/, "") });
50
+ console.log(`✓ invited @${handle.replace(/^@/, "")} to "${project.name}" — they'll be activated on their next login.`);
51
+ return;
52
+ }
42
53
  }
43
- await cloud.post(`/orgs/${orgId}/projects/${projectId}/invite`, { githubLogin: handle.replace(/^@/, "") });
44
- console.log(`✓ invited @${handle.replace(/^@/, "")} to "${projectName}" — they'll be activated on their next login.`);
54
+ console.error("This repo isn't connected yet — run `lockstep connect` first.");
55
+ process.exit(1);
45
56
  }
46
57
  //# sourceMappingURL=connect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAgBzC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAwC;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAgB,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACpG,MAAM,IAAI,GACR,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC;IAC/G,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,aAAa,CAAC,CAAC,WAAW,OAAO,MAAM,GAAG,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC;IAC/F,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,uFAAuF,CAAC,CAAC;IACvG,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAK,KAAK,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS,CAAC;IACzD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAW,SAAS,KAAK,WAAW,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,EAAE,CAAC;IAC7E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,aAAa,SAAS,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3G,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,WAAW,+CAA+C,CAAC,CAAC;AACxH,CAAC"}
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAiBzC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAwC;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAgB,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACpG,MAAM,IAAI,GACR,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC;IAC/G,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,aAAa,CAAC,CAAC,WAAW,OAAO,MAAM,GAAG,CAAC,CAAC;IAEjE,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;QACjB,gGAAgG;QAChG,4FAA4F;QAC5F,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,sBAAsB,6CAA6C,CAAC,CAAC;IAC9H,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC;IAC/F,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAK,KAAK,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,iGAAiG;IACjG,uFAAuF;IACvF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAW,SAAS,KAAK,WAAW,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC;QACpG,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,aAAa,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;YAC5G,OAAO,CAAC,GAAG,CACT,cAAc,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,OAAO,CAAC,IAAI,+CAA+C,CAC1G,CAAC;YACF,OAAO;QACT,CAAC;IACH,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
package/dist/index.js CHANGED
@@ -19,6 +19,9 @@ usage: lockstep <command>
19
19
  init [--vendor claude|all] [--scope project|user] [--dry-run]
20
20
  wire up hooks + MCP + skill for the detected agent(s)
21
21
  connect [--project <name>] link this repo to a Lockstep project (creates one if needed)
22
+ onboard [--project <name>] one step: init + connect (for a teammate joining a repo)
23
+ scan [--json] [--apply] [--dry-run] scan the repo → propose lockstep.yaml (produces + graph-resolved consumes)
24
+ sync push lockstep.yaml (produces + consumes) to the graph, no rescan
22
25
  invite <github-handle> invite a teammate to this repo's project
23
26
  status show auth + config health
24
27
  doctor diagnose vendor config
@@ -58,6 +61,23 @@ async function main() {
58
61
  });
59
62
  case "connect":
60
63
  return runConnect({ org: val("org"), project: val("project") });
64
+ case "onboard": {
65
+ // One-step teammate onboarding: wire the repo (init) then link it (connect).
66
+ await runInit({ vendor: val("vendor"), scope: val("scope") ?? "project", dryRun: has("dry-run") });
67
+ if (has("dry-run"))
68
+ return;
69
+ await runConnect({ org: val("org"), project: val("project") });
70
+ console.log("\nOnboarded. Run `lockstep scan` to propose this repo's dependencies.");
71
+ return;
72
+ }
73
+ case "scan": {
74
+ const { runScan } = await import("./scan.js");
75
+ return runScan({ json: has("json"), apply: has("apply"), dryRun: has("dry-run") });
76
+ }
77
+ case "sync": {
78
+ const { runSync } = await import("./scan.js");
79
+ return runSync();
80
+ }
61
81
  case "invite": {
62
82
  const handle = argv[1];
63
83
  if (!handle) {
@@ -80,6 +100,11 @@ async function main() {
80
100
  await runCapture(val("event") ?? "PostToolUse");
81
101
  return;
82
102
  }
103
+ case "statusline": {
104
+ const { runStatusLine } = await import("./statusline.js");
105
+ await runStatusLine();
106
+ return;
107
+ }
83
108
  case "help":
84
109
  case "--help":
85
110
  case "-h":
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/init.js CHANGED
@@ -16,7 +16,9 @@ export async function runInit(opts) {
16
16
  }
17
17
  }
18
18
  if (!opts.dryRun && opts.scope === "project") {
19
- console.log("\nCommit the written files so teammates get Lockstep automatically on clone.");
19
+ console.log("\nCommit the shared files (.mcp.json, CLAUDE.md, .claude/skills) so teammates get Lockstep on clone." +
20
+ "\n.claude/settings.local.json is personal (hooks + statusline) and auto-gitignored — each teammate" +
21
+ "\nruns `lockstep onboard` once to get their own.");
20
22
  }
21
23
  }
22
24
  export async function runStatus() {
package/dist/init.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAwD;IACpF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrF,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACjE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CACT,sGAAsG;YACpG,oGAAoG;YACpG,kDAAkD,CACrD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,qCAAqC,EAAE,CAAC,CAAC;IAClG,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,WAAW,EAAE,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACrE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,IAAI,EAAE,GAAG,IAAI,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,MAAM,WAAW,EAAE,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,CAAC,CAAC,EAAE;YAAE,EAAE,GAAG,KAAK,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;QACpD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The per-session MCP server (one process per agent session). Registers the session,
3
- * then exposes the 12 tools as thin proxies to the core API. The core stays LLM-free —
3
+ * then exposes the tools as thin proxies to the core API. The core stays LLM-free —
4
4
  * query() returns rows; the agent synthesizes. Identical across vendors (the seam).
5
5
  */
6
6
  export declare function runMcpServer(): Promise<void>;
@@ -3,15 +3,19 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
3
3
  import { z } from "zod";
4
4
  import { registerSession } from "./session.js";
5
5
  import { call } from "./api.js";
6
+ import { gitRemote } from "./git.js";
7
+ import { writeFeatureContext } from "../capture/feature-context.js";
6
8
  /**
7
9
  * The per-session MCP server (one process per agent session). Registers the session,
8
- * then exposes the 12 tools as thin proxies to the core API. The core stays LLM-free —
10
+ * then exposes the tools as thin proxies to the core API. The core stays LLM-free —
9
11
  * query() returns rows; the agent synthesizes. Identical across vendors (the seam).
10
12
  */
11
13
  export async function runMcpServer() {
12
14
  const vendor = process.env.LOCKSTEP_VENDOR ?? "unknown";
13
15
  const session = await registerSession(vendor); // stderr-safe: throws to caller on failure
14
16
  const sid = session.sessionId;
17
+ let featureCtx = null; // set via set_feature_context; defaults capabilityRef on notify/propose
18
+ const remote = gitRemote(process.cwd());
15
19
  const ok = (data) => ({ content: [{ type: "text", text: JSON.stringify(data) }] });
16
20
  const server = new McpServer({ name: "lockstep", version: "0.0.1" });
17
21
  server.tool("notify", {
@@ -22,7 +26,8 @@ export async function runMcpServer() {
22
26
  verified: z.boolean().optional(),
23
27
  verifiedAgainst: z.string().optional(),
24
28
  diffHash: z.string().optional(),
25
- }, async (a) => ok(await call("POST", "/changes", sid, a)));
29
+ capabilityRef: z.string().optional(),
30
+ }, async (a) => ok(await call("POST", "/changes", sid, { ...a, capabilityRef: a.capabilityRef ?? featureCtx ?? undefined })));
26
31
  server.tool("inbox", {}, async () => ok(await call("GET", "/inbox", sid)));
27
32
  server.tool("ack_inbox", { itemIds: z.array(z.string()).optional() }, async (a) => ok(await call("POST", "/inbox/ack", sid, { itemIds: a.itemIds })));
28
33
  server.tool("query", { question: z.string(), scope: z.string().optional() }, async (a) => ok(await call("POST", "/query", sid, a)));
@@ -30,11 +35,29 @@ export async function runMcpServer() {
30
35
  server.tool("answer", { questionId: z.string(), response: z.string() }, async (a) => ok(await call("POST", `/questions/${a.questionId}/answer`, sid, { response: a.response })));
31
36
  server.tool("delegate", { to: z.string(), task: z.string(), refs: z.any().optional() }, async (a) => ok(await call("POST", "/tasks", sid, a)));
32
37
  server.tool("complete", { taskId: z.string(), note: z.string().optional() }, async (a) => ok(await call("POST", `/tasks/${a.taskId}/complete`, sid, { note: a.note })));
33
- server.tool("propose_decision", { scopeKind: z.string(), scopeRef: z.string(), ruleText: z.string(), baseVersion: z.number() }, async (a) => ok(await call("POST", "/decisions", sid, a)));
38
+ server.tool("propose_decision", {
39
+ scopeKind: z.string(),
40
+ scopeRef: z.string(),
41
+ ruleText: z.string(),
42
+ baseVersion: z.number(),
43
+ decisionType: z.enum(["rule", "architecture", "principle"]).optional(),
44
+ capabilityRef: z.string().optional(),
45
+ rationale: z.string().optional(), // the why, one or two sentences (ADR context)
46
+ alternatives: z.array(z.string()).optional(), // options considered and rejected
47
+ reviewAt: z.string().optional(), // ISO date — when this decision should be revisited
48
+ }, async (a) => ok(await call("POST", "/decisions", sid, { ...a, capabilityRef: a.capabilityRef ?? featureCtx ?? undefined })));
34
49
  server.tool("ack_decision", { decisionId: z.string(), version: z.number(), verdict: z.string().optional() }, async (a) => ok(await call("POST", `/decisions/${a.decisionId}/ack`, sid, { version: a.version, verdict: a.verdict })));
35
50
  server.tool("register_dependency", { producedSurface: z.string(), producedRepoId: z.string().optional() }, async (a) => ok(await call("POST", "/dependencies", sid, a)));
36
51
  server.tool("decisions", { scope: z.string().optional() }, async (a) => ok(await call("GET", `/decisions${a.scope ? `?scope=${encodeURIComponent(a.scope)}` : ""}`, sid)));
37
52
  server.tool("whoowns", { path: z.string() }, async (a) => ok(await call("GET", `/owners?path=${encodeURIComponent(a.path)}`, sid)));
53
+ server.tool("consumers", { surface: z.string() }, async (a) => ok(await call("GET", `/consumers?surface=${encodeURIComponent(a.surface)}`, sid)));
54
+ server.tool("get_product_context", { scope: z.string() }, async (a) => ok(await call("GET", `/product-context?scope=${encodeURIComponent(a.scope)}`, sid)));
55
+ server.tool("set_feature_context", { capabilityRef: z.string() }, async (a) => {
56
+ featureCtx = a.capabilityRef;
57
+ if (remote)
58
+ writeFeatureContext(remote, a.capabilityRef);
59
+ return ok({ ok: true, capabilityRef: a.capabilityRef });
60
+ });
38
61
  await server.connect(new StdioServerTransport());
39
62
  }
40
63
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
package/dist/scan.d.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type { OutboundRef } from "./capture/outbound.js";
2
+ export interface CatalogEntry {
3
+ surface: string;
4
+ repoId: string;
5
+ gitRemote: string;
6
+ /** #4: producer lives in another (shared) project — shown so the human approves with attribution. */
7
+ crossProject?: boolean;
8
+ projectName?: string;
9
+ }
10
+ interface MatchedConsume {
11
+ surface: string;
12
+ producer: string;
13
+ }
14
+ interface ReviewItem {
15
+ ref: string;
16
+ via: string;
17
+ hint: string;
18
+ candidates: MatchedConsume[];
19
+ }
20
+ interface UnmatchedItem {
21
+ ref: string;
22
+ via: string;
23
+ }
24
+ /**
25
+ * The full onboarding/maintenance proposal `/lockstep-setup` renders. `produces` is deterministic
26
+ * (extracted from served routes); `consumes` is graph-resolved (outbound calls matched against the
27
+ * project's produced-surface catalog); `unmatched`/`review` are the fuzzy leftovers the human decides.
28
+ */
29
+ export interface ScanProposal {
30
+ connected: boolean;
31
+ produces: string[];
32
+ consumes: MatchedConsume[];
33
+ unmatched: UnmatchedItem[];
34
+ review: ReviewItem[];
35
+ newProduces: string[];
36
+ newConsumes: string[];
37
+ }
38
+ /** Walk the whole repo → produced surfaces + outbound-call candidates. */
39
+ export declare function scanCode(cwd: string): {
40
+ produces: string[];
41
+ outbound: OutboundRef[];
42
+ };
43
+ export declare function classify(outbound: OutboundRef[], catalog: CatalogEntry[], ownRepoId: string | undefined): {
44
+ consumes: MatchedConsume[];
45
+ unmatched: UnmatchedItem[];
46
+ review: ReviewItem[];
47
+ };
48
+ export declare function report(p: ScanProposal): string;
49
+ /**
50
+ * `lockstep scan` — bootstrap/maintenance for `lockstep.yaml`. Default prints a proposal; `--json` emits
51
+ * it for the skill; `--apply` writes the manifest (merge-preserving) and syncs it to the graph.
52
+ */
53
+ export declare function runScan(opts: {
54
+ json?: boolean;
55
+ apply?: boolean;
56
+ dryRun?: boolean;
57
+ }): Promise<void>;
58
+ /**
59
+ * `lockstep sync` — push lockstep.yaml as-is (produces + consumes) to the graph, no rescan. The
60
+ * explicit path for hand-authored manifest entries; unlike the capture hook (consumes-only,
61
+ * best-effort) this hard-errors when the repo isn't connected.
62
+ */
63
+ export declare function runSync(): Promise<void>;
64
+ export {};