@cleocode/paths 2026.9.19 → 2026.9.21

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.
@@ -29,6 +29,38 @@ export declare function getCleoPlatformPaths(): PlatformPaths;
29
29
  * @public
30
30
  */
31
31
  export declare function getCleoHome(): string;
32
+ /**
33
+ * Get the absolute path to CLEO's global state directory.
34
+ *
35
+ * State is data CLEO keeps between runs but can rebuild or lose: warn-once
36
+ * caches, deprecation telemetry, cleanup audit logs.
37
+ *
38
+ * Linux: `$XDG_STATE_HOME/cleo` (default `~/.local/state/cleo`)
39
+ * macOS: `<getCleoHome()>/state` (`~/Library/Application Support/cleo/state`)
40
+ * Windows: `<getCleoHome()>/state` (`%LOCALAPPDATA%\cleo\Data\state`)
41
+ *
42
+ * macOS and Windows have no XDG state dir, so state lives beside the data it
43
+ * describes and follows a `CLEO_HOME` override.
44
+ *
45
+ * @returns Absolute path of the state directory. Not created.
46
+ *
47
+ * @public
48
+ * @task T12602
49
+ */
50
+ export declare function getCleoStateDir(): string;
51
+ /**
52
+ * Path of the persisted stable device id — `<cleoHome>/device-id`.
53
+ *
54
+ * Core's `getStableDeviceId()` creates it; `@cleocode/worktree` reads it to
55
+ * decide whether a worktree lock holder's pid can be probed on this device
56
+ * (T12506). One path, two readers.
57
+ *
58
+ * @returns Absolute path of the device-id file.
59
+ *
60
+ * @public
61
+ * @task T12506
62
+ */
63
+ export declare function resolveStableDeviceIdPath(): string;
32
64
  /**
33
65
  * Get a cached system information snapshot scoped to CLEO.
34
66
  *
@@ -118,13 +150,61 @@ export declare function resolveLegacyCleoDir(override?: string): string;
118
150
  * @public
119
151
  */
120
152
  export interface ResolvedProject {
121
- /** Canonical runtime project ID (12-hex-char SHA-256 of git-root|name|remote). */
153
+ /**
154
+ * The project's portable identity (ADR-094, T12470): the tracked
155
+ * `.cleo/project-id` when valid, otherwise the `projectId` recorded in
156
+ * `.cleo/project-info.json`. Never derived from the path. Treat it as an
157
+ * opaque string — ids of every historical shape (UUID, 12-hex, legacy) occur.
158
+ */
122
159
  projectId: string;
123
160
  /** Absolute realpath to the project root directory. */
124
161
  projectRoot: string;
125
- /** The legacy UUID from project-info.json, if present. */
162
+ /** The `projectId` recorded in `project-info.json`, if present. */
126
163
  legacyUUID?: string;
164
+ /**
165
+ * Which declaration supplied {@link ResolvedProject.projectId}. Optional so
166
+ * callers that construct a `ResolvedProject` themselves keep compiling;
167
+ * {@link resolveProjectByCwd} always sets it.
168
+ */
169
+ source?: DeclaredProjectIdentity['source'];
170
+ }
171
+ /**
172
+ * A project identity declared by files inside `<root>/.cleo/` — the only
173
+ * sources that may name a project (ADR-094, T12470).
174
+ *
175
+ * @public
176
+ */
177
+ export interface DeclaredProjectIdentity {
178
+ /** The opaque project id. */
179
+ readonly projectId: string;
180
+ /** `tracked` = `.cleo/project-id`; `project-info` = `.cleo/project-info.json`. */
181
+ readonly source: 'tracked' | 'project-info';
182
+ /** The `projectId` recorded in `project-info.json`, when that file has one. */
183
+ readonly infoProjectId?: string;
127
184
  }
