bootproof 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +840 -152
- package/dist/agent-plan.d.ts +44 -0
- package/dist/agent-plan.js +826 -0
- package/dist/agent-run.d.ts +117 -0
- package/dist/agent-run.js +459 -0
- package/dist/ai-repair.d.ts +58 -0
- package/dist/ai-repair.js +380 -0
- package/dist/cli.js +730 -46
- package/dist/diagnosis.js +101 -16
- package/dist/diff.d.ts +29 -0
- package/dist/diff.js +569 -0
- package/dist/exec.d.ts +30 -2
- package/dist/exec.js +329 -51
- package/dist/external-health.d.ts +16 -0
- package/dist/external-health.js +214 -0
- package/dist/infer.js +238 -39
- package/dist/plan.js +2 -0
- package/dist/proof.d.ts +78 -2
- package/dist/proof.js +265 -12
- package/dist/receipt.d.ts +52 -0
- package/dist/receipt.js +356 -0
- package/dist/redact.d.ts +4 -0
- package/dist/redact.js +86 -2
- package/dist/registry.d.ts +82 -30
- package/dist/registry.js +355 -53
- package/dist/remote.js +3 -3
- package/dist/repair-playbooks.d.ts +24 -0
- package/dist/repair-playbooks.js +593 -0
- package/dist/repair-safety.d.ts +130 -0
- package/dist/repair-safety.js +766 -0
- package/dist/repair.d.ts +43 -11
- package/dist/repair.js +716 -7
- package/dist/run.d.ts +3 -0
- package/dist/run.js +218 -41
- package/dist/sbom.d.ts +22 -0
- package/dist/sbom.js +99 -0
- package/dist/taxonomy.d.ts +8 -3
- package/dist/taxonomy.js +404 -8
- package/dist/types.d.ts +40 -1
- package/docs/AGENT_IN_THE_LOOP.md +171 -0
- package/docs/AGENT_RUN_RECEIPTS.md +38 -0
- package/docs/CI_ACTION.md +67 -2
- package/docs/DETERMINISTIC_REPAIR_SAFETY_MODEL.md +705 -0
- package/docs/FAILURE_TAXONOMY.md +28 -1
- package/docs/HONESTY_CONTRACT.md +34 -12
- package/docs/LAUNCH_PLAYBOOK.md +232 -0
- package/docs/REAL_WORLD_FIXTURES.md +105 -0
- package/docs/REGISTRY.md +48 -28
- package/docs/REPAIR_RECEIPT.md +54 -8
- package/docs/agent-loop-gap-analysis.md +188 -0
- package/docs/examples/registry-seeds/advertised-port-mismatch.json +28 -0
- package/docs/examples/registry-seeds/airbyte-abctl-external-orchestrator.json +36 -0
- package/docs/examples/registry-seeds/go-ollama-service.json +36 -0
- package/docs/examples/registry-seeds/laravel-vite-sqlite.json +36 -0
- package/docs/examples/registry-seeds/monorepo-ambiguous-health.json +29 -0
- package/docs/examples/registry-seeds/php-composer.json +33 -0
- package/docs/examples/registry-seeds/rails-bundler.json +32 -0
- package/docs/examples/registry-seeds/sentry-devenv-direnv.json +41 -0
- package/docs/schemas/action-verdict-v1.schema.json +64 -0
- package/docs/schemas/agent-plan-v1.schema.json +148 -0
- package/docs/schemas/agent-run-receipts-v1.schema.json +192 -0
- package/docs/schemas/ai-repair-suggestion-v1.schema.json +70 -0
- package/docs/schemas/ci-context-v1.schema.json +63 -0
- package/docs/schemas/diff-result-v1.schema.json +66 -0
- package/docs/schemas/federated-receipt-v1.schema.json +51 -0
- package/docs/schemas/registry-entry-v1.schema.json +95 -0
- package/docs/schemas/registry-seed-example-v1.schema.json +102 -0
- package/docs/schemas/repair-action-v1.schema.json +136 -0
- package/docs/schemas/repair-receipt-v1.schema.json +221 -0
- package/package.json +10 -6
package/dist/diagnosis.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { classifyFailure, extractMissingEnvNames, safeLocalEnvValue } from "./taxonomy.js";
|
|
1
2
|
function packageManagerMismatch(evidence, inference) {
|
|
2
3
|
const expected = evidence?.match(/expected version:\s*([^\n]+)/i)?.[1]?.trim() ?? inference?.packageManagerVersion ?? "the declared version";
|
|
3
4
|
const actual = evidence?.match(/Got:\s*([^\n]+)/i)?.[1]?.trim() ?? "a different version";
|
|
@@ -15,7 +16,48 @@ function packageManagerMismatch(evidence, inference) {
|
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
export function diagnoseFailure(failureClass, evidence, explanation, inference) {
|
|
19
|
+
const classified = evidence ? classifyFailure(evidence) : null;
|
|
20
|
+
const precise = classified?.class === failureClass ? classified : null;
|
|
21
|
+
const preciseFailure = (whyRefused, fallbackSafeNextStep) => ({
|
|
22
|
+
whatHappened: precise?.explanation ?? explanation,
|
|
23
|
+
whyRefused,
|
|
24
|
+
safeNextStep: precise?.safeNextStep ?? fallbackSafeNextStep,
|
|
25
|
+
});
|
|
18
26
|
switch (failureClass) {
|
|
27
|
+
case "missing_ruby_version":
|
|
28
|
+
return preciseFailure("BootProof cannot execute the repository with a Ruby version that is not installed.", "Install the repository-required Ruby version with rbenv, then rerun BootProof.");
|
|
29
|
+
case "missing_php_runtime":
|
|
30
|
+
return preciseFailure("BootProof cannot execute the repository without a supported PHP runtime.", "Install a PHP version supported by the repository, then rerun BootProof.");
|
|
31
|
+
case "missing_composer":
|
|
32
|
+
return preciseFailure("BootProof cannot install the repository's PHP dependencies without Composer.", "Install Composer using its documented installation method, then rerun BootProof.");
|
|
33
|
+
case "unsupported_php_version_for_composer_lock":
|
|
34
|
+
return preciseFailure("Composer refused the locked dependency set because the available PHP version is unsupported.", "Use a PHP version compatible with composer.lock, then rerun composer install.");
|
|
35
|
+
case "missing_php_vendor_autoload":
|
|
36
|
+
return preciseFailure("The PHP dependency autoloader is absent, so the application cannot start reliably.", "Resolve any PHP or Composer version issue first, then run composer install to generate vendor/autoload.php.");
|
|
37
|
+
case "laravel_sqlite_database_missing":
|
|
38
|
+
return preciseFailure("Laravel cannot use the configured SQLite connection because its local database file is absent.", "After review, create database/database.sqlite and run php artisan migrate. Both steps mutate local state and require explicit approval.");
|
|
39
|
+
case "laravel_migrations_required":
|
|
40
|
+
return preciseFailure("Laravel started, but its required database tables are absent.", "Run php artisan migrate only after explicit approval because it mutates local database state.");
|
|
41
|
+
case "missing_build_tool":
|
|
42
|
+
return preciseFailure("The dependency installation cannot complete without the required native build tool.", "Install the reported build tool, then rerun BootProof.");
|
|
43
|
+
case "native_extension_compile_failed":
|
|
44
|
+
return preciseFailure("A required gem did not install, so the application cannot be started reliably.", "Inspect the preserved compiler output, install the required native dependencies, then rerun BootProof.");
|
|
45
|
+
case "missing_database_config":
|
|
46
|
+
return preciseFailure("The application has no usable database configuration, so a verified boot is impossible.", "Create config/database.yml from the repository's documented example, review it, then rerun BootProof.");
|
|
47
|
+
case "missing_required_config":
|
|
48
|
+
return preciseFailure("A repository-required configuration file is absent.", "Restore the reported file from the repository's documented example, review it, then rerun BootProof.");
|
|
49
|
+
case "postgres_unavailable":
|
|
50
|
+
return preciseFailure("The application could not reach the PostgreSQL service required for boot.", "Start PostgreSQL, verify its configured host and port, then rerun BootProof.");
|
|
51
|
+
case "postgres_role_missing":
|
|
52
|
+
return preciseFailure("PostgreSQL was reachable, but the configured role does not exist.", "Create the reported PostgreSQL role or configure an existing role, then rerun BootProof.");
|
|
53
|
+
case "database_schema_missing":
|
|
54
|
+
return preciseFailure("The database is reachable but its required schema is absent or incomplete.", "Run the repository's documented migration or database setup command, then rerun BootProof.");
|
|
55
|
+
case "unsupported_database_version":
|
|
56
|
+
return preciseFailure("The installed database version does not satisfy the repository's requirement.", "Install or select a supported PostgreSQL version, then rerun BootProof.");
|
|
57
|
+
case "unsupported_database_config":
|
|
58
|
+
return preciseFailure("The repository's database configuration contains names the application does not support.", "Update config/database.yml to use only supported database names, then rerun BootProof.");
|
|
59
|
+
case "redis_unavailable":
|
|
60
|
+
return preciseFailure("The application could not reach the Redis service required for boot.", "Start Redis, verify its configured host and port, then rerun BootProof.");
|
|
19
61
|
case "package_manager_version_mismatch":
|
|
20
62
|
return packageManagerMismatch(evidence, inference);
|
|
21
63
|
case "dependency_install_skipped":
|
|
@@ -30,12 +72,38 @@ export function diagnoseFailure(failureClass, evidence, explanation, inference)
|
|
|
30
72
|
whyRefused: "BootProof cannot yet orchestrate that multi-step application safely enough to claim a verified boot.",
|
|
31
73
|
safeNextStep: "Review the detected setup and service commands, complete the repository's documented initialization, then rerun when orchestration support is available.",
|
|
32
74
|
};
|
|
75
|
+
case "laravel_vite_ci_hmr_blocked":
|
|
76
|
+
return preciseFailure("Laravel's Vite integration blocked the HMR asset server in CI. That asset server is not proof that the Laravel application booted.", "For local verification: rerun with LARAVEL_BYPASS_ENV_CHECK=1 only if intentionally testing the Vite dev server. For CI verification: use production asset build instead of Vite HMR. For Laravel app verification: run the Laravel app server, not only the Vite asset server.");
|
|
33
77
|
case "orchestration_not_supported":
|
|
34
78
|
return {
|
|
35
79
|
whatHappened: explanation,
|
|
36
80
|
whyRefused: "The detected application requires backend/frontend or repository-specific orchestration that BootProof cannot yet execute safely.",
|
|
37
81
|
safeNextStep: "Use the repository's documented runbook. Treat this attestation as diagnosis only, not proof of a localhost boot.",
|
|
38
82
|
};
|
|
83
|
+
case "go_service_orchestration_not_supported":
|
|
84
|
+
return {
|
|
85
|
+
whatHappened: explanation,
|
|
86
|
+
whyRefused: "A Go service was detected, but repository evidence did not establish one safe runnable service command and health contract.",
|
|
87
|
+
safeNextStep: "Use the repository's documented service command, or rerun with an explicit reviewed --command and health port. Treat this attestation as diagnosis only.",
|
|
88
|
+
};
|
|
89
|
+
case "host_execution_not_acknowledged":
|
|
90
|
+
return {
|
|
91
|
+
whatHappened: explanation,
|
|
92
|
+
whyRefused: "Host execution was selected without the required explicit acknowledgement.",
|
|
93
|
+
safeNextStep: "Review the inferred commands, then rerun with --provider local --unsafe-local only if you accept host execution.",
|
|
94
|
+
};
|
|
95
|
+
case "auth_required":
|
|
96
|
+
return {
|
|
97
|
+
whatHappened: explanation,
|
|
98
|
+
whyRefused: "The external endpoint requires authentication, so its response is not sufficient public health evidence.",
|
|
99
|
+
safeNextStep: "Provide a separate unauthenticated health endpoint, or verify authentication manually without exposing credentials to BootProof.",
|
|
100
|
+
};
|
|
101
|
+
case "external_health_unreachable":
|
|
102
|
+
return {
|
|
103
|
+
whatHappened: explanation,
|
|
104
|
+
whyRefused: "BootProof did not observe a successful HTTP response from the externally managed service.",
|
|
105
|
+
safeNextStep: "Confirm the external service and endpoint are reachable, then rerun the external health verification.",
|
|
106
|
+
};
|
|
39
107
|
case "workspace_ambiguous":
|
|
40
108
|
if (/multiple workspaces in parallel|starts multiple workspaces in parallel/i.test(explanation)) {
|
|
41
109
|
return {
|
|
@@ -61,12 +129,20 @@ export function diagnoseFailure(failureClass, evidence, explanation, inference)
|
|
|
61
129
|
whyRefused: "A responding server is not a verified healthy boot when the observed response is a server error.",
|
|
62
130
|
safeNextStep: "Inspect the application logs and failing health route, fix the server error, then rerun BootProof.",
|
|
63
131
|
};
|
|
132
|
+
case "health_preoccupied":
|
|
133
|
+
return {
|
|
134
|
+
whatHappened: explanation,
|
|
135
|
+
whyRefused: "The healthy response existed before BootProof started the application, so BootProof cannot attribute it to this repository.",
|
|
136
|
+
safeNextStep: "Stop the existing service and rerun BootProof, or verify the already-running service explicitly with bootproof verify-url <url>.",
|
|
137
|
+
};
|
|
64
138
|
case "health_check_timeout":
|
|
65
139
|
return {
|
|
66
140
|
whatHappened: "No successful HTTP response was observed before the health timeout.",
|
|
67
141
|
whyRefused: "A running process alone is not proof that the application became reachable and healthy.",
|
|
68
142
|
safeNextStep: "Check the reported health candidates and application logs, then rerun with the correct port or a longer --timeout if justified.",
|
|
69
143
|
};
|
|
144
|
+
case "health_candidate_port_mismatch":
|
|
145
|
+
return preciseFailure("The supervised process advertised a different port from the inferred application health URL.", "Confirm the primary application command and intended health port. For Laravel verification, run the Laravel app server rather than only the Vite asset server.");
|
|
70
146
|
case "postgres_auth_env_missing":
|
|
71
147
|
return {
|
|
72
148
|
whatHappened: "Postgres was reached, but authentication or database environment configuration did not match.",
|
|
@@ -91,6 +167,12 @@ export function diagnoseFailure(failureClass, evidence, explanation, inference)
|
|
|
91
167
|
whyRefused: "BootProof cannot execute the repository's explicit run path without its declared runtime or build tool.",
|
|
92
168
|
safeNextStep: "Install the required tool at a version supported by the repository, then rerun BootProof.",
|
|
93
169
|
};
|
|
170
|
+
case "go_runtime_missing":
|
|
171
|
+
return preciseFailure("BootProof cannot execute the selected Go service command without the Go runtime.", "Install a Go version supported by the repository, then rerun BootProof.");
|
|
172
|
+
case "go_build_failed":
|
|
173
|
+
return preciseFailure("The selected Go service did not compile or its declared modules could not be resolved.", "Inspect the preserved Go compiler or module evidence, resolve the reported issue, then rerun BootProof.");
|
|
174
|
+
case "missing_project_cli":
|
|
175
|
+
return preciseFailure("The selected package script depends on a repository CLI that is not available in the current development environment.", "Prepare the repository's documented development environment or bootstrap services so its project CLI is available, then rerun BootProof.");
|
|
94
176
|
case "runtime_engine_mismatch":
|
|
95
177
|
return {
|
|
96
178
|
whatHappened: "The available Node.js runtime does not satisfy the repository's declared engine requirement.",
|
|
@@ -98,6 +180,17 @@ export function diagnoseFailure(failureClass, evidence, explanation, inference)
|
|
|
98
180
|
safeNextStep: "Switch to a compatible Node.js version, then rerun BootProof.",
|
|
99
181
|
};
|
|
100
182
|
case "missing_env_var":
|
|
183
|
+
{
|
|
184
|
+
const missing = extractMissingEnvNames(evidence ?? explanation);
|
|
185
|
+
const safeValue = missing.length === 1 ? safeLocalEnvValue(missing[0]) : null;
|
|
186
|
+
if (safeValue) {
|
|
187
|
+
return {
|
|
188
|
+
whatHappened: `Missing variable: ${missing[0]}. Safe local value: ${safeValue}.`,
|
|
189
|
+
whyRefused: "The application exited before BootProof could observe healthy HTTP behavior.",
|
|
190
|
+
safeNextStep: `${missing[0]}=${safeValue} bootproof up . --provider local --unsafe-local --install`,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
101
194
|
return {
|
|
102
195
|
whatHappened: explanation,
|
|
103
196
|
whyRefused: "BootProof will not invent secrets or write protected .env files to force startup.",
|
|
@@ -121,27 +214,19 @@ export function diagnoseFailure(failureClass, evidence, explanation, inference)
|
|
|
121
214
|
whyRefused: "BootProof cannot trust an application boot when its declared dependency installation failed.",
|
|
122
215
|
safeNextStep: "Inspect the preserved install evidence, fix the underlying package or environment problem, then rerun BootProof.",
|
|
123
216
|
};
|
|
124
|
-
case "app_exited_early":
|
|
217
|
+
case "app_exited_early": {
|
|
218
|
+
const processOutput = explanation.includes("Last process output")
|
|
219
|
+
? explanation.slice(explanation.indexOf("Last process output"))
|
|
220
|
+
: "";
|
|
125
221
|
return {
|
|
126
|
-
whatHappened:
|
|
222
|
+
whatHappened: processOutput
|
|
223
|
+
? `The application process exited before any health response was observed.\n${processOutput}`
|
|
224
|
+
: "The application process exited before any health response was observed.",
|
|
127
225
|
whyRefused: "No live application health signal was available to verify.",
|
|
128
226
|
safeNextStep: "Inspect the preserved process output, fix the startup error, then rerun BootProof.",
|
|
129
227
|
};
|
|
228
|
+
}
|
|
130
229
|
default:
|
|
131
|
-
if (/cloned .* but will not execute remote repository code/i.test(explanation)) {
|
|
132
|
-
return {
|
|
133
|
-
whatHappened: explanation,
|
|
134
|
-
whyRefused: "A remote clone is untrusted code, and BootProof requires explicit acknowledgement before running it on the host.",
|
|
135
|
-
safeNextStep: "Review the cloned repository, then rerun with --provider local --unsafe-local only if you accept host execution.",
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
if (/Local provider runs repository code directly/i.test(explanation)) {
|
|
139
|
-
return {
|
|
140
|
-
whatHappened: explanation,
|
|
141
|
-
whyRefused: "Host execution was selected without the required explicit acknowledgement.",
|
|
142
|
-
safeNextStep: "Review the inferred commands, then rerun with --provider local --unsafe-local only if you accept host execution.",
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
230
|
return {
|
|
146
231
|
whatHappened: explanation,
|
|
147
232
|
whyRefused: "BootProof did not observe enough evidence to issue a verified boot result.",
|
package/dist/diff.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type DiffRiskLevel = "low" | "medium" | "high";
|
|
2
|
+
export interface DiffChange {
|
|
3
|
+
source: string;
|
|
4
|
+
before: string | null;
|
|
5
|
+
after: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface DiffResult {
|
|
8
|
+
schema: "bootproof/diff-result/v1";
|
|
9
|
+
base: string;
|
|
10
|
+
head: string;
|
|
11
|
+
changedFiles: string[];
|
|
12
|
+
addedServices: string[];
|
|
13
|
+
removedServices: string[];
|
|
14
|
+
addedPorts: string[];
|
|
15
|
+
removedPorts: string[];
|
|
16
|
+
addedEnvVars: string[];
|
|
17
|
+
removedEnvVars: string[];
|
|
18
|
+
changedCommands: DiffChange[];
|
|
19
|
+
changedPackageManagers: DiffChange[];
|
|
20
|
+
riskLevel: DiffRiskLevel;
|
|
21
|
+
proofRequired: boolean;
|
|
22
|
+
suggestedReviewNotes: string[];
|
|
23
|
+
redactionsApplied: string[];
|
|
24
|
+
}
|
|
25
|
+
export declare function validateDiffResult(value: unknown): string[];
|
|
26
|
+
export declare function diffRefs(repoPath: string, options?: {
|
|
27
|
+
base?: string;
|
|
28
|
+
head?: string;
|
|
29
|
+
}): DiffResult;
|