@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.
- package/dist/cleo-paths.d.ts +144 -30
- package/dist/cleo-paths.d.ts.map +1 -1
- package/dist/cleo-paths.js +183 -54
- package/dist/cleo-paths.js.map +1 -1
- package/dist/exec-path.d.ts +183 -0
- package/dist/exec-path.d.ts.map +1 -0
- package/dist/exec-path.js +266 -0
- package/dist/exec-path.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/platform-paths.d.ts +21 -0
- package/dist/platform-paths.d.ts.map +1 -1
- package/dist/platform-paths.js +29 -4
- package/dist/platform-paths.js.map +1 -1
- package/dist/worktree-paths.d.ts +17 -0
- package/dist/worktree-paths.d.ts.map +1 -1
- package/dist/worktree-paths.js +21 -0
- package/dist/worktree-paths.js.map +1 -1
- package/package.json +1 -1
package/dist/cleo-paths.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
|
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
|
|
232
|
+
* Compute the path-derived fingerprint `sha256(gitRoot|name|remote)[0:12]`.
|
|
153
233
|
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
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
|
|
242
|
+
* @returns The 12-hex-char path fingerprint.
|
|
166
243
|
*
|
|
167
|
-
* @
|
|
168
|
-
* @task
|
|
244
|
+
* @public
|
|
245
|
+
* @task T12470
|
|
169
246
|
*/
|
|
170
|
-
export declare function
|
|
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
|
-
*
|
|
181
|
-
*
|
|
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
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
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
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
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
|
|
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: '
|
|
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
|
|
323
|
+
* @task T12470
|
|
210
324
|
*/
|
|
211
325
|
export declare function resolveProjectByCwd(cwd?: string): ResolvedProject | null;
|
|
212
326
|
/**
|
package/dist/cleo-paths.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"cleo-paths.d.ts","sourceRoot":"","sources":["../src/cleo-paths.ts"],"names":[],"mappings":"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"}
|
package/dist/cleo-paths.js
CHANGED
|
@@ -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
|
-
//
|
|
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
|
|
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
|
-
*
|
|
261
|
-
*
|
|
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
|
|
356
|
+
* @returns The 12-hex-char path fingerprint.
|
|
265
357
|
*
|
|
266
|
-
* @
|
|
267
|
-
* @task
|
|
358
|
+
* @public
|
|
359
|
+
* @task T12470
|
|
268
360
|
*/
|
|
269
|
-
export function
|
|
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
|
-
*
|
|
290
|
-
*
|
|
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
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
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
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
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
|
|
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: '
|
|
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
|
|
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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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 &&
|
package/dist/cleo-paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleo-paths.js","sourceRoot":"","sources":["../src/cleo-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQnD,OAAO,EACL,2BAA2B,GAG5B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"cleo-paths.js","sourceRoot":"","sources":["../src/cleo-paths.ts"],"names":[],"mappings":"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"}
|