@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.
- package/dist/company-resolver.d.ts +31 -1
- package/dist/company-resolver.d.ts.map +1 -1
- package/dist/company-resolver.js +329 -21
- package/dist/company-resolver.js.map +1 -1
- package/dist/company-resolver.test.js +371 -1
- package/dist/company-resolver.test.js.map +1 -1
- package/dist/skill-telemetry.js +1 -1
- package/dist/skill-telemetry.js.map +1 -1
- package/dist/telemetry.d.ts +10 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +95 -4
- package/dist/telemetry.js.map +1 -1
- package/dist/telemetry.test.js +177 -0
- package/dist/telemetry.test.js.map +1 -1
- package/dist/vault-client.d.ts +42 -0
- package/dist/vault-client.d.ts.map +1 -1
- package/dist/vault-client.js +40 -0
- package/dist/vault-client.js.map +1 -1
- package/package.json +1 -1
- package/src/company-resolver.test.ts +432 -1
- package/src/company-resolver.ts +362 -23
- package/src/skill-telemetry.ts +1 -1
- package/src/telemetry.test.ts +241 -0
- package/src/telemetry.ts +124 -6
- package/src/vault-client.ts +68 -0
|
@@ -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
|
-
/**
|
|
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
|
|
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"}
|
package/dist/company-resolver.js
CHANGED
|
@@ -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
|
|
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
|
|
268
|
+
return empty();
|
|
73
269
|
}
|
|
74
270
|
const companies = doc.companies;
|
|
75
|
-
if (!companies || typeof companies !== "object")
|
|
76
|
-
return
|
|
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
|
|
97
|
-
// `repos/private
|
|
98
|
-
const
|
|
99
|
-
|
|
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
|
-
//
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
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
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
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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"}
|