@vibe-agent-toolkit/utils 0.1.41-rc.7 → 0.1.41

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.
@@ -58,6 +58,8 @@ export declare class GitTracker {
58
58
  private readonly activeAncestors;
59
59
  private initialized;
60
60
  private activeSetPopulated;
61
+ /** Whether `git ls-files` actually answered during {@link initialize}. */
62
+ private gitAnswered;
61
63
  constructor(projectRoot: string);
62
64
  /**
63
65
  * Initialize the tracker by pre-populating cache from git ls-files.
@@ -72,6 +74,21 @@ export declare class GitTracker {
72
74
  * `git check-ignore` via {@link isIgnored}.
73
75
  */
74
76
  initialize(options?: GitTrackerInitOptions): Promise<void>;
77
+ /**
78
+ * Did git actually answer, or is this tracker an empty shell?
79
+ *
80
+ * `gitLsFiles` returns `null` for every way asking can fail — no `git` on
81
+ * `PATH`, a corrupt `.git`, an unreadable `.git`, a non-repository cwd — and
82
+ * that `null` is otherwise indistinguishable here from "git answered, and the
83
+ * repository is empty": both leave the active set with zero entries, after
84
+ * which {@link isIgnoredByActiveSet} reports every path as NOT ignored.
85
+ *
86
+ * For a walker that is fine — unfiltered is the safe default. For a caller that
87
+ * INFERS something from "not ignored" (provenance, publication, leakage) it is
88
+ * not: the inference silently becomes a fixed answer. Such callers must ask
89
+ * this first and treat `false` as "no answer available", never as a verdict.
90
+ */
91
+ isUsable(): boolean;
75
92
  /**
76
93
  * Walk up from each active-set file's directory and record every ancestor up to projectRoot.
77
94
  *
@@ -97,9 +114,21 @@ export declare class GitTracker {
97
114
  /**
98
115
  * Fast O(1) ignore check against the pre-populated active set.
99
116
  *
100
- * For paths INSIDE the project root, membership in the active set is
101
- * authoritative: a path is ignored iff it is not in the active set AND not
102
- * an ancestor of any active-set path. No `git check-ignore` spawn.
117
+ * For paths INSIDE the project root **that exist on disk**, membership in the
118
+ * active set is authoritative: such a path is ignored iff it is not in the
119
+ * active set AND not an ancestor of any active-set path. No `git
120
+ * check-ignore` spawn.
121
+ *
122
+ * The existence qualifier is load-bearing, not a caveat. The active set is
123
+ * built from `git ls-files`, so it can only ever contain paths that EXIST — a
124
+ * path that does not exist is trivially absent from it, and a bare set lookup
125
+ * would call every typo'd or never-built path "ignored". Callers acted on
126
+ * that: a broken markdown link was reported as a gitignored-data leak rather
127
+ * than a broken link. Such paths therefore fall back to {@link isIgnored},
128
+ * i.e. `git check-ignore`, which answers from the ignore PATTERNS and is
129
+ * correct for a path that is merely named (`dist/out.js` under an ignored
130
+ * `dist/` is ignored; `docs/typo.md` is not). The fallback result is cached,
131
+ * so a repeated miss on the same path stays O(1).
103
132
  *
104
133
  * For paths OUTSIDE the project root, falls back to {@link isIgnored} so
105
134
  * legacy behavior is preserved.
@@ -1 +1 @@
1
- {"version":3,"file":"git-tracker.d.ts","sourceRoot":"","sources":["../src/git-tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,kBAAkB,CAAS;gBAEvB,WAAW,EAAE,MAAM;IAK/B;;;;;;;;;;;OAWG;IACG,UAAU,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBhE;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;;;;;;;;OAWG;IACH,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAQlD;;;;;;;;;;;;;;;;OAgBG;IACH,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAenD,OAAO,CAAC,mBAAmB;IAQ3B;;;;;;;OAOG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAqBpC;;OAEG;IACH,QAAQ,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE;IAQrF;;OAEG;IACH,KAAK,IAAI,IAAI;CAOd"}
1
+ {"version":3,"file":"git-tracker.d.ts","sourceRoot":"","sources":["../src/git-tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0B;IAC1D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,kBAAkB,CAAS;IACnC,0EAA0E;IAC1E,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAK/B;;;;;;;;;;;OAWG;IACG,UAAU,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BhE;;;;;;;;;;;;;OAaG;IACH,QAAQ,IAAI,OAAO;IAInB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;;;;;;;;OAWG;IACH,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAQlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IA0BnD,OAAO,CAAC,mBAAmB;IAQ3B;;;;;;;OAOG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAqBpC;;OAEG;IACH,QAAQ,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAA;KAAE;IAQrF;;OAEG;IACH,KAAK,IAAI,IAAI;CAQd"}
@@ -4,6 +4,7 @@
4
4
  * Problem: Calling git check-ignore on every file is expensive (spawns process each time).
5
5
  * Solution: Cache results and pre-populate with git ls-files (tracked + untracked non-ignored).
6
6
  */
7
+ import { existsSync } from 'node:fs';
7
8
  import { dirname } from 'node:path';
8
9
  import { gitLsFiles, isGitIgnored } from './git-utils.js';
9
10
  import { safePath, toForwardSlash } from './path-utils.js';
@@ -43,6 +44,8 @@ export class GitTracker {
43
44
  activeAncestors = new Set();
44
45
  initialized = false;
45
46
  activeSetPopulated = false;
47
+ /** Whether `git ls-files` actually answered during {@link initialize}. */
48
+ gitAnswered = false;
46
49
  constructor(projectRoot) {
47
50
  this.projectRoot = projectRoot;
48
51
  this.normalizedProjectRoot = safePath.resolve(projectRoot);
@@ -76,9 +79,27 @@ export class GitTracker {
76
79
  }
77
80
  this.populateAncestorSet();
78
81
  }
82
+ this.gitAnswered = files !== null;
79
83
  this.activeSetPopulated = includeUntracked && files !== null;
80
84
  this.initialized = true;
81
85
  }
86
+ /**
87
+ * Did git actually answer, or is this tracker an empty shell?
88
+ *
89
+ * `gitLsFiles` returns `null` for every way asking can fail — no `git` on
90
+ * `PATH`, a corrupt `.git`, an unreadable `.git`, a non-repository cwd — and
91
+ * that `null` is otherwise indistinguishable here from "git answered, and the
92
+ * repository is empty": both leave the active set with zero entries, after
93
+ * which {@link isIgnoredByActiveSet} reports every path as NOT ignored.
94
+ *
95
+ * For a walker that is fine — unfiltered is the safe default. For a caller that
96
+ * INFERS something from "not ignored" (provenance, publication, leakage) it is
97
+ * not: the inference silently becomes a fixed answer. Such callers must ask
98
+ * this first and treat `false` as "no answer available", never as a verdict.
99
+ */
100
+ isUsable() {
101
+ return this.gitAnswered;
102
+ }
82
103
  /**
83
104
  * Walk up from each active-set file's directory and record every ancestor up to projectRoot.
84
105
  *
@@ -129,9 +150,21 @@ export class GitTracker {
129
150
  /**
130
151
  * Fast O(1) ignore check against the pre-populated active set.
131
152
  *
132
- * For paths INSIDE the project root, membership in the active set is
133
- * authoritative: a path is ignored iff it is not in the active set AND not
134
- * an ancestor of any active-set path. No `git check-ignore` spawn.
153
+ * For paths INSIDE the project root **that exist on disk**, membership in the
154
+ * active set is authoritative: such a path is ignored iff it is not in the
155
+ * active set AND not an ancestor of any active-set path. No `git
156
+ * check-ignore` spawn.
157
+ *
158
+ * The existence qualifier is load-bearing, not a caveat. The active set is
159
+ * built from `git ls-files`, so it can only ever contain paths that EXIST — a
160
+ * path that does not exist is trivially absent from it, and a bare set lookup
161
+ * would call every typo'd or never-built path "ignored". Callers acted on
162
+ * that: a broken markdown link was reported as a gitignored-data leak rather
163
+ * than a broken link. Such paths therefore fall back to {@link isIgnored},
164
+ * i.e. `git check-ignore`, which answers from the ignore PATTERNS and is
165
+ * correct for a path that is merely named (`dist/out.js` under an ignored
166
+ * `dist/` is ignored; `docs/typo.md` is not). The fallback result is cached,
167
+ * so a repeated miss on the same path stays O(1).
135
168
  *
136
169
  * For paths OUTSIDE the project root, falls back to {@link isIgnored} so
137
170
  * legacy behavior is preserved.
@@ -152,7 +185,16 @@ export class GitTracker {
152
185
  if (!this.isWithinProjectRoot(normalized)) {
153
186
  return this.isIgnored(absolutePath);
154
187
  }
155
- return !(this.activeSet.has(normalized) || this.activeAncestors.has(normalized));
188
+ if (this.activeSet.has(normalized) || this.activeAncestors.has(normalized)) {
189
+ return false;
190
+ }
191
+ // Absent from the active set. That means "ignored" only for a path that is
192
+ // actually there; otherwise the set has no opinion and git must be asked.
193
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- caller-supplied path, read-only existence probe
194
+ if (!existsSync(normalized)) {
195
+ return this.isIgnored(absolutePath);
196
+ }
197
+ return true;
156
198
  }
157
199
  isWithinProjectRoot(normalizedAbsolutePath) {
158
200
  const root = this.normalizedProjectRoot;
@@ -205,6 +247,7 @@ export class GitTracker {
205
247
  this.activeAncestors.clear();
206
248
  this.initialized = false;
207
249
  this.activeSetPopulated = false;
250
+ this.gitAnswered = false;
208
251
  }
209
252
  }
210
253
  //# sourceMappingURL=git-tracker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-tracker.js","sourceRoot":"","sources":["../src/git-tracker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git-tracker.js","sourceRoot":"","sources":["../src/git-tracker.ts"],"names":[],"mappings":"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"}
package/dist/git-url.d.ts CHANGED
@@ -6,11 +6,34 @@
6
6
  * - `ref` is an optional branch or tag name (deep commit SHAs are not
7
7
  * guaranteed to work with shallow clone — see design spec for details).
8
8
  * - `subpath` is an optional subdirectory within the cloned repo to audit.
9
+ * - `inferredFromShorthand` records whether `cloneUrl` was *inferred* from bare
10
+ * `owner/repo` shorthand rather than supplied verbatim by the user.
9
11
  */
10
12
  export interface ParsedGitUrl {
11
13
  cloneUrl: string;
12
14
  ref?: string;
13
15
  subpath?: string;
16
+ /**
17
+ * True when `cloneUrl` was synthesized from bare GitHub shorthand
18
+ * (`owner/repo`), false when the user typed a URL we pass through.
19
+ *
20
+ * This has to travel with the value: an expanded shorthand URL is
21
+ * byte-identical to a hand-typed one, so a consumer cannot recover the
22
+ * distinction by inspecting `cloneUrl`. Consumers need it because the two
23
+ * cases warrant opposite credential policies — see
24
+ * {@link nonInteractiveGitOverrides}.
25
+ */
26
+ inferredFromShorthand: boolean;
27
+ }
28
+ /**
29
+ * Environment and `git -c` overrides that make a clone non-interactive.
30
+ * Both collections are empty when no override is warranted.
31
+ */
32
+ export interface NonInteractiveGitOverrides {
33
+ /** Overlay to merge over `process.env` when spawning git. */
34
+ env: Record<string, string>;
35
+ /** `git -c <name>=<value>` arguments to place *before* the subcommand. */
36
+ configArgs: string[];
14
37
  }
15
38
  /**
16
39
  * Parse a string into a {@link ParsedGitUrl}.
@@ -27,6 +50,43 @@ export interface ParsedGitUrl {
27
50
  * Throws on malformed input.
28
51
  */
29
52
  export declare function parseGitUrl(input: string): ParsedGitUrl;
53
+ /**
54
+ * Credential-prompt overrides for cloning `parsed`.
55
+ *
56
+ * **Only inferred shorthand gets them.** A user who typed a full
57
+ * `https://…` URL for a private repo may legitimately intend to authenticate
58
+ * interactively, and silently disabling that would break a real workflow. A
59
+ * user who typed `owner/repo` and got it wrong should fail in milliseconds
60
+ * instead of sitting on a credential prompt for a minute.
61
+ *
62
+ * Why this exact set (verified against git 2.50.1 with `git credential fill`):
63
+ *
64
+ * - `GIT_TERMINAL_PROMPT=0` — suppresses git's own TTY prompt. On its own it is
65
+ * **not** sufficient: `gitcredentials(7)` consults `GIT_ASKPASS`, then
66
+ * `core.askPass`, then `SSH_ASKPASS`, and only prompts on the terminal if all
67
+ * three are unset. Each askpass hook therefore bypasses this flag entirely —
68
+ * which is exactly the case inside VS Code's integrated terminal, where
69
+ * `GIT_ASKPASS` points at a GUI prompt.
70
+ * - `GIT_ASKPASS=''` — `getenv()` returns a non-NULL empty string, so git stops
71
+ * walking the askpass chain *and* runs nothing, masking `core.askPass` and
72
+ * `SSH_ASKPASS` in one move.
73
+ * - `SSH_ASKPASS=''` and `-c core.askPass=` — belt and braces for the same
74
+ * chain, because an empty-valued environment variable is not reliably
75
+ * distinguishable from an unset one on Windows. `-c` is used rather than
76
+ * `GIT_CONFIG_*` precisely because `-c` is additive: writing
77
+ * `GIT_CONFIG_COUNT` would silently clobber an overlay the caller supplied
78
+ * (VAT's own tests use `GIT_CONFIG_*` to rewrite remotes via `insteadOf`).
79
+ * - `GCM_INTERACTIVE=never` — git's flags cannot reach a credential *helper*
80
+ * that opens its own UI. Git Credential Manager (the default on Git for
81
+ * Windows) is the common one; `never` still lets it serve a cached
82
+ * credential, it only forbids escalating to a prompt.
83
+ *
84
+ * What is deliberately **not** here: nothing resets `credential.helper` and
85
+ * nothing sets `GIT_CONFIG_NOSYSTEM`. A helper holding a valid token is how a
86
+ * private repo typed as shorthand still clones successfully; the goal is to
87
+ * forbid *interaction*, not authentication.
88
+ */
89
+ export declare function nonInteractiveGitOverrides(parsed: ParsedGitUrl): NonInteractiveGitOverrides;
30
90
  /**
31
91
  * Detect whether a string should be treated as a git URL (for the polymorphic
32
92
  * `[git-url-or-path]` audit argument). True for:
@@ -1 +1 @@
1
- {"version":3,"file":"git-url.d.ts","sourceRoot":"","sources":["../src/git-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAgEvD;AASD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAmB/C"}
1
+ {"version":3,"file":"git-url.d.ts","sourceRoot":"","sources":["../src/git-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;OASG;IACH,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,6DAA6D;IAC7D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAyBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAuEvD;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,YAAY,GAAG,0BAA0B,CAa3F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAmB/C"}
package/dist/git-url.js CHANGED
@@ -44,13 +44,13 @@ export function parseGitUrl(input) {
44
44
  // file:// natively.
45
45
  if (trimmed.startsWith('file://')) {
46
46
  const { base, ref, subpath } = splitFragment(trimmed);
47
- return buildParsed(base, ref, subpath);
47
+ return buildParsed(base, ref, subpath, false);
48
48
  }
49
49
  // HTTPS .git form: https://host/path.git[#ref[:subpath]]
50
50
  if (/^https?:\/\//.test(trimmed)) {
51
51
  const { base, ref, subpath } = splitFragment(trimmed);
52
52
  if (base.endsWith('.git')) {
53
- return buildParsed(base, ref, subpath);
53
+ return buildParsed(base, ref, subpath, false);
54
54
  }
55
55
  // GitHub web URL: https://github.com/owner/repo/tree/<ref>[/<subpath>]
56
56
  const ghWeb =
@@ -61,41 +61,98 @@ export function parseGitUrl(input) {
61
61
  const repo = ghWeb[2] ?? '';
62
62
  const webRef = ghWeb[3];
63
63
  const webSubpath = ghWeb[4];
64
- return buildParsed(`https://github.com/${owner}/${repo}.git`, webRef, webSubpath);
64
+ // A GitHub web URL is still something the user typed in full — only bare
65
+ // `owner/repo` counts as inferred.
66
+ return buildParsed(`https://github.com/${owner}/${repo}.git`, webRef, webSubpath, false);
65
67
  }
66
68
  }
67
69
  // SSH ssh:// form: ssh://git@host/path[#ref[:subpath]]
68
70
  if (trimmed.startsWith('ssh://')) {
69
71
  const { base, ref, subpath } = splitFragment(trimmed);
70
- return buildParsed(base, ref, subpath);
72
+ return buildParsed(base, ref, subpath, false);
71
73
  }
72
74
  // SSH scp-like form: git@host:owner/repo.git[#ref[:subpath]]
73
75
  // Anchored, no alternation with nested quantifiers — safe from ReDoS.
74
76
  if (/^[^@\s]+@[^:\s]+:[^#\s]+/.test(trimmed)) {
75
77
  const { base, ref, subpath } = splitFragment(trimmed);
76
- return buildParsed(base, ref, subpath);
78
+ return buildParsed(base, ref, subpath, false);
77
79
  }
78
- // GitHub shorthand: owner/repo[#ref[:subpath]] (single slash in base)
80
+ // GitHub shorthand: owner/repo[#ref[:subpath]] (single slash in base).
81
+ // NOTE: this pattern is deliberately a superset of the stricter one in
82
+ // `isGitUrl` (it also admits `.` inside a segment). `isGitUrl` gates every
83
+ // call site, so it is the effective definition of "shorthand" in practice;
84
+ // the two must stay in the isGitUrl ⊆ parseGitUrl direction, or an input
85
+ // routed here as a URL would fall through to the "Invalid git URL" throw.
79
86
  const { base, ref, subpath } = splitFragment(trimmed);
80
87
  const shorthand = /^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/.exec(base);
81
88
  if (shorthand) {
82
89
  const owner = shorthand[1] ?? '';
83
90
  const repo = shorthand[2] ?? '';
84
- return buildParsed(`https://github.com/${owner}/${repo}.git`, ref, subpath);
91
+ return buildParsed(`https://github.com/${owner}/${repo}.git`, ref, subpath, true);
85
92
  }
86
93
  throw new Error(`Invalid git URL or path: ${input}. Accepted forms: ` +
87
94
  `https://<host>/<owner>/<repo>.git, ` +
88
95
  `git@<host>:<owner>/<repo>.git, ` +
89
96
  `<owner>/<repo>, or a local filesystem path.`);
90
97
  }
91
- function buildParsed(cloneUrl, ref, subpath) {
92
- const result = { cloneUrl };
98
+ function buildParsed(cloneUrl, ref, subpath, inferredFromShorthand) {
99
+ const result = { cloneUrl, inferredFromShorthand };
93
100
  if (ref !== undefined && ref !== '')
94
101
  result.ref = ref;
95
102
  if (subpath !== undefined && subpath !== '')
96
103
  result.subpath = subpath;
97
104
  return result;
98
105
  }
106
+ /**
107
+ * Credential-prompt overrides for cloning `parsed`.
108
+ *
109
+ * **Only inferred shorthand gets them.** A user who typed a full
110
+ * `https://…` URL for a private repo may legitimately intend to authenticate
111
+ * interactively, and silently disabling that would break a real workflow. A
112
+ * user who typed `owner/repo` and got it wrong should fail in milliseconds
113
+ * instead of sitting on a credential prompt for a minute.
114
+ *
115
+ * Why this exact set (verified against git 2.50.1 with `git credential fill`):
116
+ *
117
+ * - `GIT_TERMINAL_PROMPT=0` — suppresses git's own TTY prompt. On its own it is
118
+ * **not** sufficient: `gitcredentials(7)` consults `GIT_ASKPASS`, then
119
+ * `core.askPass`, then `SSH_ASKPASS`, and only prompts on the terminal if all
120
+ * three are unset. Each askpass hook therefore bypasses this flag entirely —
121
+ * which is exactly the case inside VS Code's integrated terminal, where
122
+ * `GIT_ASKPASS` points at a GUI prompt.
123
+ * - `GIT_ASKPASS=''` — `getenv()` returns a non-NULL empty string, so git stops
124
+ * walking the askpass chain *and* runs nothing, masking `core.askPass` and
125
+ * `SSH_ASKPASS` in one move.
126
+ * - `SSH_ASKPASS=''` and `-c core.askPass=` — belt and braces for the same
127
+ * chain, because an empty-valued environment variable is not reliably
128
+ * distinguishable from an unset one on Windows. `-c` is used rather than
129
+ * `GIT_CONFIG_*` precisely because `-c` is additive: writing
130
+ * `GIT_CONFIG_COUNT` would silently clobber an overlay the caller supplied
131
+ * (VAT's own tests use `GIT_CONFIG_*` to rewrite remotes via `insteadOf`).
132
+ * - `GCM_INTERACTIVE=never` — git's flags cannot reach a credential *helper*
133
+ * that opens its own UI. Git Credential Manager (the default on Git for
134
+ * Windows) is the common one; `never` still lets it serve a cached
135
+ * credential, it only forbids escalating to a prompt.
136
+ *
137
+ * What is deliberately **not** here: nothing resets `credential.helper` and
138
+ * nothing sets `GIT_CONFIG_NOSYSTEM`. A helper holding a valid token is how a
139
+ * private repo typed as shorthand still clones successfully; the goal is to
140
+ * forbid *interaction*, not authentication.
141
+ */
142
+ export function nonInteractiveGitOverrides(parsed) {
143
+ if (!parsed.inferredFromShorthand) {
144
+ return { env: {}, configArgs: [] };
145
+ }
146
+ return {
147
+ env: {
148
+ GIT_TERMINAL_PROMPT: '0',
149
+ GIT_ASKPASS: '',
150
+ SSH_ASKPASS: '',
151
+ GCM_INTERACTIVE: 'never',
152
+ },
153
+ configArgs: ['-c', 'core.askPass='],
154
+ };
155
+ }
99
156
  /**
100
157
  * Detect whether a string should be treated as a git URL (for the polymorphic
101
158
  * `[git-url-or-path]` audit argument). True for:
@@ -1 +1 @@
1
- {"version":3,"file":"git-url.js","sourceRoot":"","sources":["../src/git-url.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git-url.js","sourceRoot":"","sources":["../src/git-url.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from './safe-exec.js';
8
8
  export * from './windows-shell.js';
9
9
  export * from './spawn-hardened.js';
10
10
  export * from './path-utils.js';
11
+ export * from './stdio-blocking.js';
11
12
  export * from './asset-reference.js';
12
13
  export * from './fs-utils.js';
13
14
  export * from './file-crawler.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,eAAe,CAAC;AAG9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAI/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,eAAe,CAAC;AAG9B,cAAc,oBAAoB,CAAC;AAInC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAG7E,cAAc,uBAAuB,CAAC;AAGtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,eAAe,CAAC;AAG9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAI/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,eAAe,CAAC;AAG9B,cAAc,oBAAoB,CAAC;AAInC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAG7E,cAAc,uBAAuB,CAAC;AAGtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -12,6 +12,8 @@ export * from './windows-shell.js';
12
12
  export * from './spawn-hardened.js';
13
13
  // Cross-platform path utilities
14
14
  export * from './path-utils.js';
15
+ // Blocking stdio for published bins (process.exit must not truncate output)
16
+ export * from './stdio-blocking.js';
15
17
  // Asset reference resolution (paths + npm bare specifiers)
16
18
  export * from './asset-reference.js';
17
19
  // Filesystem utilities
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8DAA8D;AAC9D,cAAc,gBAAgB,CAAC;AAE/B,4FAA4F;AAC5F,cAAc,oBAAoB,CAAC;AAEnC,+EAA+E;AAC/E,cAAc,qBAAqB,CAAC;AAEpC,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,2DAA2D;AAC3D,cAAc,sBAAsB,CAAC;AAErC,uBAAuB;AACvB,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,cAAc,wBAAwB,CAAC;AAEvC,uEAAuE;AACvE,cAAc,cAAc,CAAC;AAE7B,8CAA8C;AAC9C,cAAc,gBAAgB,CAAC;AAE/B,2DAA2D;AAC3D,iEAAiE;AACjE,cAAc,oBAAoB,CAAC;AAEnC,yDAAyD;AACzD,cAAc,kBAAkB,CAAC;AAEjC,oDAAoD;AACpD,cAAc,mBAAmB,CAAC;AAElC,4CAA4C;AAC5C,cAAc,wBAAwB,CAAC;AAEvC,2DAA2D;AAC3D,cAAc,eAAe,CAAC;AAE9B,oEAAoE;AACpE,cAAc,oBAAoB,CAAC;AAEnC,uDAAuD;AACvD,uEAAuE;AACvE,OAAO,EAKL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,2EAA2E;AAC3E,cAAc,uBAAuB,CAAC;AAEtC,oEAAoE;AACpE,cAAc,wBAAwB,CAAC;AAEvC,gDAAgD;AAChD,cAAc,mBAAmB,CAAC;AAElC,8EAA8E;AAC9E,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8DAA8D;AAC9D,cAAc,gBAAgB,CAAC;AAE/B,4FAA4F;AAC5F,cAAc,oBAAoB,CAAC;AAEnC,+EAA+E;AAC/E,cAAc,qBAAqB,CAAC;AAEpC,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,4EAA4E;AAC5E,cAAc,qBAAqB,CAAC;AAEpC,2DAA2D;AAC3D,cAAc,sBAAsB,CAAC;AAErC,uBAAuB;AACvB,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,cAAc,wBAAwB,CAAC;AAEvC,uEAAuE;AACvE,cAAc,cAAc,CAAC;AAE7B,8CAA8C;AAC9C,cAAc,gBAAgB,CAAC;AAE/B,2DAA2D;AAC3D,iEAAiE;AACjE,cAAc,oBAAoB,CAAC;AAEnC,yDAAyD;AACzD,cAAc,kBAAkB,CAAC;AAEjC,oDAAoD;AACpD,cAAc,mBAAmB,CAAC;AAElC,4CAA4C;AAC5C,cAAc,wBAAwB,CAAC;AAEvC,2DAA2D;AAC3D,cAAc,eAAe,CAAC;AAE9B,oEAAoE;AACpE,cAAc,oBAAoB,CAAC;AAEnC,uDAAuD;AACvD,uEAAuE;AACvE,OAAO,EAKL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,2EAA2E;AAC3E,cAAc,uBAAuB,CAAC;AAEtC,oEAAoE;AACpE,cAAc,wBAAwB,CAAC;AAEvC,gDAAgD;AAChD,cAAc,mBAAmB,CAAC;AAElC,8EAA8E;AAC9E,cAAc,yBAAyB,CAAC"}
package/dist/process.d.ts CHANGED
@@ -6,5 +6,6 @@
6
6
  * the linkAuth, git, skill-testing, or macro-expansion machinery from the
7
7
  * full `"."` barrel.
8
8
  */
9
+ export { type StdioBlockingResult, makeStdioBlocking, describeStdioBlocking, } from './stdio-blocking.js';
9
10
  export { type SafeExecOptions, type SafeExecResult, CommandExecutionError, safeExecSync, safeExecResult, isToolAvailable, getToolVersion, hasShellSyntax, safeExecFromString, } from './safe-exec.js';
10
11
  //# sourceMappingURL=process.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
package/dist/process.js CHANGED
@@ -6,5 +6,6 @@
6
6
  * the linkAuth, git, skill-testing, or macro-expansion machinery from the
7
7
  * full `"."` barrel.
8
8
  */
9
+ export { makeStdioBlocking, describeStdioBlocking, } from './stdio-blocking.js';
9
10
  export { CommandExecutionError, safeExecSync, safeExecResult, isToolAvailable, getToolVersion, hasShellSyntax, safeExecFromString, } from './safe-exec.js';
10
11
  //# sourceMappingURL=process.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAGL,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAGL,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
@@ -19,19 +19,47 @@ interface SkillTargetPaths {
19
19
  /**
20
20
  * Target → {userRel, projectRel} lookup table.
21
21
  *
22
- * @vendor-claim reviewed=2026-04-08 verify=Each of the seven platforms' own published docs for where it reads skills from (claude, codex, copilot, gemini, cursor, windsurf, agents)
23
- *
24
- * Last reviewed against vendor conventions 2026-04-08. Update this table when
25
- * platforms change theirs — and re-check the vendor's own documentation when you
26
- * do, because nothing here is verified at build or test time: the tests below
27
- * assert the table's *shape*, never that a path is where a platform actually
28
- * looks. A stale entry installs a skill somewhere the target never reads, and
29
- * every check still passes.
30
- *
31
- * (This previously cited docs/plans/2026-04-08-agent-skills-ecosystem-analysis.md
32
- * as its justification. That file is not in the repository`docs/plans/` is not
33
- * tracked so the citation could not be followed. Recording the review date and
34
- * the verification gap is honest; pointing at an unreachable document was not.)
22
+ * @vendor-claim reviewed=2026-07-30 verify=Each of the seven platforms' own published docs for where it reads skills from (claude, codex, copilot, gemini, cursor, windsurf, agents)
23
+ *
24
+ * Last reviewed against vendor documentation 2026-07-30: all fourteen paths
25
+ * re-read from the first-party sources listed below, all fourteen unchanged.
26
+ * Update this table when platforms change theirs and re-read those sources when
27
+ * you do, because nothing here is verified at build or test time. A stale entry
28
+ * installs a skill somewhere the target never reads, and every check still passes.
29
+ * The 90-day `@vendor-claim` clock above is the only thing watching these values.
30
+ *
31
+ * What the tests actually do: `packages/utils/test/skill-targets.test.ts` derives
32
+ * its expectations *from* this table and asserts invariants of it every target
33
+ * present, both scopes non-empty, relative (never absolute, never a leading `~`),
34
+ * forward-slash only plus that resolveSkillTarget composes base + rel. That
35
+ * verifies the resolver and the table's shape. It cannot verify that any path is
36
+ * where a platform actually looks; no test can. (An earlier version of that file
37
+ * restated all fourteen literals a second time. That pinned the values to a
38
+ * duplicate of this table rather than to vendor reality: a wrong path still
39
+ * passed, and a *corrected* path broke the suite until someone updated the copy —
40
+ * a change-detector masquerading as verification, and friction against exactly the
41
+ * correction the clock above exists to produce.)
42
+ *
43
+ * Sources, one per target, re-read 2026-07-30:
44
+ * - claude https://code.claude.com/docs/en/skills
45
+ * (docs.claude.com/en/docs/claude-code/skills now 301s here)
46
+ * - codex https://developers.openai.com/codex/skills/
47
+ * (308s to learn.chatgpt.com/docs/build-skills)
48
+ * - copilot https://docs.github.com/en/copilot/concepts/agents/about-agent-skills
49
+ * - gemini https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/skills.md
50
+ * - cursor https://cursor.com/docs/skills (skills shipped in Cursor 2.4)
51
+ * - windsurf https://docs.windsurf.com/windsurf/cascade/skills
52
+ * (307s to docs.devin.ai/desktop/cascade/skills — Devin rebrand)
53
+ * - agents https://agentskills.io/client-implementation/adding-skills-support
54
+ * (convention, not specification — see AGENTS_SKILLS_PATH above)
55
+ *
56
+ * Deliberately non-exhaustive: each row is the ONE directory VAT installs into for
57
+ * that (target, scope). Most of these targets *read* several directories, which a
58
+ * 1:1 struct cannot express — so do not read a row as a claim of exclusivity.
59
+ * Notably `.agents/skills` is read by six of the seven targets (every one except
60
+ * `claude`), and both `gemini` and `cursor` rank it at or above the client-native
61
+ * path VAT writes to. Changing where VAT installs is a product decision, not a
62
+ * comment fix.
35
63
  */
36
64
  export declare const SKILL_TARGETS: Readonly<Record<SkillTarget, SkillTargetPaths>>;
37
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"skill-targets.d.ts","sourceRoot":"","sources":["../src/skill-targets.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,eAAO,MAAM,kBAAkB,mFAQrB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,eAAO,MAAM,iBAAiB,8BAA+B,CAAC;AAE9D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,UAAU,gBAAgB;IACxB,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAQzE,CAAC;AAUF;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,GACV,MAAM,CAgBR"}
1
+ {"version":3,"file":"skill-targets.d.ts","sourceRoot":"","sources":["../src/skill-targets.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,eAAO,MAAM,kBAAkB,mFAQrB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,eAAO,MAAM,iBAAiB,8BAA+B,CAAC;AAE9D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,UAAU,gBAAgB;IACxB,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAQzE,CAAC;AAUF;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,GACV,MAAM,CAgBR"}
@@ -18,24 +18,67 @@ export const SKILL_TARGET_NAMES = [
18
18
  'agents',
19
19
  ];
20
20
  export const SKILL_SCOPE_NAMES = ['user', 'project'];
21
- /** Shared path used by both codex and agents targets (and their user/project scopes). */
21
+ /**
22
+ * Shared path used by both codex and agents targets (and their user/project scopes).
23
+ *
24
+ * Epistemic status — weaker than the other six rows, deliberately recorded here.
25
+ * `.agents/skills` is a cross-client *convention*, not a specified path. The Agent
26
+ * Skills specification defines only what goes *inside* a skill directory and
27
+ * explicitly declines to say where those directories live. The load-bearing
28
+ * citation is agentskills.io's client-implementation guide, which calls
29
+ * `.agents/skills/` "a widely-adopted convention for cross-client skill sharing"
30
+ * while stating the specification "does not mandate where skill directories live".
31
+ * Note also what is NOT a citation for this: agents.md says nothing about skills at
32
+ * all — no `.agents/skills`, no SKILL.md, no discovery paths — so anyone reaching
33
+ * for it to justify this row is citing a document that does not support it. Every
34
+ * other target below is documented by that target's own vendor for its own client;
35
+ * `agents` is documented convention instead.
36
+ */
22
37
  const AGENTS_SKILLS_PATH = '.agents/skills';
23
38
  /**
24
39
  * Target → {userRel, projectRel} lookup table.
25
40
  *
26
- * @vendor-claim reviewed=2026-04-08 verify=Each of the seven platforms' own published docs for where it reads skills from (claude, codex, copilot, gemini, cursor, windsurf, agents)
41
+ * @vendor-claim reviewed=2026-07-30 verify=Each of the seven platforms' own published docs for where it reads skills from (claude, codex, copilot, gemini, cursor, windsurf, agents)
42
+ *
43
+ * Last reviewed against vendor documentation 2026-07-30: all fourteen paths
44
+ * re-read from the first-party sources listed below, all fourteen unchanged.
45
+ * Update this table when platforms change theirs — and re-read those sources when
46
+ * you do, because nothing here is verified at build or test time. A stale entry
47
+ * installs a skill somewhere the target never reads, and every check still passes.
48
+ * The 90-day `@vendor-claim` clock above is the only thing watching these values.
49
+ *
50
+ * What the tests actually do: `packages/utils/test/skill-targets.test.ts` derives
51
+ * its expectations *from* this table and asserts invariants of it — every target
52
+ * present, both scopes non-empty, relative (never absolute, never a leading `~`),
53
+ * forward-slash only — plus that resolveSkillTarget composes base + rel. That
54
+ * verifies the resolver and the table's shape. It cannot verify that any path is
55
+ * where a platform actually looks; no test can. (An earlier version of that file
56
+ * restated all fourteen literals a second time. That pinned the values to a
57
+ * duplicate of this table rather than to vendor reality: a wrong path still
58
+ * passed, and a *corrected* path broke the suite until someone updated the copy —
59
+ * a change-detector masquerading as verification, and friction against exactly the
60
+ * correction the clock above exists to produce.)
27
61
  *
28
- * Last reviewed against vendor conventions 2026-04-08. Update this table when
29
- * platforms change theirs — and re-check the vendor's own documentation when you
30
- * do, because nothing here is verified at build or test time: the tests below
31
- * assert the table's *shape*, never that a path is where a platform actually
32
- * looks. A stale entry installs a skill somewhere the target never reads, and
33
- * every check still passes.
62
+ * Sources, one per target, re-read 2026-07-30:
63
+ * - claude https://code.claude.com/docs/en/skills
64
+ * (docs.claude.com/en/docs/claude-code/skills now 301s here)
65
+ * - codex https://developers.openai.com/codex/skills/
66
+ * (308s to learn.chatgpt.com/docs/build-skills)
67
+ * - copilot https://docs.github.com/en/copilot/concepts/agents/about-agent-skills
68
+ * - gemini https://github.com/google-gemini/gemini-cli/blob/main/docs/cli/skills.md
69
+ * - cursor https://cursor.com/docs/skills (skills shipped in Cursor 2.4)
70
+ * - windsurf https://docs.windsurf.com/windsurf/cascade/skills
71
+ * (307s to docs.devin.ai/desktop/cascade/skills — Devin rebrand)
72
+ * - agents https://agentskills.io/client-implementation/adding-skills-support
73
+ * (convention, not specification — see AGENTS_SKILLS_PATH above)
34
74
  *
35
- * (This previously cited docs/plans/2026-04-08-agent-skills-ecosystem-analysis.md
36
- * as its justification. That file is not in the repository `docs/plans/` is not
37
- * tracked — so the citation could not be followed. Recording the review date and
38
- * the verification gap is honest; pointing at an unreachable document was not.)
75
+ * Deliberately non-exhaustive: each row is the ONE directory VAT installs into for
76
+ * that (target, scope). Most of these targets *read* several directories, which a
77
+ * 1:1 struct cannot express — so do not read a row as a claim of exclusivity.
78
+ * Notably `.agents/skills` is read by six of the seven targets (every one except
79
+ * `claude`), and both `gemini` and `cursor` rank it at or above the client-native
80
+ * path VAT writes to. Changing where VAT installs is a product decision, not a
81
+ * comment fix.
39
82
  */
40
83
  export const SKILL_TARGETS = {
41
84
  claude: { userRel: '.claude/skills', projectRel: '.claude/skills' },
@@ -1 +1 @@
1
- {"version":3,"file":"skill-targets.js","sourceRoot":"","sources":["../src/skill-targets.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,QAAQ;IACR,OAAO;IACP,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,QAAQ;CACA,CAAC;AAIX,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,SAAS,CAAU,CAAC;AAW9D,yFAAyF;AACzF,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoD;IAC5E,MAAM,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACnE,KAAK,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,kBAAkB,EAAE;IACtE,OAAO,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACrE,MAAM,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACnE,MAAM,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACnE,QAAQ,EAAE,EAAE,OAAO,EAAE,0BAA0B,EAAE,UAAU,EAAE,kBAAkB,EAAE;IACjF,MAAM,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,kBAAkB,EAAE;CACxE,CAAC;AAEF,SAAS,aAAa,CAAC,KAAa;IAClC,OAAQ,kBAAwC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAQ,iBAAuC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAmB,EACnB,KAAiB,EACjB,GAAW;IAEX,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,mBAAmB,MAAM,CAAC,MAAM,CAAC,qBAAqB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,CAAC,KAAK,CAAC,oBAAoB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAChD,MAAM,GAAG,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;IAChE,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"skill-targets.js","sourceRoot":"","sources":["../src/skill-targets.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,QAAQ;IACR,OAAO;IACP,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,QAAQ;CACA,CAAC;AAIX,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,SAAS,CAAU,CAAC;AAW9D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoD;IAC5E,MAAM,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACnE,KAAK,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,kBAAkB,EAAE;IACtE,OAAO,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACrE,MAAM,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACnE,MAAM,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACnE,QAAQ,EAAE,EAAE,OAAO,EAAE,0BAA0B,EAAE,UAAU,EAAE,kBAAkB,EAAE;IACjF,MAAM,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,kBAAkB,EAAE;CACxE,CAAC;AAEF,SAAS,aAAa,CAAC,KAAa;IAClC,OAAQ,kBAAwC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAQ,iBAAuC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAmB,EACnB,KAAiB,EACjB,GAAW;IAEX,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,mBAAmB,MAAM,CAAC,MAAM,CAAC,qBAAqB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,CAAC,KAAK,CAAC,oBAAoB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAChD,MAAM,GAAG,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;IAChE,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Make a process's stdio blocking, so `process.exit()` can never discard output.
3
+ *
4
+ * Lives in utils rather than in the CLI because it is not CLI-specific: it
5
+ * belongs to any published bin that writes a payload and then exits. VAT ships
6
+ * two of those (`vat` and the resource-compiler bin), and the CLI package sits
7
+ * at the top of the dependency chain — nothing may depend on it — so a bin
8
+ * outside `packages/cli` could not reach this fix while it lived there.
9
+ */
10
+ /** Whether each stdio stream was actually switched into blocking mode. */
11
+ export interface StdioBlockingResult {
12
+ stdout: boolean;
13
+ stderr: boolean;
14
+ }
15
+ /**
16
+ * Make stdout/stderr BLOCKING, so that `process.exit()` can never discard output.
17
+ *
18
+ * Call once, first thing, from a bin's entry point.
19
+ *
20
+ * Node makes a pipe's stdio non-blocking, which is what turns `console.log` and
21
+ * `process.stdout.write` into buffered, asynchronous writes. `process.exit` does
22
+ * not drain those buffers, so a command that exits the moment it finishes can
23
+ * lose whatever had not yet reached the pipe (64 KB on Linux/macOS) — with exit
24
+ * code 0, so nothing signals the loss. An interactive TTY is unbuffered and
25
+ * looks perfect, which is why this class of bug survives: it only bites the
26
+ * piped consumer (`vat command | jq .status`).
27
+ *
28
+ * Fixing this at a single YAML writer would cover stdout only. It is done here
29
+ * because the same truncation applies to STDERR, which carries progress lines
30
+ * and `file:line:column: severity:` findings, and a report that loses its tail
31
+ * at 64 KB is worse than one that never printed. One mechanism covers both
32
+ * streams and every writer, present and future.
33
+ *
34
+ * `setBlocking` is the libuv behaviour behind `process.stdout` and the mechanism
35
+ * Node itself uses for TTYs; it is reached through the stream's INTERNAL handle,
36
+ * so every access is guarded and a failure is non-fatal — a platform where this
37
+ * is unavailable keeps the previous behaviour rather than crashing at startup.
38
+ *
39
+ * That guard is exactly why this reports back instead of returning `void`.
40
+ * Depending on an internal API means the silent-failure path is a genuine
41
+ * possibility — Windows named pipes do not present the same handle shape as
42
+ * POSIX pipes — and a silent failure here reverts to truncating output with
43
+ * nothing to distinguish it from a working run. Callers surface the result
44
+ * under a debug flag so a truncation report can be diagnosed rather than
45
+ * guessed at. See {@link describeStdioBlocking}.
46
+ */
47
+ export declare function makeStdioBlocking(): StdioBlockingResult;
48
+ /**
49
+ * Render {@link makeStdioBlocking}'s result as one debug line.
50
+ *
51
+ * Lives next to the thing it describes because every bin that calls
52
+ * `makeStdioBlocking` reports it, and hand-written copies of the wording
53
+ * would drift.
54
+ */
55
+ export declare function describeStdioBlocking(result: StdioBlockingResult): string;
56
+ //# sourceMappingURL=stdio-blocking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-blocking.d.ts","sourceRoot":"","sources":["../src/stdio-blocking.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CAChB;AAwBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,iBAAiB,IAAI,mBAAmB,CAKvD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAMzE"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Make a process's stdio blocking, so `process.exit()` can never discard output.
3
+ *
4
+ * Lives in utils rather than in the CLI because it is not CLI-specific: it
5
+ * belongs to any published bin that writes a payload and then exits. VAT ships
6
+ * two of those (`vat` and the resource-compiler bin), and the CLI package sits
7
+ * at the top of the dependency chain — nothing may depend on it — so a bin
8
+ * outside `packages/cli` could not reach this fix while it lived there.
9
+ */
10
+ /**
11
+ * Switch one stream's underlying handle into blocking mode.
12
+ *
13
+ * @returns `true` only if `setBlocking` was present AND completed without
14
+ * throwing. Both failure modes are real: a handle can be absent (stdio replaced,
15
+ * or a shape libuv does not wrap), and `setBlocking` can throw on a handle type
16
+ * that does not support it.
17
+ */
18
+ function setStreamBlocking(stream) {
19
+ try {
20
+ const handle = stream._handle;
21
+ if (typeof handle?.setBlocking !== 'function')
22
+ return false;
23
+ handle.setBlocking(true);
24
+ return true;
25
+ }
26
+ catch {
27
+ // Best-effort: never let a startup nicety take down the process.
28
+ return false;
29
+ }
30
+ }
31
+ /**
32
+ * Make stdout/stderr BLOCKING, so that `process.exit()` can never discard output.
33
+ *
34
+ * Call once, first thing, from a bin's entry point.
35
+ *
36
+ * Node makes a pipe's stdio non-blocking, which is what turns `console.log` and
37
+ * `process.stdout.write` into buffered, asynchronous writes. `process.exit` does
38
+ * not drain those buffers, so a command that exits the moment it finishes can
39
+ * lose whatever had not yet reached the pipe (64 KB on Linux/macOS) — with exit
40
+ * code 0, so nothing signals the loss. An interactive TTY is unbuffered and
41
+ * looks perfect, which is why this class of bug survives: it only bites the
42
+ * piped consumer (`vat command | jq .status`).
43
+ *
44
+ * Fixing this at a single YAML writer would cover stdout only. It is done here
45
+ * because the same truncation applies to STDERR, which carries progress lines
46
+ * and `file:line:column: severity:` findings, and a report that loses its tail
47
+ * at 64 KB is worse than one that never printed. One mechanism covers both
48
+ * streams and every writer, present and future.
49
+ *
50
+ * `setBlocking` is the libuv behaviour behind `process.stdout` and the mechanism
51
+ * Node itself uses for TTYs; it is reached through the stream's INTERNAL handle,
52
+ * so every access is guarded and a failure is non-fatal — a platform where this
53
+ * is unavailable keeps the previous behaviour rather than crashing at startup.
54
+ *
55
+ * That guard is exactly why this reports back instead of returning `void`.
56
+ * Depending on an internal API means the silent-failure path is a genuine
57
+ * possibility — Windows named pipes do not present the same handle shape as
58
+ * POSIX pipes — and a silent failure here reverts to truncating output with
59
+ * nothing to distinguish it from a working run. Callers surface the result
60
+ * under a debug flag so a truncation report can be diagnosed rather than
61
+ * guessed at. See {@link describeStdioBlocking}.
62
+ */
63
+ export function makeStdioBlocking() {
64
+ return {
65
+ stdout: setStreamBlocking(process.stdout),
66
+ stderr: setStreamBlocking(process.stderr),
67
+ };
68
+ }
69
+ /**
70
+ * Render {@link makeStdioBlocking}'s result as one debug line.
71
+ *
72
+ * Lives next to the thing it describes because every bin that calls
73
+ * `makeStdioBlocking` reports it, and hand-written copies of the wording
74
+ * would drift.
75
+ */
76
+ export function describeStdioBlocking(result) {
77
+ const failed = ['stdout', 'stderr'].filter((name) => !result[name]);
78
+ if (failed.length === 0) {
79
+ return 'stdio: stdout and stderr are blocking; process.exit cannot truncate output';
80
+ }
81
+ return `stdio: could NOT make ${failed.join(' and ')} blocking — output on ${failed.length === 1 ? 'that stream' : 'those streams'} may be truncated at the pipe buffer when the CLI exits`;
82
+ }
83
+ //# sourceMappingURL=stdio-blocking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-blocking.js","sourceRoot":"","sources":["../src/stdio-blocking.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH;;;;;;;GAOG;AACH,SAAS,iBAAiB,CAAC,MAA0B;IACpD,IAAI,CAAC;QACJ,MAAM,MAAM,GACX,MACA,CAAC,OAAO,CAAC;QACV,IAAI,OAAO,MAAM,EAAE,WAAW,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC;QAC5D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,iEAAiE;QACjE,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,iBAAiB;IAChC,OAAO;QACN,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC;QACzC,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC;KACzC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAA2B;IAChE,MAAM,MAAM,GAAI,CAAC,QAAQ,EAAE,QAAQ,CAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,4EAA4E,CAAC;IACrF,CAAC;IACD,OAAO,yBAAyB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,yBAAyB,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,yDAAyD,CAAC;AAC7L,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-agent-toolkit/utils",
3
- "version": "0.1.41-rc.7",
3
+ "version": "0.1.41",
4
4
  "type": "module",
5
5
  "description": "Core utility functions shared across the vibe-agent-toolkit packages",
6
6
  "sideEffects": false,