carrick 0.3.84 → 0.3.85
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 +15 -0
- package/bin/carrick.mjs +89 -0
- package/dist/auth/credentials.d.ts +9 -0
- package/dist/auth/credentials.js +13 -2
- package/dist/auth/credentials.js.map +1 -1
- package/dist/auth/read.d.ts +4 -4
- package/dist/global-install.d.ts +183 -0
- package/dist/global-install.js +393 -0
- package/dist/global-install.js.map +1 -0
- package/dist/hook/post-edit.js +10 -0
- package/dist/hook/post-edit.js.map +1 -1
- package/dist/hook/session-start.js +34 -0
- package/dist/hook/session-start.js.map +1 -1
- package/dist/hook/stop.js +18 -4
- package/dist/hook/stop.js.map +1 -1
- package/dist/hook/user-prompt.js +16 -4
- package/dist/hook/user-prompt.js.map +1 -1
- package/dist/init/doctor.d.ts +40 -0
- package/dist/init/doctor.js +125 -0
- package/dist/init/doctor.js.map +1 -1
- package/dist/init/outdated.d.ts +47 -0
- package/dist/init/outdated.js +104 -0
- package/dist/init/outdated.js.map +1 -1
- package/dist/init/projects.d.ts +2 -2
- package/dist/init/run.d.ts +9 -0
- package/dist/init/run.js +57 -12
- package/dist/init/run.js.map +1 -1
- package/dist/scan.d.ts +26 -0
- package/dist/scan.js +92 -0
- package/dist/scan.js.map +1 -1
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +25 -0
- package/dist/update-check.js.map +1 -0
- package/dist/update.d.ts +128 -0
- package/dist/update.js +398 -0
- package/dist/update.js.map +1 -0
- package/package.json +7 -7
- package/sidecar/dist/src/capture/anchors.js +69 -8
- package/sidecar/dist/src/capture/api.d.ts +4 -1
- package/sidecar/dist/src/capture/deep-walk.js +4 -1
- package/sidecar/dist/src/capture/node-builder.d.ts +28 -1
- package/sidecar/dist/src/capture/node-builder.js +89 -3
- package/sidecar/dist/src/capture/unresolved.d.ts +7 -0
- package/sidecar/dist/src/capture/unresolved.js +1 -1
- package/sidecar/dist/src/type-inferrer.d.ts +118 -4
- package/sidecar/dist/src/type-inferrer.js +433 -15
- package/templates/skills/carrick-census.md +3 -1
package/dist/update.d.ts
ADDED
|
@@ -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.
|
|
3
|
+
"version": "0.3.85",
|
|
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.
|
|
62
|
-
"@carrick-tools/cli-darwin-x64": "0.3.
|
|
63
|
-
"@carrick-tools/cli-linux-arm64": "0.3.
|
|
64
|
-
"@carrick-tools/cli-linux-x64": "0.3.
|
|
65
|
-
"@carrick-tools/cli-win32-x64": "0.3.
|
|
61
|
+
"@carrick-tools/cli-darwin-arm64": "0.3.85",
|
|
62
|
+
"@carrick-tools/cli-darwin-x64": "0.3.85",
|
|
63
|
+
"@carrick-tools/cli-linux-arm64": "0.3.85",
|
|
64
|
+
"@carrick-tools/cli-linux-x64": "0.3.85",
|
|
65
|
+
"@carrick-tools/cli-win32-x64": "0.3.85"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/node": "^24.13.3",
|