@indigoai-us/hq-cloud 6.14.24 → 6.14.25

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.
@@ -46,9 +46,14 @@
46
46
  * repo root is the longest prefix of (or equal to) the cwd.
47
47
  */
48
48
  export interface RepoCompanyMap {
49
- /** Absolute, normalized repo root → owning company `cmp_*` uid. */
49
+ /**
50
+ * Absolute, normalized repo root → owning company `cmp_*` uid. `matchKey` is
51
+ * the precomputed `canonicalPath(repoRoot)` used for the containment test, so
52
+ * per-event matching stays a plain string compare.
53
+ */
50
54
  entries: Array<{
51
55
  repoRoot: string;
56
+ matchKey: string;
52
57
  companyUid: string;
53
58
  }>;
54
59
  /**
@@ -59,6 +64,22 @@ export interface RepoCompanyMap {
59
64
  * so a slug resolves to exactly one cloud-backed company here.
60
65
  */
61
66
  bySlug: Map<string, string>;
67
+ /**
68
+ * Whether the HQ filesystem folds case, PROBED at build time rather than
69
+ * inferred from `process.platform`. APFS can be case-sensitive on macOS and
70
+ * Windows supports per-directory case sensitivity, so the OS is only a hint;
71
+ * getting this wrong in the folding direction risks cross-tenant
72
+ * misattribution. Defaults to `false` (exact matching) when the probe fails.
73
+ */
74
+ foldsCase: boolean;
75
+ /**
76
+ * Match keys that two or more companies claimed. They are excluded from
77
+ * `entries` (fail closed), and resolution must ALSO refuse to reach them via
78
+ * the worktree fallback — otherwise an ambiguous `foo-wt-team` would collapse
79
+ * to `foo` and hand the event to whichever company owns `foo`, quietly
80
+ * undoing the protection.
81
+ */
82
+ ambiguous: Set<string>;
62
83
  }
63
84
  /**
64
85
  * Parse `<hqRoot>/companies/manifest.yaml` ONCE and build the repo-path →
@@ -93,6 +114,15 @@ export declare function resolveCompanyForSkill(skill: string | undefined, map: R
93
114
  * that merely shares a string prefix (`<repoRoot>-other`) from matching.
94
115
  * Entries are pre-sorted longest-first, so the first match is the most
95
116
  * specific.
117
+ *
118
+ * If nothing matches, one lexical retry strips HQ's `-wt-<branch>` worktree
119
+ * suffix from the path. `buildRepoCompanyMap` discovers worktrees by reading
120
+ * the directory, which only sees the ones that exist RIGHT NOW — but telemetry
121
+ * is read from a cursor and a branch worktree is routinely deleted before the
122
+ * next pass. Those pending rows still carry the worktree cwd, and because a
123
+ * successful POST advances the cursor permanently, failing to resolve them
124
+ * loses that attribution for good. The suffix is documented convention, so
125
+ * deriving it from the recorded path needs no directory to still exist.
96
126
  */
97
127
  export declare function resolveCompanyForCwd(cwd: string | undefined, map: RepoCompanyMap): string | undefined;
98
128
  //# sourceMappingURL=company-resolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"company-resolver.d.ts","sourceRoot":"","sources":["../src/company-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAOH;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD;;;;;;OAMG;IACH,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAiBD;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA4CjF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,GAAG,EAAE,cAAc,GAClB,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,GAAG,EAAE,cAAc,GAClB,MAAM,GAAG,SAAS,CASpB"}