185
+ /**
186
+ * Read the identity a project root DECLARES, in precedence order (T12470):
187
+ *
188
+ * 1. the tracked, write-once `.cleo/project-id` (ADR-094);
189
+ * 2. the `projectId` in `.cleo/project-info.json`.
190
+ *
191
+ * A malformed tracked file is skipped here (it is reported by
192
+ * `cleo doctor project-identity`) and never replaced by a derived value.
193
+ * Nothing about the path — its spelling, realpath, git root or remote — takes
194
+ * part: moving or re-cloning a project keeps its id.
195
+ *
196
+ * @param projectRoot - Directory containing `.cleo/`.
197
+ * @returns The declared identity, or `null` when the root declares none.
198
+ *
199
+ * @example
200
+ * ```ts
201
+ * readDeclaredProjectIdentity('/repo'); // { projectId: 'c78d09c3a8ee', source: 'tracked' }
202
+ * ```
203
+ *
204
+ * @public
205
+ * @task T12470
206
+ */
207
+ export declare function readDeclaredProjectIdentity(projectRoot: string): DeclaredProjectIdentity | null;
128
208
  /**
129
209
  * Canonicalize a filesystem path across operating systems — resolve symlinks
130
210
  * and mount/alias divergence (macOS `/var` → `/private/var`, Windows
@@ -149,25 +229,30 @@ export interface ResolvedProject {
149
229
  */
150
230
  export declare function canonicalizePath(p: string): string;
151
231
  /**
152
- * Compute the canonical project ID for a given repository path (T9149/T11023).
232
+ * Compute the path-derived fingerprint `sha256(gitRoot|name|remote)[0:12]`.
153
233
  *
154
- * Algorithm:
155
- * 1. Resolve `repoPath` to its `realpath` (resolves symlinks, normalises mounts).
156
- * 2. Detect the git root via `git rev-parse --show-toplevel` (falls back to realpath).
157
- * 3. Read `.cleo/project-info.json` name (optional).
158
- * 4. Read `git remote get-url origin` (optional).
159
- * 5. SHA-256 of `<gitRoot>|<projectName>|<remoteUrl>`, first 12 hex chars.
160
- *
161
- * This ensures `/mnt/projects/X` and `/workspace/X` (same git root,
162
- * same remote) produce the same ID.
234
+ * **Not an identity (T12470, supersedes the T9149/T11023 design).** A project
235
+ * is identified only by its declared id ({@link readDeclaredProjectIdentity}).
236
+ * This fingerprint survives solely as a LOOKUP KEY into
237
+ * `nexus_project_id_aliases`, so ids that older CLEO versions derived from a
238
+ * path keep resolving to the project that now owns them. Never return it as a
239
+ * project id and never mint a registry row from it.
163
240
  *
164
241
  * @param repoPath - Absolute path to the project root.
165
- * @returns The 12-hex-char canonical project ID.
242
+ * @returns The 12-hex-char path fingerprint.
166
243
  *
167
- * @task T11023
168
- * @task T9149
244
+ * @public
245
+ * @task T12470
169
246
  */
170
- export declare function computeCanonicalProjectId(repoPath: string): string;
247
+ export declare function computePathFingerprintId(repoPath: string): string;
248
+ /**
249
+ * Former name of {@link computePathFingerprintId}.
250
+ *
251
+ * @deprecated T12470 — the value is a path fingerprint (alias key), not a
252
+ * project id. Use {@link readDeclaredProjectIdentity} for identity and
253
+ * {@link computePathFingerprintId} for alias lookups.
254
+ */
255
+ export declare const computeCanonicalProjectId: (repoPath: string) => string;
171
256
  /**
172
257
  * Compute the legacy base64url(path) ID for a given path.
173
258
  *
@@ -176,29 +261,58 @@ export declare function computeCanonicalProjectId(repoPath: string): string;
176
261
  * before T9149 W5: `Buffer.from(path).toString('base64url').slice(0, 32)`.
177
262
  */
178
263
  export declare function legacyProjectId(repoPath: string): string;
