carrick 0.3.84 → 0.3.86

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.
Files changed (47) hide show
  1. package/README.md +15 -0
  2. package/bin/carrick.mjs +89 -0
  3. package/dist/auth/credentials.d.ts +9 -0
  4. package/dist/auth/credentials.js +13 -2
  5. package/dist/auth/credentials.js.map +1 -1
  6. package/dist/auth/read.d.ts +4 -4
  7. package/dist/global-install.d.ts +183 -0
  8. package/dist/global-install.js +393 -0
  9. package/dist/global-install.js.map +1 -0
  10. package/dist/hook/post-edit.js +10 -0
  11. package/dist/hook/post-edit.js.map +1 -1
  12. package/dist/hook/session-start.js +34 -0
  13. package/dist/hook/session-start.js.map +1 -1
  14. package/dist/hook/stop.js +18 -4
  15. package/dist/hook/stop.js.map +1 -1
  16. package/dist/hook/user-prompt.js +16 -4
  17. package/dist/hook/user-prompt.js.map +1 -1
  18. package/dist/init/doctor.d.ts +40 -0
  19. package/dist/init/doctor.js +125 -0
  20. package/dist/init/doctor.js.map +1 -1
  21. package/dist/init/outdated.d.ts +47 -0
  22. package/dist/init/outdated.js +104 -0
  23. package/dist/init/outdated.js.map +1 -1
  24. package/dist/init/projects.d.ts +2 -2
  25. package/dist/init/run.d.ts +9 -0
  26. package/dist/init/run.js +57 -12
  27. package/dist/init/run.js.map +1 -1
  28. package/dist/scan.d.ts +26 -0
  29. package/dist/scan.js +92 -0
  30. package/dist/scan.js.map +1 -1
  31. package/dist/update-check.d.ts +1 -0
  32. package/dist/update-check.js +25 -0
  33. package/dist/update-check.js.map +1 -0
  34. package/dist/update.d.ts +128 -0
  35. package/dist/update.js +398 -0
  36. package/dist/update.js.map +1 -0
  37. package/package.json +7 -7
  38. package/sidecar/dist/src/capture/anchors.js +69 -8
  39. package/sidecar/dist/src/capture/api.d.ts +4 -1
  40. package/sidecar/dist/src/capture/deep-walk.js +4 -1
  41. package/sidecar/dist/src/capture/node-builder.d.ts +28 -1
  42. package/sidecar/dist/src/capture/node-builder.js +89 -3
  43. package/sidecar/dist/src/capture/unresolved.d.ts +7 -0
  44. package/sidecar/dist/src/capture/unresolved.js +1 -1
  45. package/sidecar/dist/src/type-inferrer.d.ts +128 -5
  46. package/sidecar/dist/src/type-inferrer.js +444 -17
  47. package/templates/skills/carrick-census.md +3 -1