1
+ {"version":3,"file":"company-resolver.d.ts","sourceRoot":"","sources":["../src/company-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAOH;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E;;;;;;OAMG;IACH,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B;;;;;;OAMG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxB;AAmND;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyIjF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,GAAG,EAAE,cAAc,GAClB,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,GAAG,EAAE,cAAc,GAClB,MAAM,GAAG,SAAS,CAgCpB"}
@@ -47,6 +47,197 @@ import yaml from "js-yaml";
47
47
  function normalizePath(p) {
48
48
  return p.length > 1 ? p.replace(/\/+$/, "") : p;
49
49
  }
50
+ /**
51
+ * Canonical comparison key for a filesystem path.
52
+ *
53
+ * Both sides of the containment test (`repoRoot` and the event `cwd`) run
54
+ * through this so a match does not hinge on the emitting machine's path
55
+ * dialect. Real prod `cwd` values include Windows roots (`C:\Users\eggsa\HQ`)
56
+ * alongside POSIX ones, and the manifest side is built with `path.resolve`,
57
+ * which emits the HOST separator. Comparing those raw meant Windows clients
58
+ * could never match.
59
+ *
60
+ * Two normalizations, both deliberate:
61
+ * - Separators collapse to `/` so `C:\Users\x\HQ` and `C:/Users/x/HQ` agree.
62
+ * - Case is folded only when the HQ filesystem actually folds case, as
63
+ * PROBED by `probeCaseFolding`. Where it does, `.../HQ` and `.../hq` are
64
+ * the same directory and not folding would drop real attribution. Where it
65
+ * does not, they are different directories and folding could attribute a
66
+ * cwd to a company that does not own it.
67
+ *
68
+ * Correct-but-unattributed always beats attributed-to-the-wrong-company, so the
69
+ * probe defaults to NOT folding whenever it cannot determine the answer.
70
+ */
71
+ function canonicalPath(p, foldsCase) {
72
+ const normalized = normalizePath(p.replace(/\\/g, "/"));
73
+ return foldsCase ? normalized.toLowerCase() : normalized;
74
+ }
75
+ /**
76
+ * Determine whether the filesystem folds case for entries INSIDE `hqRoot`, by
77
+ * asking it.
78
+ *
79
+ * `process.platform` is only a hint: APFS volumes can be created case-SENSITIVE
80
+ * on macOS, and Windows supports per-directory case sensitivity — in both cases
81
+ * the platform still reads `darwin`/`win32`. Since folding on a case-sensitive
82
+ * filesystem risks cross-tenant misattribution, we probe instead of assume.
83
+ *
84
+ * The probe deliberately targets a CHILD of `hqRoot` (`companies/`, which must
85
+ * exist — the manifest was just read from inside it) rather than `hqRoot`
86
+ * itself. Under Windows per-directory case sensitivity, the lookup of a
87
+ * directory's own name is governed by its PARENT, so probing `hqRoot` would
88
+ * report the parent's behaviour while every path we actually compare lives
89
+ * inside `hqRoot`. Probing a child measures the directory that matters.
90
+ *
91
+ * The probe stats the child with its basename case inverted and compares inode
92
+ * identity. Any failure (missing, permission denied, no inode) returns `false`,
93
+ * the conservative answer.
94
+ */
95
+ async function probeDirFoldsCase(dir) {
96
+ const base = path.basename(dir);
97
+ const flippedBase = base
98
+ .split("")
99
+ .map((c) => (c === c.toLowerCase() ? c.toUpperCase() : c.toLowerCase()))
100
+ .join("");
101
+ if (flippedBase === base)
102
+ return false; // no cased characters to test with
103
+ try {
104
+ const [a, b] = await Promise.all([
105
+ fs.stat(dir),
106
+ fs.stat(path.join(path.dirname(dir), flippedBase)),
107
+ ]);
108
+ // Same file identity via the flipped-case name ⇒ this directory folds case.
109
+ return a.ino !== 0 && a.ino === b.ino && a.dev === b.dev;
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
115
+ /**
116
+ * Whether case may be folded for EVERY directory we actually match under.
117
+ *
118
+ * Windows configures case sensitivity PER DIRECTORY, so one probe cannot speak
119
+ * for the whole tree: `companies/`, `repos/private/`, and an external symlink
120
+ * target can each behave differently. Folding a path whose parent is
121
+ * case-sensitive is the direction that risks stamping the wrong `companyUid`,
122
+ * so this requires unanimity — if any probe says case-sensitive, or there is
123
+ * nothing to probe, matching stays case-exact everywhere.
124
+ *
125
+ * Pass the ROOTS, not their parents. Case behaviour for a name is a property of
126
+ * the directory the name is looked up IN, so flipping a root's basename
127
+ * measures that root's PARENT — precisely the directory we match under.
128
+ * Flipping the parent's own basename would instead measure the grandparent and
129
+ * could report folding for a parent that is actually case-sensitive.
130
+ *
131
+ * The cost is one `stat` pair per distinct root, concurrently, once per run.
132
+ */
133
+ async function probeCaseFolding(roots) {
134
+ const distinct = [...new Set(roots)];
135
+ if (distinct.length === 0)
136
+ return false;
137
+ const results = await Promise.all(distinct.map(probeDirFoldsCase));
138
+ return results.every(Boolean);
139
+ }
140
+ /**
141
+ * Expand one manifest `repos` entry into the absolute roots it may live at.
142
+ *
143
+ * The manifest records repos as BARE NAMES (`hq-cloud`, `hq-console`) — see
144
+ * `companies/manifest.yaml` — while the checkout lives under
145
+ * `<hqRoot>/repos/{private,public}/<name>`. The original implementation did a
146
+ * plain `path.resolve(hqRoot, repo)`, producing `<hqRoot>/hq-cloud`, a path
147
+ * that exists for no repo. Every entry therefore matched no cwd and NO event
148
+ * was ever attributed (verified in prod: 0 of 3200 sampled usage events across
149
+ * 9 people carried a `companyUid`).
150
+ *
151
+ * An entry that already contains a separator is treated as an HQ-root-relative
152
+ * path verbatim, so the documented `repos/private/<name>` form keeps working.
153
+ */
154
+ function repoRootCandidates(hqRoot, repo) {
155
+ const trimmed = repo.trim().replace(/^\.\//, "");
156
+ if (trimmed.includes("/") || trimmed.includes("\\")) {
157
+ return [path.resolve(hqRoot, trimmed)];
158
+ }
159
+ return [
160
+ path.resolve(hqRoot, "repos", "private", trimmed),
161
+ path.resolve(hqRoot, "repos", "public", trimmed),
162
+ ];
163
+ }
164
+ /**
165
+ * Sibling git-worktree checkouts of `repoRoot`, per HQ's `<repo>-wt-<branch>`
166
+ * convention (e.g. `repos/private/hq-pro-wt-feature-x`).
167
+ *
168
+ * These matter a lot in practice: a large share of HQ work happens INSIDE a
169
+ * worktree rather than the primary checkout, and the resolver's slash boundary
170
+ * deliberately rejects `…/hq-pro-wt-feature-x` as a mere string-prefix sibling
171
+ * of `…/hq-pro`. Without this expansion every worktree session stays
172
+ * unattributed — which is exactly the emptiness this whole change is fixing.
173
+ *
174
+ * The prefix test honours `foldsCase`: `readdir` returns the casing stored on
175
+ * disk while `name` comes from the manifest, so on a case-folding filesystem a
176
+ * manifest entry `hq-cloud` must still find a checkout stored as
177
+ * `HQ-Cloud-wt-x`. Using a case-sensitive comparison there would drop the
178
+ * worktree even though the later match treats those casings as the same path.
179
+ *
180
+ * Best-effort: an unreadable parent directory yields no worktrees rather than
181
+ * failing the run.
182
+ */
183
+ async function worktreeSiblings(repoRoot, foldsCase) {
184
+ const parent = path.dirname(repoRoot);
185
+ const prefix = `${path.basename(repoRoot)}-wt-`;
186
+ const wanted = foldsCase ? prefix.toLowerCase() : prefix;
187
+ try {
188
+ const dirents = await fs.readdir(parent, { withFileTypes: true });
189
+ return dirents
190
+ .filter((d) => {
191
+ if (!d.isDirectory() && !d.isSymbolicLink())
192
+ return false;
193
+ const candidate = foldsCase ? d.name.toLowerCase() : d.name;
194
+ return candidate.startsWith(wanted);
195
+ })
196
+ .map((d) => path.join(parent, d.name));
197
+ }
198
+ catch {
199
+ return [];
200
+ }
201
+ }
202
+ /**
203
+ * The physical path behind `p`, when it differs from the lexical one.
204
+ *
205
+ * HQ's knowledge-repo layout uses symlinked checkouts, and a process launched
206
+ * inside one can report the RESOLVED path as its `cwd`. Matching only the
207
+ * lexical path would then miss the event entirely, so both are registered.
208
+ * Returns `null` when the path does not exist or already is its own realpath.
209
+ */
210
+ /**
211
+ * Whether `candidate` is strictly beneath `root`.
212
+ *
213
+ * Guards manifest-supplied paths. The HQ root itself is NOT inside itself: it
214
+ * spans every tenant, so claiming it for one company would misattribute all of
215
+ * them.
216
+ */
217
+ function isInsideRoot(root, candidate) {
218
+ const rel = path.relative(root, candidate);
219
+ return rel.length > 0 && !rel.startsWith("..") && !path.isAbsolute(rel);
220
+ }
221
+ async function physicalAlias(p) {
222
+ try {
223
+ const real = await fs.realpath(p);
224
+ return real !== p ? real : null;
225
+ }
226
+ catch {
227
+ return null;
228
+ }
229
+ }
230
+ /** Whether the path exists at all (used to keep absent candidates out of the
231
+ * case probe, where they would look indistinguishable from case-sensitive). */
232
+ async function physicalExists(p) {
233
+ try {
234
+ await fs.stat(p);
235
+ return true;
236
+ }
237
+ catch {
238
+ return false;
239
+ }
240
+ }
50
241
  /**
51
242
  * Parse `<hqRoot>/companies/manifest.yaml` ONCE and build the repo-path →
52
243
  * companyUid lookup. Best-effort: a missing/unparseable manifest yields an
@@ -58,25 +249,31 @@ function normalizePath(p) {
58
249
  */
59
250
  export async function buildRepoCompanyMap(hqRoot) {
60
251
  const manifestPath = path.join(hqRoot, "companies", "manifest.yaml");
252
+ const empty = (foldsCase = false) => ({
253
+ entries: [],
254
+ bySlug: new Map(),
255
+ foldsCase,
256
+ ambiguous: new Set(),
257
+ });
61
258
  let doc;
62
259
  try {
63
260
  const raw = await fs.readFile(manifestPath, "utf-8");
64
261
  const parsed = yaml.load(raw);
65
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
66
- return { entries: [], bySlug: new Map() };
67
- }
262
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
263
+ return empty();
68
264
  doc = parsed;
69
265
  }
70
266
  catch {
71
267
  // Missing / unreadable / unparseable — no attribution this run.
72
- return { entries: [], bySlug: new Map() };
268
+ return empty();
73
269
  }
74
270
  const companies = doc.companies;
75
- if (!companies || typeof companies !== "object") {
76
- return { entries: [], bySlug: new Map() };
77
- }
78
- const entries = [];
271
+ if (!companies || typeof companies !== "object")
272
+ return empty();
79
273
  const bySlug = new Map();
274
+ // Roots are collected BEFORE anything is canonicalized, because the case
275
+ // probe needs to know which parent directories we will actually match under.
276
+ const rootsToExpand = [];
80
277
  for (const [slug, company] of Object.entries(companies)) {
81
278
  if (!company || typeof company !== "object")
82
279
  continue;
@@ -87,22 +284,103 @@ export async function buildRepoCompanyMap(hqRoot) {
87
284
  // Slug → uid for skill-based attribution (a `<slug>:<skill>` invocation).
88
285
  if (typeof slug === "string" && slug.length > 0)
89
286
  bySlug.set(slug, cloudUid);
287
+ // The company's own HQ directory (`companies/<slug>`) is company-owned work
288
+ // too — skills, knowledge, and project files all live there, and in prod a
289
+ // large share of sessions run from inside the HQ root rather than a repo
290
+ // checkout. Without this, that work is silently unattributed.
291
+ const declaredPath = typeof company.path === "string" && company.path.trim().length > 0
292
+ ? company.path.trim()
293
+ : `companies/${slug}`;
294
+ // `path` is documented as HQ-root-RELATIVE, but the manifest is synced and
295
+ // hand-editable. An absolute path, `.`, or `..` would otherwise register the
296
+ // HQ root — or an arbitrary directory — as owned by this company, stamping
297
+ // its uid on every event beneath. Anything that escapes the root is dropped.
298
+ const companyDir = path.resolve(hqRoot, declaredPath);
299
+ if (isInsideRoot(hqRoot, companyDir)) {
300
+ rootsToExpand.push({ root: companyDir, companyUid: cloudUid });
301
+ }
90
302
  const repos = company.repos;
91
303
  if (!Array.isArray(repos))
92
304
  continue;
93
305
  for (const repo of repos) {
94
306
  if (typeof repo !== "string" || repo.trim().length === 0)
95
307
  continue;
96
- // Manifest repo paths are relative to the HQ root (e.g.
97
- // `repos/private/hq-cloud`). Resolve to an absolute, normalized root.
98
- const repoRoot = normalizePath(path.resolve(hqRoot, repo));
99
- entries.push({ repoRoot, companyUid: cloudUid });
308
+ // Manifest `repos` are BARE NAMES; expand to the real checkout roots
309
+ // under `repos/{private,public}/`. See `repoRootCandidates`.
310
+ for (const candidate of repoRootCandidates(hqRoot, repo)) {
311
+ rootsToExpand.push({ root: candidate, companyUid: cloudUid });
312
+ }
100
313
  }
101
314
  }
102
- // Longest repoRoot first so the first containment match is the most specific
103
- // (handles nested repo layouts where one repo path prefixes another).
104
- entries.sort((a, b) => b.repoRoot.length - a.repoRoot.length);
105
- return { entries, bySlug };
315
+ // Discover BEFORE probing, so the probe can cover every directory we will
316
+ // actually match under including the parents of external symlink targets,
317
+ // which are unknown until the aliases are resolved.
318
+ //
319
+ // Worktree discovery matches its prefix case-INSENSITIVELY here regardless of
320
+ // the filesystem. That deliberately yields a superset: claims are still keyed
321
+ // by the probed `foldsCase` below, so a case-variant that the filesystem
322
+ // considers distinct simply becomes its own (possibly ambiguous) claim rather
323
+ // than being silently missed at discovery time.
324
+ const expansions = await Promise.all(rootsToExpand.map(async ({ root, companyUid }) => {
325
+ const [worktrees, real] = await Promise.all([
326
+ worktreeSiblings(root, true),
327
+ physicalAlias(root),
328
+ ]);
329
+ const paths = real ? [...worktrees, real] : [...worktrees];
330
+ const worktreeReals = await Promise.all(worktrees.map(physicalAlias));
331
+ for (const wr of worktreeReals)
332
+ if (wr)
333
+ paths.push(wr);
334
+ return { paths, companyUid };
335
+ }));
336
+ const allPaths = [
337
+ ...rootsToExpand.map((r) => r.root),
338
+ ...expansions.flatMap((e) => e.paths),
339
+ ];
340
+ // Probe the actual filesystem rather than trusting `process.platform`, over
341
+ // every path we may match under. Only paths that EXIST are probed: a bare
342
+ // repo name expands to both `repos/private` and `repos/public` and normally
343
+ // only one is real, so including the missing one would report
344
+ // case-sensitivity for a directory that is simply absent and wrongly force
345
+ // the whole map exact.
346
+ const existing = await Promise.all(allPaths.map(async (p) => ((await physicalExists(p)) ? p : null)));
347
+ const foldsCase = await probeCaseFolding(existing.filter((p) => p !== null));
348
+ // Collect claims first, resolve conflicts second. A path claimed by two
349
+ // DIFFERENT companies is ambiguous and must not be attributed to whichever
350
+ // one the manifest happened to list first.
351
+ const claims = new Map();
352
+ const claim = (absPath, companyUid) => {
353
+ const repoRoot = normalizePath(absPath);
354
+ const matchKey = canonicalPath(repoRoot, foldsCase);
355
+ const existingClaim = claims.get(matchKey);
356
+ if (existingClaim)
357
+ existingClaim.companyUids.add(companyUid);
358
+ else
359
+ claims.set(matchKey, { repoRoot, companyUids: new Set([companyUid]) });
360
+ };
361
+ for (const { root, companyUid } of rootsToExpand)
362
+ claim(root, companyUid);
363
+ for (const { paths, companyUid } of expansions) {
364
+ for (const p of paths)
365
+ claim(p, companyUid);
366
+ }
367
+ const entries = [];
368
+ const ambiguous = new Set();
369
+ for (const [matchKey, { repoRoot, companyUids }] of claims) {
370
+ // Fail CLOSED on ambiguity. Two companies listing the same bare repo name,
371
+ // or two roots colliding under case folding, cannot be told apart here —
372
+ // and attributing to the wrong tenant is far worse than not attributing.
373
+ if (companyUids.size !== 1) {
374
+ ambiguous.add(matchKey);
375
+ continue;
376
+ }
377
+ entries.push({ repoRoot, matchKey, companyUid: [...companyUids][0] });
378
+ }
379
+ // Longest root first so the first containment match is the most specific
380
+ // (handles nested layouts where one repo path prefixes another — notably a
381
+ // worktree root, which must win over the company dir that contains it).
382
+ entries.sort((a, b) => b.matchKey.length - a.matchKey.length);
383
+ return { entries, bySlug, foldsCase, ambiguous };
106
384
  }
107
385
  /**
108
386
  * Resolve a skill INVOCATION to its owning company's `cmp_*` uid, or `undefined`
@@ -134,16 +412,46 @@ export function resolveCompanyForSkill(skill, map) {
134
412
  * that merely shares a string prefix (`<repoRoot>-other`) from matching.
135
413
  * Entries are pre-sorted longest-first, so the first match is the most
136
414
  * specific.
415
+ *
416
+ * If nothing matches, one lexical retry strips HQ's `-wt-<branch>` worktree
417
+ * suffix from the path. `buildRepoCompanyMap` discovers worktrees by reading
418
+ * the directory, which only sees the ones that exist RIGHT NOW — but telemetry
419
+ * is read from a cursor and a branch worktree is routinely deleted before the
420
+ * next pass. Those pending rows still carry the worktree cwd, and because a
421
+ * successful POST advances the cursor permanently, failing to resolve them
422
+ * loses that attribution for good. The suffix is documented convention, so
423
+ * deriving it from the recorded path needs no directory to still exist.
137
424
  */
138
425
  export function resolveCompanyForCwd(cwd, map) {
139
426
  if (typeof cwd !== "string" || cwd.length === 0)
140
427
  return undefined;
141
- const c = normalizePath(cwd);
142
- for (const { repoRoot, companyUid } of map.entries) {
143
- if (c === repoRoot || c.startsWith(`${repoRoot}/`)) {
144
- return companyUid;
428
+ const foldsCase = map.foldsCase === true;
429
+ const c = canonicalPath(cwd, foldsCase);
430
+ const match = (candidate) => {
431
+ for (const { matchKey, companyUid } of map.entries) {
432
+ if (candidate === matchKey || candidate.startsWith(`${matchKey}/`)) {
433
+ return companyUid;
434
+ }
435
+ }
436
+ return undefined;
437
+ };
438
+ const direct = match(c);
439
+ if (direct)
440
+ return direct;
441
+ // The path may have been dropped for AMBIGUITY (claimed by two companies).
442
+ // Falling back would collapse e.g. an ambiguous `foo-wt-team` to `foo` and
443
+ // hand the event to whoever owns `foo`, silently undoing the fail-closed
444
+ // protection. An ambiguous path stays unattributed, full stop.
445
+ const ambiguous = map.ambiguous;
446
+ if (ambiguous) {
447
+ for (const key of ambiguous) {
448
+ if (c === key || c.startsWith(`${key}/`))
449
+ return undefined;
145
450
  }
146
451
  }
147
- return undefined;
452
+ // `<...>/hq-pro-wt-feature-x/src` → `<...>/hq-pro/src`. Only the FIRST such
453
+ // segment is rewritten; `-wt-` deeper in the path is left alone.
454
+ const collapsed = c.replace(/^(.*?\/[^/]+?)-wt-[^/]*(\/.*)?$/, "$1$2");
455
+ return collapsed !== c ? match(collapsed) : undefined;
148
456
  }
149
457
  //# sourceMappingURL=company-resolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"company-resolver.js","sourceRoot":"","sources":["../src/company-resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"company-resolver.js","sourceRoot":"","sources":["../src/company-resolver.ts"],"names":[],"mappings":"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"}