264
+ /** A project and one path recorded for it, as read from the registry (T12589). */
265
+ export interface RecordedProjectPath {
266
+ /** Immutable project id. */
267
+ readonly projectId: string;
268
+ /** A path recorded for the project (registry row or location). */
269
+ readonly path: string;
270
+ }
179
271
  /**
180
- * Walk up from `cwd` (or `process.cwd()`) looking for `.cleo/project-info.json`
181
- * and return the project identity if found.
272
+ * Every project that can claim an alias key (T12589): the alias row's owner
273
+ * plus each project with a recorded path whose {@link legacyProjectId} is the
274
+ * key.
275
+ *
276
+ * The legacy id encodes only the first 24 bytes of a path, so every project
277
+ * under a long shared prefix (`/Users/<name>/projects/…`) derives the SAME
278
+ * key. A key with more than one claimant is ambiguous: it names no project,
279
+ * and a resolver must refuse it rather than return whichever project happened
280
+ * to record it first. A non-legacy key (full-path fingerprint, UUID) is never
281
+ * derived from a path by this function, so only its owner claims it.
282
+ *
283
+ * @param alias - The alias key being resolved or recorded.
284
+ * @param owner - `canonical_id` of the alias row for `alias`, when one exists.
285
+ * @param paths - Every recorded project path to check.
286
+ * @returns Distinct claimant ids, sorted; ambiguous when longer than one.
287
+ * @example
288
+ * ```ts
289
+ * const claimants = legacyAliasClaimants(id, row?.canonicalId, registryPaths);
290
+ * if (claimants.length > 1) return null; // ambiguous — resolves to no project
291
+ * ```
292
+ */
293
+ export declare function legacyAliasClaimants(alias: string, owner: string | null | undefined, paths: Iterable<RecordedProjectPath>): string[];
294
+ /**
295
+ * Walk up from `cwd` (or `process.cwd()`) to the nearest directory whose
296
+ * `.cleo/` DECLARES a project identity, and return that identity.
182
297
  *
183
- * The project-info file acts as the local sentinel and supplies `legacyUUID`.
184
- * The returned `projectId` is the derived canonical runtime ID, not the raw
185
- * project-local UUID stored in the file.
298
+ * Resolution order at each level (T12470 · ADR-094): the tracked
299
+ * `.cleo/project-id`, then `project-info.json`'s `projectId`. The returned
300
+ * `projectId` is that declared id — never a hash of the path — so the same
301
+ * project resolves to the same id from any absolute location, mount or device.
302
+ * `projectRoot` is realpath-canonicalized (bind-mounts, macOS `/private/var`).
186
303
  *
187
- * **Cross-mount divergence (T11023):** Uses `realpathSync` to normalize
188
- * bind-mounts and symlinks so the same repo at `/mnt/projects/X` and
189
- * `/workspace/X` resolves to the same `projectRoot`. The `projectId` is
190
- * the T9149 canonical 12-hex-char SHA-256 fingerprint of git-root + name
191
- * + remote URL, which is also mount-invariant.
304
+ * A `.cleo/` that holds only the tracked id (no `project-info.json`) counts as
305
+ * a project root only when the directory is a git toplevel (has `.git`), so a
306
+ * monorepo subdirectory carrying a committed id does not shadow its parent.
192
307
  *
193
308
  * @param cwd - Optional working directory to start the ancestor walk from.
194
309
  * Defaults to `process.cwd()`.
195
- * @returns The resolved project identity, or `null` if no CLEO project is
196
- * found anywhere in the ancestor chain.
310
+ * @returns The resolved project identity, or `null` if no ancestor declares one.
197
311
  *
198
312
  * @example
199
313
  * ```typescript
200
314
  * const project = resolveProjectByCwd('/repo/packages/core');
201
- * // { projectId: 'a1b2c3d4e5f6', projectRoot: '/repo' }
315
+ * // { projectId: 'c78d09c3a8ee', projectRoot: '/repo', source: 'tracked' }
202
316
  *
203
317
  * const notFound = resolveProjectByCwd('/tmp/empty');
204
318
  * // null
@@ -206,7 +320,7 @@ export declare function legacyProjectId(repoPath: string): string;
206
320
  *
207
321
  * @public
208
322
  * @task T11008
209
- * @task T11023
323
+ * @task T12470
210
324
  */
211
325
  export declare function resolveProjectByCwd(cwd?: string): ResolvedProject | null;