@@ -0,0 +1,128 @@
1
+ import { spawn } from "node:child_process";
2
+ /** The registry's smallest answer to "what is published": a two-key document. */
3
+ export declare const DIST_TAGS_URL = "https://registry.npmjs.org/-/package/carrick/dist-tags";
4
+ /**
5
+ * How long an answer stands before another is fetched.
6
+ *
7
+ * Short enough that a morning's work does not run on yesterday's news — the
8
+ * incident was a customer on a three-release-old build for a whole morning —
9
+ * and long enough that a repository of hooks firing on every edit does not
10
+ * become registry traffic.
11
+ */
12
+ export declare const CHECK_TTL_MS: number;
13
+ /** The whole budget for a fetch, on the one path where it is synchronous. */
14
+ export declare const FETCH_TIMEOUT_MS = 2000;
15
+ /** What the last check learned. `latest` is null when it never got an answer. */
16
+ export type UpdateState = {
17
+ checked_at: string;
18
+ latest: string | null;
19
+ };
20
+ export declare function updateStatePath(env?: NodeJS.ProcessEnv): string;
21
+ /** True when the user has asked for no version checking at all. */
22
+ export declare function suppressed(env?: NodeJS.ProcessEnv): boolean;
23
+ /**
24
+ * True on a build machine.
25
+ *
26
+ * `CI` is the convention every provider sets; `GITHUB_ACTIONS` additionally
27
+ * decides how a notice is spelled. CI never gets the background check: the
28
+ * machine is thrown away at the end of the job, so a cache written for the next
29
+ * invocation is a cache nobody reads.
30
+ */
31
+ export declare function inCi(env?: NodeJS.ProcessEnv): boolean;
32
+ /** This package's own version, which is the version a user is running. */
33
+ export declare function currentVersion(root?: string): string | null;
34
+ /**
35
+ * Whether `candidate` is a release a user should move to.
36
+ *
37
+ * Deliberately narrow: both sides must be a plain `x.y.z`, so a prerelease on
38
+ * either side answers false and nobody is ever nagged towards one. The
39
+ * registry's `latest` tag is a release by definition, and a scanner built from
40
+ * a checkout carries whatever `Cargo.toml` said, so the guard costs nothing and
41
+ * removes a whole class of wrong notice.
42
+ */
43
+ export declare function isNewer(candidate: string, current: string): boolean;
44
+ export declare function readUpdateState(env?: NodeJS.ProcessEnv): UpdateState | null;
45
+ /**
46
+ * Replace the cache atomically, or do nothing.
47
+ *
48
+ * Returns whether the write landed, because the caller uses a failed write as
49
+ * its reason not to spawn a checker: a machine whose config directory cannot be
50
+ * written would otherwise fork a child on every single invocation forever.
51
+ */
52
+ export declare function writeUpdateState(state: UpdateState, env?: NodeJS.ProcessEnv): boolean;
53
+ export declare function isStale(state: UpdateState | null, now?: number): boolean;
54
+ /** How this copy of the package got onto the machine, and the way out of it. */
55
+ export type InstallShape = {
56
+ kind: "npx" | "volta" | "bun" | "pnpm" | "project" | "npm";
57
+ /** A command a person or an agent can run verbatim. */
58
+ command: string;
59
+ /** The manifest that pins it, when one does. Named so the fix is findable. */
60
+ manifest?: string;
61
+ };
62
+ /**
63
+ * The install shape, read off the path this file was loaded from.
64
+ *
65
+ * Nothing here runs a package manager or shells out: it is string work on an
66
+ * absolute path plus at most two small file reads, so it costs nothing and
67
+ * cannot hang. Every branch ends in a runnable command, and the ordering
68
+ * matters — a pnpm project install and a pnpm global install both sit under
69
+ * `.pnpm`, and only the enclosing manifest tells them apart.
70
+ */
71
+ export declare function installShape(root?: string, env?: NodeJS.ProcessEnv): InstallShape;
72
+ export type NoticeOptions = {
73
+ env?: NodeJS.ProcessEnv;
74
+ root?: string;
75
+ };
76
+ /**
77
+ * The one line a user sees, or null when there is nothing to say.
78
+ *
79
+ * It carries three things on purpose: the version running, the version
80
+ * published, and a command. The first two are the reporting half — a bug report
81
+ * that quotes this line names the build it came from — and the third is the
82
+ * only reason anybody acts on it. On GitHub Actions it is spelled as a workflow
83
+ * warning so it lands in the run's annotations rather than scrolling past in a
84
+ * multi-minute log, and it says plainly that the run continues on the old
85
+ * version: CI reproducibility means the workflow decides what runs, not us.
86
+ */
87
+ export declare function updateNotice(current: string | null, latest: string | null, options?: NoticeOptions): string | null;
88
+ /** One bounded GET of the registry's dist-tags, answering null on anything at all. */
89
+ export declare function fetchLatest(fetchImpl?: typeof fetch, timeoutMs?: number): Promise<string | null>;
90
+ /**
91
+ * Start a detached child to refresh the cache, if the cache is due a refresh.
92
+ *
93
+ * The parent stamps the cache with the current time BEFORE spawning, keeping
94
+ * whatever `latest` it already knew. That stamp is what makes a dead network
95
+ * cheap: the child can fail silently and no further invocation forks another
96
+ * one until the TTL comes round again. A stamp that cannot be written is the
97
+ * signal to spawn nothing at all.
98
+ *
99
+ * Returns whether a child was started, for the tests and for the log.
100
+ */
101
+ export declare function scheduleUpdateCheck(env?: NodeJS.ProcessEnv, spawnImpl?: typeof spawn): boolean;
102
+ /**
103
+ * The laptop path: print what the last check learned, then start the next one.
104
+ *
105
+ * Nothing is awaited, so the cost to the command is one file read and one
106
+ * `spawn` at most once every four hours.
107
+ */
108
+ export declare function updateNoticeFromCache(env?: NodeJS.ProcessEnv): string | null;
109
+ /**
110
+ * Whether this invocation is a scan.
111
+ *
112
+ * Only used to decide whether CI pays for a synchronous check: a two-second
113
+ * bound in front of a multi-minute scan is invisible, and in front of
114
+ * `carrick status` it is the whole command.
115
+ */
116
+ export declare function isScanInvocation(argv: string[]): boolean;
117
+ /**
118
+ * The CI path: one bounded fetch, in front of a scan only, warning and
119
+ * continuing.
120
+ *
121
+ * A build machine is thrown away at the end of the job, so the cached model a
122
+ * laptop uses would never get a second invocation to read it. This is the one
123
+ * place a check is on the critical path, and it is bounded at two seconds
124
+ * before work that takes minutes. It never refuses the run: CI's contract is
125
+ * that the workflow decides what runs, and a scanner that declined to start
126
+ * because a newer one exists would be a worse outage than the stale build.
127
+ */
128
+ export declare function ciUpdateNotice(argv: string[], env?: NodeJS.ProcessEnv, fetchImpl?: typeof fetch): Promise<string | null>;
package/dist/update.js ADDED
@@ -0,0 +1,398 @@
1
+ // Telling a machine that the Carrick it is running is not the Carrick that is
2
+ // published.
3
+ //
4
+ // `npx --yes carrick@latest` resolves fresh on every invocation, so it is never
5
+ // the problem. An INSTALLED `carrick` is: `npm install -g carrick` is what the
6
+ // README, the plugin docs and `carrick init` all tell people to run, and from
7
+ // that moment the version on that machine is frozen until someone remembers to
8
+ // bump it. A pilot customer ran a scan on a build three releases old and it
9
+ // failed on a defect that was already fixed; the same morning two versions were
10
+ // live on one machine, which is what a stale global install beside a fresh npx
11
+ // looks like.
12
+ //
13
+ // The design this file implements, and why, is
14
+ // `docs/reference/update-check.md`.
15
+ //
16
+ // Four properties it must not lose:
17
+ //
18
+ // 1. **Fail open.** No network, a 500, a rate limit, a corrupt cache, an
19
+ // unwritable config directory — every one of them yields no output and
20
+ // changes nothing. A scan must never fail because a registry did.
21
+ // 2. **No latency.** On a laptop the invocation reads one small file and
22
+ // prints from it; the fetch happens in a detached child whose answer the
23
+ // NEXT invocation reads. One run's lag after a release, and zero
24
+ // milliseconds on the path a person waits on.
25
+ // 3. **It never changes what runs.** The notice names the exact command for
26
+ // the install shape it detected. Nothing here installs anything. The
27
+ // reasoning is in the doc: we do not own the install location (npm global,
28
+ // pnpm, bun, volta, an npx cache, a devDependency), and a self-update that
29
+ // guesses wrong leaves two Carricks on one machine — which is the incident
30
+ // this exists to prevent, not a fix for it.
31
+ // 4. **Suppressible.** `CARRICK_NO_UPDATE_CHECK=1` turns the whole thing off,
32
+ // for a reproducible run or an air-gapped machine.
33
+ import fs from "node:fs";
34
+ import path from "node:path";
35
+ import { spawn } from "node:child_process";
36
+ import { fileURLToPath } from "node:url";
37
+ import { configDir } from "./auth/credentials.js";
38
+ import { packageRoot } from "./native.js";
39
+ /** The registry's smallest answer to "what is published": a two-key document. */
40
+ export const DIST_TAGS_URL = "https://registry.npmjs.org/-/package/carrick/dist-tags";
41
+ /**
42
+ * How long an answer stands before another is fetched.
43
+ *
44
+ * Short enough that a morning's work does not run on yesterday's news — the
45
+ * incident was a customer on a three-release-old build for a whole morning —
46
+ * and long enough that a repository of hooks firing on every edit does not
47
+ * become registry traffic.
48
+ */
49
+ export const CHECK_TTL_MS = 4 * 60 * 60 * 1000;
50
+ /** The whole budget for a fetch, on the one path where it is synchronous. */
51
+ export const FETCH_TIMEOUT_MS = 2000;
52
+ export function updateStatePath(env = process.env) {
53
+ return path.join(configDir(env), "update-check.json");
54
+ }
55
+ /** True when the user has asked for no version checking at all. */
56
+ export function suppressed(env = process.env) {
57
+ const raw = env["CARRICK_NO_UPDATE_CHECK"];
58
+ return raw !== undefined && raw !== "" && raw !== "0" && raw !== "false";
59
+ }
60
+ /**
61
+ * True on a build machine.
62
+ *
63
+ * `CI` is the convention every provider sets; `GITHUB_ACTIONS` additionally
64
+ * decides how a notice is spelled. CI never gets the background check: the
65
+ * machine is thrown away at the end of the job, so a cache written for the next
66
+ * invocation is a cache nobody reads.
67
+ */
68
+ export function inCi(env = process.env) {
69
+ return env["CI"] === "true" || env["CI"] === "1" || Boolean(env["GITHUB_ACTIONS"]);
70
+ }
71
+ /** This package's own version, which is the version a user is running. */
72
+ export function currentVersion(root = packageRoot()) {
73
+ try {
74
+ const manifest = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
75
+ return typeof manifest.version === "string" ? manifest.version : null;
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ /**
82
+ * Whether `candidate` is a release a user should move to.
83
+ *
84
+ * Deliberately narrow: both sides must be a plain `x.y.z`, so a prerelease on
85
+ * either side answers false and nobody is ever nagged towards one. The
86
+ * registry's `latest` tag is a release by definition, and a scanner built from
87
+ * a checkout carries whatever `Cargo.toml` said, so the guard costs nothing and
88
+ * removes a whole class of wrong notice.
89
+ */
90
+ export function isNewer(candidate, current) {
91
+ const parse = (value) => {
92
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value.trim());
93
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
94
+ };
95
+ const a = parse(candidate);
96
+ const b = parse(current);
97
+ if (!a || !b)
98
+ return false;
99
+ for (let index = 0; index < 3; index += 1) {
100
+ if (a[index] > b[index])
101
+ return true;
102
+ if (a[index] < b[index])
103
+ return false;
104
+ }
105
+ return false;
106
+ }
107
+ export function readUpdateState(env = process.env) {
108
+ try {
109
+ const parsed = JSON.parse(fs.readFileSync(updateStatePath(env), "utf8"));
110
+ if (typeof parsed?.checked_at !== "string")
111
+ return null;
112
+ const latest = typeof parsed.latest === "string" ? parsed.latest : null;
113
+ return { checked_at: parsed.checked_at, latest };
114
+ }
115
+ catch {
116
+ // Absent, unreadable, or not the shape this build writes. All three mean
117
+ // "nothing is known", which is a state this file already handles.
118
+ return null;
119
+ }
120
+ }
121
+ /**
122
+ * Replace the cache atomically, or do nothing.
123
+ *
124
+ * Returns whether the write landed, because the caller uses a failed write as
125
+ * its reason not to spawn a checker: a machine whose config directory cannot be
126
+ * written would otherwise fork a child on every single invocation forever.
127
+ */
128
+ export function writeUpdateState(state, env = process.env) {
129
+ const target = updateStatePath(env);
130
+ const temporary = `${target}.${process.pid}.tmp`;
131
+ try {
132
+ fs.mkdirSync(path.dirname(target), { recursive: true });
133
+ fs.writeFileSync(temporary, `${JSON.stringify(state)}\n`, { mode: 0o600 });
134
+ fs.renameSync(temporary, target);
135
+ return true;
136
+ }
137
+ catch {
138
+ try {
139
+ fs.unlinkSync(temporary);
140
+ }
141
+ catch {
142
+ // The temporary file is the one thing here worth tidying, and failing to
143
+ // tidy it is still not a reason to say anything to anybody.
144
+ }
145
+ return false;
146
+ }
147
+ }
148
+ export function isStale(state, now = Date.now()) {
149
+ if (!state)
150
+ return true;
151
+ const at = Date.parse(state.checked_at);
152
+ if (!Number.isFinite(at))
153
+ return true;
154
+ // A clock that moved backwards (a VM restored, a timezone fixed) reads as
155
+ // stale rather than as "checked in the future, wait four hours".
156
+ return now - at >= CHECK_TTL_MS || at > now;
157
+ }
158
+ function readJson(file) {
159
+ try {
160
+ const parsed = JSON.parse(fs.readFileSync(file, "utf8"));
161
+ return parsed && typeof parsed === "object" ? parsed : null;
162
+ }
163
+ catch {
164
+ return null;
165
+ }
166
+ }
167
+ function dependsOnCarrick(manifest) {
168
+ for (const field of ["dependencies", "devDependencies", "optionalDependencies"]) {
169
+ const block = manifest[field];
170
+ if (block && typeof block === "object" && "carrick" in block)
171
+ return true;
172
+ }
173
+ return false;
174
+ }
175
+ /**
176
+ * The install shape, read off the path this file was loaded from.
177
+ *
178
+ * Nothing here runs a package manager or shells out: it is string work on an
179
+ * absolute path plus at most two small file reads, so it costs nothing and
180
+ * cannot hang. Every branch ends in a runnable command, and the ordering
181
+ * matters — a pnpm project install and a pnpm global install both sit under
182
+ * `.pnpm`, and only the enclosing manifest tells them apart.
183
+ */
184
+ export function installShape(root = packageRoot(), env = process.env) {
185
+ const normalized = root.split(path.sep).join("/");
186
+ const segments = `/${normalized}/`;
187
+ // npx keeps each resolved tree under a content-addressed directory and reuses
188
+ // it, so a bare `npx carrick` is as frozen as a global install. `@latest` is
189
+ // the whole fix, and it is the fix for the next invocation too.
190
+ if (segments.includes("/_npx/")) {
191
+ return { kind: "npx", command: "npx --yes carrick@latest" };
192
+ }
193
+ if (segments.includes("/.volta/")) {
194
+ return { kind: "volta", command: "volta install carrick@latest" };
195
+ }
196
+ if (segments.includes("/.bun/")) {
197
+ return { kind: "bun", command: "bun add -g carrick@latest" };
198
+ }
199
+ // pnpm's global root is a real project directory with a real manifest that
200
+ // lists what was installed into it, so it has to be recognised before the
201
+ // project branch below would claim it.
202
+ if (segments.includes("/pnpm/global/")) {
203
+ return { kind: "pnpm", command: "pnpm add -g carrick@latest" };
204
+ }
205
+ // Everything below the OUTERMOST `node_modules` belongs to whatever encloses
206
+ // it. For a project install that is the repository; for `npm -g` it is the
207
+ // prefix directory, which has no manifest, so the project branch declines and
208
+ // the global default answers.
209
+ const outer = normalized.split("/node_modules/")[0];
210
+ if (outer && outer !== normalized) {
211
+ const manifestPath = path.join(outer.split("/").join(path.sep), "package.json");
212
+ const manifest = readJson(manifestPath);
213
+ if (manifest && dependsOnCarrick(manifest)) {
214
+ const has = (name) => fs.existsSync(path.join(outer.split("/").join(path.sep), name));
215
+ const command = has("pnpm-lock.yaml")
216
+ ? "pnpm add -D carrick@latest"
217
+ : has("yarn.lock")
218
+ ? "yarn add -D carrick@latest"
219
+ : has("bun.lockb") || has("bun.lock")
220
+ ? "bun add -d carrick@latest"
221
+ : "npm install -D carrick@latest";
222
+ return { kind: "project", command, manifest: manifestPath };
223
+ }
224
+ }
225
+ void env;
226
+ return { kind: "npm", command: "npm install -g carrick@latest" };
227
+ }
228
+ /**
229
+ * The one line a user sees, or null when there is nothing to say.
230
+ *
231
+ * It carries three things on purpose: the version running, the version
232
+ * published, and a command. The first two are the reporting half — a bug report
233
+ * that quotes this line names the build it came from — and the third is the
234
+ * only reason anybody acts on it. On GitHub Actions it is spelled as a workflow
235
+ * warning so it lands in the run's annotations rather than scrolling past in a
236
+ * multi-minute log, and it says plainly that the run continues on the old
237
+ * version: CI reproducibility means the workflow decides what runs, not us.
238
+ */
239
+ export function updateNotice(current, latest, options = {}) {
240
+ const env = options.env ?? process.env;
241
+ if (!current || !latest)
242
+ return null;
243
+ if (!isNewer(latest, current))
244
+ return null;
245
+ if (env["GITHUB_ACTIONS"]) {
246
+ const head = `::warning::Carrick ${current} is running here and ${latest} is published. ` +
247
+ `This run continues on ${current} — nothing was changed. `;
248
+ // Two different fixes, and naming the wrong one sends a reader to a line
249
+ // their workflow does not contain. The runner sets
250
+ // GITHUB_ACTION_REPOSITORY for a step that belongs to an action, so a run
251
+ // through the Carrick action says so: there, the version comes from the
252
+ // action checkout's own Cargo.toml, and the ref is the only thing the
253
+ // workflow chose. A workflow that calls the CLI directly wrote a version
254
+ // string, and that is what it has to change.
255
+ if ((env["GITHUB_ACTION_REPOSITORY"] ?? "").endsWith("/carrick")) {
256
+ return `${head}This workflow pins the Carrick action to a ref that does not move; use \`carrick-tools/carrick@v1\`, which moves to each release.`;
257
+ }
258
+ return `${head}Run \`carrick@latest\`, or ${latest}, so the next run is not on a build with defects already fixed.`;
259
+ }
260
+ const shape = installShape(options.root ?? packageRoot(), env);
261
+ const where = shape.manifest ? ` (pinned in ${shape.manifest})` : "";
262
+ // No mention of CARRICK_NO_UPDATE_CHECK here. This line is read by agents as
263
+ // well as people — the session-start hook puts it on stdout, straight into
264
+ // the session — and the failure this exists for is an agent that does not
265
+ // upgrade. Handing it an off switch in the same sentence as the fix invites
266
+ // the wrong one. The variable is documented in `carrick --help` and in the
267
+ // package README, where a person reads it.
268
+ return (`carrick ${current} is installed${where} and ${latest} is published. ` +
269
+ `Update with \`${shape.command}\` — a scan on an older build can fail on defects that are already fixed.`);
270
+ }
271
+ /** One bounded GET of the registry's dist-tags, answering null on anything at all. */
272
+ export async function fetchLatest(fetchImpl = fetch, timeoutMs = FETCH_TIMEOUT_MS) {
273
+ try {
274
+ const response = await fetchImpl(DIST_TAGS_URL, {
275
+ signal: AbortSignal.timeout(timeoutMs),
276
+ headers: { accept: "application/json" },
277
+ });
278
+ if (!response.ok)
279
+ return null;
280
+ const body = (await response.json());
281
+ const latest = body?.["latest"];
282
+ return typeof latest === "string" && /^\d+\.\d+\.\d+$/.test(latest) ? latest : null;
283
+ }
284
+ catch {
285
+ return null;
286
+ }
287
+ }
288
+ /**
289
+ * Start a detached child to refresh the cache, if the cache is due a refresh.
290
+ *
291
+ * The parent stamps the cache with the current time BEFORE spawning, keeping
292
+ * whatever `latest` it already knew. That stamp is what makes a dead network
293
+ * cheap: the child can fail silently and no further invocation forks another
294
+ * one until the TTL comes round again. A stamp that cannot be written is the
295
+ * signal to spawn nothing at all.
296
+ *
297
+ * Returns whether a child was started, for the tests and for the log.
298
+ */
299
+ export function scheduleUpdateCheck(env = process.env, spawnImpl = spawn) {
300
+ if (suppressed(env) || inCi(env))
301
+ return false;
302
+ const state = readUpdateState(env);
303
+ if (!isStale(state))
304
+ return false;
305
+ if (!writeUpdateState({ checked_at: new Date().toISOString(), latest: state?.latest ?? null }, env)) {
306
+ return false;
307
+ }
308
+ try {
309
+ const child = spawnImpl(process.execPath, [fileURLToPath(new URL("./update-check.js", import.meta.url))],
310
+ // `windowsHide` because a detached child on Windows gets its own console
311
+ // window otherwise, and win32-x64 is a platform this package publishes:
312
+ // a window flashing up once every four hours is not a version notice.
313
+ { detached: true, stdio: "ignore", env, windowsHide: true });
314
+ child.unref();
315
+ return true;
316
+ }
317
+ catch {
318
+ return false;
319
+ }
320
+ }
321
+ /**
322
+ * The laptop path: print what the last check learned, then start the next one.
323
+ *
324
+ * Nothing is awaited, so the cost to the command is one file read and one
325
+ * `spawn` at most once every four hours.
326
+ */
327
+ export function updateNoticeFromCache(env = process.env) {
328
+ if (suppressed(env))
329
+ return null;
330
+ const state = readUpdateState(env);
331
+ const notice = updateNotice(currentVersion(), state?.latest ?? null, { env });
332
+ scheduleUpdateCheck(env);
333
+ return notice;
334
+ }
335
+ /**
336
+ * Every command name this CLI answers: the binary's own
337
+ * (`src/local_mode/cli.rs`, `LOCAL_COMMANDS`) and this package's.
338
+ *
339
+ * Needed only to tell a command from a path. The scanner reads a first
340
+ * argument it does not recognise as a directory to scan, and that is the
341
+ * invocation this list exists to identify.
342
+ */
343
+ const COMMANDS = new Set([
344
+ // The binary's.
345
+ "derive",
346
+ "index",
347
+ "refresh",
348
+ "resume",
349
+ "status",
350
+ "check",
351
+ "touch",
352
+ // This package's.
353
+ "login",
354
+ "logout",
355
+ "lsp",
356
+ "hook",
357
+ "init",
358
+ "remove",
359
+ "doctor",
360
+ "templates",
361
+ ]);
362
+ /** The commands that pay for a model and take minutes. */
363
+ const SCAN_COMMANDS = new Set(["index"]);
364
+ /**
365
+ * Whether this invocation is a scan.
366
+ *
367
+ * Only used to decide whether CI pays for a synchronous check: a two-second
368
+ * bound in front of a multi-minute scan is invisible, and in front of
369
+ * `carrick status` it is the whole command.
370
+ */
371
+ export function isScanInvocation(argv) {
372
+ const first = argv[0];
373
+ if (first === undefined)
374
+ return false;
375
+ if (first.startsWith("-"))
376
+ return false;
377
+ if (SCAN_COMMANDS.has(first))
378
+ return true;
379
+ return !COMMANDS.has(first);
380
+ }
381
+ /**
382
+ * The CI path: one bounded fetch, in front of a scan only, warning and
383
+ * continuing.
384
+ *
385
+ * A build machine is thrown away at the end of the job, so the cached model a
386
+ * laptop uses would never get a second invocation to read it. This is the one
387
+ * place a check is on the critical path, and it is bounded at two seconds
388
+ * before work that takes minutes. It never refuses the run: CI's contract is
389
+ * that the workflow decides what runs, and a scanner that declined to start
390
+ * because a newer one exists would be a worse outage than the stale build.
391
+ */
392
+ export async function ciUpdateNotice(argv, env = process.env, fetchImpl = fetch) {
393
+ if (suppressed(env) || !inCi(env) || !isScanInvocation(argv))
394
+ return null;
395
+ const latest = await fetchLatest(fetchImpl);
396
+ return updateNotice(currentVersion(), latest, { env });
397
+ }
398
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carrick",
3
- "version": "0.3.84",
3
+ "version": "0.3.86",
4
4
  "description": "The API contract index for a TypeScript workspace: what the other services do with the routes and calls in the file you are editing, in your editor and in your agent's context",
5
5
  "keywords": [
6
6
  "typescript",
@@ -41,7 +41,7 @@
41
41
  "LICENSE.md"
42
42
  ],
43
43
  "scripts": {
44
- "test": "tsc --noEmit && npm run build && node --test 'test/**/*.test.ts'",
44
+ "test": "tsc --noEmit && npm run build && node --test --import=./test/no-update-check.mjs 'test/**/*.test.ts'",
45
45
  "typecheck": "tsc --noEmit",
46
46
  "selftest": "node test/selftest.ts",
47
47
  "bundle": "node scripts/bundle-sidecar.mjs",
@@ -58,11 +58,11 @@
58
58
  "zod": "^3.23.0"
59
59
  },
60
60
  "optionalDependencies": {
61
- "@carrick-tools/cli-darwin-arm64": "0.3.84",
62
- "@carrick-tools/cli-darwin-x64": "0.3.84",
63
- "@carrick-tools/cli-linux-arm64": "0.3.84",
64
- "@carrick-tools/cli-linux-x64": "0.3.84",
65
- "@carrick-tools/cli-win32-x64": "0.3.84"
61
+ "@carrick-tools/cli-darwin-arm64": "0.3.86",
62
+ "@carrick-tools/cli-darwin-x64": "0.3.86",
63
+ "@carrick-tools/cli-linux-arm64": "0.3.86",
64
+ "@carrick-tools/cli-linux-x64": "0.3.86",
65
+ "@carrick-tools/cli-win32-x64": "0.3.86"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/node": "^24.13.3",