@codyswann/lisa 4.71.7 → 4.71.8
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/all/copy-overwrite/scripts/check-threshold-ratchet.mjs +571 -0
- package/all/copy-overwrite/scripts/check-workflow-load-failures.mjs +31 -9
- package/all/copy-overwrite/scripts/lib/automation-provenance-contract.mjs +19 -0
- package/all/copy-overwrite/scripts/lib/automation-provenance-files.mjs +49 -0
- package/all/copy-overwrite/scripts/lib/automation-provenance-local.mjs +54 -38
- package/all/copy-overwrite/scripts/lib/npm-update-allocate.mjs +8 -2
- package/all/copy-overwrite/scripts/lib/npm-update-bun.mjs +189 -0
- package/all/copy-overwrite/scripts/lib/npm-update-cancel-origin.mjs +7 -3
- package/all/copy-overwrite/scripts/lib/npm-update-cancellation-proof.mjs +6 -1
- package/all/copy-overwrite/scripts/lib/npm-update-contract.mjs +26 -5
- package/all/copy-overwrite/scripts/lib/npm-update-gate.mjs +8 -5
- package/all/copy-overwrite/scripts/lib/npm-update-github.mjs +2 -2
- package/all/copy-overwrite/scripts/lib/npm-update-helper-inventory.mjs +3 -4
- package/all/copy-overwrite/scripts/lib/npm-update-hook-installation.mjs +68 -1
- package/all/copy-overwrite/scripts/lib/npm-update-hosted-gate.mjs +13 -80
- package/all/copy-overwrite/scripts/lib/npm-update-leaf-contract.mjs +6 -5
- package/all/copy-overwrite/scripts/lib/npm-update-prepare.mjs +35 -7
- package/all/copy-overwrite/scripts/lib/npm-update-publish.mjs +1 -1
- package/all/copy-overwrite/scripts/npm-updater-helper-graph.json +43 -16
- package/all/copy-overwrite/scripts/threshold-ratchet-compare.mjs +521 -0
- package/all/copy-overwrite/scripts/threshold-ratchet-families.mjs +546 -0
- package/dist/configs/repo-scan.js +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +60 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +44 -31
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +3 -3
- package/plugins/lisa/hooks/threshold-ratchet.mjs +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +3 -3
- package/plugins/lisa-copilot/hooks/threshold-ratchet.mjs +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +3 -3
- package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/materialized-artifacts.json +3 -0
- package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +3 -3
- package/plugins/src/base/hooks/threshold-ratchet.mjs +1 -1
- package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +1 -1
- package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +3 -3
- package/scripts/build-plugins.sh +2 -1
- package/scripts/generate-scratch-supervisor-profile.mjs +1 -1
- package/scripts/two-channel-couplings.json +9 -7
- package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +1 -1
- package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +3 -3
- /package/{rails → all}/copy-contents/scripts/lisa-mutation.sh +0 -0
- /package/{rails → all}/copy-overwrite/scripts/lisa-clean-git-env.sh +0 -0
- /package/{rails → all}/copy-overwrite/scripts/lisa-scratch-run.sh +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Do not edit directly — durable changes belong upstream in Lisa.
|
|
3
3
|
|
|
4
4
|
/** Original manager readback preserves installed bytes; dispatch qualification is a separate obligation. */
|
|
5
|
-
import { lstatSync, realpathSync } from "node:fs";
|
|
5
|
+
import { existsSync, lstatSync, realpathSync, readFileSync } from "node:fs";
|
|
6
6
|
import { join, resolve } from "node:path";
|
|
7
7
|
import { keys, required } from "./npm-update-contract.mjs";
|
|
8
8
|
import { readBytes } from "./npm-update-process.mjs";
|
|
@@ -114,3 +114,70 @@ export async function originalHookInstallation(cwd, command, authority) {
|
|
|
114
114
|
export async function originalPrePush(cwd, command, authority) {
|
|
115
115
|
return (await originalHookInstallation(cwd, command, authority)).path;
|
|
116
116
|
}
|
|
117
|
+
|
|
118
|
+
/** Husky 8 declares its real installer in package metadata; dependency install remains script-disabled. */
|
|
119
|
+
function huskyInstaller(cwd) {
|
|
120
|
+
const root = join(cwd, "node_modules/husky");
|
|
121
|
+
const metadata = JSON.parse(
|
|
122
|
+
readBytes(join(root, "package.json"), 65_536, false)
|
|
123
|
+
);
|
|
124
|
+
const bin =
|
|
125
|
+
typeof metadata.bin === "string" ? metadata.bin : metadata.bin?.husky;
|
|
126
|
+
required(
|
|
127
|
+
metadata.name === "husky" &&
|
|
128
|
+
/^8\.\d+\.\d+$/.test(metadata.version) &&
|
|
129
|
+
typeof bin === "string" &&
|
|
130
|
+
/^(?:[A-Za-z0-9_-]+\/)*[A-Za-z0-9_-]+\.js$/.test(bin),
|
|
131
|
+
"original Husky 8 installer declaration is unsupported"
|
|
132
|
+
);
|
|
133
|
+
const path = join(root, bin);
|
|
134
|
+
required(
|
|
135
|
+
realpathSync(root) === root &&
|
|
136
|
+
realpathSync(path) === path &&
|
|
137
|
+
lstatSync(path).isFile(),
|
|
138
|
+
"original Husky installer is unavailable or aliased"
|
|
139
|
+
);
|
|
140
|
+
return path;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** The original supported manager installs its own wrappers; no synthetic replacement hook is written. */
|
|
144
|
+
export async function installOriginalManager(context, env, nativeStep) {
|
|
145
|
+
const lefthook = existsSync(join(context.cwd, "lefthook.yml"));
|
|
146
|
+
if (lefthook)
|
|
147
|
+
await nativeStep(context, env, "bundle", ["exec", "lefthook", "install"]);
|
|
148
|
+
else {
|
|
149
|
+
required(
|
|
150
|
+
existsSync(join(context.cwd, ".husky/pre-push")),
|
|
151
|
+
"original hook manager installation is unavailable"
|
|
152
|
+
);
|
|
153
|
+
await nativeStep(context, env, process.execPath, [
|
|
154
|
+
huskyInstaller(context.cwd),
|
|
155
|
+
"install",
|
|
156
|
+
]);
|
|
157
|
+
}
|
|
158
|
+
const git = args => nativeStep(context, env, "/usr/bin/git", args);
|
|
159
|
+
const result = await git(["rev-parse", "--git-path", "hooks"]);
|
|
160
|
+
const text = result.stdout.toString();
|
|
161
|
+
required(
|
|
162
|
+
text.endsWith("\n") && !/[\n\r\0]/.test(text.slice(0, -1)),
|
|
163
|
+
"original hook path is unsupported"
|
|
164
|
+
);
|
|
165
|
+
const directory = resolve(context.cwd, text.slice(0, -1));
|
|
166
|
+
const wrappers = {};
|
|
167
|
+
for (const name of [
|
|
168
|
+
"pre-commit",
|
|
169
|
+
"prepare-commit-msg",
|
|
170
|
+
"commit-msg",
|
|
171
|
+
"pre-push",
|
|
172
|
+
]) {
|
|
173
|
+
const path = join(directory, name);
|
|
174
|
+
required(
|
|
175
|
+
lstatSync(path).isFile() && !lstatSync(path).isSymbolicLink(),
|
|
176
|
+
"original hook wrapper is missing or aliased"
|
|
177
|
+
);
|
|
178
|
+
wrappers[name] = sha256(readFileSync(path));
|
|
179
|
+
}
|
|
180
|
+
const installation = { manager: lefthook ? "lefthook" : "husky", wrappers };
|
|
181
|
+
await originalHookInstallation(context.cwd, git, installation);
|
|
182
|
+
return installation;
|
|
183
|
+
}
|
|
@@ -2,28 +2,21 @@
|
|
|
2
2
|
// Do not edit directly — durable changes belong upstream in Lisa.
|
|
3
3
|
|
|
4
4
|
/** Supported disposable Actions Linux gates use original native tools; publisher authority stays in another job. */
|
|
5
|
-
import {
|
|
6
|
-
existsSync,
|
|
7
|
-
lstatSync,
|
|
8
|
-
realpathSync,
|
|
9
|
-
readFileSync,
|
|
10
|
-
mkdirSync,
|
|
11
|
-
writeFileSync,
|
|
12
|
-
} from "node:fs";
|
|
5
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
13
6
|
import { join, resolve } from "node:path";
|
|
14
7
|
import { fileURLToPath } from "node:url";
|
|
15
|
-
import { required } from "./npm-update-contract.mjs";
|
|
16
|
-
import {
|
|
8
|
+
import { required, proposalFileNames } from "./npm-update-contract.mjs";
|
|
9
|
+
import { qualifiedBun, frozenBun } from "./npm-update-bun.mjs";
|
|
10
|
+
import { runProcess, writeJson } from "./npm-update-process.mjs";
|
|
17
11
|
import { qualifiedControllerGraph } from "./npm-update-helper.mjs";
|
|
18
12
|
import {
|
|
19
13
|
controllerTools,
|
|
20
14
|
controllerSubject,
|
|
21
15
|
} from "./npm-update-controller-factory.mjs";
|
|
22
16
|
import { startHookReadBroker } from "./npm-update-hook-provider.mjs";
|
|
23
|
-
import {
|
|
17
|
+
import { installOriginalManager } from "./npm-update-hook-installation.mjs";
|
|
24
18
|
import { withStage } from "./npm-update-invariants.mjs";
|
|
25
19
|
import {
|
|
26
|
-
sha256,
|
|
27
20
|
PROPOSAL_PREDICATE,
|
|
28
21
|
RECOVERY_PREDICATE,
|
|
29
22
|
} from "./github-attestation-verifier.mjs";
|
|
@@ -86,6 +79,7 @@ async function installHostedDependencies(context, root, env) {
|
|
|
86
79
|
const before = [
|
|
87
80
|
"package.json",
|
|
88
81
|
"package-lock.json",
|
|
82
|
+
...(context.proposal.bunLockSha256 === undefined ? [] : ["bun.lock"]),
|
|
89
83
|
...(ruby ? ["Gemfile", "Gemfile.lock"] : []),
|
|
90
84
|
].map(name => [name, readFileSync(join(context.cwd, name))]);
|
|
91
85
|
await nativeStep(context, installed, "npm", [
|
|
@@ -94,6 +88,12 @@ async function installHostedDependencies(context, root, env) {
|
|
|
94
88
|
"--no-audit",
|
|
95
89
|
"--no-fund",
|
|
96
90
|
]);
|
|
91
|
+
if (context.proposal.bunLockSha256 !== undefined) {
|
|
92
|
+
const bun = await qualifiedBun(installed, { deadline: context.deadline });
|
|
93
|
+
await frozenBun(bun, context.cwd, proposalFileNames(context.proposal), {
|
|
94
|
+
timeout: remainingGateTime(context.deadline),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
97
|
if (ruby)
|
|
98
98
|
await nativeStep(context, installed, "bundle", [
|
|
99
99
|
"install",
|
|
@@ -111,73 +111,6 @@ async function installHostedDependencies(context, root, env) {
|
|
|
111
111
|
return installed;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
/** Husky 8 declares its real installer in package metadata; dependency install remains script-disabled. */
|
|
115
|
-
function huskyInstaller(cwd) {
|
|
116
|
-
const root = join(cwd, "node_modules/husky");
|
|
117
|
-
const metadata = JSON.parse(
|
|
118
|
-
readBytes(join(root, "package.json"), 65_536, false)
|
|
119
|
-
);
|
|
120
|
-
const bin =
|
|
121
|
-
typeof metadata.bin === "string" ? metadata.bin : metadata.bin?.husky;
|
|
122
|
-
required(
|
|
123
|
-
metadata.name === "husky" &&
|
|
124
|
-
/^8\.\d+\.\d+$/.test(metadata.version) &&
|
|
125
|
-
typeof bin === "string" &&
|
|
126
|
-
/^(?:[A-Za-z0-9_-]+\/)*[A-Za-z0-9_-]+\.js$/.test(bin),
|
|
127
|
-
"original Husky 8 installer declaration is unsupported"
|
|
128
|
-
);
|
|
129
|
-
const path = join(root, bin);
|
|
130
|
-
required(
|
|
131
|
-
realpathSync(root) === root &&
|
|
132
|
-
realpathSync(path) === path &&
|
|
133
|
-
lstatSync(path).isFile(),
|
|
134
|
-
"original Husky installer is unavailable or aliased"
|
|
135
|
-
);
|
|
136
|
-
return path;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** The original supported manager installs its own wrappers; no synthetic replacement hook is written. */
|
|
140
|
-
async function installOriginalManager(context, env) {
|
|
141
|
-
const lefthook = existsSync(join(context.cwd, "lefthook.yml"));
|
|
142
|
-
if (lefthook)
|
|
143
|
-
await nativeStep(context, env, "bundle", ["exec", "lefthook", "install"]);
|
|
144
|
-
else {
|
|
145
|
-
required(
|
|
146
|
-
existsSync(join(context.cwd, ".husky/pre-push")),
|
|
147
|
-
"original hook manager installation is unavailable"
|
|
148
|
-
);
|
|
149
|
-
await nativeStep(context, env, process.execPath, [
|
|
150
|
-
huskyInstaller(context.cwd),
|
|
151
|
-
"install",
|
|
152
|
-
]);
|
|
153
|
-
}
|
|
154
|
-
const git = args => nativeStep(context, env, "/usr/bin/git", args);
|
|
155
|
-
const result = await git(["rev-parse", "--git-path", "hooks"]);
|
|
156
|
-
const text = result.stdout.toString();
|
|
157
|
-
required(
|
|
158
|
-
text.endsWith("\n") && !/[\n\r\0]/.test(text.slice(0, -1)),
|
|
159
|
-
"original hook path is unsupported"
|
|
160
|
-
);
|
|
161
|
-
const directory = resolve(context.cwd, text.slice(0, -1));
|
|
162
|
-
const wrappers = {};
|
|
163
|
-
for (const name of [
|
|
164
|
-
"pre-commit",
|
|
165
|
-
"prepare-commit-msg",
|
|
166
|
-
"commit-msg",
|
|
167
|
-
"pre-push",
|
|
168
|
-
]) {
|
|
169
|
-
const path = join(directory, name);
|
|
170
|
-
required(
|
|
171
|
-
lstatSync(path).isFile() && !lstatSync(path).isSymbolicLink(),
|
|
172
|
-
"original hook wrapper is missing or aliased"
|
|
173
|
-
);
|
|
174
|
-
wrappers[name] = sha256(readFileSync(path));
|
|
175
|
-
}
|
|
176
|
-
const installation = { manager: lefthook ? "lefthook" : "husky", wrappers };
|
|
177
|
-
await originalHookInstallation(context.cwd, git, installation);
|
|
178
|
-
return installation;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
114
|
/** Proof paths are the actual fixed slots installed for the unchanged canonical verifier. */
|
|
182
115
|
async function proofScope(context, env) {
|
|
183
116
|
const result = await nativeStep(context, env, "/usr/bin/git", [
|
|
@@ -276,7 +209,7 @@ export async function createHostedGate(context, root, env) {
|
|
|
276
209
|
installHostedDependencies(context, root, env)
|
|
277
210
|
);
|
|
278
211
|
const installation = await withStage("gate-hooks", () =>
|
|
279
|
-
installOriginalManager(context, installed)
|
|
212
|
+
installOriginalManager(context, installed, nativeStep)
|
|
280
213
|
);
|
|
281
214
|
const scope = await withStage("gate-scope", () =>
|
|
282
215
|
proofScope(context, installed)
|
|
@@ -78,6 +78,7 @@ export function buildDraft(proposal, policy, config, evidence) {
|
|
|
78
78
|
const versions = proposal.updates
|
|
79
79
|
.map(update => `${update.name}: ${update.from} -> ${update.to}`)
|
|
80
80
|
.join("\n");
|
|
81
|
+
const bun = Object.hasOwn(proposal, "bunLockSha256");
|
|
81
82
|
const body = `## Context / Business Value
|
|
82
83
|
|
|
83
84
|
Keep the selected dependencies current while preserving ordinary review, required checks and runtime verification. This Task owns one exact dependency proposal; its implementation ticket is never reused for another update.
|
|
@@ -87,7 +88,7 @@ Keep the selected dependencies current while preserving ordinary review, require
|
|
|
87
88
|
Base parent: ${proposal.parent}
|
|
88
89
|
Proposal key: ${proposal.key}
|
|
89
90
|
Selection key: ${proposal.selectionKey}
|
|
90
|
-
Update exactly package.json and package-lock.json:
|
|
91
|
+
Update exactly package.json and package-lock.json${bun ? " and bun.lock" : ""}:
|
|
91
92
|
${versions}
|
|
92
93
|
Use the trusted four-job npm updater. Preparation performs an installed-tree npm outdated check and npm ci with lifecycle scripts disabled. Allocation precedes the first attributed commit. Ordinary commit and original pre-push gates remain mandatory. Publish only the exact gated unsigned raw Git object with unchanged parent, tree, identities, times and message. Preserve every unrelated dependency, script and existing assignee. Stop on stale base, unavailable authorization, hold, failed gate or mismatching bytes. Lisa is excluded only with verified local full-apply ownership.
|
|
93
94
|
|
|
@@ -97,8 +98,8 @@ Use the trusted four-job npm updater. Preparation performs an installed-tree npm
|
|
|
97
98
|
Scenario: publish one coherent dependency proposal
|
|
98
99
|
Given parent ${proposal.parent} and the selected versions above
|
|
99
100
|
When the trusted updater claims this leaf and completes ordinary gates
|
|
100
|
-
Then the manifest and lock agree and npm ci preserves both file hashes
|
|
101
|
-
And the pull request into main contains exactly the gated commit and two files
|
|
101
|
+
Then the manifest and lock agree and npm ci preserves both file hashes${bun ? " and frozen Bun preserves all three hashes" : ""}
|
|
102
|
+
And the pull request into main contains exactly the gated commit and ${bun ? "three" : "two"} files
|
|
102
103
|
Scenario: refuse unauthorized or stale publication
|
|
103
104
|
Given a hold, changed parent, failed gate or mismatching proposal
|
|
104
105
|
When publication is attempted
|
|
@@ -147,7 +148,7 @@ Matches are read completely before allocating this deterministic proposal. No pa
|
|
|
147
148
|
## Validation Journey
|
|
148
149
|
|
|
149
150
|
1. Prepare the selected update from the exact parent with installed npm outdated; record actual exit and versions. [EVIDENCE: cli-output: npm-outdated]
|
|
150
|
-
2. Run script-disabled npm ci against the proposed files and record unchanged hashes. [EVIDENCE: cli-output: npm-ci]
|
|
151
|
+
2. Run script-disabled npm ci${bun ? " and Bun1.3.8 frozen installation" : ""} against the proposed files and record unchanged hashes. [EVIDENCE: cli-output: npm-ci]
|
|
151
152
|
3. Record normal commit/pre-push hook exits, all-ref stdin/ranges and the exact raw commit identity. [EVIDENCE: test-run-log: ordinary-gates]
|
|
152
153
|
4. Read the current-head pull request, required checks and genuine human approval. [EVIDENCE: state-dump: current-head-review]
|
|
153
154
|
5. Verify ordinary application behavior in ${env}; record actual environment and deployed identity. [EVIDENCE: test-run-log: runtime-verification]
|
|
@@ -156,7 +157,7 @@ Matches are read completely before allocating this deterministic proposal. No pa
|
|
|
156
157
|
## Proposal Bytes
|
|
157
158
|
|
|
158
159
|
package.json SHA256: ${proposal.hashes["package.json"]}
|
|
159
|
-
package-lock.json SHA256: ${proposal.hashes["package-lock.json"]}
|
|
160
|
+
package-lock.json SHA256: ${proposal.hashes["package-lock.json"]}${bun ? `\nbun.lock SHA256: ${proposal.hashes["bun.lock"]}\nOriginal bun.lock SHA256: ${proposal.bunLockSha256}` : ""}
|
|
160
161
|
|
|
161
162
|
<!-- [lisa-npm-filing] ${Buffer.from(canonicalJson(evidence)).toString("base64")} -->
|
|
162
163
|
<!-- [lisa-npm-proposal] ${proposal.key} -->
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
validateHost,
|
|
23
23
|
validateLock,
|
|
24
24
|
proposalFrom,
|
|
25
|
+
proposalFileNames,
|
|
25
26
|
} from "./npm-update-contract.mjs";
|
|
26
27
|
import {
|
|
27
28
|
runProcess,
|
|
@@ -33,6 +34,7 @@ import { canonicalJson } from "../lisa-automation-provenance.mjs";
|
|
|
33
34
|
import { qualifyLisaOwner } from "./npm-update-owner.mjs";
|
|
34
35
|
export { qualifyLisaOwner } from "./npm-update-owner.mjs";
|
|
35
36
|
import { sha256 } from "./github-attestation-verifier.mjs";
|
|
37
|
+
import { committedBun, qualifiedBun, frozenBun } from "./npm-update-bun.mjs";
|
|
36
38
|
|
|
37
39
|
const NPM_FLAGS = ["--ignore-scripts", "--no-audit", "--no-fund"];
|
|
38
40
|
|
|
@@ -71,6 +73,8 @@ export async function baseline(cwd, env, proposal) {
|
|
|
71
73
|
"utf8"
|
|
72
74
|
);
|
|
73
75
|
}
|
|
76
|
+
const bun = await committedBun(cwd, command, proposal);
|
|
77
|
+
if (bun !== undefined) files["bun.lock"] = bun;
|
|
74
78
|
if (proposal)
|
|
75
79
|
required(
|
|
76
80
|
parent === proposal.parent &&
|
|
@@ -146,7 +150,7 @@ async function installUpdates(updates, npm, npmFlags) {
|
|
|
146
150
|
}
|
|
147
151
|
}
|
|
148
152
|
|
|
149
|
-
/**
|
|
153
|
+
/** Preserve the exact original lock cohort in a private HOME without repository scripts. */
|
|
150
154
|
async function preparedProposal({
|
|
151
155
|
app,
|
|
152
156
|
npm,
|
|
@@ -158,29 +162,47 @@ async function preparedProposal({
|
|
|
158
162
|
version,
|
|
159
163
|
outdated,
|
|
160
164
|
installedBefore,
|
|
165
|
+
bun,
|
|
161
166
|
}) {
|
|
162
167
|
await installUpdates(updates, npm, npmFlags);
|
|
168
|
+
const names = Object.keys(original.files).sort();
|
|
169
|
+
if (bun)
|
|
170
|
+
await bun(
|
|
171
|
+
[
|
|
172
|
+
"install",
|
|
173
|
+
"--lockfile-only",
|
|
174
|
+
"--ignore-scripts",
|
|
175
|
+
"--registry",
|
|
176
|
+
"https://registry.npmjs.org/",
|
|
177
|
+
],
|
|
178
|
+
{ cwd: app }
|
|
179
|
+
);
|
|
163
180
|
const files = Object.fromEntries(
|
|
164
|
-
|
|
181
|
+
names.map(file => [file, readFileSync(join(app, file), "utf8")])
|
|
165
182
|
);
|
|
166
183
|
const proposal = proposalFrom(
|
|
167
184
|
policy,
|
|
168
185
|
original.parent,
|
|
169
186
|
before,
|
|
170
187
|
files,
|
|
171
|
-
updates
|
|
188
|
+
updates,
|
|
189
|
+
bun ? sha256(original.files["bun.lock"]) : undefined
|
|
172
190
|
);
|
|
173
191
|
const hashes = Object.fromEntries(
|
|
174
|
-
|
|
192
|
+
proposalFileNames(proposal).map(file => [
|
|
193
|
+
file,
|
|
194
|
+
sha256(readFileSync(join(app, file))),
|
|
195
|
+
])
|
|
175
196
|
);
|
|
176
197
|
await npm(["ci", ...npmFlags]);
|
|
198
|
+
if (bun) await frozenBun(bun, app, names);
|
|
177
199
|
required(
|
|
178
|
-
|
|
200
|
+
names.every(file => hashes[file] === sha256(readFileSync(join(app, file)))),
|
|
179
201
|
"npm ci rewrote manifest or lock"
|
|
180
202
|
);
|
|
181
203
|
required(
|
|
182
204
|
readdirSync(app).sort().join("\n") ===
|
|
183
|
-
["node_modules", ...
|
|
205
|
+
["node_modules", ...names].sort().join("\n"),
|
|
184
206
|
"unexpected npm output path or lifecycle effect"
|
|
185
207
|
);
|
|
186
208
|
return {
|
|
@@ -224,11 +246,16 @@ export async function prepareUpdate({ cwd, policy: input, config }) {
|
|
|
224
246
|
);
|
|
225
247
|
await qualifyLisaOwner(cwd, before, policy, config, engineStrict);
|
|
226
248
|
validateLock(JSON.parse(original.files["package-lock.json"]), before, []);
|
|
227
|
-
for (const file of
|
|
249
|
+
for (const file of Object.keys(original.files))
|
|
228
250
|
writeFileSync(join(app, file), original.files[file], { mode: 0o600 });
|
|
251
|
+
const bun =
|
|
252
|
+
original.files["bun.lock"] === undefined
|
|
253
|
+
? undefined
|
|
254
|
+
: await qualifiedBun(env);
|
|
229
255
|
const npm = (args, allowed = [0]) =>
|
|
230
256
|
runNpm(args, { cwd: app, env, timeout: 120_000, allowed });
|
|
231
257
|
await npm(["ci", ...npmFlags]);
|
|
258
|
+
if (bun) await frozenBun(bun, app, Object.keys(original.files));
|
|
232
259
|
const installedBefore = installedVersions(app, policy.packages);
|
|
233
260
|
const outdated = await npm(["outdated", "--json", "--long"], [0, 1]);
|
|
234
261
|
const detected = JSON.parse(outdated.stdout.toString() || "{}");
|
|
@@ -256,6 +283,7 @@ export async function prepareUpdate({ cwd, policy: input, config }) {
|
|
|
256
283
|
version,
|
|
257
284
|
outdated,
|
|
258
285
|
installedBefore,
|
|
286
|
+
bun,
|
|
259
287
|
});
|
|
260
288
|
});
|
|
261
289
|
required(!existsSync(privatePath), "private npm resources remain");
|
|
@@ -127,7 +127,7 @@ export async function publishDestination({
|
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
/** The publisher consumes signed/gated data and writes only
|
|
130
|
+
/** The publisher consumes signed/gated data and writes only the identical original lock cohort. */
|
|
131
131
|
export async function publishProposal({
|
|
132
132
|
api,
|
|
133
133
|
proposal,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"members": {
|
|
22
22
|
"check-threshold-ratchet.mjs": {
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "d4afc90ba8faf10925fff5fb0d6cd0ace22df2eaa0ec609ee969d0ec84092299",
|
|
24
24
|
"staticImports": [
|
|
25
25
|
"node:child_process",
|
|
26
26
|
"node:fs",
|
|
@@ -33,17 +33,27 @@
|
|
|
33
33
|
"children": []
|
|
34
34
|
},
|
|
35
35
|
"lib/automation-provenance-contract.mjs": {
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "b12e64711bf05c357d0cfebfda90540dcac413d34de9c6f2405fe0ad37d137dc",
|
|
37
37
|
"staticImports": [
|
|
38
38
|
"lib/github-attestation-verifier.mjs"
|
|
39
39
|
],
|
|
40
40
|
"dynamicImports": [],
|
|
41
41
|
"children": []
|
|
42
42
|
},
|
|
43
|
+
"lib/automation-provenance-files.mjs": {
|
|
44
|
+
"sha256": "5c3b2a88669e3e187c123850798e3dfafb3c078b6b25aa00da0ba93db03424c9",
|
|
45
|
+
"staticImports": [
|
|
46
|
+
"lib/github-attestation-verifier.mjs",
|
|
47
|
+
"node:fs"
|
|
48
|
+
],
|
|
49
|
+
"dynamicImports": [],
|
|
50
|
+
"children": []
|
|
51
|
+
},
|
|
43
52
|
"lib/automation-provenance-local.mjs": {
|
|
44
|
-
"sha256": "
|
|
53
|
+
"sha256": "e36147aef8b725147a26322b689e0fcef3c7cb5ae36f32e483a3da59667e3592",
|
|
45
54
|
"staticImports": [
|
|
46
55
|
"lib/automation-provenance-contract.mjs",
|
|
56
|
+
"lib/automation-provenance-files.mjs",
|
|
47
57
|
"lib/bounded-spawn.mjs",
|
|
48
58
|
"lib/github-attestation-verifier.mjs",
|
|
49
59
|
"lisa-work-item.mjs",
|
|
@@ -176,7 +186,7 @@
|
|
|
176
186
|
"children": []
|
|
177
187
|
},
|
|
178
188
|
"lib/npm-update-allocate.mjs": {
|
|
179
|
-
"sha256": "
|
|
189
|
+
"sha256": "85de2576d1c5e954b57f1c9274dbc34d0d24689fbc0964d8f86ec4f91f52b7bc",
|
|
180
190
|
"staticImports": [
|
|
181
191
|
"lib/github-attestation-verifier.mjs",
|
|
182
192
|
"lib/npm-update-contract.mjs",
|
|
@@ -221,8 +231,22 @@
|
|
|
221
231
|
"dynamicImports": [],
|
|
222
232
|
"children": []
|
|
223
233
|
},
|
|
234
|
+
"lib/npm-update-bun.mjs": {
|
|
235
|
+
"sha256": "898cdafe2e119b9c3004ea55ae222d2f33d8b668020cda09e90184474055a676",
|
|
236
|
+
"staticImports": [
|
|
237
|
+
"lib/automation-provenance-contract.mjs",
|
|
238
|
+
"lib/github-attestation-verifier.mjs",
|
|
239
|
+
"lib/npm-update-invariants.mjs",
|
|
240
|
+
"lib/npm-update-process-core.mjs",
|
|
241
|
+
"lib/npm-update-worker-lifecycle.mjs",
|
|
242
|
+
"node:fs",
|
|
243
|
+
"node:path"
|
|
244
|
+
],
|
|
245
|
+
"dynamicImports": [],
|
|
246
|
+
"children": []
|
|
247
|
+
},
|
|
224
248
|
"lib/npm-update-cancel-origin.mjs": {
|
|
225
|
-
"sha256": "
|
|
249
|
+
"sha256": "635dd82d23042337d68e441b43cec26c171fef9ac57c7e9c5de14af0587d7e43",
|
|
226
250
|
"staticImports": [
|
|
227
251
|
"lib/automation-provenance-contract.mjs",
|
|
228
252
|
"lib/github-attestation-provider.mjs",
|
|
@@ -240,7 +264,7 @@
|
|
|
240
264
|
"children": []
|
|
241
265
|
},
|
|
242
266
|
"lib/npm-update-cancellation-proof.mjs": {
|
|
243
|
-
"sha256": "
|
|
267
|
+
"sha256": "9262c81836683572d1135112b8cfd0f43abcb050c9f8d84ef7dfb77b8caac59c",
|
|
244
268
|
"staticImports": [
|
|
245
269
|
"lib/github-attestation-verifier.mjs",
|
|
246
270
|
"lib/npm-update-contract.mjs",
|
|
@@ -289,8 +313,9 @@
|
|
|
289
313
|
"children": []
|
|
290
314
|
},
|
|
291
315
|
"lib/npm-update-contract.mjs": {
|
|
292
|
-
"sha256": "
|
|
316
|
+
"sha256": "d8e7e94d7b33d0088ea01d32d659f00408487465f7d857a64daa1b09b16fcd8c",
|
|
293
317
|
"staticImports": [
|
|
318
|
+
"lib/automation-provenance-contract.mjs",
|
|
294
319
|
"lib/github-attestation-verifier.mjs",
|
|
295
320
|
"lib/npm-update-invariants.mjs",
|
|
296
321
|
"lib/npm-update-object.mjs",
|
|
@@ -411,7 +436,7 @@
|
|
|
411
436
|
"children": []
|
|
412
437
|
},
|
|
413
438
|
"lib/npm-update-gate.mjs": {
|
|
414
|
-
"sha256": "
|
|
439
|
+
"sha256": "3d53ff811b0cce52fb4b33dbfb48c54e928b58fffa5b8ca67569f1bcd35aea45",
|
|
415
440
|
"staticImports": [
|
|
416
441
|
"lib/github-attestation-verifier.mjs",
|
|
417
442
|
"lib/npm-update-contract.mjs",
|
|
@@ -467,7 +492,7 @@
|
|
|
467
492
|
"children": []
|
|
468
493
|
},
|
|
469
494
|
"lib/npm-update-github.mjs": {
|
|
470
|
-
"sha256": "
|
|
495
|
+
"sha256": "2be34eca5ceb38cc535fac6ca0a655e14993231cd37b1a3e26ea09756042c488",
|
|
471
496
|
"staticImports": [
|
|
472
497
|
"lib/github-attestation-verifier.mjs",
|
|
473
498
|
"lib/npm-update-contract.mjs",
|
|
@@ -480,7 +505,7 @@
|
|
|
480
505
|
"children": []
|
|
481
506
|
},
|
|
482
507
|
"lib/npm-update-helper-inventory.mjs": {
|
|
483
|
-
"sha256": "
|
|
508
|
+
"sha256": "647c83dc72c21c4d68e27679e9f3b35b4b541bd8957c779495f78392d099cdd9",
|
|
484
509
|
"staticImports": [],
|
|
485
510
|
"dynamicImports": [],
|
|
486
511
|
"children": []
|
|
@@ -506,7 +531,7 @@
|
|
|
506
531
|
"children": []
|
|
507
532
|
},
|
|
508
533
|
"lib/npm-update-hook-installation.mjs": {
|
|
509
|
-
"sha256": "
|
|
534
|
+
"sha256": "af3cf29c76f583a7e18b974d2862f5fc273ac0f13c36bd28c284bcd0d480d045",
|
|
510
535
|
"staticImports": [
|
|
511
536
|
"lib/github-attestation-verifier.mjs",
|
|
512
537
|
"lib/npm-update-contract.mjs",
|
|
@@ -559,9 +584,10 @@
|
|
|
559
584
|
"children": []
|
|
560
585
|
},
|
|
561
586
|
"lib/npm-update-hosted-gate.mjs": {
|
|
562
|
-
"sha256": "
|
|
587
|
+
"sha256": "4d6635ec26435e642dc08de27d21eff033962f1508307e12c78a9c7c4cc12425",
|
|
563
588
|
"staticImports": [
|
|
564
589
|
"lib/github-attestation-verifier.mjs",
|
|
590
|
+
"lib/npm-update-bun.mjs",
|
|
565
591
|
"lib/npm-update-contract.mjs",
|
|
566
592
|
"lib/npm-update-controller-factory.mjs",
|
|
567
593
|
"lib/npm-update-helper.mjs",
|
|
@@ -611,7 +637,7 @@
|
|
|
611
637
|
"children": []
|
|
612
638
|
},
|
|
613
639
|
"lib/npm-update-leaf-contract.mjs": {
|
|
614
|
-
"sha256": "
|
|
640
|
+
"sha256": "9a68e50c354cac20fec847e02668c153f0f3c5783faaa29f51f2b4adf93ba99a",
|
|
615
641
|
"staticImports": [
|
|
616
642
|
"lib/npm-update-contract.mjs",
|
|
617
643
|
"lisa-automation-provenance.mjs",
|
|
@@ -703,9 +729,10 @@
|
|
|
703
729
|
"children": []
|
|
704
730
|
},
|
|
705
731
|
"lib/npm-update-prepare.mjs": {
|
|
706
|
-
"sha256": "
|
|
732
|
+
"sha256": "66520d441ba6413cf189016f35f3babdc3b5d29f962b01cede0846aa924edf26",
|
|
707
733
|
"staticImports": [
|
|
708
734
|
"lib/github-attestation-verifier.mjs",
|
|
735
|
+
"lib/npm-update-bun.mjs",
|
|
709
736
|
"lib/npm-update-contract.mjs",
|
|
710
737
|
"lib/npm-update-owner.mjs",
|
|
711
738
|
"lib/npm-update-process.mjs",
|
|
@@ -755,7 +782,7 @@
|
|
|
755
782
|
"children": []
|
|
756
783
|
},
|
|
757
784
|
"lib/npm-update-publish.mjs": {
|
|
758
|
-
"sha256": "
|
|
785
|
+
"sha256": "781d1abe61cc0ec991f0ca299e8fbbc84cf9b5bf4b541de8954904218b83b007",
|
|
759
786
|
"staticImports": [
|
|
760
787
|
"lib/npm-update-authorization.mjs",
|
|
761
788
|
"lib/npm-update-contract.mjs",
|
|
@@ -1147,7 +1174,7 @@
|
|
|
1147
1174
|
"children": []
|
|
1148
1175
|
},
|
|
1149
1176
|
"threshold-ratchet-compare.mjs": {
|
|
1150
|
-
"sha256": "
|
|
1177
|
+
"sha256": "761a0f32ab4bc138b3ed216f0edc9ad28c36783ccd3b62fbd57ef1b7fdc32681",
|
|
1151
1178
|
"staticImports": [
|
|
1152
1179
|
"threshold-ratchet-families.mjs"
|
|
1153
1180
|
],
|