@vibe-commit/capture 0.8.0 → 0.10.0
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/README.md +149 -1
- package/dist/agents/claude_code.js +13 -0
- package/dist/agents/claude_code.js.map +1 -1
- package/dist/agents/codex_cli.js +11 -0
- package/dist/agents/codex_cli.js.map +1 -1
- package/dist/agents/cursor.js +7 -1
- package/dist/agents/cursor.js.map +1 -1
- package/dist/agents/registry.d.ts +7 -0
- package/dist/agents/registry.js +9 -0
- package/dist/agents/registry.js.map +1 -1
- package/dist/agents/types.d.ts +32 -0
- package/dist/agents/types.js.map +1 -1
- package/dist/bounded_id.d.ts +29 -0
- package/dist/bounded_id.js +42 -0
- package/dist/bounded_id.js.map +1 -0
- package/dist/codex_folders.d.ts +340 -0
- package/dist/codex_folders.js +1448 -0
- package/dist/codex_folders.js.map +1 -0
- package/dist/commands/backfill.d.ts +29 -7
- package/dist/commands/backfill.js +387 -109
- package/dist/commands/backfill.js.map +1 -1
- package/dist/commands/connect.d.ts +1 -1
- package/dist/commands/connect.js +1 -1
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connect_picker.js +48 -7
- package/dist/commands/connect_picker.js.map +1 -1
- package/dist/commands/finalize.d.ts +67 -0
- package/dist/commands/finalize.js +452 -114
- package/dist/commands/finalize.js.map +1 -1
- package/dist/commands/scan.d.ts +28 -0
- package/dist/commands/scan.js +11 -0
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/status_machine.js +47 -10
- package/dist/commands/status_machine.js.map +1 -1
- package/dist/commands/why.d.ts +19 -1
- package/dist/commands/why.js +35 -3
- package/dist/commands/why.js.map +1 -1
- package/dist/commit_files.d.ts +64 -0
- package/dist/commit_files.js +83 -0
- package/dist/commit_files.js.map +1 -0
- package/dist/consent.d.ts +22 -0
- package/dist/consent.js +38 -1
- package/dist/consent.js.map +1 -1
- package/dist/copy/strings.d.ts +55 -9
- package/dist/copy/strings.js +60 -12
- package/dist/copy/strings.js.map +1 -1
- package/dist/folder_grants.d.ts +44 -0
- package/dist/folder_grants.js +101 -0
- package/dist/folder_grants.js.map +1 -0
- package/dist/git.d.ts +26 -4
- package/dist/git.js +82 -11
- package/dist/git.js.map +1 -1
- package/dist/hooks/entry.d.ts +30 -50
- package/dist/hooks/entry.js +595 -559
- package/dist/hooks/entry.js.map +1 -1
- package/dist/hooks/fire_lock.d.ts +31 -0
- package/dist/hooks/fire_lock.js +120 -12
- package/dist/hooks/fire_lock.js.map +1 -1
- package/dist/hooks/post_commit.d.ts +9 -0
- package/dist/hooks/post_commit.js +9 -5
- package/dist/hooks/post_commit.js.map +1 -1
- package/dist/machine_state.d.ts +44 -1
- package/dist/machine_state.js +75 -12
- package/dist/machine_state.js.map +1 -1
- package/dist/oauth/discovery.js +2 -1
- package/dist/oauth/discovery.js.map +1 -1
- package/dist/oauth/pkce.js +2 -1
- package/dist/oauth/pkce.js.map +1 -1
- package/dist/paths.d.ts +34 -1
- package/dist/paths.js +62 -12
- package/dist/paths.js.map +1 -1
- package/dist/physical_path.d.ts +46 -0
- package/dist/physical_path.js +151 -0
- package/dist/physical_path.js.map +1 -0
- package/dist/picker.d.ts +52 -3
- package/dist/picker.js +129 -5
- package/dist/picker.js.map +1 -1
- package/dist/picker_checklist.d.ts +9 -1
- package/dist/picker_checklist.js +41 -2
- package/dist/picker_checklist.js.map +1 -1
- package/dist/policy.d.ts +9 -1
- package/dist/policy.js +11 -2
- package/dist/policy.js.map +1 -1
- package/dist/post.d.ts +25 -0
- package/dist/post.js +49 -13
- package/dist/post.js.map +1 -1
- package/dist/project.d.ts +89 -0
- package/dist/project.js +123 -0
- package/dist/project.js.map +1 -1
- package/dist/redact.d.ts +77 -2
- package/dist/redact.js +713 -47
- package/dist/redact.js.map +1 -1
- package/dist/session_targets.d.ts +713 -0
- package/dist/session_targets.js +2602 -0
- package/dist/session_targets.js.map +1 -0
- package/dist/spool.d.ts +23 -5
- package/dist/spool.js +37 -6
- package/dist/spool.js.map +1 -1
- package/dist/spool_union.d.ts +51 -0
- package/dist/spool_union.js +57 -0
- package/dist/spool_union.js.map +1 -0
- package/dist/state.d.ts +5 -0
- package/dist/state.js +19 -1
- package/dist/state.js.map +1 -1
- package/dist/text_tail.d.ts +8 -0
- package/dist/text_tail.js +19 -0
- package/dist/text_tail.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +3 -3
package/dist/machine_state.js
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
* Reads `grants.json` and `projects.json` and, for each per-clone consent, the clone's remote (one `git remote get-url`
|
|
6
6
|
* apiece). Opens no transcript and writes nothing.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { dirname } from "node:path";
|
|
10
|
+
import { EMPTY_GRANTS, normalizeSlug, ownerOfSlug, isLocalSlug, readAccountState, readAllowList, readGrants } from "./consent.js";
|
|
11
|
+
import { folderStandingOf, grantedFolders } from "./folder_grants.js";
|
|
12
|
+
import { resolveProjectKeys } from "./project.js";
|
|
13
|
+
import { readStoppedFolders, readUndecidedNames } from "./session_targets.js";
|
|
9
14
|
import { remoteSlugOfCommonDir } from "./git.js";
|
|
10
15
|
import { PICKER } from "./copy/index.js";
|
|
11
16
|
export function readPerClone(home) {
|
|
@@ -24,25 +29,73 @@ export function machineCapture(home) {
|
|
|
24
29
|
const perClone = readPerClone(home);
|
|
25
30
|
const excluded = new Set(grants.excluded);
|
|
26
31
|
const owners = grants.owners;
|
|
27
|
-
const
|
|
32
|
+
const entries = new Map();
|
|
28
33
|
for (const slug of grants.repos) {
|
|
29
|
-
if (!excluded.has(slug) && !owners.includes(ownerOfSlug(slug)))
|
|
30
|
-
|
|
34
|
+
if (!excluded.has(slug) && !owners.includes(ownerOfSlug(slug))) {
|
|
35
|
+
entries.set(slug, { key: slug, slug, commonDir: null, state: "slug", path: null });
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
38
|
for (const entry of perClone) {
|
|
33
39
|
const slug = entry.slug === null ? null : normalizeSlug(entry.slug);
|
|
34
|
-
if (slug === null || isLocalSlug(slug))
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
if (slug === null || isLocalSlug(slug)) {
|
|
41
|
+
const key = `local:${entry.commonDir}`;
|
|
42
|
+
entries.set(key, {
|
|
43
|
+
key,
|
|
44
|
+
slug: null,
|
|
45
|
+
commonDir: entry.commonDir,
|
|
46
|
+
state: existsSync(entry.commonDir) ? "no-remote" : "missing",
|
|
47
|
+
path: dirname(entry.commonDir),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (!excluded.has(slug) && !owners.includes(ownerOfSlug(slug)) && !entries.has(slug)) {
|
|
51
|
+
entries.set(slug, { key: slug, slug, commonDir: entry.commonDir, state: "slug", path: null });
|
|
52
|
+
}
|
|
38
53
|
}
|
|
39
|
-
|
|
54
|
+
const folders = grantedFolders(home);
|
|
55
|
+
if (owners.length === 0 && entries.size === 0 && folders.length === 0)
|
|
40
56
|
return { kind: "none" };
|
|
41
|
-
return { kind: "on", grants, perClone, owners: owners.length, repos:
|
|
57
|
+
return { kind: "on", grants, perClone, owners: owners.length, repos: entries.size, repoEntries: [...entries.values()], folders };
|
|
42
58
|
}
|
|
43
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* The names `status` lists as "not chosen yet": what the resolver recorded as undecided in the last `sinceMs`, MINUS anything
|
|
61
|
+
* that has been decided since (granted, turned off, declined, or a clone that no longer exists). Names only, read from the target
|
|
62
|
+
* records: no transcript is opened. Re-checked against today's consent, so declining a folder or granting a repo removes it the
|
|
63
|
+
* moment it is done, not when the record ages out (P1, A-T5 review: a declined folder must not read "undecided" forever).
|
|
64
|
+
*/
|
|
65
|
+
export function undecidedNow(home, sinceMs) {
|
|
66
|
+
const read = readGrants(home);
|
|
67
|
+
const grants = read.kind === "ok" ? read.grants : EMPTY_GRANTS;
|
|
68
|
+
const account = readAccountState(home);
|
|
69
|
+
const denied = [grants.excluded, grants.refused, account.refused, account.account?.excluded ?? []];
|
|
70
|
+
const perCloneSlugs = new Set(readPerClone(home).flatMap((c) => (c.slug === null ? [] : [normalizeSlug(c.slug)])));
|
|
71
|
+
const allowed = readAllowList(home);
|
|
72
|
+
const out = [];
|
|
73
|
+
for (const name of readUndecidedNames(home, sinceMs)) {
|
|
74
|
+
if (name.kind === "folder") {
|
|
75
|
+
if (folderStandingOf(home, name.name) === "undecided")
|
|
76
|
+
out.push({ kind: "folder", name: name.name });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (name.name.startsWith("/")) {
|
|
80
|
+
// A repo with no remote is named by its work tree. One that is gone cannot be connected, so it is not offered.
|
|
81
|
+
const keys = resolveProjectKeys(name.name);
|
|
82
|
+
if (keys !== null && !Object.prototype.hasOwnProperty.call(allowed, keys.consent))
|
|
83
|
+
out.push({ kind: "repo", name: name.name });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const slug = normalizeSlug(name.name);
|
|
87
|
+
const decided = denied.some((list) => list.includes(slug)) ||
|
|
88
|
+
grants.repos.includes(slug) ||
|
|
89
|
+
grants.owners.includes(ownerOfSlug(slug)) ||
|
|
90
|
+
perCloneSlugs.has(slug);
|
|
91
|
+
if (!decided)
|
|
92
|
+
out.push({ kind: "repo", name: name.name });
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
/** `1 owner and 2 repos` — or the empty string when nothing is on. A granted folder adds `and 1 folder`. */
|
|
44
97
|
export function machineSummary(capture) {
|
|
45
|
-
return capture.kind === "on" ? PICKER.summary(capture.owners, capture.repos) : "";
|
|
98
|
+
return capture.kind === "on" ? PICKER.summary(capture.owners, capture.repos, capture.folders.length) : "";
|
|
46
99
|
}
|
|
47
100
|
/**
|
|
48
101
|
* Meaningful only for a clone `isCaptureAllowed` admits. An owner grant outranks a repo grant, which outranks a per-clone
|
|
@@ -60,4 +113,14 @@ export function captureBasis(home, slug) {
|
|
|
60
113
|
}
|
|
61
114
|
return { kind: "clone" };
|
|
62
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* The granted folders `status` names as refused: what the target records stopped in the last `sinceMs`, MINUS any folder that is no
|
|
118
|
+
* longer granted (excluded, or removed), so a folder the user has since turned off does not read as refused for ever. A record the
|
|
119
|
+
* drain forgot (DRAIN_FORGET_MS) is not listed either: names only, read from the target records, no transcript is opened.
|
|
120
|
+
*/
|
|
121
|
+
export function refusedFoldersNow(home, sinceMs) {
|
|
122
|
+
return readStoppedFolders(home, sinceMs)
|
|
123
|
+
.filter((stop) => folderStandingOf(home, stop.folder) === "granted")
|
|
124
|
+
.map((stop) => ({ folder: stop.folder, at: stop.at }));
|
|
125
|
+
}
|
|
63
126
|
//# sourceMappingURL=machine_state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"machine_state.js","sourceRoot":"","sources":["../src/machine_state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAe,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"machine_state.js","sourceRoot":"","sources":["../src/machine_state.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth/discovery.js
CHANGED
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
*/
|
|
39
39
|
import { isAllowedIngestUrl } from "../post.js";
|
|
40
40
|
import { CHALLENGE_METHOD } from "./pkce.js";
|
|
41
|
+
import { stripTrailing } from "../text_tail.js";
|
|
41
42
|
/** RFC 9728 §3.1. */
|
|
42
43
|
export const PROTECTED_RESOURCE_PATH = "/.well-known/oauth-protected-resource";
|
|
43
44
|
/** RFC 8414 §3. */
|
|
@@ -115,7 +116,7 @@ export async function discover(resourceUrl, deps) {
|
|
|
115
116
|
if (!isAllowedIngestUrl(issuer)) {
|
|
116
117
|
return { kind: "malformed", url: prmUrl, detail: "insecure_endpoint" };
|
|
117
118
|
}
|
|
118
|
-
const asUrl = `${issuer
|
|
119
|
+
const asUrl = `${stripTrailing(issuer, "/")}${AUTHORIZATION_SERVER_PATH}`;
|
|
119
120
|
const as = await getJson(asUrl, deps);
|
|
120
121
|
if (!as.ok)
|
|
121
122
|
return { kind: "unreachable", url: asUrl };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth/pkce.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* @provenance vibecommit-mcp src/oauth/discovery.ts — `code_challenge_methods_supported`, retyped
|
|
20
20
|
*/
|
|
21
21
|
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
22
|
+
import { stripTrailing } from "../text_tail.js";
|
|
22
23
|
/**
|
|
23
24
|
* The one supported challenge method. Declared `const` so it is a literal type:
|
|
24
25
|
* `method: "S256"` cannot be assigned `"plain"` anywhere downstream.
|
|
@@ -36,7 +37,7 @@ const VERIFIER_BYTES = 32;
|
|
|
36
37
|
const STATE_BYTES = 32;
|
|
37
38
|
/** RFC 4648 §5 base64url, unpadded — the encoding both ends of PKCE use. */
|
|
38
39
|
export function base64url(bytes) {
|
|
39
|
-
return bytes.toString("base64")
|
|
40
|
+
return stripTrailing(bytes.toString("base64"), "=").replace(/\+/g, "-").replace(/\//g, "_");
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
42
43
|
* Mint a fresh verifier and its challenge.
|
package/dist/oauth/pkce.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAe,CAAC;AAGhD;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,+EAA+E;AAC/E,MAAM,WAAW,GAAG,EAAE,CAAC;AAUvB,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC9F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,QAAQ,GAAG,SAAS,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;AACnF,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,SAAiB;IAC7D,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|
package/dist/paths.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ export declare function rootDir(home: string): string;
|
|
|
19
19
|
export declare function credentialsPath(home: string): string;
|
|
20
20
|
/** The per-project consent allow list. Consulted BEFORE any transcript read (D56 §D19). */
|
|
21
21
|
export declare function projectsPath(home: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Folder grants (any-folder capture, R3): a folder whose no-repo sessions may be captured under a `local:folder:` identity.
|
|
24
|
+
* ⛔ A separate file from `projects.json` on purpose: that one is keyed by git common dir and enumerated as clones (`status`,
|
|
25
|
+
* `machine_state`), and a folder in it would be listed as one. Keyed by the folder's REALPATH. Client-side only: never synced,
|
|
26
|
+
* because the server holds no path and never refuses a `local:` slug. Absent file: no folder is granted.
|
|
27
|
+
*/
|
|
28
|
+
export declare function foldersPath(home: string): string;
|
|
22
29
|
/**
|
|
23
30
|
* The slug-keyed grant list — owners, repos, exclusions and refusals. Read next to
|
|
24
31
|
* `projects.json` by `consent.ts`'s `isCaptureAllowed`, BEFORE any transcript read.
|
|
@@ -183,6 +190,27 @@ export declare function sessionStatePath(home: string, key: SessionKey): string
|
|
|
183
190
|
* repo-less bucket, and a caller with no repo has nothing to scan.
|
|
184
191
|
*/
|
|
185
192
|
export declare function repoSessionsDir(home: string, repoKey: string): string | null;
|
|
193
|
+
/**
|
|
194
|
+
* ⛔ The directory that holds per-SESSION state which is not any one repo's: the session's target record
|
|
195
|
+
* (`session_targets.ts`) and the digest → work-tree notes.
|
|
196
|
+
*
|
|
197
|
+
* Under `state/notices/` and NOT beside the repo digests, and not a new `state/` entry, on purpose: two suites pin entry-name
|
|
198
|
+
* sets (`study-contract.test.ts` pins `state/` to `notices` and `sessions`; `agent-registry.test.ts` counts the entries of
|
|
199
|
+
* `state/sessions/` as repo digests, and the study harness binds both). `notices/` is already a mixed namespace
|
|
200
|
+
* (`machine-day`, `machine-epoch`, `clone`, `repo-day`, one directory per session id) that nothing enumerates. None of the
|
|
201
|
+
* files here has a `.json` suffix, so no scan that reads `*.json` can mistake one for a repo's session state.
|
|
202
|
+
*/
|
|
203
|
+
export declare function targetsDir(home: string): string;
|
|
204
|
+
/** Where every repo's `<digest>/` state directory lives. */
|
|
205
|
+
export declare function sessionsRoot(home: string): string;
|
|
206
|
+
/** One session's target record: scan cursors, resolved roots, targets, undecided names. Not a `.json` (see `targetsDir`). */
|
|
207
|
+
export declare function sessionTargetsPath(home: string, sessionId: string): string;
|
|
208
|
+
/** Which work tree a state digest names — written by `spool.ts` when a commit is spooled. Null for no repo key. */
|
|
209
|
+
export declare function repoKeyNotePath(home: string, repoKey: string): string | null;
|
|
210
|
+
/** The digest a work tree's state directory is named by (`repoSessionsDir`). Exposed for the spool-evidence reader. */
|
|
211
|
+
export declare function repoKeyDigest(repoKey: string): string;
|
|
212
|
+
/** The stem every file of one session is named by (`<stem>.json`, `.spool.jsonl`, …). */
|
|
213
|
+
export declare function sessionFileStem(sessionId: string): string;
|
|
186
214
|
/**
|
|
187
215
|
* Where Claude Code writes transcripts.
|
|
188
216
|
*
|
|
@@ -226,7 +254,12 @@ export declare function codexTranscriptRoot(home: string, env: NodeJS.ProcessEnv
|
|
|
226
254
|
* all**. The repository that IS one sits a directory below it, so its project
|
|
227
255
|
* key munges to that workspace's name with the child directory appended — a
|
|
228
256
|
* name with no directory under `projects/` — and a project-key-derived root
|
|
229
|
-
* would refuse the one real transcript there is.
|
|
257
|
+
* would refuse the one real transcript there is. (That is the same shape as the
|
|
258
|
+
* parent-folder sessions any-folder capture now reads: a session launched in a
|
|
259
|
+
* folder above its repos has no single repo whose key could name its transcript's
|
|
260
|
+
* directory. The boundary therefore stays registry-computed and can only refuse;
|
|
261
|
+
* WHICH repos or folder a session's bytes go to is `session_targets`' decision,
|
|
262
|
+
* made after this confinement, never an input to it.)
|
|
230
263
|
*
|
|
231
264
|
* ⇒ ⛔ **The interior shape is enforced by `isCursorTranscript` instead**, which
|
|
232
265
|
* runs AFTER the registry-computed boundary and can only refuse. Read that
|
package/dist/paths.js
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* @provenance vibecommit-schema ingest_sessions.file_key — CHECK bound 1..128, retyped
|
|
15
15
|
*/
|
|
16
16
|
import { createHash } from "node:crypto";
|
|
17
|
-
import { realpathSync } from "node:fs";
|
|
18
17
|
import { join, sep } from "node:path";
|
|
18
|
+
import { physicalPath } from "./physical_path.js";
|
|
19
19
|
/** Root of the client's own state. Never Claude Code's — see the plan's keychain note. */
|
|
20
20
|
export function rootDir(home) {
|
|
21
21
|
return join(home, ".vibecommit");
|
|
@@ -28,6 +28,15 @@ export function credentialsPath(home) {
|
|
|
28
28
|
export function projectsPath(home) {
|
|
29
29
|
return join(rootDir(home), "projects.json");
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Folder grants (any-folder capture, R3): a folder whose no-repo sessions may be captured under a `local:folder:` identity.
|
|
33
|
+
* ⛔ A separate file from `projects.json` on purpose: that one is keyed by git common dir and enumerated as clones (`status`,
|
|
34
|
+
* `machine_state`), and a folder in it would be listed as one. Keyed by the folder's REALPATH. Client-side only: never synced,
|
|
35
|
+
* because the server holds no path and never refuses a `local:` slug. Absent file: no folder is granted.
|
|
36
|
+
*/
|
|
37
|
+
export function foldersPath(home) {
|
|
38
|
+
return join(rootDir(home), "folders.json");
|
|
39
|
+
}
|
|
31
40
|
/**
|
|
32
41
|
* The slug-keyed grant list — owners, repos, exclusions and refusals. Read next to
|
|
33
42
|
* `projects.json` by `consent.ts`'s `isCaptureAllowed`, BEFORE any transcript read.
|
|
@@ -204,6 +213,41 @@ export function repoSessionsDir(home, repoKey) {
|
|
|
204
213
|
return null;
|
|
205
214
|
return join(stateDir(home), "sessions", repoDigest(repoKey));
|
|
206
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* ⛔ The directory that holds per-SESSION state which is not any one repo's: the session's target record
|
|
218
|
+
* (`session_targets.ts`) and the digest → work-tree notes.
|
|
219
|
+
*
|
|
220
|
+
* Under `state/notices/` and NOT beside the repo digests, and not a new `state/` entry, on purpose: two suites pin entry-name
|
|
221
|
+
* sets (`study-contract.test.ts` pins `state/` to `notices` and `sessions`; `agent-registry.test.ts` counts the entries of
|
|
222
|
+
* `state/sessions/` as repo digests, and the study harness binds both). `notices/` is already a mixed namespace
|
|
223
|
+
* (`machine-day`, `machine-epoch`, `clone`, `repo-day`, one directory per session id) that nothing enumerates. None of the
|
|
224
|
+
* files here has a `.json` suffix, so no scan that reads `*.json` can mistake one for a repo's session state.
|
|
225
|
+
*/
|
|
226
|
+
export function targetsDir(home) {
|
|
227
|
+
return join(stateDir(home), "notices", "_session-targets");
|
|
228
|
+
}
|
|
229
|
+
/** Where every repo's `<digest>/` state directory lives. */
|
|
230
|
+
export function sessionsRoot(home) {
|
|
231
|
+
return join(stateDir(home), "sessions");
|
|
232
|
+
}
|
|
233
|
+
/** One session's target record: scan cursors, resolved roots, targets, undecided names. Not a `.json` (see `targetsDir`). */
|
|
234
|
+
export function sessionTargetsPath(home, sessionId) {
|
|
235
|
+
return join(targetsDir(home), `${sanitise(sessionId)}.targets`);
|
|
236
|
+
}
|
|
237
|
+
/** Which work tree a state digest names — written by `spool.ts` when a commit is spooled. Null for no repo key. */
|
|
238
|
+
export function repoKeyNotePath(home, repoKey) {
|
|
239
|
+
if (repoKey === "")
|
|
240
|
+
return null;
|
|
241
|
+
return join(targetsDir(home), `${repoDigest(repoKey)}.repo`);
|
|
242
|
+
}
|
|
243
|
+
/** The digest a work tree's state directory is named by (`repoSessionsDir`). Exposed for the spool-evidence reader. */
|
|
244
|
+
export function repoKeyDigest(repoKey) {
|
|
245
|
+
return repoDigest(repoKey);
|
|
246
|
+
}
|
|
247
|
+
/** The stem every file of one session is named by (`<stem>.json`, `.spool.jsonl`, …). */
|
|
248
|
+
export function sessionFileStem(sessionId) {
|
|
249
|
+
return sanitise(sessionId);
|
|
250
|
+
}
|
|
207
251
|
/** A fixed-length, collision-free filename component for a work-tree path. */
|
|
208
252
|
function repoDigest(repoKey) {
|
|
209
253
|
return createHash("sha256").update(repoKey).digest("hex").slice(0, 32);
|
|
@@ -263,7 +307,12 @@ export function codexTranscriptRoot(home, env) {
|
|
|
263
307
|
* all**. The repository that IS one sits a directory below it, so its project
|
|
264
308
|
* key munges to that workspace's name with the child directory appended — a
|
|
265
309
|
* name with no directory under `projects/` — and a project-key-derived root
|
|
266
|
-
* would refuse the one real transcript there is.
|
|
310
|
+
* would refuse the one real transcript there is. (That is the same shape as the
|
|
311
|
+
* parent-folder sessions any-folder capture now reads: a session launched in a
|
|
312
|
+
* folder above its repos has no single repo whose key could name its transcript's
|
|
313
|
+
* directory. The boundary therefore stays registry-computed and can only refuse;
|
|
314
|
+
* WHICH repos or folder a session's bytes go to is `session_targets`' decision,
|
|
315
|
+
* made after this confinement, never an input to it.)
|
|
267
316
|
*
|
|
268
317
|
* ⇒ ⛔ **The interior shape is enforced by `isCursorTranscript` instead**, which
|
|
269
318
|
* runs AFTER the registry-computed boundary and can only refuse. Read that
|
|
@@ -357,15 +406,11 @@ export function isTranscriptFile(_root, path) {
|
|
|
357
406
|
export function isCursorTranscript(root, path) {
|
|
358
407
|
if (!isInside(root, path))
|
|
359
408
|
return false;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
realPath = realpathSync(path);
|
|
365
|
-
}
|
|
366
|
-
catch {
|
|
409
|
+
// C71 (3): the one resolver.
|
|
410
|
+
const realRoot = physicalPath(root, "fail");
|
|
411
|
+
const realPath = physicalPath(path, "fail");
|
|
412
|
+
if (realRoot === null || realPath === null)
|
|
367
413
|
return false;
|
|
368
|
-
}
|
|
369
414
|
if (!realPath.endsWith(TRANSCRIPT_SUFFIX))
|
|
370
415
|
return false;
|
|
371
416
|
const segments = realPath.slice(realRoot.length + 1).split(sep);
|
|
@@ -491,8 +536,13 @@ export function isInside(root, candidate) {
|
|
|
491
536
|
let realRoot;
|
|
492
537
|
let realCandidate;
|
|
493
538
|
try {
|
|
494
|
-
|
|
495
|
-
|
|
539
|
+
// C70: physical resolution (`..` after a link is the link target's parent), missing = outside, as `realpathSync` threw.
|
|
540
|
+
const rootPath = physicalPath(root, "fail");
|
|
541
|
+
const candidatePath = physicalPath(candidate, "fail");
|
|
542
|
+
if (rootPath === null || candidatePath === null)
|
|
543
|
+
return false;
|
|
544
|
+
realRoot = rootPath;
|
|
545
|
+
realCandidate = candidatePath;
|
|
496
546
|
}
|
|
497
547
|
catch {
|
|
498
548
|
return false;
|
package/dist/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C70: ONE resolver for every path judgement.
|
|
3
|
+
*
|
|
4
|
+
* JavaScript's `realpathSync` runs `path.resolve` FIRST, which collapses `..` lexically: `A/shared/../secret.env`, with `A/shared` a link to `/repos/B/pkg`, is judged
|
|
5
|
+
* `A/secret.env`, while the kernel (and `realpathSync.native`) open `/repos/B/secret.env`. A call that runs in, or writes into, another repository through a link
|
|
6
|
+
* and a `..` was judged as this one. `physicalPath` walks the RAW components forward with a physical cursor, as the kernel does: `.` and empty components are
|
|
7
|
+
* skipped, `..` is the parent of the PHYSICAL cursor, and a component that is a link is replaced by its fully resolved target. Nothing is normalised before it.
|
|
8
|
+
*
|
|
9
|
+
* Fail closed: a component that exists but cannot be resolved (a dangling link, a loop, an unreadable folder) makes the whole path `null`.
|
|
10
|
+
*/
|
|
11
|
+
/** The longest path, in bytes, that is resolved at all: at least the longest the kernel accepts (Linux 4,095 bytes, macOS 1,024), so nothing longer could have been opened. */
|
|
12
|
+
export declare const MAX_PATH_BYTES = 4096;
|
|
13
|
+
/** C74 (3): is this path (as a record wrote it) longer than any path the kernel could have opened? Such a path is unresolvable AT PLACEMENT: it is never stored. */
|
|
14
|
+
export declare function pathTooLong(path: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* `base` + `relative`, the way the kernel reads them: a trailing separator is not doubled and `.` / empty components are dropped, but `..` is KEPT (it is only
|
|
17
|
+
* meaningful after the links before it are resolved, which is `physicalPath`'s job).
|
|
18
|
+
*/
|
|
19
|
+
export declare function joinRaw(base: string, relative: string): string;
|
|
20
|
+
/** Where a walk ended: `path` is the physical cursor (with the `depth` components below the last place that exists appended, lexically). */
|
|
21
|
+
export interface PhysicalWalk {
|
|
22
|
+
readonly path: string;
|
|
23
|
+
/** How many trailing components of `path` do not exist (0: the whole path exists). Not counted: `..` that came back up through them. */
|
|
24
|
+
readonly depth: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The walk behind `physicalPath`. The kernel's own: a component that is a link is replaced, in place, by the components of its target (a relative target is read from
|
|
28
|
+
* the link's own physical parent, an absolute one from the root), so a `..` inside a target is also taken after the links before it. Only `lstat` and `readlink`
|
|
29
|
+
* are used. A link whose target is missing is dangling: `null` (it exists, so it is never "continued past"); so is a loop, a path longer than MAX_PATH_BYTES, and a
|
|
30
|
+
* component `lstat` cannot read (EACCES, ENAMETOOLONG, EIO): the hook cannot tell whether it is a link, so a `..` after it is the same case as a `..` after a link, and
|
|
31
|
+
* when the physical answer cannot be known the rule fails closed (C49 (8)). C72 (1): Claude's `isInside` therefore equals 0.8.0 on every path with no `..` after a link
|
|
32
|
+
* and no `..` after a component that cannot be read; on those paths it WITHHOLDS (over-withholding, never a leak).
|
|
33
|
+
*
|
|
34
|
+
* BELOW the last place that exists nothing can be a link and nothing needs a syscall: a missing component sets `depth` to 1, a name there is appended (depth + 1) and a
|
|
35
|
+
* `..` there takes the parent (depth - 1), all lexically; once `depth` is back at 0 the walk looks at the file system again. So a path with thousands of missing
|
|
36
|
+
* components costs no more than its existing part.
|
|
37
|
+
*/
|
|
38
|
+
export declare function physicalWalk(raw: string): PhysicalWalk | null;
|
|
39
|
+
/**
|
|
40
|
+
* The physical place `raw` names. `missing`: `"extend"` (default) keeps a path whose last components are not there (a file that is to be created; the caller
|
|
41
|
+
* works up to the nearest place that exists); `"fail"`: the whole path must exist (`null` otherwise, as `realpathSync` threw). `..` is taken in both after the links
|
|
42
|
+
* before it. A relative `raw` is read from the working folder.
|
|
43
|
+
*/
|
|
44
|
+
export declare function physicalPath(raw: string, missing?: "extend" | "fail"): string | null;
|
|
45
|
+
/** The nearest place that EXISTS at or above `raw`, physically; `null` for a dangling link or a loop, or when more than `maxMissing` components are missing. */
|
|
46
|
+
export declare function nearestExistingPhysical(raw: string, maxMissing?: number): string | null;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C70: ONE resolver for every path judgement.
|
|
3
|
+
*
|
|
4
|
+
* JavaScript's `realpathSync` runs `path.resolve` FIRST, which collapses `..` lexically: `A/shared/../secret.env`, with `A/shared` a link to `/repos/B/pkg`, is judged
|
|
5
|
+
* `A/secret.env`, while the kernel (and `realpathSync.native`) open `/repos/B/secret.env`. A call that runs in, or writes into, another repository through a link
|
|
6
|
+
* and a `..` was judged as this one. `physicalPath` walks the RAW components forward with a physical cursor, as the kernel does: `.` and empty components are
|
|
7
|
+
* skipped, `..` is the parent of the PHYSICAL cursor, and a component that is a link is replaced by its fully resolved target. Nothing is normalised before it.
|
|
8
|
+
*
|
|
9
|
+
* Fail closed: a component that exists but cannot be resolved (a dangling link, a loop, an unreadable folder) makes the whole path `null`.
|
|
10
|
+
*/
|
|
11
|
+
import { lstatSync, readlinkSync } from "node:fs";
|
|
12
|
+
import { dirname, isAbsolute, parse, sep } from "node:path";
|
|
13
|
+
/** More components than any path the OS accepts (PATH_MAX is 4096): a longer one is not resolved. */
|
|
14
|
+
const MAX_COMPONENTS = 4096;
|
|
15
|
+
/** The longest path, in bytes, that is resolved at all: at least the longest the kernel accepts (Linux 4,095 bytes, macOS 1,024), so nothing longer could have been opened. */
|
|
16
|
+
export const MAX_PATH_BYTES = 4096;
|
|
17
|
+
/** C74 (3): is this path (as a record wrote it) longer than any path the kernel could have opened? Such a path is unresolvable AT PLACEMENT: it is never stored. */
|
|
18
|
+
export function pathTooLong(path) {
|
|
19
|
+
return Buffer.byteLength(path, "utf8") > MAX_PATH_BYTES;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `base` + `relative`, the way the kernel reads them: a trailing separator is not doubled and `.` / empty components are dropped, but `..` is KEPT (it is only
|
|
23
|
+
* meaningful after the links before it are resolved, which is `physicalPath`'s job).
|
|
24
|
+
*/
|
|
25
|
+
export function joinRaw(base, relative) {
|
|
26
|
+
const parts = relative.split("/").filter((part) => part !== "" && part !== ".");
|
|
27
|
+
if (parts.length === 0)
|
|
28
|
+
return base;
|
|
29
|
+
return `${base.endsWith(sep) ? base : base + sep}${parts.join(sep)}`;
|
|
30
|
+
}
|
|
31
|
+
/** The kernel's own limit on links followed while resolving one path (MAXSYMLINKS is 32 on Linux, 40 elsewhere). */
|
|
32
|
+
const MAX_LINKS = 40;
|
|
33
|
+
/**
|
|
34
|
+
* The walk behind `physicalPath`. The kernel's own: a component that is a link is replaced, in place, by the components of its target (a relative target is read from
|
|
35
|
+
* the link's own physical parent, an absolute one from the root), so a `..` inside a target is also taken after the links before it. Only `lstat` and `readlink`
|
|
36
|
+
* are used. A link whose target is missing is dangling: `null` (it exists, so it is never "continued past"); so is a loop, a path longer than MAX_PATH_BYTES, and a
|
|
37
|
+
* component `lstat` cannot read (EACCES, ENAMETOOLONG, EIO): the hook cannot tell whether it is a link, so a `..` after it is the same case as a `..` after a link, and
|
|
38
|
+
* when the physical answer cannot be known the rule fails closed (C49 (8)). C72 (1): Claude's `isInside` therefore equals 0.8.0 on every path with no `..` after a link
|
|
39
|
+
* and no `..` after a component that cannot be read; on those paths it WITHHOLDS (over-withholding, never a leak).
|
|
40
|
+
*
|
|
41
|
+
* BELOW the last place that exists nothing can be a link and nothing needs a syscall: a missing component sets `depth` to 1, a name there is appended (depth + 1) and a
|
|
42
|
+
* `..` there takes the parent (depth - 1), all lexically; once `depth` is back at 0 the walk looks at the file system again. So a path with thousands of missing
|
|
43
|
+
* components costs no more than its existing part.
|
|
44
|
+
*/
|
|
45
|
+
export function physicalWalk(raw) {
|
|
46
|
+
// C72 (2): a bound at least as large as the longest path the kernel accepts (Linux PATH_MAX counts the NUL, so 4,095 bytes; macOS 1,024): a longer path is refused with
|
|
47
|
+
// ENAMETOOLONG before any lookup, so nothing could have been opened through it. Checked before any split, so one crafted line cannot cost more than 4,096 bytes of
|
|
48
|
+
// walking (below a missing component the walk is a growing string). The absolute half rests on the agents handing the kernel the cwd-joined form (Codex joins first,
|
|
49
|
+
// mirrored by codex_folders.ts `joinRaw`; Claude's paths are absolute): a tool that passed a long relative string itself would be over-withheld, never leaked.
|
|
50
|
+
if (pathTooLong(raw))
|
|
51
|
+
return null;
|
|
52
|
+
const absolute = isAbsolute(raw) ? raw : joinRaw(process.cwd(), raw);
|
|
53
|
+
if (pathTooLong(absolute))
|
|
54
|
+
return null;
|
|
55
|
+
const root = parse(absolute).root;
|
|
56
|
+
const pending = [];
|
|
57
|
+
const parts = absolute.slice(root.length).split(sep);
|
|
58
|
+
if (parts.length > MAX_COMPONENTS)
|
|
59
|
+
return null;
|
|
60
|
+
for (let i = parts.length - 1; i >= 0; i -= 1)
|
|
61
|
+
pending.push({ part: parts[i], viaLink: false });
|
|
62
|
+
let current = root;
|
|
63
|
+
let depth = 0;
|
|
64
|
+
let links = 0;
|
|
65
|
+
let steps = 0;
|
|
66
|
+
for (let item = pending.pop(); item !== undefined; item = pending.pop()) {
|
|
67
|
+
steps += 1;
|
|
68
|
+
if (steps > 4 * MAX_COMPONENTS)
|
|
69
|
+
return null;
|
|
70
|
+
const { part, viaLink } = item;
|
|
71
|
+
if (part === "" || part === ".")
|
|
72
|
+
continue;
|
|
73
|
+
if (part === "..") {
|
|
74
|
+
current = dirname(current);
|
|
75
|
+
if (depth > 0)
|
|
76
|
+
depth -= 1;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const next = current.endsWith(sep) ? current + part : current + sep + part;
|
|
80
|
+
if (depth > 0) {
|
|
81
|
+
current = next;
|
|
82
|
+
depth += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
let isLink;
|
|
86
|
+
try {
|
|
87
|
+
isLink = lstatSync(next).isSymbolicLink();
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const code = error.code;
|
|
91
|
+
if (code !== "ENOENT" && code !== "ENOTDIR")
|
|
92
|
+
return null;
|
|
93
|
+
// A component the target of a link names that is not there makes the link dangling: it exists, so it is never continued past.
|
|
94
|
+
if (viaLink)
|
|
95
|
+
return null;
|
|
96
|
+
current = next;
|
|
97
|
+
depth = 1;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (!isLink) {
|
|
101
|
+
current = next;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
links += 1;
|
|
105
|
+
if (links > MAX_LINKS)
|
|
106
|
+
return null;
|
|
107
|
+
let target;
|
|
108
|
+
try {
|
|
109
|
+
target = readlinkSync(next);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
if (target === "")
|
|
115
|
+
return null;
|
|
116
|
+
let rest = target;
|
|
117
|
+
if (isAbsolute(target)) {
|
|
118
|
+
const targetRoot = parse(target).root;
|
|
119
|
+
current = targetRoot;
|
|
120
|
+
rest = target.slice(targetRoot.length);
|
|
121
|
+
}
|
|
122
|
+
const targetParts = rest.split(sep);
|
|
123
|
+
if (pending.length + targetParts.length > 4 * MAX_COMPONENTS)
|
|
124
|
+
return null;
|
|
125
|
+
for (let i = targetParts.length - 1; i >= 0; i -= 1)
|
|
126
|
+
pending.push({ part: targetParts[i], viaLink: true });
|
|
127
|
+
}
|
|
128
|
+
return { path: current, depth };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The physical place `raw` names. `missing`: `"extend"` (default) keeps a path whose last components are not there (a file that is to be created; the caller
|
|
132
|
+
* works up to the nearest place that exists); `"fail"`: the whole path must exist (`null` otherwise, as `realpathSync` threw). `..` is taken in both after the links
|
|
133
|
+
* before it. A relative `raw` is read from the working folder.
|
|
134
|
+
*/
|
|
135
|
+
export function physicalPath(raw, missing = "extend") {
|
|
136
|
+
const walk = physicalWalk(raw);
|
|
137
|
+
if (walk === null)
|
|
138
|
+
return null;
|
|
139
|
+
return missing === "fail" && walk.depth > 0 ? null : walk.path;
|
|
140
|
+
}
|
|
141
|
+
/** The nearest place that EXISTS at or above `raw`, physically; `null` for a dangling link or a loop, or when more than `maxMissing` components are missing. */
|
|
142
|
+
export function nearestExistingPhysical(raw, maxMissing = 64) {
|
|
143
|
+
const walk = physicalWalk(raw);
|
|
144
|
+
if (walk === null || walk.depth > maxMissing)
|
|
145
|
+
return null;
|
|
146
|
+
let current = walk.path;
|
|
147
|
+
for (let i = 0; i < walk.depth; i += 1)
|
|
148
|
+
current = dirname(current);
|
|
149
|
+
return current;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=physical_path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"physical_path.js","sourceRoot":"","sources":["../src/physical_path.ts"],"names":[],"mappings":"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"}
|