overlane 0.1.132 → 0.1.133

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/overlane.mjs CHANGED
@@ -20629,18 +20629,127 @@ var init_project_binding = __esm({
20629
20629
  }
20630
20630
  });
20631
20631
 
20632
+ // ../contracts/src/clients.ts
20633
+ var CLIENT_IDS, ClientId, CLIENT_LABELS, ClientSurface;
20634
+ var init_clients = __esm({
20635
+ "../contracts/src/clients.ts"() {
20636
+ "use strict";
20637
+ init_zod();
20638
+ CLIENT_IDS = ["claude", "codex", "grok", "cursor", "gemini"];
20639
+ ClientId = external_exports.enum(CLIENT_IDS);
20640
+ CLIENT_LABELS = {
20641
+ claude: "Claude Code",
20642
+ codex: "Codex",
20643
+ grok: "Grok Build",
20644
+ cursor: "Cursor",
20645
+ gemini: "Gemini CLI"
20646
+ };
20647
+ ClientSurface = external_exports.enum(["cli", "ide", "cloud"]);
20648
+ }
20649
+ });
20650
+
20651
+ // ../contracts/src/code-map.ts
20652
+ function codeMapDefault(setting, results = GATE_07_LATEST) {
20653
+ const result = results[setting];
20654
+ if (result.verdict === "failed") return { setting, on: false, basis: "gate-07-failed", reason: `off: ${result.summary} (${result.evidence})`, gate07: "failed" };
20655
+ if (result.verdict === "passed") return { setting, on: true, basis: "gate-07-passed", reason: `on: ${result.summary} (${result.evidence})`, gate07: "passed" };
20656
+ const on = SPEC_DEFAULT[setting];
20657
+ if (result.verdict === "pending") {
20658
+ return { setting, on, basis: "spec-default-provisional", reason: `${on ? "on" : "off"} by the spec default, provisional: ${result.summary} (${result.evidence})`, gate07: "pending" };
20659
+ }
20660
+ return { setting, on, basis: "spec-default", reason: `${on ? "on" : "off"} by the spec default: ${result.summary}`, gate07: "not-applicable" };
20661
+ }
20662
+ var CODE_MAP_SETTINGS, CodeMapSetting, GATE_07_VERDICTS, Gate07Verdict, GATE_07_LATEST, SPEC_DEFAULT, CODE_MAP_BASES, CodeMapDefault, CODE_MAP_CHARS_PER_TOKEN, estimateCodeMapTokens, CODE_MAP_CONTEXT_SETTINGS, CodeMapContextSetting, CODE_MAP_INTENTS, CodeMapIntent, CODE_MAP_CONTEXT_MODES, CodeMapContextMode, CodeMapContextRow, CodeMapClientStatus, CodeMapStatus, codeMapPaths;
20663
+ var init_code_map = __esm({
20664
+ "../contracts/src/code-map.ts"() {
20665
+ "use strict";
20666
+ init_zod();
20667
+ init_clients();
20668
+ init_common();
20669
+ CODE_MAP_SETTINGS = ["local-agent-with-grep", "cloud-session", "bot", "review-service", "cross-repo", "wiki"];
20670
+ CodeMapSetting = external_exports.enum(CODE_MAP_SETTINGS);
20671
+ GATE_07_VERDICTS = ["passed", "failed", "pending", "not-applicable"];
20672
+ Gate07Verdict = external_exports.enum(GATE_07_VERDICTS);
20673
+ GATE_07_LATEST = {
20674
+ "local-agent-with-grep": {
20675
+ verdict: "failed",
20676
+ summary: "GATE-07 failed with a local checkout and grep: cueline 115% and afltables 109% of the native-search token cost",
20677
+ evidence: "ADR 0018, docs/findings/gate-07-preliminary.md, docs/findings/gate-07-realism-afltables.md"
20678
+ },
20679
+ "cloud-session": {
20680
+ verdict: "pending",
20681
+ summary: "re-run for agents without a checkout: the mechanical leg is recorded, the agent leg waits on a model",
20682
+ evidence: "docs/findings/MS-A5-results.md (MS-A5.6)"
20683
+ },
20684
+ bot: {
20685
+ verdict: "pending",
20686
+ summary: "re-run for agents without a checkout: the mechanical leg is recorded, the agent leg waits on a model",
20687
+ evidence: "docs/findings/MS-A5-results.md (MS-A5.6)"
20688
+ },
20689
+ "review-service": { verdict: "not-applicable", summary: "the review service has no grep to compare with; it uses the map as context", evidence: "ADR 0032 decision 3" },
20690
+ "cross-repo": { verdict: "not-applicable", summary: "cross-repository questions have no single checkout to search", evidence: "ADR 0032 decision 2" },
20691
+ wiki: { verdict: "not-applicable", summary: "the generated wiki is built from the map", evidence: "ADR 0032 decision 3" }
20692
+ };
20693
+ SPEC_DEFAULT = {
20694
+ "local-agent-with-grep": false,
20695
+ "cloud-session": true,
20696
+ bot: true,
20697
+ "review-service": true,
20698
+ "cross-repo": true,
20699
+ wiki: true
20700
+ };
20701
+ CODE_MAP_BASES = ["gate-07-failed", "gate-07-passed", "spec-default-provisional", "spec-default", "project-setting"];
20702
+ CodeMapDefault = external_exports.object({ setting: CodeMapSetting, on: external_exports.boolean(), basis: external_exports.enum(CODE_MAP_BASES), reason: external_exports.string().min(1), gate07: Gate07Verdict }).strict();
20703
+ CODE_MAP_CHARS_PER_TOKEN = 2.3;
20704
+ estimateCodeMapTokens = (text) => Math.ceil(text.length * 10 / (CODE_MAP_CHARS_PER_TOKEN * 10));
20705
+ CODE_MAP_CONTEXT_SETTINGS = ["default", "on", "off"];
20706
+ CodeMapContextSetting = external_exports.enum(CODE_MAP_CONTEXT_SETTINGS);
20707
+ CODE_MAP_INTENTS = ["read-only", "edit", "unknown"];
20708
+ CodeMapIntent = external_exports.enum(CODE_MAP_INTENTS);
20709
+ CODE_MAP_CONTEXT_MODES = ["on", "read-only", "off"];
20710
+ CodeMapContextMode = external_exports.enum(CODE_MAP_CONTEXT_MODES);
20711
+ CodeMapContextRow = external_exports.object({ mode: CodeMapContextMode, basis: external_exports.enum(["setting-default", "project-setting"]), reason: external_exports.string().min(1) }).strict();
20712
+ CodeMapClientStatus = external_exports.object({
20713
+ subject: external_exports.string().min(1),
20714
+ client: external_exports.string().min(1),
20715
+ setting: CodeMapSetting,
20716
+ on: external_exports.boolean(),
20717
+ basis: external_exports.enum(CODE_MAP_BASES),
20718
+ reason: external_exports.string().min(1),
20719
+ gate07: Gate07Verdict,
20720
+ /** ADR 0055: the map as context at session start. Separate from `on`, which is about the code tools. */
20721
+ context: CodeMapContextRow.optional()
20722
+ }).strict();
20723
+ CodeMapStatus = external_exports.object({
20724
+ tenantId: TenantId,
20725
+ projectId: ProjectId,
20726
+ /** ADR 0018: the Worker serves code routes and the MCP code tool only when the project turns the code layer on. */
20727
+ projectCodeLayer: external_exports.boolean(),
20728
+ /** ADR 0055: the project's `codeMapContext` setting. Absent in answers from before it existed, which read as `default`. */
20729
+ projectCodeMapContext: CodeMapContextSetting.optional(),
20730
+ clients: external_exports.array(CodeMapClientStatus)
20731
+ }).strict();
20732
+ codeMapPaths = {
20733
+ status: (tenantId, projectId) => `/v1/tenants/${encodeURIComponent(tenantId)}/projects/${encodeURIComponent(projectId)}/code-map/status`
20734
+ };
20735
+ }
20736
+ });
20737
+
20632
20738
  // ../contracts/src/context-packet.ts
20633
20739
  var ProjectIdentity, Checkpoint, ActiveTask, WorkingCopyRevision, HardPolicy, SkillSummary, ContextPacket;
