getculpa 1.0.1 → 1.0.3
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/LICENSE +41 -0
- package/assets/culpa-compose.yml +6 -6
- package/assets/uninstall-culpa.ps1 +115 -5
- package/bin/getculpa.js +34 -6
- package/lib/bootstrap.d.mts +29 -0
- package/lib/bootstrap.mjs +97 -0
- package/lib/dispatch.d.mts +12 -0
- package/lib/dispatch.mjs +59 -0
- package/lib/docker.d.mts +4 -0
- package/lib/docker.mjs +19 -0
- package/lib/doctor.mjs +38 -10
- package/lib/install-summary.d.mts +18 -0
- package/lib/install-summary.mjs +156 -0
- package/lib/paths.mjs +6 -0
- package/lib/provision.d.mts +30 -1
- package/lib/provision.mjs +86 -5
- package/lib/repair.d.mts +1 -0
- package/lib/repair.mjs +174 -135
- package/lib/start.d.mts +2 -0
- package/lib/start.mjs +99 -7
- package/lib/tty.d.mts +18 -0
- package/lib/tty.mjs +58 -0
- package/lib/uninstall.mjs +45 -6
- package/package.json +25 -24
- package/scripts/install.js +35 -12
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// T-CF28-5 (postinstall output) + T-CF28-7 (the install-time half of the
|
|
2
|
+
// Docker ask) — the lines postinstall prints when it finishes.
|
|
3
|
+
//
|
|
4
|
+
// Extracted from scripts/install.js's main() as a PURE function. The words
|
|
5
|
+
// are the product here: the shipped 1.0.1 printed "Culpa installed
|
|
6
|
+
// successfully." on a fresh Mac with no Docker, where nothing could actually
|
|
7
|
+
// start. That line lived inline in a CommonJS script with no export, so no
|
|
8
|
+
// test could assert it. It is a line-builder now so the claims it makes are
|
|
9
|
+
// checked by tests/npm-core-install-summary.test.ts.
|
|
10
|
+
//
|
|
11
|
+
// TWO RULES THIS FILE EXISTS TO ENFORCE:
|
|
12
|
+
//
|
|
13
|
+
// 1. Never claim "ready" unless it IS ready. The founder's ruled headline is
|
|
14
|
+
// "Culpa is installed and ready." with `ready` in green — printed when
|
|
15
|
+
// Docker is genuinely usable. When Docker is missing or stopped, the
|
|
16
|
+
// headline drops to "Culpa is installed." and the Docker requirement is
|
|
17
|
+
// stated plainly. Printing the ruled line unconditionally would repeat the
|
|
18
|
+
// exact defect that created T-CF28-7.
|
|
19
|
+
//
|
|
20
|
+
// 2. Say what each platform will really do. postinstall CANNOT prompt
|
|
21
|
+
// (scripts/install.js:13-15 — npm installs run headless and a stdin read
|
|
22
|
+
// would hang), so this file only DETECTS and TELLS; the asking happens at
|
|
23
|
+
// first `getculpa`. win32 already ships that flow
|
|
24
|
+
// (installers/windows/launch-culpa.ps1:179-234); darwin gains it in
|
|
25
|
+
// lib/start.mjs; linux stays guidance-only, because installing a system
|
|
26
|
+
// package without explicit consent is out of bounds (the same rule
|
|
27
|
+
// lib/docker.mjs:73-79 already follows for starting the engine).
|
|
28
|
+
|
|
29
|
+
import { green } from "./tty.mjs";
|
|
30
|
+
|
|
31
|
+
const DOCKER_DESKTOP_URL = "https://www.docker.com/products/docker-desktop/";
|
|
32
|
+
const DOCKER_ENGINE_DOCS_URL = "https://docs.docker.com/engine/install/";
|
|
33
|
+
|
|
34
|
+
function headline(classification, version, previousVersion, dockerReady, colour) {
|
|
35
|
+
switch (classification) {
|
|
36
|
+
case "upgrade":
|
|
37
|
+
return `Culpa updated: ${previousVersion} -> ${version} (staged; applies at next \`getculpa\`).`;
|
|
38
|
+
case "downgrade-package":
|
|
39
|
+
return `Culpa ${previousVersion} is already installed; this package (${version}) is older and was not applied.`;
|
|
40
|
+
case "same-version":
|
|
41
|
+
case "repair":
|
|
42
|
+
return "Culpa installation repaired.";
|
|
43
|
+
default:
|
|
44
|
+
// "fresh" — the only case the founder's ruled wording describes.
|
|
45
|
+
return dockerReady ? `Culpa is installed and ${green("ready", colour)}.` : "Culpa is installed.";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// V102 T-V102-15 (M3, D-113): the row reports the three REAL states read
|
|
50
|
+
// from updates/state.json (readPayloadState), never the updater's exit code
|
|
51
|
+
// — the shipped 1.0.2 printed "Culpa CLI: installed" on a Mac whose
|
|
52
|
+
// state.json read current: null, while doctor FAILed the same install.
|
|
53
|
+
const PAYLOAD_ROW = {
|
|
54
|
+
installed: "installed",
|
|
55
|
+
staged: "staged - activates at your next `getculpa`",
|
|
56
|
+
missing: "deferred - run `getculpa update` to finish",
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
function inventory(appDir, imagesStaged, collectorStaged, payloadState) {
|
|
60
|
+
return [
|
|
61
|
+
` Location: ${appDir}`,
|
|
62
|
+
// T-CF28-4b: the CLI payload is the program `getculpa` actually runs. When
|
|
63
|
+
// it is missing the install is not usable at all, so this row names the
|
|
64
|
+
// one command that finishes the job rather than leaving a dead first run.
|
|
65
|
+
` Culpa CLI: ${PAYLOAD_ROW[payloadState] ?? PAYLOAD_ROW.missing}`,
|
|
66
|
+
` Images: ${imagesStaged ? "staged" : "deferred to first run"}`,
|
|
67
|
+
` Capture: ${collectorStaged ? "collector installed" : "off (collector not installed)"}`,
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Docker is MISSING. Each platform gets only what is true for it.
|
|
72
|
+
function dockerMissingLines(platform) {
|
|
73
|
+
const lines = [
|
|
74
|
+
"Culpa needs Docker to run: its database and services run in containers.",
|
|
75
|
+
"Docker was not found on this machine.",
|
|
76
|
+
];
|
|
77
|
+
if (platform === "darwin") {
|
|
78
|
+
lines.push(
|
|
79
|
+
" Install it with: brew install --cask docker",
|
|
80
|
+
" Homebrew asks for your password, and you must open Docker once from",
|
|
81
|
+
" Applications before Culpa can start - it is not a one-click install.",
|
|
82
|
+
` Or download it: ${DOCKER_DESKTOP_URL}`,
|
|
83
|
+
"Culpa will offer to do this for you the first time you run `getculpa`.",
|
|
84
|
+
);
|
|
85
|
+
} else if (platform === "win32") {
|
|
86
|
+
lines.push(
|
|
87
|
+
"Culpa will offer to install Docker for you the first time you run `getculpa`.",
|
|
88
|
+
` Or download it: ${DOCKER_DESKTOP_URL}`,
|
|
89
|
+
);
|
|
90
|
+
} else {
|
|
91
|
+
lines.push(
|
|
92
|
+
` Install Docker Engine: ${DOCKER_ENGINE_DOCS_URL}`,
|
|
93
|
+
"Culpa will not install system packages for you - install it yourself, then",
|
|
94
|
+
"run `getculpa`.",
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return lines;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Docker is PRESENT but the engine is stopped. Starting it is something Culpa
|
|
101
|
+
// really does do on darwin (lib/docker.mjs:69-72, `open -a Docker`) and win32
|
|
102
|
+
// (installers/windows/launch-culpa.ps1:236-244) — but never on linux.
|
|
103
|
+
function dockerStoppedLines(platform) {
|
|
104
|
+
const lines = ["Docker is installed but its engine is not running."];
|
|
105
|
+
if (platform === "linux") {
|
|
106
|
+
lines.push(" Start it yourself, for example: sudo systemctl start docker");
|
|
107
|
+
} else {
|
|
108
|
+
lines.push(" Culpa will start it for you when you run `getculpa`.");
|
|
109
|
+
}
|
|
110
|
+
return lines;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function buildInstallSummary(opts) {
|
|
114
|
+
const {
|
|
115
|
+
classification,
|
|
116
|
+
version,
|
|
117
|
+
previousVersion = null,
|
|
118
|
+
appDir,
|
|
119
|
+
dockerState,
|
|
120
|
+
imagesStaged = false,
|
|
121
|
+
collectorStaged = false,
|
|
122
|
+
// T-CF28-4b / V102 T-V102-15. Fail-CLOSED, matching imagesStaged/
|
|
123
|
+
// collectorStaged above: a caller that cannot say whether the payload is
|
|
124
|
+
// there has no evidence for "ready", and this function exists precisely
|
|
125
|
+
// to stop readiness being claimed without evidence. scripts/install.js
|
|
126
|
+
// passes the real state read from updates/state.json (readPayloadState).
|
|
127
|
+
payloadState = "missing",
|
|
128
|
+
platform = process.platform,
|
|
129
|
+
isTTY = false,
|
|
130
|
+
env = {},
|
|
131
|
+
} = opts;
|
|
132
|
+
|
|
133
|
+
const dockerReady = dockerState === "ready";
|
|
134
|
+
// "ready" means the next command will work. A MISSING CLI payload breaks
|
|
135
|
+
// that just as completely as a missing Docker, so it gates the word too.
|
|
136
|
+
// "staged" keeps it: the pending version activates at that very launch.
|
|
137
|
+
const ready = dockerReady && payloadState !== "missing";
|
|
138
|
+
const colour = { isTTY, env };
|
|
139
|
+
const lines = [headline(classification, version, previousVersion, ready, colour)];
|
|
140
|
+
|
|
141
|
+
// A refused downgrade staged nothing — an inventory there would describe a
|
|
142
|
+
// state this run did not produce (lib/provision.mjs:175-183).
|
|
143
|
+
if (classification !== "downgrade-package") {
|
|
144
|
+
lines.push(...inventory(appDir, imagesStaged, collectorStaged, payloadState));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!dockerReady) {
|
|
148
|
+
lines.push("");
|
|
149
|
+
lines.push(...(dockerState === "missing" ? dockerMissingLines(platform) : dockerStoppedLines(platform)));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
lines.push("");
|
|
153
|
+
lines.push(ready ? "Run:" : "Then run:");
|
|
154
|
+
lines.push(" getculpa");
|
|
155
|
+
return lines;
|
|
156
|
+
}
|
package/lib/paths.mjs
CHANGED
|
@@ -19,6 +19,12 @@ import path from "node:path";
|
|
|
19
19
|
// "a test set this" from "an operator set this" from inside the module, and
|
|
20
20
|
// refusing a real operator's override would be a worse failure mode than
|
|
21
21
|
// honoring it.
|
|
22
|
+
//
|
|
23
|
+
// D-108 (cli-v1.0.2): the vendored Rust launcher honors CULPA_APP_DIR too —
|
|
24
|
+
// as a fallback when its own CULPA_HOME is unset (native/culpa-launcher/
|
|
25
|
+
// src/home.rs). So relocating with this variable moves BOTH halves: the
|
|
26
|
+
// stack/licence state this module resolves AND the launcher's
|
|
27
|
+
// versions/updates state. Keep the two sides in step if either changes.
|
|
22
28
|
export function getAppDir(opts = {}) {
|
|
23
29
|
const env = opts.env ?? process.env;
|
|
24
30
|
const platform = opts.platform ?? process.platform;
|
package/lib/provision.d.mts
CHANGED
|
@@ -2,9 +2,31 @@ import type { UpgradeClassification } from "./preflight.d.mts";
|
|
|
2
2
|
|
|
3
3
|
export const PARITY_ASSETS: string[];
|
|
4
4
|
|
|
5
|
+
// T-CF28-6 — the Windows-only subset, and the platform-scoped accessor that
|
|
6
|
+
// provision(), repair() and doctor() all read.
|
|
7
|
+
export const WINDOWS_ONLY_ASSETS: readonly string[];
|
|
8
|
+
export function parityAssetsFor(platform?: string): string[];
|
|
9
|
+
|
|
10
|
+
// T-CF29-8 — the app-dir name culpa-collector.ps1 reads (Node platform-arch),
|
|
11
|
+
// not the Rust target triple the release asset uses.
|
|
12
|
+
export function collectorBinaryName(platform?: string, arch?: string): string;
|
|
13
|
+
|
|
14
|
+
// Exported so lib/repair.mjs stages the collector to the SAME place with the
|
|
15
|
+
// SAME name — the two must never disagree about where capture lives.
|
|
16
|
+
export function stageCollectorBinary(opts: {
|
|
17
|
+
appDir: string;
|
|
18
|
+
vendorDir: string;
|
|
19
|
+
platform?: string;
|
|
20
|
+
arch?: string;
|
|
21
|
+
}): boolean;
|
|
22
|
+
|
|
5
23
|
// CF20-T5: exported for lib/repair.mjs's reuse — see provision.mjs's comment
|
|
6
24
|
// on the export.
|
|
7
|
-
export function stageParityFiles(
|
|
25
|
+
export function stageParityFiles(
|
|
26
|
+
appDir: string,
|
|
27
|
+
env?: Record<string, string | undefined>,
|
|
28
|
+
platform?: string,
|
|
29
|
+
): void;
|
|
8
30
|
export function stageLiveComposeIfAbsent(appDir: string): boolean;
|
|
9
31
|
|
|
10
32
|
export interface ProvisionOptions {
|
|
@@ -12,14 +34,21 @@ export interface ProvisionOptions {
|
|
|
12
34
|
currentVersion: string;
|
|
13
35
|
collectorFetched?: boolean;
|
|
14
36
|
platform?: string;
|
|
37
|
+
arch?: string;
|
|
38
|
+
vendorDir?: string;
|
|
15
39
|
dockerSpawnSync?: (cmd: string, args?: string[], opts?: unknown) => { status: number | null };
|
|
16
40
|
delegateWindowsInstaller?: (appDir: string) => boolean;
|
|
17
41
|
env?: Record<string, string | undefined>;
|
|
18
42
|
}
|
|
19
43
|
|
|
44
|
+
export type DockerState = "missing" | "installed-not-running" | "ready";
|
|
45
|
+
|
|
20
46
|
export interface ProvisionResult {
|
|
21
47
|
classification: UpgradeClassification;
|
|
22
48
|
previousVersion: string | null;
|
|
49
|
+
dockerState: DockerState;
|
|
50
|
+
imagesStaged: boolean;
|
|
51
|
+
collectorStaged: boolean;
|
|
23
52
|
}
|
|
24
53
|
|
|
25
54
|
export function provision(opts: ProvisionOptions): Promise<ProvisionResult>;
|
package/lib/provision.mjs
CHANGED
|
@@ -16,12 +16,20 @@
|
|
|
16
16
|
import { spawnSync as realSpawnSync } from "node:child_process";
|
|
17
17
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
18
18
|
import path from "node:path";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
19
20
|
import { checkDockerEngineReachable, checkDockerPresent, classifyUpgrade, isIncomingComposeOlder } from "./preflight.mjs";
|
|
20
21
|
import { resolveAssetPath } from "./assets.mjs";
|
|
21
22
|
import { canonicalAppDir } from "./paths.mjs";
|
|
22
23
|
|
|
24
|
+
// T-CF29-8: where lib/fetch.mjs stages the vendored binaries. Same derivation
|
|
25
|
+
// lib/repair.mjs already uses, so the two agree on one vendor directory.
|
|
26
|
+
const packageRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
27
|
+
|
|
23
28
|
// The full parity file-set (Windows inventory: culpa-setup.iss:43-54, minus
|
|
24
29
|
// the collectord binary, which lib/fetch.mjs stages separately by triple).
|
|
30
|
+
// This is the WINDOWS inventory and stays the canonical full list — use
|
|
31
|
+
// parityAssetsFor(platform) to get what a given platform should actually
|
|
32
|
+
// receive.
|
|
25
33
|
export const PARITY_ASSETS = [
|
|
26
34
|
"culpa-compose.yml",
|
|
27
35
|
"install-culpa.ps1",
|
|
@@ -31,6 +39,29 @@ export const PARITY_ASSETS = [
|
|
|
31
39
|
"register.mjs",
|
|
32
40
|
];
|
|
33
41
|
|
|
42
|
+
// T-CF28-6 — four of the six are PowerShell scripts that only win32 can run:
|
|
43
|
+
// lib/start.mjs delegates to launch-culpa.ps1 only when platform === "win32"
|
|
44
|
+
// (start.mjs:457), lib/uninstall.mjs only delegates to uninstall-culpa.ps1 on
|
|
45
|
+
// win32 (uninstall.mjs:80-82), and install-culpa.ps1/culpa-collector.ps1 are
|
|
46
|
+
// invoked by the Windows installer path alone. Staging them on darwin/linux
|
|
47
|
+
// put four inert files in the user's app dir and made `getculpa doctor` grade
|
|
48
|
+
// them as part of a healthy install.
|
|
49
|
+
export const WINDOWS_ONLY_ASSETS = Object.freeze([
|
|
50
|
+
"install-culpa.ps1",
|
|
51
|
+
"launch-culpa.ps1",
|
|
52
|
+
"uninstall-culpa.ps1",
|
|
53
|
+
"culpa-collector.ps1",
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
// The single source of truth for "which parity files belong on this platform".
|
|
57
|
+
// provision(), repair() and doctor() ALL read it — if any one of them used the
|
|
58
|
+
// flat list instead, repair would restore what provision skipped, or doctor
|
|
59
|
+
// would fail an install for a file that is correctly absent.
|
|
60
|
+
export function parityAssetsFor(platform = process.platform) {
|
|
61
|
+
if (platform === "win32") return PARITY_ASSETS;
|
|
62
|
+
return PARITY_ASSETS.filter((name) => !WINDOWS_ONLY_ASSETS.includes(name));
|
|
63
|
+
}
|
|
64
|
+
|
|
34
65
|
// CF20-T6 — protects the SHIPPED culpa-compose.yml the same way
|
|
35
66
|
// stageLiveComposeIfAbsent already protects the live one, mirroring
|
|
36
67
|
// launch-culpa.ps1's QW-1 one-direction rule: an older incoming pin must
|
|
@@ -60,10 +91,10 @@ function stageShippedCompose(appDir, env) {
|
|
|
60
91
|
// logic — same reason the task instructions call out reuse over a second
|
|
61
92
|
// copy. Purely additive: behavior and call sites inside this file are
|
|
62
93
|
// unchanged.
|
|
63
|
-
export function stageParityFiles(appDir, env = process.env) {
|
|
94
|
+
export function stageParityFiles(appDir, env = process.env, platform = process.platform) {
|
|
64
95
|
mkdirSync(appDir, { recursive: true });
|
|
65
96
|
stageShippedCompose(appDir, env);
|
|
66
|
-
for (const name of
|
|
97
|
+
for (const name of parityAssetsFor(platform)) {
|
|
67
98
|
if (name === "culpa-compose.yml") continue;
|
|
68
99
|
copyFileSync(resolveAssetPath(name), path.join(appDir, name));
|
|
69
100
|
}
|
|
@@ -79,6 +110,40 @@ export function stageLiveComposeIfAbsent(appDir) {
|
|
|
79
110
|
return true;
|
|
80
111
|
}
|
|
81
112
|
|
|
113
|
+
// T-CF29-8 — the name culpa-collector.ps1:35 reads from the app dir, and the
|
|
114
|
+
// same name culpa-setup.iss:52 installs there. NOT the Rust target triple
|
|
115
|
+
// lib/fetch.mjs uses for the release asset (x86_64-pc-windows-msvc): this is
|
|
116
|
+
// the Node-style platform-arch pair.
|
|
117
|
+
export function collectorBinaryName(platform = process.platform, arch = process.arch) {
|
|
118
|
+
const exe = platform === "win32" ? ".exe" : "";
|
|
119
|
+
return `culpa-collectord-${platform}-${arch}${exe}`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// T-CF29-8 — capture was silently OFF on every Windows npm install:
|
|
123
|
+
// "culpa-collectord-win32-x64.exe not present in this package - skipping
|
|
124
|
+
// capture setup". lib/fetch.mjs stages the binary into the PACKAGE's vendor/
|
|
125
|
+
// as culpa-collectord.exe, the .ps1 reads it from the APP DIR under the
|
|
126
|
+
// triple-suffixed name, and nothing bridged the two. The Windows installer
|
|
127
|
+
// path has always put it in the app dir, so this is the npm path catching up
|
|
128
|
+
// to installer parity, not a new convention.
|
|
129
|
+
//
|
|
130
|
+
// Returns whether the binary is really there afterwards — never a hopeful
|
|
131
|
+
// echo of the caller's collectorFetched flag, because "capture is on" is
|
|
132
|
+
// exactly the kind of claim that must be backed by a file on disk.
|
|
133
|
+
export function stageCollectorBinary({ appDir, vendorDir, platform, arch }) {
|
|
134
|
+
const exe = platform === "win32" ? ".exe" : "";
|
|
135
|
+
const src = path.join(vendorDir, `culpa-collectord${exe}`);
|
|
136
|
+
if (!existsSync(src)) return false;
|
|
137
|
+
const dest = path.join(appDir, collectorBinaryName(platform, arch));
|
|
138
|
+
try {
|
|
139
|
+
copyFileSync(src, dest);
|
|
140
|
+
} catch (e) {
|
|
141
|
+
console.warn(`getculpa: capture collector could not be staged (${e.message}) - capture OFF, everything else works.`);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return existsSync(dest);
|
|
145
|
+
}
|
|
146
|
+
|
|
82
147
|
function detectDockerState(dockerSpawnSync) {
|
|
83
148
|
if (!checkDockerPresent(dockerSpawnSync)) return "missing";
|
|
84
149
|
if (!checkDockerEngineReachable(dockerSpawnSync)) return "installed-not-running";
|
|
@@ -152,6 +217,8 @@ export async function provision(opts) {
|
|
|
152
217
|
currentVersion,
|
|
153
218
|
collectorFetched = false,
|
|
154
219
|
platform = process.platform,
|
|
220
|
+
arch = process.arch,
|
|
221
|
+
vendorDir = path.join(packageRoot, "vendor"),
|
|
155
222
|
dockerSpawnSync = realSpawnSync,
|
|
156
223
|
delegateWindowsInstaller = defaultDelegateWindowsInstaller,
|
|
157
224
|
env = process.env,
|
|
@@ -179,10 +246,19 @@ export async function provision(opts) {
|
|
|
179
246
|
`getculpa: this package is older than the installed Culpa ${previousVersion} - skipping the parity file re-stage entirely (compose, scripts, register.mjs) to avoid a mixed-version app dir (set CULPA_ALLOW_DOWNGRADE=1 to override).`,
|
|
180
247
|
);
|
|
181
248
|
} else {
|
|
182
|
-
stageParityFiles(appDir, env);
|
|
249
|
+
stageParityFiles(appDir, env, platform);
|
|
183
250
|
}
|
|
184
251
|
stageLiveComposeIfAbsent(appDir);
|
|
185
252
|
|
|
253
|
+
// T-CF29-8: only attempt it when the fetch reported success; the result is
|
|
254
|
+
// what gets recorded, not the intent.
|
|
255
|
+
const collectorStaged = collectorFetched && stageCollectorBinary({ appDir, vendorDir, platform, arch });
|
|
256
|
+
if (collectorFetched && !collectorStaged) {
|
|
257
|
+
console.warn(
|
|
258
|
+
"getculpa: the capture collector was downloaded but could not be placed in the app directory - capture OFF, everything else works.",
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
186
262
|
const dockerState = detectDockerState(dockerSpawnSync);
|
|
187
263
|
let imagesStaged = false;
|
|
188
264
|
if (dockerState === "ready") {
|
|
@@ -229,9 +305,14 @@ export async function provision(opts) {
|
|
|
229
305
|
updatedAt: new Date().toISOString(),
|
|
230
306
|
dockerState,
|
|
231
307
|
imagesStaged,
|
|
232
|
-
collectorStaged
|
|
308
|
+
collectorStaged,
|
|
233
309
|
platform,
|
|
234
310
|
});
|
|
235
311
|
|
|
236
|
-
|
|
312
|
+
// T-CF28-5/7: the Docker and staging facts were already computed above and
|
|
313
|
+
// written to install-state.json, but the caller that has to REPORT them
|
|
314
|
+
// (scripts/install.js) could not see them — which is how a Docker-less
|
|
315
|
+
// install still printed "Culpa installed successfully." Returning them
|
|
316
|
+
// changes no behavior here; it just stops postinstall from having to guess.
|
|
317
|
+
return { classification, previousVersion, dockerState, imagesStaged, collectorStaged };
|
|
237
318
|
}
|
package/lib/repair.d.mts
CHANGED