212
326
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cleo-paths.d.ts","sourceRoot":"","sources":["../src/cleo-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAeH,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAwB7B;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,aAAa,CAEpD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,CAE9C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAelD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAMvD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAuDD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CASlD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWlE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA0CxE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsExE;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
1
+ {"version":3,"file":"cleo-paths.d.ts","sourceRoot":"","sources":["../src/cleo-paths.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ import { createRequire } from 'node:module';
15
15
  import { homedir } from 'node:os';
16
16
  import { dirname, join, resolve } from 'node:path';
17
17
  import { createPlatformPathsResolver, } from './platform-paths.js';
18
+ import { readPortableProjectId } from './portable-project-id.js';
18
19
  const TEMPLATES_SUBDIR = 'templates';
19
20
  /**
20
21
  * Returns the `node:sqlite` `DatabaseSync` constructor, loaded on first use.
@@ -54,6 +55,47 @@ export function getCleoPlatformPaths() {
54
55
  export function getCleoHome() {
55
56
  return cleoResolver.getPlatformPaths().data;
56
57
  }
58
+ /**
59
+ * Get the absolute path to CLEO's global state directory.
60
+ *
61
+ * State is data CLEO keeps between runs but can rebuild or lose: warn-once
62
+ * caches, deprecation telemetry, cleanup audit logs.
63
+ *
64
+ * Linux: `$XDG_STATE_HOME/cleo` (default `~/.local/state/cleo`)
65
+ * macOS: `<getCleoHome()>/state` (`~/Library/Application Support/cleo/state`)
66
+ * Windows: `<getCleoHome()>/state` (`%LOCALAPPDATA%\cleo\Data\state`)
67
+ *
68
+ * macOS and Windows have no XDG state dir, so state lives beside the data it
69
+ * describes and follows a `CLEO_HOME` override.
70
+ *
71
+ * @returns Absolute path of the state directory. Not created.
72
+ *
73
+ * @public
74
+ * @task T12602
75
+ */
76
+ export function getCleoStateDir() {
77
+ const paths = cleoResolver.getPlatformPaths();
78
+ if (process.platform === 'darwin' || process.platform === 'win32') {
79
+ return join(paths.data, 'state');
80
+ }
81
+ // env-paths maps `log` to $XDG_STATE_HOME/<app> on Linux.
82
+ return paths.log;
83
+ }
84
+ /**
85
+ * Path of the persisted stable device id — `<cleoHome>/device-id`.
86
+ *
87
+ * Core's `getStableDeviceId()` creates it; `@cleocode/worktree` reads it to
88
+ * decide whether a worktree lock holder's pid can be probed on this device
89
+ * (T12506). One path, two readers.
90
+ *
91
+ * @returns Absolute path of the device-id file.
92
+ *
93
+ * @public
94
+ * @task T12506
95
+ */
96
+ export function resolveStableDeviceIdPath() {
97
+ return join(getCleoHome(), 'device-id');
98
+ }
57
99
  /**
58
100
  * Get a cached system information snapshot scoped to CLEO.
59
101
  *
@@ -162,8 +204,61 @@ export function resolveLegacyCleoDir(override) {
162
204
  return override;
163
205
  return join(homedir(), '.cleo');
164
206
  }
207
+ /**
208
+ * Read the `projectId` field from `<root>/.cleo/project-info.json`.
209
+ * Returns `undefined` when the file is absent, unparseable or has no id.
210
+ */
211
+ function _readProjectInfoId(projectRoot) {
212
+ try {
213
+ const raw = readFileSync(join(projectRoot, '.cleo', 'project-info.json'), 'utf-8');
214
+ const data = JSON.parse(raw);
215
+ return typeof data.projectId === 'string' && data.projectId.length > 0
216
+ ? data.projectId
217
+ : undefined;
218
+ }
219
+ catch {
220
+ return undefined;
221
+ }
222
+ }
223
+ /**
224
+ * Read the identity a project root DECLARES, in precedence order (T12470):
225
+ *
226
+ * 1. the tracked, write-once `.cleo/project-id` (ADR-094);
227
+ * 2. the `projectId` in `.cleo/project-info.json`.
228
+ *
229
+ * A malformed tracked file is skipped here (it is reported by
230
+ * `cleo doctor project-identity`) and never replaced by a derived value.
231
+ * Nothing about the path — its spelling, realpath, git root or remote — takes
232
+ * part: moving or re-cloning a project keeps its id.
233
+ *
234
+ * @param projectRoot - Directory containing `.cleo/`.
235
+ * @returns The declared identity, or `null` when the root declares none.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * readDeclaredProjectIdentity('/repo'); // { projectId: 'c78d09c3a8ee', source: 'tracked' }
240
+ * ```
241
+ *
242
+ * @public
243
+ * @task T12470
244
+ */
245
+ export function readDeclaredProjectIdentity(projectRoot) {
246
+ const infoProjectId = _readProjectInfoId(projectRoot);
247
+ const tracked = readPortableProjectId(projectRoot);
248
+ if (tracked.status === 'valid') {
249
+ return {
250
+ projectId: tracked.projectId,
251
+ source: 'tracked',
252
+ ...(infoProjectId !== undefined && { infoProjectId }),
253
+ };
254
+ }
255
+ if (infoProjectId !== undefined) {
256
+ return { projectId: infoProjectId, source: 'project-info', infoProjectId };
257
+ }
258
+ return null;
259
+ }
165
260
  // ---------------------------------------------------------------------------
166
- // Canonical project ID computation (T11023 — cross-mount divergence)
261
+ // Path fingerprint (alias key only — never an identity, T12470)
167
262
  // ---------------------------------------------------------------------------
168
263
  /**
169
264
  * Synchronously find the git root for a given directory.
@@ -248,25 +343,22 @@ export function canonicalizePath(p) {
248
343
  }
249
344
  }
250
345
  /**
251
- * Compute the canonical project ID for a given repository path (T9149/T11023).
252
- *
253
- * Algorithm:
254
- * 1. Resolve `repoPath` to its `realpath` (resolves symlinks, normalises mounts).
255
- * 2. Detect the git root via `git rev-parse --show-toplevel` (falls back to realpath).
256
- * 3. Read `.cleo/project-info.json` name (optional).
257
- * 4. Read `git remote get-url origin` (optional).
258
- * 5. SHA-256 of `<gitRoot>|<projectName>|<remoteUrl>`, first 12 hex chars.
346
+ * Compute the path-derived fingerprint `sha256(gitRoot|name|remote)[0:12]`.
259
347
  *
260
- * This ensures `/mnt/projects/X` and `/workspace/X` (same git root,
261
- * same remote) produce the same ID.
348
+ * **Not an identity (T12470, supersedes the T9149/T11023 design).** A project
349
+ * is identified only by its declared id ({@link readDeclaredProjectIdentity}).
350
+ * This fingerprint survives solely as a LOOKUP KEY into
351
+ * `nexus_project_id_aliases`, so ids that older CLEO versions derived from a
352
+ * path keep resolving to the project that now owns them. Never return it as a
353
+ * project id and never mint a registry row from it.
262
354
  *
263
355
  * @param repoPath - Absolute path to the project root.
264
- * @returns The 12-hex-char canonical project ID.
356
+ * @returns The 12-hex-char path fingerprint.
265
357
  *
266
- * @task T11023
267
- * @task T9149
358
+ * @public
359
+ * @task T12470
268
360
  */
269
- export function computeCanonicalProjectId(repoPath) {
361
+ export function computePathFingerprintId(repoPath) {
270
362
  const realRepoPath = canonicalizePath(repoPath);
271
363
  const gitRoot = _findGitRootSync(realRepoPath);
272
364
  const effectiveRoot = gitRoot ?? realRepoPath;
@@ -275,6 +367,14 @@ export function computeCanonicalProjectId(repoPath) {
275
367
  const fingerprint = [effectiveRoot, projectName ?? '', remoteUrl ?? ''].join('|');
276
368
  return createHash('sha256').update(fingerprint).digest('hex').substring(0, 12);
277
369
  }
370
+ /**
371
+ * Former name of {@link computePathFingerprintId}.
372
+ *
373
+ * @deprecated T12470 — the value is a path fingerprint (alias key), not a
374
+ * project id. Use {@link readDeclaredProjectIdentity} for identity and
375
+ * {@link computePathFingerprintId} for alias lookups.
376
+ */
377
+ export const computeCanonicalProjectId = computePathFingerprintId;
278
378
  /**
279
379
  * Compute the legacy base64url(path) ID for a given path.
280
380
  *
@@ -286,28 +386,56 @@ export function legacyProjectId(repoPath) {
286
386
  return Buffer.from(repoPath).toString('base64url').slice(0, 32);
287
387
  }
288
388
  /**
289
- * Walk up from `cwd` (or `process.cwd()`) looking for `.cleo/project-info.json`
290
- * and return the project identity if found.
389
+ * Every project that can claim an alias key (T12589): the alias row's owner
390
+ * plus each project with a recorded path whose {@link legacyProjectId} is the
391
+ * key.
392
+ *
393
+ * The legacy id encodes only the first 24 bytes of a path, so every project
394
+ * under a long shared prefix (`/Users/<name>/projects/…`) derives the SAME
395
+ * key. A key with more than one claimant is ambiguous: it names no project,
396
+ * and a resolver must refuse it rather than return whichever project happened
397
+ * to record it first. A non-legacy key (full-path fingerprint, UUID) is never
398
+ * derived from a path by this function, so only its owner claims it.
399
+ *
400
+ * @param alias - The alias key being resolved or recorded.
401
+ * @param owner - `canonical_id` of the alias row for `alias`, when one exists.
402
+ * @param paths - Every recorded project path to check.
403
+ * @returns Distinct claimant ids, sorted; ambiguous when longer than one.
404
+ * @example
405
+ * ```ts
406
+ * const claimants = legacyAliasClaimants(id, row?.canonicalId, registryPaths);
407
+ * if (claimants.length > 1) return null; // ambiguous — resolves to no project
408
+ * ```
409
+ */
410
+ export function legacyAliasClaimants(alias, owner, paths) {
411
+ const claimants = new Set(owner ? [owner] : []);
412
+ for (const { projectId, path } of paths)
413
+ if (path && legacyProjectId(path) === alias)
414
+ claimants.add(projectId);
415
+ return [...claimants].sort();
416
+ }
417
+ /**
418
+ * Walk up from `cwd` (or `process.cwd()`) to the nearest directory whose
419
+ * `.cleo/` DECLARES a project identity, and return that identity.
291
420
  *
292
- * The project-info file acts as the local sentinel and supplies `legacyUUID`.
293
- * The returned `projectId` is the derived canonical runtime ID, not the raw
294
- * project-local UUID stored in the file.
421
+ * Resolution order at each level (T12470 · ADR-094): the tracked
422
+ * `.cleo/project-id`, then `project-info.json`'s `projectId`. The returned
423
+ * `projectId` is that declared id — never a hash of the path — so the same
424
+ * project resolves to the same id from any absolute location, mount or device.
425
+ * `projectRoot` is realpath-canonicalized (bind-mounts, macOS `/private/var`).
295
426
  *
296
- * **Cross-mount divergence (T11023):** Uses `realpathSync` to normalize
297
- * bind-mounts and symlinks so the same repo at `/mnt/projects/X` and
298
- * `/workspace/X` resolves to the same `projectRoot`. The `projectId` is
299
- * the T9149 canonical 12-hex-char SHA-256 fingerprint of git-root + name
300
- * + remote URL, which is also mount-invariant.
427
+ * A `.cleo/` that holds only the tracked id (no `project-info.json`) counts as
428
+ * a project root only when the directory is a git toplevel (has `.git`), so a
429
+ * monorepo subdirectory carrying a committed id does not shadow its parent.
301
430
  *
302
431
  * @param cwd - Optional working directory to start the ancestor walk from.
303
432
  * Defaults to `process.cwd()`.
304
- * @returns The resolved project identity, or `null` if no CLEO project is
305
- * found anywhere in the ancestor chain.
433
+ * @returns The resolved project identity, or `null` if no ancestor declares one.
306
434
  *
307
435
  * @example
308
436
  * ```typescript
309
437
  * const project = resolveProjectByCwd('/repo/packages/core');
310
- * // { projectId: 'a1b2c3d4e5f6', projectRoot: '/repo' }
438
+ * // { projectId: 'c78d09c3a8ee', projectRoot: '/repo', source: 'tracked' }
311
439
  *
312
440
  * const notFound = resolveProjectByCwd('/tmp/empty');
313
441
  * // null
@@ -315,38 +443,29 @@ export function legacyProjectId(repoPath) {
315
443
  *
316
444
  * @public
317
445
  * @task T11008
318
- * @task T11023
446
+ * @task T12470
319
447
  */
320
448
  export function resolveProjectByCwd(cwd) {
321
449
  const start = resolve(cwd ?? process.cwd());
322
450
  let current = start;
323
451
  while (true) {
324
- const infoPath = join(current, '.cleo', 'project-info.json');
325
- if (existsSync(infoPath)) {
326
- try {
327
- const raw = readFileSync(infoPath, 'utf-8');
328
- const data = JSON.parse(raw);
329
- if (typeof data.projectId === 'string' && data.projectId.length > 0) {
330
- // T11023: Normalize projectRoot via the canonicalizePath SSoT to
331
- // handle cross-mount + cross-OS divergence — same repo at
332
- // /mnt/projects/X and /workspace/X (and macOS /var vs /private/var)
333
- // resolves to the same real path (AC2, AC3). Falls back to the
334
- // lexical path when `current` no longer exists on disk.
335
- const realRoot = canonicalizePath(current);
336
- // T11023: Compute canonical projectId using T9149 algorithm
337
- // (git-root + realpath fingerprint) for mount-invariant identity (AC1).
338
- const canonicalId = computeCanonicalProjectId(realRoot);
339
- return {
340
- projectId: canonicalId,
341
- projectRoot: realRoot,
342
- legacyUUID: data.projectId,
343
- };
344
- }
345
- }
346
- catch {
347
- // Corrupt or unparseable project-info.json — keep walking up.
348
- // A higher ancestor may have a valid one.
452
+ if (existsSync(join(current, '.cleo'))) {
453
+ const declared = readDeclaredProjectIdentity(current);
454
+ // A `.cleo/` holding ONLY a committed project-id (no project-info.json)
455
+ // is a project root only at a git toplevel. Otherwise a monorepo
456
+ // subdirectory that carries a committed id would shadow its parent.
457
+ const trackedOnly = declared?.source === 'tracked' && declared.infoProjectId === undefined;
458
+ if (declared !== null && (!trackedOnly || existsSync(join(current, '.git')))) {
459
+ return {
460
+ projectId: declared.projectId,
461
+ projectRoot: canonicalizePath(current),
462
+ ...(declared.infoProjectId !== undefined && { legacyUUID: declared.infoProjectId }),
463
+ source: declared.source,
464
+ };
349
465
  }
466
+ // A `.cleo/` that declares nothing (corrupt / id-less project-info.json),
467
+ // or only a tracked id below a git toplevel, keeps walking — a higher
468
+ // ancestor may declare one.
350
469
  }
351
470
  const parent = dirname(current);
352
471
  if (parent === current)
@@ -425,6 +544,16 @@ export function resolveCanonicalCleoDir(projectId) {
425
544
  if (aliasRow &&
426
545
  typeof aliasRow.canonical_id === 'string' &&
427
546
  aliasRow.canonical_id.length > 0) {
547
+ // T12589: a truncated legacy key shared by several projects names none.
548
+ const recorded = db
549
+ .prepare('SELECT project_id, project_path FROM nexus_project_registry')
550
+ .all()
551
+ .map((row) => ({
552
+ projectId: String(row['project_id']),
553
+ path: String(row['project_path']),
554
+ }));
555
+ if (legacyAliasClaimants(projectId, aliasRow.canonical_id, recorded).length > 1)
556
+ return null;
428
557
  // Resolved a legacy alias — look up the canonical ID.
429
558
  const canonicalRow = directStmt.get(aliasRow.canonical_id);
430
559
  if (canonicalRow &&
@@ -1 +1 @@
1
- {"version":3,"file":"cleo-paths.js","sourceRoot":"","sources":["../src/cleo-paths.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cleo-paths.js","sourceRoot":"","sources":["../src/cleo-paths.ts"],"names":[],"mappings":"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"}