20634
20740
  var init_context_packet = __esm({
20635
20741
  "../contracts/src/context-packet.ts"() {
20636
20742
  "use strict";
20637
20743
  init_zod();
20744
+ init_code_map();
20638
20745
  init_common();
20639
20746
  init_task_contract();
20640
20747
  ProjectIdentity = external_exports.object({
20641
20748
  projectId: ProjectId,
20642
20749
  releaseVersion: SemVer,
20643
- releaseDigest: Sha256Digest
20750
+ releaseDigest: Sha256Digest,
20751
+ /** ADR 0055: the project's `codeMapContext` setting, present only when it is not `default`. The agent never sees it (agentView leaves it out). */
20752
+ codeMapContext: CodeMapContextSetting.optional()
20644
20753
  }).strict();
20645
20754
  Checkpoint = external_exports.object({
20646
20755
  taskId: TaskId,
@@ -20734,6 +20843,7 @@ var init_api2 = __esm({
20734
20843
  "../contracts/src/api.ts"() {
20735
20844
  "use strict";
20736
20845
  init_zod();
20846
+ init_code_map();
20737
20847
  init_common();
20738
20848
  apiPaths = {
20739
20849
  projects: (tenantId) => `/v1/tenants/${encodeURIComponent(tenantId)}/projects`,
@@ -20779,10 +20889,12 @@ var init_api2 = __esm({
20779
20889
  connection: ProjectConnection.optional(),
20780
20890
  name: external_exports.string().min(1).max(100),
20781
20891
  /** ADR 0018: the hosted code layer is off unless a project turns it on. Missing means false. */
20782
- codeLayer: external_exports.boolean().optional()
20892
+ codeLayer: external_exports.boolean().optional(),
20893
+ /** ADR 0055: the code map as session-start context, separate from `codeLayer`. Missing means `default`. */
20894
+ codeMapContext: CodeMapContextSetting.optional()
20783
20895
  }).strict().superRefine(checkProviderShape)
20784
20896
  );
20785
- UpdateProjectRequest = external_exports.object({ codeLayer: external_exports.boolean() }).strict();
20897
+ UpdateProjectRequest = external_exports.object({ codeLayer: external_exports.boolean().optional(), codeMapContext: CodeMapContextSetting.optional() }).strict().refine((body2) => body2.codeLayer !== void 0 || body2.codeMapContext !== void 0, { message: "send codeLayer or codeMapContext" });
20786
20898
  ProjectRecord = withCompat(
20787
20899
  fillProvider,
20788
20900
  external_exports.object({
@@ -20798,7 +20910,9 @@ var init_api2 = __esm({
20798
20910
  releaseDigest: Sha256Digest,
20799
20911
  createdAt: Timestamp,
20800
20912
  /** ADR 0018: registers the MCP `code` tool and opens the code routes. Missing in older records means false. */
20801
- codeLayer: external_exports.boolean().default(false)
20913
+ codeLayer: external_exports.boolean().default(false),
20914
+ /** ADR 0055: `default` follows the per-client default; `on` and `off` override it. Missing in older records means `default`. */
20915
+ codeMapContext: CodeMapContextSetting.optional()
20802
20916
  }).strict().superRefine(checkProviderShape)
20803
20917
  );
20804
20918
  WhoAmI = external_exports.object({
@@ -20954,25 +21068,6 @@ var init_code_index = __esm({
20954
21068
  }
20955
21069
  });
20956
21070
 
20957
- // ../contracts/src/clients.ts
20958
- var CLIENT_IDS, ClientId, CLIENT_LABELS, ClientSurface;
20959
- var init_clients = __esm({
20960
- "../contracts/src/clients.ts"() {
20961
- "use strict";
20962
- init_zod();
20963
- CLIENT_IDS = ["claude", "codex", "grok", "cursor", "gemini"];
20964
- ClientId = external_exports.enum(CLIENT_IDS);
20965
- CLIENT_LABELS = {
20966
- claude: "Claude Code",
20967
- codex: "Codex",
20968
- grok: "Grok Build",
20969
- cursor: "Cursor",
20970
- gemini: "Gemini CLI"
20971
- };
20972
- ClientSurface = external_exports.enum(["cli", "ide", "cloud"]);
20973
- }
20974
- });
20975
-
20976
21071
  // ../contracts/src/release.ts
20977
21072
  async function releaseDigestOf(files) {
20978
21073
  const lines = [...files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0).map((file2) => `${file2.path}\0${file2.digest}
@@ -23457,69 +23552,25 @@ var init_wording = __esm({
23457
23552
  }
23458
23553
  });
23459
23554
 
23460
- // ../contracts/src/code-map.ts
23461
- function codeMapDefault(setting, results = GATE_07_LATEST) {
23462
- const result = results[setting];
23463
- if (result.verdict === "failed") return { setting, on: false, basis: "gate-07-failed", reason: `off: ${result.summary} (${result.evidence})`, gate07: "failed" };
23464
- if (result.verdict === "passed") return { setting, on: true, basis: "gate-07-passed", reason: `on: ${result.summary} (${result.evidence})`, gate07: "passed" };
23465
- const on = SPEC_DEFAULT[setting];
23466
- if (result.verdict === "pending") {
23467
- return { setting, on, basis: "spec-default-provisional", reason: `${on ? "on" : "off"} by the spec default, provisional: ${result.summary} (${result.evidence})`, gate07: "pending" };
23468
- }
23469
- return { setting, on, basis: "spec-default", reason: `${on ? "on" : "off"} by the spec default: ${result.summary}`, gate07: "not-applicable" };
23470
- }
23471
- var CODE_MAP_SETTINGS, CodeMapSetting, GATE_07_VERDICTS, Gate07Verdict, GATE_07_LATEST, SPEC_DEFAULT, CODE_MAP_BASES, CodeMapDefault, CodeMapClientStatus, CodeMapStatus, codeMapPaths;
23472
- var init_code_map = __esm({
23473
- "../contracts/src/code-map.ts"() {
23555
+ // ../contracts/src/code-map-context.ts
23556
+ var CodeMapDigest, CODE_MAP_DIGEST_PATH;
23557
+ var init_code_map_context = __esm({
23558
+ "../contracts/src/code-map-context.ts"() {
23474
23559
  "use strict";
23475
23560
  init_zod();
23476
- init_clients();
23561
+ init_code_map();
23477
23562
  init_common();
23478
- CODE_MAP_SETTINGS = ["local-agent-with-grep", "cloud-session", "bot", "review-service", "cross-repo", "wiki"];
23479
- CodeMapSetting = external_exports.enum(CODE_MAP_SETTINGS);
23480
- GATE_07_VERDICTS = ["passed", "failed", "pending", "not-applicable"];
23481
- Gate07Verdict = external_exports.enum(GATE_07_VERDICTS);
23482
- GATE_07_LATEST = {
23483
- "local-agent-with-grep": {
23484
- verdict: "failed",
23485
- summary: "GATE-07 failed with a local checkout and grep: cueline 115% and afltables 109% of the native-search token cost",
23486
- evidence: "ADR 0018, docs/findings/gate-07-preliminary.md, docs/findings/gate-07-realism-afltables.md"
23487
- },
23488
- "cloud-session": {
23489
- verdict: "pending",
23490
- summary: "re-run for agents without a checkout: the mechanical leg is recorded, the agent leg waits on a model",
23491
- evidence: "docs/findings/MS-A5-results.md (MS-A5.6)"
23492
- },
23493
- bot: {
23494
- verdict: "pending",
23495
- summary: "re-run for agents without a checkout: the mechanical leg is recorded, the agent leg waits on a model",
23496
- evidence: "docs/findings/MS-A5-results.md (MS-A5.6)"
23497
- },
23498
- "review-service": { verdict: "not-applicable", summary: "the review service has no grep to compare with; it uses the map as context", evidence: "ADR 0032 decision 3" },
23499
- "cross-repo": { verdict: "not-applicable", summary: "cross-repository questions have no single checkout to search", evidence: "ADR 0032 decision 2" },
23500
- wiki: { verdict: "not-applicable", summary: "the generated wiki is built from the map", evidence: "ADR 0032 decision 3" }
23501
- };
23502
- SPEC_DEFAULT = {
23503
- "local-agent-with-grep": false,
23504
- "cloud-session": true,
23505
- bot: true,
23506
- "review-service": true,
23507
- "cross-repo": true,
23508
- wiki: true
23509
- };
23510
- CODE_MAP_BASES = ["gate-07-failed", "gate-07-passed", "spec-default-provisional", "spec-default", "project-setting"];
23511
- CodeMapDefault = external_exports.object({ setting: CodeMapSetting, on: external_exports.boolean(), basis: external_exports.enum(CODE_MAP_BASES), reason: external_exports.string().min(1), gate07: Gate07Verdict }).strict();
23512
- CodeMapClientStatus = external_exports.object({ subject: external_exports.string().min(1), client: external_exports.string().min(1), setting: CodeMapSetting, on: external_exports.boolean(), basis: external_exports.enum(CODE_MAP_BASES), reason: external_exports.string().min(1), gate07: Gate07Verdict }).strict();
23513
- CodeMapStatus = external_exports.object({
23514
- tenantId: TenantId,
23515
- projectId: ProjectId,
23516
- /** ADR 0018: the Worker serves code routes and the MCP code tool only when the project turns the code layer on. */
23517
- projectCodeLayer: external_exports.boolean(),
23518
- clients: external_exports.array(CodeMapClientStatus)
23563
+ CodeMapDigest = external_exports.object({
23564
+ schemaVersion: external_exports.literal("1"),
23565
+ revision: external_exports.object({ commitSha: CommitSha, branch: external_exports.string().min(1).optional() }).strict(),
23566
+ builtAt: Timestamp,
23567
+ coverage: external_exports.object({ files: external_exports.number().int().nonnegative(), symbols: external_exports.number().int().nonnegative(), uncovered: external_exports.number().int().nonnegative() }).strict(),
23568
+ /** Ranked body lines, most useful first. Trimming drops lines from the end, never the middle of a line. */
23569
+ lines: external_exports.array(external_exports.string()),
23570
+ /** Qualified names of the symbols the ranking put first. */
23571
+ seeds: external_exports.array(external_exports.string())
23519
23572
  }).strict();
23520
- codeMapPaths = {
23521
- status: (tenantId, projectId) => `/v1/tenants/${encodeURIComponent(tenantId)}/projects/${encodeURIComponent(projectId)}/code-map/status`
23522
- };
23573
+ CODE_MAP_DIGEST_PATH = ".harness/code-map.json";
23523
23574
  }
23524
23575
  });
23525
23576
 
@@ -24546,8 +24597,8 @@ function parsePipelineConfig(text) {
24546
24597
  for (const key of issue2.keys) issues.push({ line: lineFor([...path, key]), message: `unknown key '${key}'` });
24547
24598
  continue;
24548
24599
  }
24549
- const where = path.length === 0 ? "" : `${path.map(String).join(".")}: `;
24550
- issues.push({ line: lineFor(path), message: `${where}${issue2.message}` });
24600
+ const where2 = path.length === 0 ? "" : `${path.map(String).join(".")}: `;
24601
+ issues.push({ line: lineFor(path), message: `${where2}${issue2.message}` });
24551
24602
  }
24552
24603
  return { ok: false, issues: dedupeIssues(issues) };
24553
24604
  }
@@ -25019,6 +25070,7 @@ var init_src = __esm({
25019
25070
  init_autonomy();
25020
25071
  init_wording();
25021
25072
  init_code_map();
25073
+ init_code_map_context();
25022
25074
  init_agent();
25023
25075
  init_plans();
25024
25076
  init_billing();
@@ -32378,7 +32430,7 @@ var VERSION;
32378
32430
  var init_assets = __esm({
32379
32431
  "src/assets.ts"() {
32380
32432
  "use strict";
32381
- VERSION = true ? "0.1.132" : "0.0.0-dev";
32433
+ VERSION = true ? "0.1.133" : "0.0.0-dev";
32382
32434
  }
32383
32435
  });
32384
32436
 
@@ -40516,14 +40568,407 @@ var init_oidc = __esm({
40516
40568
  }
40517
40569
  });
40518
40570
 
40519
- // ../index-builder/src/run.ts
40571
+ // ../index-builder/src/context-map.ts
40572
+ function stripNoise(text) {
40573
+ return text.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/[^\n]*/g, " ").replace(/"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|`(?:[^`\\]|\\.)*`/g, '""');
40574
+ }
40575
+ function wordsOf(text) {
40576
+ const parts2 = text.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[^A-Za-z0-9]+/);
40577
+ const out2 = [];
40578
+ for (const part of parts2) {
40579
+ let word = part.toLowerCase();
40580
+ if (word.length < 3 || /^\d+$/.test(word) || STOP.has(word)) continue;
40581
+ if (word.endsWith("ies") && word.length > 4) word = `${word.slice(0, -3)}y`;
40582
+ else if (word.endsWith("s") && !word.endsWith("ss") && word.length > 3) word = word.slice(0, -1);
40583
+ if (word.endsWith("ing") && word.length > 6) word = word.slice(0, -3);
40584
+ else if (word.endsWith("ed") && word.length > 5) word = word.slice(0, -2);
40585
+ out2.push(word);
40586
+ }
40587
+ return out2;
40588
+ }
40589
+ function resolveImport(from, spec) {
40590
+ if (!spec.startsWith(".")) return null;
40591
+ const parts2 = from.split("/").slice(0, -1);
40592
+ for (const piece of spec.split("/")) {
40593
+ if (piece === "." || piece === "") continue;
40594
+ if (piece === "..") parts2.pop();
40595
+ else parts2.push(piece);
40596
+ }
40597
+ return stripModuleExtension(parts2.join("/"));
40598
+ }
40599
+ function stripModuleExtension(path) {
40600
+ return path.replace(/\.(?:[cm]?[jt]sx?|d\.ts)$/, "");
40601
+ }
40602
+ function reaches(visible, path) {
40603
+ const bare = stripModuleExtension(path);
40604
+ return visible.has(bare) || visible.has(path) || bare.endsWith("/index") && visible.has(bare.slice(0, -"/index".length));
40605
+ }
40606
+ function headerOf(content, symbol2) {
40607
+ const lines = content.split("\n");
40608
+ const start2 = symbol2.range[0];
40609
+ const chunk = [];
40610
+ for (let i2 = start2; i2 < Math.min(lines.length, start2 + 4); i2 += 1) {
40611
+ const line2 = lines[i2] ?? "";
40612
+ chunk.push(line2);
40613
+ if (line2.includes("{")) break;
40614
+ }
40615
+ return chunk.join(" ");
40616
+ }
40617
+ async function buildRepoIndex(files) {
40618
+ const symbols2 = /* @__PURE__ */ new Map();
40619
+ const byName = /* @__PURE__ */ new Map();
40620
+ const byFile = /* @__PURE__ */ new Map();
40621
+ const imports = /* @__PURE__ */ new Map();
40622
+ const ranges = /* @__PURE__ */ new Map();
40623
+ const headers = /* @__PURE__ */ new Map();
40624
+ const paths = [...files.keys()].filter((path) => languageForPath(path) !== null).sort();
40625
+ for (const path of paths) {
40626
+ const content = files.get(path);
40627
+ const shard = await parseDeclarations(path, content);
40628
+ if (shard === null) continue;
40629
+ const targets = /* @__PURE__ */ new Set();
40630
+ for (const match of content.matchAll(/from\s+["']([^"']+)["']/g)) {
40631
+ const resolved = resolveImport(path, match[1] ?? "");
40632
+ if (resolved !== null) targets.add(resolved);
40633
+ }
40634
+ imports.set(path, targets);
40635
+ for (const symbol2 of shard.symbols) {
40636
+ const hash2 = symbol2.symbol.indexOf("#");
40637
+ const entry = { id: symbol2.symbol, name: symbol2.name, qualified: symbol2.symbol.slice(hash2 + 1), kind: symbol2.kind, path, line: symbol2.range[0] + 1, parent: symbol2.parent };
40638
+ symbols2.set(entry.id, entry);
40639
+ ranges.set(entry.id, symbol2);
40640
+ byName.set(entry.name, [...byName.get(entry.name) ?? [], entry]);
40641
+ byFile.set(path, [...byFile.get(path) ?? [], entry]);
40642
+ if (symbol2.kind === "class" || symbol2.kind === "interface") headers.set(entry.id, headerOf(content, symbol2));
40643
+ }
40644
+ }
40645
+ const callees = /* @__PURE__ */ new Map();
40646
+ const callers = /* @__PURE__ */ new Map();
40647
+ for (const entry of symbols2.values()) {
40648
+ if (!CALLABLE.has(entry.kind)) continue;
40649
+ const range = ranges.get(entry.id)?.enclosingRange;
40650
+ if (range === void 0) continue;
40651
+ const text = stripNoise(files.get(entry.path).split("\n").slice(range[0], range[2] + 1).join("\n"));
40652
+ const visible = imports.get(entry.path) ?? /* @__PURE__ */ new Set();
40653
+ const seen = /* @__PURE__ */ new Set();
40654
+ for (const match of text.matchAll(/[A-Za-z_$][\w$]*/g)) {
40655
+ const id2 = match[0];
40656
+ if (KEYWORDS.has(id2) || seen.has(id2)) continue;
40657
+ seen.add(id2);
40658
+ for (const target of byName.get(id2) ?? []) {
40659
+ if (target.id === entry.id || target.kind === "property" || target.kind === "parameter") continue;
40660
+ if (target.path !== entry.path && !reaches(visible, target.path)) continue;
40661
+ if (target.id === entry.parent) continue;
40662
+ callees.set(entry.id, (callees.get(entry.id) ?? /* @__PURE__ */ new Set()).add(target.id));
40663
+ callers.set(target.id, (callers.get(target.id) ?? /* @__PURE__ */ new Set()).add(entry.id));
40664
+ }
40665
+ }
40666
+ }
40667
+ const heritage = /* @__PURE__ */ new Map();
40668
+ const heirs = /* @__PURE__ */ new Map();
40669
+ const resolve16 = (from, name2) => {
40670
+ const visible = imports.get(from.path) ?? /* @__PURE__ */ new Set();
40671
+ return (byName.get(baseName(name2)) ?? []).find((candidate) => candidate.path === from.path || reaches(visible, candidate.path));
40672
+ };
40673
+ for (const [id2, header] of headers) {
40674
+ const entry = symbols2.get(id2);
40675
+ const stem2 = header.slice(header.indexOf(entry.name) + entry.name.length).replace(/^<[^>]*>/, "").replace(/\{.*$/, "");
40676
+ const ext = /\bextends\s+([A-Za-z_$][\w$.]*)/.exec(stem2)?.[1];
40677
+ const impl = /\bimplements\s+(.+)$/.exec(stem2)?.[1];
40678
+ const extendsIds = ext === void 0 ? [] : [resolve16(entry, ext)?.id].filter((value) => value !== void 0);
40679
+ const implementsIds = (impl === void 0 ? [] : impl.split(/,(?![^<]*>)/).map((part) => resolve16(entry, part.trim()))).filter((value) => value !== void 0).map((value) => value.id);
40680
+ if (extendsIds.length === 0 && implementsIds.length === 0) continue;
40681
+ heritage.set(id2, { extends: extendsIds, implements: implementsIds });
40682
+ for (const target of extendsIds) heirs.set(target, { extendedBy: [...heirs.get(target)?.extendedBy ?? [], id2], implementedBy: heirs.get(target)?.implementedBy ?? [] });
40683
+ for (const target of implementsIds) heirs.set(target, { extendedBy: heirs.get(target)?.extendedBy ?? [], implementedBy: [...heirs.get(target)?.implementedBy ?? [], id2] });
40684
+ }
40685
+ const words = /* @__PURE__ */ new Map();
40686
+ for (const entry of symbols2.values()) for (const word of new Set(wordsOf(entry.name))) words.set(word, (words.get(word) ?? 0) + 1);
40687
+ return { files: paths.length, symbols: symbols2, byName, byFile, callees, callers, heritage, heirs, imports, words, wordDocs: symbols2.size };
40688
+ }
40689
+ function idf(index, word) {
40690
+ return Math.log(index.wordDocs / (1 + (index.words.get(word) ?? 0)));
40691
+ }
40692
+ function scoreSymbols(index, task) {
40693
+ const exactNames = /* @__PURE__ */ new Set();
40694
+ for (const match of task.matchAll(/[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*/g)) {
40695
+ const token = match[0];
40696
+ if (token.length >= 4 && index.byName.has(token)) exactNames.add(token);
40697
+ if (token.includes(".")) exactNames.add(token);
40698
+ }
40699
+ const taskWords = new Set(wordsOf(task));
40700
+ const scored = [];
40701
+ for (const symbol2 of index.symbols.values()) {
40702
+ if (!SEEDABLE.has(symbol2.kind)) continue;
40703
+ if (symbol2.kind === "constant" && !/^[A-Z][A-Z0-9_]+$/.test(symbol2.name)) continue;
40704
+ let score = 0;
40705
+ let exact = false;
40706
+ if (exactNames.has(symbol2.qualified)) {
40707
+ score = 200;
40708
+ exact = true;
40709
+ } else if (exactNames.has(symbol2.name) && !symbol2.qualified.includes(".")) {
40710
+ score = 150;
40711
+ exact = true;
40712
+ } else if (exactNames.has(symbol2.name)) {
40713
+ score = 100;
40714
+ exact = true;
40715
+ } else {
40716
+ const own2 = new Set(wordsOf(symbol2.name));
40717
+ const fileWords = new Set(wordsOf(symbol2.path.split("/").pop()?.replace(/\.ts$/, "") ?? ""));
40718
+ let hits = 0;
40719
+ for (const word of own2) if (taskWords.has(word) && idf(index, word) >= MIN_WORD_IDF) {
40720
+ score += idf(index, word);
40721
+ hits += 1;
40722
+ }
40723
+ for (const word of fileWords) if (!own2.has(word) && taskWords.has(word) && idf(index, word) >= MIN_WORD_IDF) score += idf(index, word) * 0.4;
40724
+ if (hits === 0) score = 0;
40725
+ else score /= 1 + 0.15 * own2.size;
40726
+ if (score < MIN_SOFT_SCORE) score = 0;
40727
+ }
40728
+ if (score > 0) scored.push({ symbol: symbol2, score, exact });
40729
+ }
40730
+ return scored.sort((a, b) => b.score - a.score || a.symbol.path.localeCompare(b.symbol.path) || a.symbol.line - b.symbol.line);
40731
+ }
40732
+ function pageRank(index, personal) {
40733
+ const neighbours = /* @__PURE__ */ new Map();
40734
+ const link = (a, b, weight) => {
40735
+ if (a === b) return;
40736
+ neighbours.set(a, (neighbours.get(a) ?? /* @__PURE__ */ new Map()).set(b, (neighbours.get(a)?.get(b) ?? 0) + weight));
40737
+ neighbours.set(b, (neighbours.get(b) ?? /* @__PURE__ */ new Map()).set(a, (neighbours.get(b)?.get(a) ?? 0) + weight));
40738
+ };
40739
+ for (const [from, targets] of index.callees) {
40740
+ const a = index.symbols.get(from)?.path;
40741
+ if (a === void 0) continue;
40742
+ for (const target of targets) {
40743
+ const b = index.symbols.get(target)?.path;
40744
+ if (b !== void 0) link(a, b, 1);
40745
+ }
40746
+ }
40747
+ let total = 0;
40748
+ for (const value of personal.values()) total += value;
40749
+ const damping = 0.5;
40750
+ let rank = /* @__PURE__ */ new Map();
40751
+ for (const [path, value] of personal) rank.set(path, total === 0 ? 0 : value / total);
40752
+ for (let step2 = 0; step2 < 15; step2 += 1) {
40753
+ const next = /* @__PURE__ */ new Map();
40754
+ for (const [path, value] of personal) next.set(path, (1 - damping) * (total === 0 ? 0 : value / total));
40755
+ for (const [path, mass] of rank) {
40756
+ const out2 = neighbours.get(path);
40757
+ if (out2 === void 0 || mass === 0) continue;
40758
+ let sum = 0;
40759
+ for (const weight of out2.values()) sum += weight;
40760
+ for (const [other, weight] of out2) next.set(other, (next.get(other) ?? 0) + damping * mass * (weight / sum));
40761
+ }
40762
+ rank = next;
40763
+ }
40764
+ return rank;
40765
+ }
40766
+ function callerLines(index, seed) {
40767
+ const lines = [];
40768
+ const seen = /* @__PURE__ */ new Set([seed.id]);
40769
+ let frontier = [seed.id];
40770
+ for (let depth = 1; depth <= 3 && frontier.length > 0 && lines.length < 12; depth += 1) {
40771
+ const next = [];
40772
+ for (const id2 of frontier) {
40773
+ const target = index.symbols.get(id2);
40774
+ const callers = [...index.callers.get(id2) ?? []].filter((caller) => !seen.has(caller)).map((caller) => index.symbols.get(caller)).sort((a, b) => a.path.localeCompare(b.path) || a.line - b.line);
40775
+ for (const caller of callers.slice(0, 8)) {
40776
+ seen.add(caller.id);
40777
+ next.push(caller.id);
40778
+ if (lines.length < 12) lines.push(`${" ".repeat(depth)}${caller.qualified} ${caller.path}:${caller.line} -> ${target.qualified}`);
40779
+ }
40780
+ if (callers.length > 8) lines.push(`${" ".repeat(depth)}(+${callers.length - 8} more callers of ${target.qualified})`);
40781
+ }
40782
+ frontier = next;
40783
+ }
40784
+ return lines;
40785
+ }
40786
+ function seedBlock(index, seed) {
40787
+ const out2 = [`${seed.kind} ${where(seed)}`];
40788
+ const heirs = index.heirs.get(seed.id);
40789
+ const heritage = index.heritage.get(seed.id);
40790
+ const list = (ids, limit) => {
40791
+ const shown2 = ids.slice(0, limit).map((id2) => index.symbols.get(id2)).filter((value) => value !== void 0).sort((a, b) => a.path.localeCompare(b.path));
40792
+ return `${shown2.map((entry) => `${entry.name} ${entry.path}:${entry.line}`).join("; ")}${ids.length > limit ? `; (+${ids.length - limit} more, ${ids.length} total)` : ""}`;
40793
+ };
40794
+ if (heritage !== void 0) {
40795
+ if (heritage.extends.length > 0) out2.push(` extends: ${list(heritage.extends, 4)}`);
40796
+ if (heritage.implements.length > 0) out2.push(` implements: ${list(heritage.implements, 4)}`);
40797
+ }
40798
+ if (heirs !== void 0) {
40799
+ if (heirs.implementedBy.length > 0) out2.push(` implemented by: ${list(heirs.implementedBy, 12)}`);
40800
+ if (heirs.extendedBy.length > 0) out2.push(` extended by: ${list(heirs.extendedBy, 6)}`);
40801
+ }
40802
+ const calls = [...index.callees.get(seed.id) ?? []].map((id2) => index.symbols.get(id2)).sort((a, b) => a.path.localeCompare(b.path) || a.line - b.line);
40803
+ if (calls.length > 0) out2.push(` calls: ${calls.slice(0, 8).map((entry) => `${entry.qualified} ${entry.path}:${entry.line}`).join("; ")}${calls.length > 8 ? `; (+${calls.length - 8} more)` : ""}`);
40804
+ const up = callerLines(index, seed);
40805
+ if (up.length > 0) out2.push(" called by (up to 3 levels):", ...up);
40806
+ return out2;
40807
+ }
40808
+ function outline(index, path) {
40809
+ const entries = (index.byFile.get(path) ?? []).filter((symbol2) => symbol2.kind !== "property" && symbol2.kind !== "parameter");
40810
+ const tops = entries.filter((symbol2) => symbol2.parent === void 0);
40811
+ const parts2 = tops.slice(0, 8).map((symbol2) => {
40812
+ const members2 = entries.filter((member) => member.parent === symbol2.id).map((member) => member.name);
40813
+ return members2.length > 0 ? `${symbol2.name}{${members2.slice(0, 8).join(",")}}` : symbol2.name;
40814
+ });
40815
+ return `${path}: ${parts2.join(" ")}`;
40816
+ }
40817
+ function layout(index) {
40818
+ const domains = /* @__PURE__ */ new Map();
40819
+ for (const path of index.imports.keys()) {
40820
+ const parts2 = path.split("/");
40821
+ const key = parts2.length > 2 ? `${parts2[0]}/${parts2[1]}` : parts2[0] ?? path;
40822
+ domains.set(key, (domains.get(key) ?? 0) + 1);
40823
+ }
40824
+ return [`Layout: ${index.files} source files. ${[...domains].sort().map(([key, count]) => `${key}(${count})`).join(" ")}`];
40825
+ }
40826
+ function mostCalled(index, limit) {
40827
+ const counts2 = [];
40828
+ for (const [id2, callers] of index.callers) {
40829
+ const symbol2 = index.symbols.get(id2);
40830
+ if (symbol2 === void 0 || !SEEDABLE.has(symbol2.kind) || symbol2.kind === "constant") continue;
40831
+ counts2.push({ symbol: symbol2, callers: callers.size });
40832
+ }
40833
+ counts2.sort((a, b) => b.callers - a.callers || a.symbol.path.localeCompare(b.symbol.path) || a.symbol.line - b.symbol.line);
40834
+ return counts2.slice(0, limit).map((entry) => entry.symbol);
40835
+ }
40836
+ function buildCodeMap(index, task, options = DEFAULT_MAP_OPTIONS) {
40837
+ const lines = [...layout(index), "Edges: 'called by' and 'calls' are resolved by name within imported files, ignoring comments and strings. Lines are file:line of the declaration."];
40838
+ const fits = (extra) => estimateTokens(`${[...lines, ...extra].join("\n")}
40839
+ `) <= options.maxTokens;
40840
+ const scored = scoreSymbols(index, task);
40841
+ const seeds = [];
40842
+ const shownFiles = /* @__PURE__ */ new Set();
40843
+ const taskFree = scored.length === 0;
40844
+ const candidates = taskFree ? mostCalled(index, options.maxSeeds).map((symbol2) => ({ symbol: symbol2, score: 1 })) : scored;
40845
+ lines.push("", taskFree ? "Most called symbols:" : "Symbols most relevant to the task:");
40846
+ for (const item of candidates) {
40847
+ if (seeds.length >= options.maxSeeds) break;
40848
+ const block2 = seedBlock(index, item.symbol);
40849
+ if (!fits(block2)) {
40850
+ const short = block2.slice(0, 1);
40851
+ if (!fits(short)) continue;
40852
+ lines.push(...short);
40853
+ } else lines.push(...block2);
40854
+ seeds.push(item.symbol);
40855
+ shownFiles.add(item.symbol.path);
40856
+ }
40857
+ const personal = /* @__PURE__ */ new Map();
40858
+ if (taskFree) for (const path of index.byFile.keys()) personal.set(path, 1);
40859
+ else for (const item of scored.slice(0, 40)) personal.set(item.symbol.path, (personal.get(item.symbol.path) ?? 0) + item.score);
40860
+ const rank = pageRank(index, personal);
40861
+ const ordered = [...rank].filter(([path]) => !shownFiles.has(path)).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
40862
+ const related = [];
40863
+ const top = ordered[0]?.[1] ?? 0;
40864
+ for (const [path, mass] of ordered) {
40865
+ if (mass <= 0 || mass < top * 0.05 || related.length >= MAX_RELATED_FILES) break;
40866
+ const line2 = outline(index, path);
40867
+ if (!fits(["", taskFree ? "Central files:" : "Related files:", ...related, line2])) break;
40868
+ related.push(line2);
40869
+ }
40870
+ if (related.length > 0) lines.push("", taskFree ? "Central files:" : "Related files:", ...related);
40871
+ const text = `${lines.join("\n")}
40872
+ `;
40873
+ return { lines, text, estimatedTokens: estimateTokens(text), seeds: seeds.map((seed) => seed.qualified), files: index.files, symbols: index.symbols.size };
40874
+ }
40875
+ function buildCodeMapDigest(input2) {
40876
+ const map2 = buildCodeMap(input2.index, input2.task ?? "", input2.options ?? DEFAULT_MAP_OPTIONS);
40877
+ return {
40878
+ schemaVersion: "1",
40879
+ revision: { commitSha: input2.commitSha, ...input2.branch === void 0 ? {} : { branch: input2.branch } },
40880
+ builtAt: input2.builtAt,
40881
+ coverage: { files: map2.files, symbols: map2.symbols, uncovered: input2.uncovered },
40882
+ lines: map2.lines,
40883
+ seeds: map2.seeds
40884
+ };
40885
+ }
40886
+ var KEYWORDS, CALLABLE, SEEDABLE, MIN_WORD_IDF, MIN_SOFT_SCORE, MAX_RELATED_FILES, STOP, baseName, DEFAULT_MAP_OPTIONS, estimateTokens, where;
40887
+ var init_context_map = __esm({
40888
+ "../index-builder/src/context-map.ts"() {
40889
+ "use strict";
40890
+ init_src();
40891
+ init_languages();
40892
+ init_treesitter();
40893
+ KEYWORDS = /* @__PURE__ */ new Set(["const", "let", "var", "function", "return", "if", "else", "new", "this", "class", "extends", "implements", "import", "export", "from", "type", "interface", "async", "await", "string", "number", "boolean", "void", "null", "undefined", "true", "false", "private", "protected", "public", "readonly", "static", "abstract", "super", "typeof", "for", "of", "in", "while", "throw", "try", "catch", "as"]);
40894
+ CALLABLE = /* @__PURE__ */ new Set(["function", "method", "constant", "variable"]);
40895
+ SEEDABLE = /* @__PURE__ */ new Set(["function", "method", "class", "interface", "type", "constant"]);
40896
+ MIN_WORD_IDF = 2.5;
40897
+ MIN_SOFT_SCORE = 3.5;
40898
+ MAX_RELATED_FILES = 14;
40899
+ STOP = /* @__PURE__ */ new Set(["the", "a", "an", "of", "to", "in", "is", "are", "and", "or", "for", "that", "this", "it", "its", "by", "be", "on", "as", "at", "with", "from", "which", "what", "when", "where", "who", "how", "do", "does", "not", "any", "each", "every", "all", "also", "than", "then", "so", "if", "into", "file", "path", "answer", "end", "final", "message", "line", "start", "follow", "separate", "comma", "give", "name", "modify", "files", "repository", "source", "code", "change", "update", "make", "use", "uses", "used", "other", "only", "about", "will", "can", "should", "need", "needs", "happen", "merely", "share", "same", "return", "returns", "pass", "passes"]);
40900
+ baseName = (name2) => name2.replace(/<.*$/, "").split(".").pop() ?? name2;
40901
+ DEFAULT_MAP_OPTIONS = { maxTokens: 3400, maxSeeds: 6 };
40902
+ estimateTokens = estimateCodeMapTokens;
40903
+ where = (symbol2) => `${symbol2.qualified} ${symbol2.path}:${symbol2.line}`;
40904
+ }
40905
+ });
40906
+
40907
+ // ../index-builder/src/context-map-build.ts
40520
40908
  import { execFile as execFile2 } from "node:child_process";
40521
- import { mkdir as mkdir3, readdir as readdir4, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
40522
- import { join as join26, resolve as resolve14 } from "node:path";
40523
- import { parseArgs as parseArgs2 } from "node:util";
40909
+ import { mkdir as mkdir3, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
40910
+ import { dirname as dirname9, join as join26 } from "node:path";
40524
40911
  import { promisify as promisify2 } from "node:util";
40525
40912
  async function git3(root, args2) {
40526
- const { stdout } = await execFileAsync2("git", args2, { cwd: root, encoding: "utf8" });
40913
+ const { stdout } = await execFileAsync2("git", args2, { cwd: root, encoding: "utf8", maxBuffer: 256 * 1024 * 1024 });
40914
+ return stdout.trim();
40915
+ }
40916
+ async function buildDigestForCheckout(options) {
40917
+ const tracked = (await execFileAsync2("git", ["ls-files", "-z"], { cwd: options.root, encoding: "utf8", maxBuffer: 256 * 1024 * 1024 })).stdout.split("\0").filter((path) => path !== "");
40918
+ const files = /* @__PURE__ */ new Map();
40919
+ let uncovered = 0;
40920
+ for (const path of tracked) {
40921
+ if (languageForPath(path) === null) continue;
40922
+ try {
40923
+ const bytes = await readFile5(join26(options.root, path));
40924
+ if (bytes.byteLength > MAX_PARSE_BYTES) {
40925
+ uncovered += 1;
40926
+ continue;
40927
+ }
40928
+ files.set(path, bytes.toString("utf8"));
40929
+ } catch {
40930
+ uncovered += 1;
40931
+ }
40932
+ }
40933
+ const index = await buildRepoIndex(files);
40934
+ const commitSha = await git3(options.root, ["rev-parse", "HEAD"]);
40935
+ let branch;
40936
+ try {
40937
+ branch = await git3(options.root, ["symbolic-ref", "--short", "-q", "HEAD"]) || void 0;
40938
+ } catch {
40939
+ branch = void 0;
40940
+ }
40941
+ return CodeMapDigest.parse(
40942
+ buildCodeMapDigest({ index, commitSha, ...branch === void 0 ? {} : { branch }, uncovered, builtAt: options.builtAt ?? (/* @__PURE__ */ new Date()).toISOString(), ...options.task === void 0 ? {} : { task: options.task } })
40943
+ );
40944
+ }
40945
+ async function writeDigest(root, digest, out2) {
40946
+ const path = out2 ?? join26(root, CODE_MAP_DIGEST_PATH);
40947
+ await mkdir3(dirname9(path), { recursive: true });
40948
+ await writeFile3(path, `${JSON.stringify(digest)}
40949
+ `);
40950
+ return path;
40951
+ }
40952
+ var execFileAsync2;
40953
+ var init_context_map_build = __esm({
40954
+ "../index-builder/src/context-map-build.ts"() {
40955
+ "use strict";
40956
+ init_src();
40957
+ init_context_map();
40958
+ init_languages();
40959
+ init_snapshot();
40960
+ execFileAsync2 = promisify2(execFile2);
40961
+ }
40962
+ });
40963
+
40964
+ // ../index-builder/src/run.ts
40965
+ import { execFile as execFile3 } from "node:child_process";
40966
+ import { mkdir as mkdir4, readdir as readdir4, rm as rm2, writeFile as writeFile4 } from "node:fs/promises";
40967
+ import { join as join27, resolve as resolve14 } from "node:path";
40968
+ import { parseArgs as parseArgs2 } from "node:util";
40969
+ import { promisify as promisify3 } from "node:util";
40970
+ async function git4(root, args2) {
40971
+ const { stdout } = await execFileAsync3("git", args2, { cwd: root, encoding: "utf8" });
40527
40972
  return stdout.trim();
40528
40973
  }
40529
40974
  function parseRepository(value) {
@@ -40533,7 +40978,7 @@ function parseRepository(value) {
40533
40978
  }
40534
40979
  async function repositoryFromRemote(root) {
40535
40980
  try {
40536
- const url2 = await git3(root, ["remote", "get-url", "origin"]);
40981
+ const url2 = await git4(root, ["remote", "get-url", "origin"]);
40537
40982
  return /github\.com[:/]([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/.exec(url2)?.slice(1, 3).join("/");
40538
40983
  } catch {
40539
40984
  return void 0;
@@ -40545,7 +40990,7 @@ async function snapshotFromArgs(values, env) {
40545
40990
  if (projectId !== void 0 && !ProjectId.safeParse(projectId).success) throw new UsageError2(`--project must be a project identifier, got "${projectId}"`);
40546
40991
  const repoText = projectId !== void 0 ? typeof values["repo"] === "string" ? values["repo"] : void 0 : (typeof values["repo"] === "string" ? values["repo"] : void 0) ?? env["GITHUB_REPOSITORY"] ?? await repositoryFromRemote(root);
40547
40992
  if (!repoText && projectId === void 0) throw new UsageError2("cannot determine the repository; pass --project ID, or --repo owner/name");
40548
- const commit = (typeof values["commit"] === "string" ? values["commit"] : void 0) ?? env["GITHUB_SHA"] ?? await git3(root, ["rev-parse", "HEAD"]);
40993
+ const commit = (typeof values["commit"] === "string" ? values["commit"] : void 0) ?? env["GITHUB_SHA"] ?? await git4(root, ["rev-parse", "HEAD"]);
40549
40994
  const branch = typeof values["branch"] === "string" ? values["branch"] : void 0;
40550
40995
  const tenant = (typeof values["tenant"] === "string" ? values["tenant"] : void 0) ?? env["HARNESS_TENANT"];
40551
40996
  if (!tenant) throw new UsageError2("missing --tenant (or HARNESS_TENANT)");
@@ -40572,6 +41017,13 @@ async function runCli2(argv, env, out2 = console.log, err2 = console.error) {
40572
41017
  out2(`built ${built.shards.length} shards (${built.uncovered.length} files uncovered) into ${resolve14(outDir)}`);
40573
41018
  return 0;
40574
41019
  }
41020
+ if (command === "map") {
41021
+ const root = resolve14(values.root ?? process.cwd());
41022
+ const digest = await buildDigestForCheckout({ root, ...values.task === void 0 ? {} : { task: values.task } });
41023
+ const path = await writeDigest(root, digest, values.out === void 0 ? void 0 : resolve14(values.out));
41024
+ out2(`wrote the code map digest for ${digest.revision.commitSha.slice(0, 12)} (${digest.coverage.files} files, ${digest.coverage.symbols} symbols, ${digest.lines.length} lines) to ${path}`);
41025
+ return 0;
41026
+ }
40575
41027
  if (command === "upload") {
40576
41028
  const service = values.service;
40577
41029
  if (!service) throw new UsageError2("upload needs --service URL");
@@ -40595,28 +41047,31 @@ ${USAGE}`);
40595
41047
  }
40596
41048
  }
40597
41049
  async function writeSnapshot(dir, built) {
40598
- await mkdir3(join26(dir, "shards"), { recursive: true });
40599
- for (const name2 of await readdir4(join26(dir, "shards"))) await rm2(join26(dir, "shards", name2));
40600
- await writeFile3(join26(dir, "manifest.json"), JSON.stringify(built.manifest, null, 2));
40601
- await writeFile3(join26(dir, "uncovered.json"), JSON.stringify(built.uncovered, null, 2));
41050
+ await mkdir4(join27(dir, "shards"), { recursive: true });
41051
+ for (const name2 of await readdir4(join27(dir, "shards"))) await rm2(join27(dir, "shards", name2));
41052
+ await writeFile4(join27(dir, "manifest.json"), JSON.stringify(built.manifest, null, 2));
41053
+ await writeFile4(join27(dir, "uncovered.json"), JSON.stringify(built.uncovered, null, 2));
40602
41054
  for (const shard of built.shards) {
40603
41055
  const name2 = shardKeyOf(shard).slice("sha256:".length);
40604
- await writeFile3(join26(dir, "shards", `${name2}.json`), JSON.stringify(shard));
41056
+ await writeFile4(join27(dir, "shards", `${name2}.json`), JSON.stringify(shard));
40605
41057
  }
40606
41058
  }
40607
- var execFileAsync2, USAGE, UsageError2, OPTIONS;
41059
+ var execFileAsync3, USAGE, UsageError2, OPTIONS;
40608
41060
  var init_run = __esm({
40609
41061
  "../index-builder/src/run.ts"() {
40610
41062
  "use strict";
40611
41063
  init_src();
41064
+ init_context_map_build();
40612
41065
  init_oidc();
40613
41066
  init_snapshot();
40614
41067
  init_upload();
40615
- execFileAsync2 = promisify2(execFile2);
41068
+ execFileAsync3 = promisify3(execFile3);
40616
41069
  USAGE = `usage:
40617
41070
  mvrx-index build --scip FILE [--scip FILE ...] --out DIR [--project ID | --repo owner/name] [--tenant ID] [--commit SHA] [--branch B] [--root DIR]
41071
+ mvrx-index map [--root DIR] [--out FILE] [--task TEXT]
40618
41072
  mvrx-index upload --service URL --tenant ID (--project ID | --repo owner/name) --commit SHA [--branch B] [--scip FILE ...] [--root DIR] [--audience URL]
40619
41073
 
41074
+ map writes the ranked code map digest (default .harness/code-map.json in the root) that the session-start hook delivers as context (ADR 0055). No model; --task ranks by the words of a task.
40620
41075
  --project indexes an Overlane project (no GitHub repository needed) and uploads with HARNESS_TOKEN.
40621
41076
  --repo names a GitHub repository; in GitHub Actions the OIDC token is used when ACTIONS_ID_TOKEN_REQUEST_URL is set.
40622
41077
  Authentication for upload: HARNESS_TOKEN (always for --project), or the GitHub Actions OIDC token for --repo.
@@ -40633,7 +41088,8 @@ Authentication for upload: HARNESS_TOKEN (always for --project), or the GitHub A
40633
41088
  commit: { type: "string" },
40634
41089
  branch: { type: "string" },
40635
41090
  root: { type: "string" },
40636
- audience: { type: "string" }
41091
+ audience: { type: "string" },
41092
+ task: { type: "string" }
40637
41093
  };
40638
41094
  }
40639
41095
  });
@@ -40648,6 +41104,8 @@ var init_src2 = __esm({
40648
41104
  init_snapshot();
40649
41105
  init_upload();
40650
41106
  init_oidc();
41107
+ init_context_map();
41108
+ init_context_map_build();
40651
41109
  init_run();
40652
41110
  }
40653
41111
  });
@@ -55442,8 +55900,8 @@ var init_cloud = __esm({
55442
55900
  // ../code-shim/src/git.ts
55443
55901
  import { execFileSync } from "node:child_process";
55444
55902
  import { existsSync as existsSync8 } from "node:fs";
55445
- import { join as join30 } from "node:path";
55446
- function git4(root, args2) {
55903
+ import { join as join31 } from "node:path";
55904
+ function git5(root, args2) {
55447
55905
  try {
55448
55906
  return execFileSync("git", args2, { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 64 * 1024 * 1024, timeout: 1e4 });
55449
55907
  } catch {
@@ -55451,12 +55909,12 @@ function git4(root, args2) {
55451
55909
  }
55452
55910
  }
55453
55911
  function headCommit2(root) {
55454
- const out2 = git4(root, ["rev-parse", "--verify", "HEAD"]);
55912
+ const out2 = git5(root, ["rev-parse", "--verify", "HEAD"]);
55455
55913
  const sha = out2?.trim();
55456
55914
  return sha !== void 0 && /^[0-9a-f]{40,64}$/.test(sha) ? sha : null;
55457
55915
  }
55458
55916
  function originRepository(root) {
55459
- const url2 = git4(root, ["remote", "get-url", "origin"])?.trim();
55917
+ const url2 = git5(root, ["remote", "get-url", "origin"])?.trim();
55460
55918
  if (url2 === void 0 || url2.length === 0) return null;
55461
55919
  const match = /[:/]([^/:]+)\/([^/]+?)(?:\.git)?\/?$/.exec(url2);
55462
55920
  const owner = match?.[1];
@@ -55502,9 +55960,9 @@ function parseStatus(raw, exists) {
55502
55960
  }
55503
55961
  function readWorkingCopyState(root) {
55504
55962
  const head = headCommit2(root);
55505
- const raw = git4(root, ["status", "--porcelain=v2", "-z", "--untracked-files=all"]);
55963
+ const raw = git5(root, ["status", "--porcelain=v2", "-z", "--untracked-files=all"]);
55506
55964
  if (raw === null) return { head, dirty: /* @__PURE__ */ new Set(), deleted: /* @__PURE__ */ new Set(), renamed: /* @__PURE__ */ new Map() };
55507
- return { head, ...parseStatus(raw, (path) => existsSync8(join30(root, path))) };
55965
+ return { head, ...parseStatus(raw, (path) => existsSync8(join31(root, path))) };
55508
55966
  }
55509
55967
  var init_git2 = __esm({
55510
55968
  "../code-shim/src/git.ts"() {
@@ -55515,16 +55973,16 @@ var init_git2 = __esm({
55515
55973
  // ../code-shim/src/config.ts
55516
55974
  import { readFileSync as readFileSync14 } from "node:fs";
55517
55975
  import { homedir as homedir2 } from "node:os";
55518
- import { join as join31 } from "node:path";
55976
+ import { join as join32 } from "node:path";
55519
55977
  function configDir(env) {
55520
- const base4 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join31(homedir2(), ".config");
55521
- return join31(base4, "mvrx-harness");
55978
+ const base4 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join32(homedir2(), ".config");
55979
+ return join32(base4, "mvrx-harness");
55522
55980
  }
55523
55981
  function findToken2(env, serviceUrl, now) {
55524
55982
  const fromEnv = env["HARNESS_TOKEN"];
55525
55983
  if (fromEnv !== void 0 && fromEnv.length > 0) return fromEnv;
55526
55984
  try {
55527
- const file2 = JSON.parse(readFileSync14(join31(configDir(env), "credentials.json"), "utf8"));
55985
+ const file2 = JSON.parse(readFileSync14(join32(configDir(env), "credentials.json"), "utf8"));
55528
55986
  const stored = file2[serviceUrl];
55529
55987
  if (stored === void 0 || typeof stored.accessToken !== "string" || stored.accessToken.length === 0) return null;
55530
55988
  if (typeof stored.expiresAt === "number" && stored.expiresAt <= now) return null;
@@ -55536,7 +55994,7 @@ function findToken2(env, serviceUrl, now) {
55536
55994
  function resolveCloudConfig(root, env, now) {
55537
55995
  let binding;
55538
55996
  try {
55539
- const parsed = ProjectBinding.safeParse(JSON.parse(readFileSync14(join31(root, ".harness", "project.json"), "utf8")));
55997
+ const parsed = ProjectBinding.safeParse(JSON.parse(readFileSync14(join32(root, ".harness", "project.json"), "utf8")));
55540
55998
  if (!parsed.success) return null;
55541
55999
  binding = parsed.data;
55542
56000
  } catch {
@@ -55958,8 +56416,8 @@ async function locate(index, path, namePath) {
55958
56416
  const [only] = matches;
55959
56417
  if (only === void 0) return { ok: false, reason: `symbol ${namePath} not found in ${path}` };
55960
56418
  if (matches.length > 1) {
55961
- const where = matches.map((m) => `line ${m.range[0] + 1}`).join(", ");
55962
- return { ok: false, reason: `symbol ${namePath} is ambiguous in ${path} (${matches.length} matches: ${where}); give a longer name_path` };
56419
+ const where2 = matches.map((m) => `line ${m.range[0] + 1}`).join(", ");
56420
+ return { ok: false, reason: `symbol ${namePath} is ambiguous in ${path} (${matches.length} matches: ${where2}); give a longer name_path` };
55963
56421
  }
55964
56422
  return { ok: true, shard, symbol: only };
55965
56423
  }
@@ -58783,17 +59241,17 @@ function naturalCompare(a, b) {
58783
59241
  }
58784
59242
  return left.length - right.length || (a < b ? -1 : a > b ? 1 : 0);
58785
59243
  }
58786
- function splitFrontMatter(text, where) {
59244
+ function splitFrontMatter(text, where2) {
58787
59245
  const normalized = text.replace(/\r\n/g, "\n");
58788
59246
  const match = /^---\n([\s\S]*?)\n?---\n?([\s\S]*)$/.exec(normalized);
58789
- if (!match) throw new KitError(`${where}: missing YAML front matter`);
59247
+ if (!match) throw new KitError(`${where2}: missing YAML front matter`);
58790
59248
  let data;
58791
59249
  try {
58792
59250
  data = (0, import_yaml.parse)(match[1] ?? "");
58793
59251
  } catch (error62) {
58794
- throw new KitError(`${where}: front matter is not valid YAML`, [error62 instanceof Error ? error62.message : String(error62)]);
59252
+ throw new KitError(`${where2}: front matter is not valid YAML`, [error62 instanceof Error ? error62.message : String(error62)]);
58795
59253
  }
58796
- if (data === null || typeof data !== "object" || Array.isArray(data)) throw new KitError(`${where}: front matter must be a mapping`);
59254
+ if (data === null || typeof data !== "object" || Array.isArray(data)) throw new KitError(`${where2}: front matter must be a mapping`);
58797
59255
  return { data, body: match[2] ?? "" };
58798
59256
  }
58799
59257
  function joinFrontMatter(data, body2) {
@@ -58822,21 +59280,21 @@ function sectionsOf(body2, level = 2) {
58822
59280
  function sectionText(lines) {
58823
59281
  return (lines ?? []).join("\n").replace(/^\n+|\s+$/g, "");
58824
59282
  }
58825
- function bulletsOf(lines, where) {
59283
+ function bulletsOf(lines, where2) {
58826
59284
  const items = [];
58827
59285
  for (const line2 of lines ?? []) {
58828
59286
  if (line2.trim() === "") continue;
58829
59287
  const match = /^- (.*)$/.exec(line2);
58830
- if (!match) throw new KitError(`${where}: expected a "- " bullet, found "${line2}"`);
59288
+ if (!match) throw new KitError(`${where2}: expected a "- " bullet, found "${line2}"`);
58831
59289
  items.push(match[1] ?? "");
58832
59290
  }
58833
59291
  return items;
58834
59292
  }
58835
- function assertLine(value, where) {
58836
- if (value !== value.trim() || /[\r\n]/.test(value)) throw new KitError(`${where} must be one line without surrounding whitespace`, [JSON.stringify(value)]);
59293
+ function assertLine(value, where2) {
59294
+ if (value !== value.trim() || /[\r\n]/.test(value)) throw new KitError(`${where2} must be one line without surrounding whitespace`, [JSON.stringify(value)]);
58837
59295
  }
58838
- function assertBlock(value, where) {
58839
- if (value !== value.trim() || /\r/.test(value) || /^#{1,2}\s/m.test(value)) throw new KitError(`${where} must be trimmed text with no line starting with "# " or "## "`, [JSON.stringify(value.slice(0, 80))]);
59296
+ function assertBlock(value, where2) {
59297
+ if (value !== value.trim() || /\r/.test(value) || /^#{1,2}\s/m.test(value)) throw new KitError(`${where2} must be trimmed text with no line starting with "# " or "## "`, [JSON.stringify(value.slice(0, 80))]);
58840
59298
  }
58841
59299
  function slugify2(value) {
58842
59300
  return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "project";
@@ -58848,9 +59306,9 @@ var planPaths = (repoDir) => {
58848
59306
  const root = join15(repoDir, PLAN_DIR);
58849
59307
  return { root, project: join15(root, "project.md"), milestones: join15(root, "milestones.md"), tasks: join15(root, "tasks"), task: (id2) => join15(root, "tasks", `${id2}.md`) };
58850
59308
  };
58851
- function parsePlan(input2, where) {
59309
+ function parsePlan(input2, where2) {
58852
59310
  const result = Plan.safeParse(input2);
58853
- if (!result.success) throw new KitError(`${where}: plan is invalid`, result.error.issues.map((issue2) => `${issue2.path.join(".") || "(root)"}: ${issue2.message}`));
59311
+ if (!result.success) throw new KitError(`${where2}: plan is invalid`, result.error.issues.map((issue2) => `${issue2.path.join(".") || "(root)"}: ${issue2.message}`));
58854
59312
  return result.data;
58855
59313
  }
58856
59314
  function canonicalizePlan(plan3) {
@@ -58916,16 +59374,16 @@ async function readText2(file2) {
58916
59374
  throw new KitError(`cannot read ${file2}`, [error62 instanceof Error ? error62.message : String(error62)]);
58917
59375
  }
58918
59376
  }
58919
- function parseProject(text, where) {
58920
- const { data, body: body2 } = splitFrontMatter(text, where);
59377
+ function parseProject(text, where2) {
59378
+ const { data, body: body2 } = splitFrontMatter(text, where2);
58921
59379
  const sections = sectionsOf(body2);
58922
59380
  return {
58923
59381
  schemaVersion: data["schemaVersion"],
58924
- project: { name: data["name"], goal: sectionText(sections.get("Goal")), constraints: bulletsOf(sections.get("Constraints"), `${where} Constraints`) }
59382
+ project: { name: data["name"], goal: sectionText(sections.get("Goal")), constraints: bulletsOf(sections.get("Constraints"), `${where2} Constraints`) }
58925
59383
  };
58926
59384
  }
58927
- function parseMilestones(text, where) {
58928
- const { body: body2 } = splitFrontMatter(text, where);
59385
+ function parseMilestones(text, where2) {
59386
+ const { body: body2 } = splitFrontMatter(text, where2);
58929
59387
  const milestones = [];
58930
59388
  let current2;
58931
59389
  let inAcceptance = false;
@@ -58949,12 +59407,12 @@ function parseMilestones(text, where) {
58949
59407
  const depends = /^Depends on: (.+)$/.exec(line2);
58950
59408
  if (depends && !inAcceptance) current2.dependsOn = (depends[1] ?? "").split(",").map((id2) => id2.trim());
58951
59409
  else if (inAcceptance && line2.startsWith("- ")) current2.acceptance.push(line2.slice(2));
58952
- else throw new KitError(`${where}: unexpected line under ${current2.id}: "${line2}"`);
59410
+ else throw new KitError(`${where2}: unexpected line under ${current2.id}: "${line2}"`);
58953
59411
  }
58954
59412
  return milestones;
58955
59413
  }
58956
- function parseTask(text, where) {
58957
- const { data, body: body2 } = splitFrontMatter(text, where);
59414
+ function parseTask(text, where2) {
59415
+ const { data, body: body2 } = splitFrontMatter(text, where2);
58958
59416
  const sections = sectionsOf(body2);
58959
59417
  return {
58960
59418
  id: data["id"],
@@ -58962,7 +59420,7 @@ function parseTask(text, where) {
58962
59420
  milestone: data["milestone"],
58963
59421
  outcome: sectionText(sections.get("Outcome")),
58964
59422
  allowedPaths: data["allowedPaths"],
58965
- acceptance: bulletsOf(sections.get("Acceptance"), `${where} Acceptance`),
59423
+ acceptance: bulletsOf(sections.get("Acceptance"), `${where2} Acceptance`),
58966
59424
  verification: data["verification"],
58967
59425
  evidenceLevel: data["evidenceLevel"],
58968
59426
  dependsOn: data["dependsOn"],
@@ -59195,14 +59653,14 @@ async function readOptional2(file2) {
59195
59653
  return void 0;
59196
59654
  }
59197
59655
  }
59198
- function parseTasksFile(text, where) {
59656
+ function parseTasksFile(text, where2) {
59199
59657
  let block2 = { milestones: {}, tasks: {} };
59200
59658
  const match = BLOCK_PATTERN.exec(text);
59201
59659
  if (match) {
59202
59660
  try {
59203
59661
  block2 = BlockSchema.parse(JSON.parse(match[1] ?? ""));
59204
59662
  } catch (error62) {
59205
- throw new KitError(`${where}: the mvrx-kit comment block is invalid`, [error62 instanceof Error ? error62.message : String(error62)]);
59663
+ throw new KitError(`${where2}: the mvrx-kit comment block is invalid`, [error62 instanceof Error ? error62.message : String(error62)]);
59206
59664
  }
59207
59665
  }
59208
59666
  const phases = [];
@@ -63967,13 +64425,16 @@ var reviewSettingsSetCommand = defineCommand({
63967
64425
  var codeMapStatusCommand = defineCommand({
63968
64426
  path: ["code-map", "status"],
63969
64427
  summary: "Show, per client, whether the code map is on and why",
63970
- description: "Lists every supported client in its local and cloud setting, and the bots, review service, cross-repository questions and wiki, with whether the code map is on and the reason. The default for a setting follows the latest GATE-07 result for that setting: off for a local agent with grep (the local run failed, ADR 0018), on where there is no checkout until a re-run says otherwise.",
64428
+ description: "Lists every supported client in its local and cloud setting, and the bots, review service, cross-repository questions and wiki, with two settings each. The code tools (codeLayer): the default follows the latest GATE-07 result for that setting, off for a local agent with grep (ADR 0018), on where there is no checkout. The map as context (codeMapContext, ADR 0055): a ranked map delivered once at session start, on where there is no checkout, on for read-only work for a local agent, and opt-in for edits and when the intent is unknown. The project setting codeMapContext (default, on or off) overrides the default.",
63971
64429
  examples: ["overlane code-map status", "overlane code-map status --json"],
63972
64430
  effect: "read",
63973
64431
  ...common8,
63974
64432
  keywords: ["code map", "code tools", "is the code map on", "gate-07", "code layer", "per client"],
63975
64433
  result: CodeMapStatus,
63976
- text: (d) => d.clients.map((row) => `${row.on ? "on " : "off"} ${row.subject}: ${row.reason}`),
64434
+ text: (d) => [
64435
+ `Project settings: codeLayer ${d.projectCodeLayer ? "on" : "off"}, codeMapContext ${d.projectCodeMapContext ?? "default"}.`,
64436
+ ...d.clients.flatMap((row) => [`tools ${row.on ? "on " : "off"} ${row.subject}: ${row.reason}`, ...row.context === void 0 ? [] : [`context ${row.context.mode.padEnd(9)} ${row.subject}: ${row.context.reason}`]])
64437
+ ],
63977
64438
  handler: async (inv) => {
63978
64439
  const { call: call2, tenantId, projectId } = await connected4(inv);
63979
64440
  return { data: await call2(CodeMapStatus, "GET", codeMapPaths.status(tenantId, projectId)) };
@@ -64161,8 +64622,8 @@ function searchCommands(specs, query, limit = SEARCH_LIMIT) {
64161
64622
  const frequency = doc.weighted.get(term) ?? 0;
64162
64623
  if (frequency === 0) continue;
64163
64624
  const containing = documents.filter((other) => other.weighted.has(term)).length;
64164
- const idf = Math.log(1 + (documents.length - containing + 0.5) / (containing + 0.5));
64165
- score += idf * (frequency * (K1 + 1) / (frequency + K1 * (1 - B + B * doc.length / averageLength)));
64625
+ const idf2 = Math.log(1 + (documents.length - containing + 0.5) / (containing + 0.5));
64626
+ score += idf2 * (frequency * (K1 + 1) / (frequency + K1 * (1 - B + B * doc.length / averageLength)));
64166
64627
  }
64167
64628
  if (score > 0) scored.push({ doc, score });
64168
64629
  }
@@ -66297,35 +66758,35 @@ init_src2();
66297
66758
 
66298
66759
  // src/data-dir.ts
66299
66760
  import { homedir } from "node:os";
66300
- import { join as join27 } from "node:path";
66761
+ import { join as join28 } from "node:path";
66301
66762
  function dataDir(env = process.env, home = homedir()) {
66302
66763
  const override = env["MVRX_DATA_DIR"];
66303
66764
  if (override !== void 0 && override !== "") return override;
66304
- const base4 = env["XDG_DATA_HOME"] ?? (process.platform === "win32" ? env["LOCALAPPDATA"] : void 0) ?? (process.platform === "darwin" ? join27(home, "Library", "Application Support") : join27(home, ".local", "share"));
66305
- return join27(base4, "mvrx-harness");
66765
+ const base4 = env["XDG_DATA_HOME"] ?? (process.platform === "win32" ? env["LOCALAPPDATA"] : void 0) ?? (process.platform === "darwin" ? join28(home, "Library", "Application Support") : join28(home, ".local", "share"));
66766
+ return join28(base4, "mvrx-harness");
66306
66767
  }
66307
66768
  function marketplaceRoot(env = process.env, home = homedir()) {
66308
- return join27(dataDir(env, home), "marketplace");
66769
+ return join28(dataDir(env, home), "marketplace");
66309
66770
  }
66310
66771
 
66311
66772
  // src/plugin.ts
66312
66773
  import { readFileSync as readFileSync13 } from "node:fs";
66313
- import { join as join29 } from "node:path";
66774
+ import { join as join30 } from "node:path";
66314
66775
  import { parseArgs as parseArgs3 } from "node:util";
66315
66776
 
66316
66777
  // src/marketplace.ts
66317
66778
  init_src();
66318
66779
  import { createHash as createHash7 } from "node:crypto";
66319
66780
  import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync9, readdirSync as readdirSync3, readFileSync as readFileSync12, renameSync as renameSync6, rmSync as rmSync4, statSync as statSync2, writeFileSync as writeFileSync8 } from "node:fs";
66320
- import { dirname as dirname9, join as join28, relative as relative2, sep } from "node:path";
66781
+ import { dirname as dirname10, join as join29, relative as relative2, sep } from "node:path";
66321
66782
  var CLIENT_DIRS = ["claude", "codex"];
66322
66783
  var EMBEDDED_MANIFEST = "release-manifest.json";
66323
- var INSTALLED_MANIFEST = join28(".release", "manifest.json");
66784
+ var INSTALLED_MANIFEST = join29(".release", "manifest.json");
66324
66785
  var MarketplaceError = class extends Error {
66325
66786
  };
66326
66787
  function loadEmbedded(packageRoot2) {
66327
- const dir = join28(packageRoot2, "plugins");
66328
- const path = join28(dir, EMBEDDED_MANIFEST);
66788
+ const dir = join29(packageRoot2, "plugins");
66789
+ const path = join29(dir, EMBEDDED_MANIFEST);
66329
66790
  if (!existsSync7(path)) throw new MarketplaceError(`this package has no embedded plugin release (${path} is missing)`);
66330
66791
  const parsed = ReleaseManifest.safeParse(JSON.parse(readFileSync12(path, "utf8")));
66331
66792
  if (!parsed.success) throw new MarketplaceError(`the embedded release manifest is invalid: ${parsed.error.message}`);
@@ -66338,7 +66799,7 @@ function listFiles(root, dir = root) {
66338
66799
  if (!existsSync7(dir)) return [];
66339
66800
  const out2 = [];
66340
66801
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
66341
- const full = join28(dir, entry.name);
66802
+ const full = join29(dir, entry.name);
66342
66803
  if (entry.isDirectory()) out2.push(...listFiles(root, full));
66343
66804
  else out2.push(relative2(root, full).split(sep).join("/"));
66344
66805
  }
@@ -66350,7 +66811,7 @@ async function verifyTree(treeRoot, manifest) {
66350
66811
  if (recomputed !== manifest.digest) problems.push(`manifest digest ${manifest.digest} does not match its file list (${recomputed})`);
66351
66812
  const listed = new Set(manifest.files.map((file2) => file2.path));
66352
66813
  for (const file2 of manifest.files) {
66353
- const path = join28(treeRoot, file2.path);
66814
+ const path = join29(treeRoot, file2.path);
66354
66815
  if (!existsSync7(path)) {
66355
66816
  problems.push(`missing: ${file2.path}`);
66356
66817
  continue;
@@ -66358,7 +66819,7 @@ async function verifyTree(treeRoot, manifest) {
66358
66819
  if (sha2562(readFileSync12(path)) !== file2.digest) problems.push(`modified: ${file2.path}`);
66359
66820
  }
66360
66821
  for (const client of CLIENT_DIRS) {
66361
- for (const found of listFiles(join28(treeRoot, client))) {
66822
+ for (const found of listFiles(join29(treeRoot, client))) {
66362
66823
  if (!listed.has(`${client}/${found}`)) problems.push(`unlisted: ${client}/${found}`);
66363
66824
  }
66364
66825
  }
@@ -66366,7 +66827,7 @@ async function verifyTree(treeRoot, manifest) {
66366
66827
  }
66367
66828
  function readInstalledManifest(target) {
66368
66829
  try {
66369
- const parsed = ReleaseManifest.safeParse(JSON.parse(readFileSync12(join28(target, INSTALLED_MANIFEST), "utf8")));
66830
+ const parsed = ReleaseManifest.safeParse(JSON.parse(readFileSync12(join29(target, INSTALLED_MANIFEST), "utf8")));
66370
66831
  return parsed.success ? parsed.data : null;
66371
66832
  } catch {
66372
66833
  return null;
@@ -66394,15 +66855,15 @@ async function syncMarketplace(embedded, target) {
66394
66855
  mkdirSync9(staging, { recursive: true });
66395
66856
  try {
66396
66857
  for (const client of CLIENT_DIRS) {
66397
- if (existsSync7(join28(embedded.dir, client))) cpSync(join28(embedded.dir, client), join28(staging, client), { recursive: true });
66858
+ if (existsSync7(join29(embedded.dir, client))) cpSync(join29(embedded.dir, client), join29(staging, client), { recursive: true });
66398
66859
  }
66399
- mkdirSync9(join28(staging, ".release"), { recursive: true });
66400
- writeFileSync8(join28(staging, INSTALLED_MANIFEST), `${JSON.stringify(embedded.manifest, null, 2)}
66860
+ mkdirSync9(join29(staging, ".release"), { recursive: true });
66861
+ writeFileSync8(join29(staging, INSTALLED_MANIFEST), `${JSON.stringify(embedded.manifest, null, 2)}
66401
66862
  `);
66402
66863
  const after = await verifyTree(staging, embedded.manifest);
66403
66864
  if (after.length > 0) throw new MarketplaceError(`the copied plugin files do not match the release manifest:
66404
66865
  ${after.join("\n ")}`);
66405
- mkdirSync9(dirname9(target), { recursive: true });
66866
+ mkdirSync9(dirname10(target), { recursive: true });
66406
66867
  if (existsSync7(target)) renameSync6(target, previous);
66407
66868
  try {
66408
66869
  renameSync6(staging, target);
@@ -66429,7 +66890,7 @@ var PLUGIN_USAGE = ` overlane plugin install [--scope project|user] [--client c
66429
66890
  var PluginUsageError = class extends Error {
66430
66891
  };
66431
66892
  function readNames(treeRoot, client) {
66432
- const file2 = client === "claude" ? join29(treeRoot, "claude", ".claude-plugin", "marketplace.json") : join29(treeRoot, "codex", ".agents", "plugins", "marketplace.json");
66893
+ const file2 = client === "claude" ? join30(treeRoot, "claude", ".claude-plugin", "marketplace.json") : join30(treeRoot, "codex", ".agents", "plugins", "marketplace.json");
66433
66894
  const parsed = JSON.parse(readFileSync13(file2, "utf8"));
66434
66895
  const record3 = parsed;
66435
66896
  const plugin = record3.plugins?.[0]?.name;
@@ -66476,7 +66937,7 @@ ${PLUGIN_USAGE}`);
66476
66937
  const key = `${names.plugin}@${names.marketplace}`;
66477
66938
  if (!await available(deps, client)) {
66478
66939
  if (explicit !== void 0) {
66479
- deps.stderr(`overlane: \`${client}\` was not found on PATH; the marketplace is at ${join29(root, client)}
66940
+ deps.stderr(`overlane: \`${client}\` was not found on PATH; the marketplace is at ${join30(root, client)}
66480
66941
  `);
66481
66942
  failed = true;
66482
66943
  } else {
@@ -66488,7 +66949,7 @@ ${PLUGIN_USAGE}`);
66488
66949
  ranAny = true;
66489
66950
  deps.stdout(`${client}:
66490
66951
  `);
66491
- const dir = join29(root, client);
66952
+ const dir = join30(root, client);
66492
66953
  const steps = client === "claude" ? [
66493
66954
  ["claude", ["plugin", "marketplace", "add", dir, "--scope", scope]],
66494
66955
  ["claude", ["plugin", "marketplace", "update", names.marketplace]],
@@ -66654,13 +67115,13 @@ var pluginInstallCommand = defineCommand({
66654
67115
  var packageCommands = [indexBuildCommand, indexUploadCommand, shimCommand, pluginInstallCommand];
66655
67116
 
66656
67117
  // src/deps.ts
66657
- import { execFile as execFile3, spawn } from "node:child_process";
67118
+ import { execFile as execFile4, spawn } from "node:child_process";
66658
67119
  import { homedir as homedir3 } from "node:os";
66659
- import { join as join32 } from "node:path";
67120
+ import { join as join33 } from "node:path";
66660
67121
  import { createInterface } from "node:readline/promises";
66661
67122
  function exec(command, args2, options) {
66662
67123
  return new Promise((resolveResult) => {
66663
- execFile3(command, [...args2], { cwd: options?.cwd, encoding: "utf8", maxBuffer: 16 * 1024 * 1024 }, (error62, stdout, stderr) => {
67124
+ execFile4(command, [...args2], { cwd: options?.cwd, encoding: "utf8", maxBuffer: 16 * 1024 * 1024 }, (error62, stdout, stderr) => {
66664
67125
  if (error62 === null) {
66665
67126
  resolveResult({ code: 0, stdout, stderr });
66666
67127
  } else if ("code" in error62 && typeof error62.code === "number") {
@@ -66702,8 +67163,8 @@ async function confirm(question) {
66702
67163
  }
66703
67164
  }
66704
67165
  function configDir2(env) {
66705
- const base4 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join32(homedir3(), ".config");
66706
- return join32(base4, "mvrx-harness");
67166
+ const base4 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join33(homedir3(), ".config");
67167
+ return join33(base4, "mvrx-harness");
66707
67168
  }
66708
67169
  function createDeps2(env = process.env) {
66709
67170
  return {