@codyswann/lisa 3.12.0 → 3.13.1
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/lisa-hooks/block-no-verify.sh +15 -2
- package/all/create-only/scripts/remote-agent-aws-setup.sh +3 -0
- package/cdk/create-only/.github/workflows/deploy.yml +2 -1
- package/cdk/create-only/vitest.config.local.ts +3 -0
- package/dist/cli/doctor-lisa-owned-artifacts.d.ts +11 -2
- package/dist/cli/doctor-lisa-owned-artifacts.d.ts.map +1 -1
- package/dist/cli/doctor-lisa-owned-artifacts.js +60 -15
- package/dist/cli/doctor-lisa-owned-artifacts.js.map +1 -1
- package/dist/core/config.d.ts +21 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +1 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/guard-capabilities.d.ts +60 -0
- package/dist/core/guard-capabilities.d.ts.map +1 -0
- package/dist/core/guard-capabilities.js +102 -0
- package/dist/core/guard-capabilities.js.map +1 -0
- package/dist/core/lisa-owned-hash-ledger.d.ts +11 -0
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -0
- package/dist/core/lisa-owned-hash-ledger.js +127 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -0
- package/dist/core/lisa-owned-provenance.d.ts +71 -0
- package/dist/core/lisa-owned-provenance.d.ts.map +1 -0
- package/dist/core/lisa-owned-provenance.js +144 -0
- package/dist/core/lisa-owned-provenance.js.map +1 -0
- package/dist/core/lisa.d.ts +18 -0
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +38 -0
- package/dist/core/lisa.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +59 -51
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/strategies/copy-overwrite.d.ts +28 -1
- package/dist/strategies/copy-overwrite.d.ts.map +1 -1
- package/dist/strategies/copy-overwrite.js +53 -3
- package/dist/strategies/copy-overwrite.js.map +1 -1
- package/dist/strategies/strategy.interface.d.ts +13 -0
- package/dist/strategies/strategy.interface.d.ts.map +1 -1
- package/expo/create-only/.github/workflows/ci.yml +3 -0
- package/expo/create-only/.github/workflows/deploy.yml +2 -1
- package/expo/create-only/.github/workflows/maestro-e2e.yml +3 -0
- package/expo/create-only/.github/workflows/nightly-e2e-bypass-reaper.yml +3 -0
- package/expo/create-only/.github/workflows/nightly-e2e-health.yml +3 -0
- package/expo/create-only/.github/workflows/nightly-e2e-report.yml +3 -0
- package/expo/create-only/babel.config.js +3 -0
- package/expo/create-only/jest.config.local.ts +3 -0
- package/expo/create-only/jest.config.react-native-mock.js +3 -0
- package/expo/create-only/jest.setup.local.ts +3 -0
- package/expo/create-only/jest.setup.pre.local.js +3 -0
- package/expo/create-only/scripts/zap-baseline.sh +3 -0
- package/harper-fabric/create-only/.github/workflows/deploy.yml +3 -0
- package/harper-fabric/create-only/.github/workflows/zap-baseline.yml +3 -0
- package/harper-fabric/create-only/scripts/zap-baseline.sh +3 -0
- package/nestjs/create-only/.github/workflows/deploy.yml +3 -0
- package/nestjs/create-only/scripts/zap-baseline.sh +3 -0
- package/nestjs/create-only/vitest.config.local.ts +3 -0
- package/npm-package/create-only/.github/workflows/publish-to-npm.yml +2 -1
- package/package.json +3 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/block-no-verify.sh +15 -2
- 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/block-no-verify.sh +15 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/block-no-verify.sh +15 -2
- 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/src/base/hooks/block-no-verify.sh +15 -2
- package/rails/create-only/.github/workflows/claude-code-review-response.yml +2 -1
- package/rails/create-only/.github/workflows/claude-nightly-code-complexity.yml +2 -1
- package/rails/create-only/.github/workflows/claude-nightly-test-coverage.yml +2 -1
- package/rails/create-only/.github/workflows/claude-nightly-test-improvement.yml +2 -1
- package/rails/create-only/.github/workflows/claude-sync-down-branches.yml +2 -1
- package/rails/create-only/.github/workflows/deploy.yml +2 -1
- package/rails/create-only/.mutant.yml +3 -0
- package/rails/create-only/.reek.yml +3 -0
- package/rails/create-only/.rubocop_todo.yml +3 -0
- package/rails/create-only/mutation.gate.yml +3 -0
- package/rails/create-only/rubocop.thresholds.yml +3 -0
- package/rails/create-only/spec/rails_helper.rb +2 -0
- package/rails/create-only/spec/spec_helper.rb +2 -0
- package/scripts/generate-lisa-owned-hash-ledger.mjs +279 -0
- package/typescript/create-only/.github/workflows/auto-update-pr-branches-dispatch.yml +2 -1
- package/typescript/create-only/.github/workflows/auto-update-pr-branches.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-ci-auto-fix.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-code-review-response.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-deploy-auto-fix.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-nightly-code-complexity.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-nightly-test-coverage.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-nightly-test-improvement.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-sync-down-branches.yml +2 -1
- package/typescript/create-only/.github/workflows/claude.yml +2 -1
- package/typescript/create-only/.github/workflows/required-checks-drift.yml +2 -1
- package/typescript/create-only/eslint.config.local.ts +3 -0
- package/typescript/create-only/jest.config.local.ts +3 -0
- package/typescript/create-only/vitest.config.local.ts +3 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate the ledger of every content hash Lisa has ever shipped at each
|
|
4
|
+
* Lisa-owned destination path.
|
|
5
|
+
*
|
|
6
|
+
* Refresh uses it to tell a host copy that is *behind* Lisa (its bytes are some
|
|
7
|
+
* past Lisa release, so overwriting is correct) from one that is *ahead* (its
|
|
8
|
+
* bytes match no Lisa release, so overwriting would delete downstream work).
|
|
9
|
+
*
|
|
10
|
+
* Two properties are load-bearing:
|
|
11
|
+
*
|
|
12
|
+
* - **Keyed by destination, not source.** Several stacks ship a variant of the
|
|
13
|
+
* same installed path; a host has exactly one of them and refresh must accept
|
|
14
|
+
* whichever it has. The union across stacks is the honest answer to "has Lisa
|
|
15
|
+
* ever shipped these bytes here?".
|
|
16
|
+
* - **Append-only.** Existing entries are unioned in, never dropped. That makes
|
|
17
|
+
* the generator safe under a shallow clone: less history yields fewer new
|
|
18
|
+
* hashes, never the loss of known-good ones. Losing a hash would reclassify a
|
|
19
|
+
* legitimately stale file as host-modified and stop refreshing it — failing
|
|
20
|
+
* safe, but permanently.
|
|
21
|
+
*/
|
|
22
|
+
import { execFileSync } from "node:child_process";
|
|
23
|
+
import { createHash } from "node:crypto";
|
|
24
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
|
|
27
|
+
const repoRoot = path.resolve(import.meta.dirname, "..");
|
|
28
|
+
const outputPath = path.join(repoRoot, "src/core/lisa-owned-hash-ledger.ts");
|
|
29
|
+
const COPY_OVERWRITE = "copy-overwrite";
|
|
30
|
+
const LISA_NAMESPACE_PREFIX = "lisa-";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Run a git command in the repository and return stdout as latin1 text.
|
|
34
|
+
*
|
|
35
|
+
* Blobs are read as `binary` so arbitrary bytes survive the round trip into the
|
|
36
|
+
* Buffer that gets hashed; decoding as UTF-8 would corrupt any non-text file.
|
|
37
|
+
* @param {readonly string[]} args - Arguments passed to git
|
|
38
|
+
* @returns {string} Command stdout, or an empty string when git fails
|
|
39
|
+
*/
|
|
40
|
+
function git(args) {
|
|
41
|
+
try {
|
|
42
|
+
return execFileSync("git", args, {
|
|
43
|
+
cwd: repoRoot,
|
|
44
|
+
encoding: "buffer",
|
|
45
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
46
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
47
|
+
}).toString("binary");
|
|
48
|
+
} catch {
|
|
49
|
+
return "";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Whether a destination path sits in the namespace Lisa owns outright.
|
|
55
|
+
*
|
|
56
|
+
* Mirrors `isLisaOwnedTemplate` in `src/core/lisa-owned-templates.ts`. The
|
|
57
|
+
* duplication is deliberate — this script runs before the TypeScript build, so
|
|
58
|
+
* it cannot import the compiled module — and a test asserts the two agree.
|
|
59
|
+
*
|
|
60
|
+
* This is also the ledger's boundary, and it is inherited rather than chosen.
|
|
61
|
+
* The `lisa-` path segment is what decides which files refresh at all, so a file
|
|
62
|
+
* outside it is never refreshed after its initial create and has nothing for
|
|
63
|
+
* provenance to decide — recording hashes for it would add a regeneration gate
|
|
64
|
+
* to ~120 more templates and buy nothing today. If that predicate is ever
|
|
65
|
+
* replaced (CodySwannGT/lisa#2491 tracks it freezing non-`lisa-` guards at
|
|
66
|
+
* whatever version first landed), widening enrolment is this one function: the
|
|
67
|
+
* ledger answers "has Lisa ever shipped these bytes here?" for any managed path.
|
|
68
|
+
* @param {string} destination - Repo-relative destination path
|
|
69
|
+
* @returns {boolean} True when Lisa owns the file outright
|
|
70
|
+
*/
|
|
71
|
+
function isLisaOwned(destination) {
|
|
72
|
+
return destination
|
|
73
|
+
.split("/")
|
|
74
|
+
.some(segment => segment.startsWith(LISA_NAMESPACE_PREFIX));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Every tracked copy-overwrite source that installs a Lisa-owned file.
|
|
79
|
+
* @returns {Map<string, string[]>} Destination path to the source paths producing it
|
|
80
|
+
*/
|
|
81
|
+
function lisaOwnedSources() {
|
|
82
|
+
const byDestination = new Map();
|
|
83
|
+
const marker = `/${COPY_OVERWRITE}/`;
|
|
84
|
+
for (const tracked of git(["ls-files"]).split("\n")) {
|
|
85
|
+
const at = tracked.indexOf(marker);
|
|
86
|
+
if (at === -1) continue;
|
|
87
|
+
const destination = tracked.slice(at + marker.length);
|
|
88
|
+
if (!isLisaOwned(destination)) continue;
|
|
89
|
+
const sources = byDestination.get(destination) ?? [];
|
|
90
|
+
sources.push(tracked);
|
|
91
|
+
byDestination.set(destination, sources);
|
|
92
|
+
}
|
|
93
|
+
return byDestination;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The bytes currently on disk for a tracked source.
|
|
98
|
+
*
|
|
99
|
+
* Read from the working tree rather than `HEAD:` so an author who edits a guard
|
|
100
|
+
* and regenerates gets *their* new hash recorded. Reading HEAD would record the
|
|
101
|
+
* pre-edit bytes and force a commit-then-regenerate-then-amend dance, and the
|
|
102
|
+
* `--check` gate would be asserting against a version nobody is shipping. In CI
|
|
103
|
+
* the working tree is the checked-out commit, so the two agree there.
|
|
104
|
+
* @param {string} source - Repo-relative source path
|
|
105
|
+
* @returns {Buffer|undefined} File contents, or undefined when unreadable
|
|
106
|
+
*/
|
|
107
|
+
function workingCopy(source) {
|
|
108
|
+
try {
|
|
109
|
+
return readFileSync(path.join(repoRoot, source));
|
|
110
|
+
} catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Hex sha256 of a blob's bytes.
|
|
117
|
+
* @param {Buffer} bytes - Blob contents
|
|
118
|
+
* @returns {string} Lower-case hex digest
|
|
119
|
+
*/
|
|
120
|
+
function digest(bytes) {
|
|
121
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Every hash this source path has ever had, across all of its history.
|
|
126
|
+
*
|
|
127
|
+
* `--follow` keeps a renamed guard's earlier hashes, which is exactly the case
|
|
128
|
+
* where a host is most likely to be running an older copy.
|
|
129
|
+
* @param {string} source - Repo-relative source path
|
|
130
|
+
* @returns {string[]} Hashes of every historical revision plus the checked-in copy
|
|
131
|
+
*/
|
|
132
|
+
function historicalHashes(source) {
|
|
133
|
+
const hashes = [];
|
|
134
|
+
const current = workingCopy(source);
|
|
135
|
+
if (current !== undefined) hashes.push(digest(current));
|
|
136
|
+
|
|
137
|
+
// `--name-only` is what makes rename-following actually work. Asking for the
|
|
138
|
+
// commit list alone and then reading `<rev>:<source>` fails for every revision
|
|
139
|
+
// before a rename, because the file did not live at that path yet — the very
|
|
140
|
+
// revisions a long-installed host is most likely to be running.
|
|
141
|
+
const log = git([
|
|
142
|
+
"log",
|
|
143
|
+
"--format=%H",
|
|
144
|
+
"--follow",
|
|
145
|
+
"--name-only",
|
|
146
|
+
"--",
|
|
147
|
+
source,
|
|
148
|
+
]).split("\n");
|
|
149
|
+
let revision = "";
|
|
150
|
+
for (const line of log) {
|
|
151
|
+
if (/^[0-9a-f]{40}$/.test(line)) {
|
|
152
|
+
revision = line;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (line === "" || revision === "") continue;
|
|
156
|
+
const blob = git(["show", `${revision}:${line}`]);
|
|
157
|
+
if (blob !== "") hashes.push(digest(Buffer.from(blob, "binary")));
|
|
158
|
+
}
|
|
159
|
+
return hashes;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Hashes already recorded in the checked-in ledger, so none is ever lost.
|
|
164
|
+
* @returns {Map<string, string[]>} Destination path to previously recorded hashes
|
|
165
|
+
*/
|
|
166
|
+
function existingLedger() {
|
|
167
|
+
const previous = new Map();
|
|
168
|
+
let source = "";
|
|
169
|
+
try {
|
|
170
|
+
source = readFileSync(outputPath, "utf8");
|
|
171
|
+
} catch {
|
|
172
|
+
return previous;
|
|
173
|
+
}
|
|
174
|
+
const entry = /"([^"]+)": Object\.freeze\(\[([^\]]*)\]\)/g;
|
|
175
|
+
for (const match of source.matchAll(entry)) {
|
|
176
|
+
previous.set(
|
|
177
|
+
match[1],
|
|
178
|
+
[...match[2].matchAll(/"([0-9a-f]{64})"/g)].map(hash => hash[1])
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
return previous;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Render the ledger module.
|
|
186
|
+
* @param {Map<string, string[]>} ledger - Destination path to known-good hashes
|
|
187
|
+
* @returns {string} TypeScript module source
|
|
188
|
+
*/
|
|
189
|
+
function render(ledger) {
|
|
190
|
+
const entries = [...ledger.entries()]
|
|
191
|
+
.sort(([left], [right]) => (left < right ? -1 : 1))
|
|
192
|
+
// Indentation matches what Prettier produces. `lint-staged` reformats every
|
|
193
|
+
// staged file, so a generator whose output Prettier would reindent leaves
|
|
194
|
+
// `--check` failing immediately after the commit that regenerated it.
|
|
195
|
+
.map(([destination, hashes]) => {
|
|
196
|
+
const rendered = hashes.map(hash => ` "${hash}",`).join("\n");
|
|
197
|
+
return ` "${destination}": Object.freeze([\n${rendered}\n ]),`;
|
|
198
|
+
})
|
|
199
|
+
.join("\n");
|
|
200
|
+
return `/** Generated by scripts/generate-lisa-owned-hash-ledger.mjs. Do not edit. */
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Every content hash Lisa has published at each Lisa-owned destination path.
|
|
204
|
+
*
|
|
205
|
+
* A host copy whose hash appears here is provably an older Lisa artifact and may
|
|
206
|
+
* be refreshed. One that appears nowhere here was edited downstream, and refresh
|
|
207
|
+
* refuses rather than risk deleting a stronger guard. See
|
|
208
|
+
* \`src/core/lisa-owned-provenance.ts\`.
|
|
209
|
+
*/
|
|
210
|
+
export const LISA_OWNED_HASH_LEDGER: Readonly<
|
|
211
|
+
Record<string, readonly string[]>
|
|
212
|
+
> = Object.freeze({
|
|
213
|
+
${entries}
|
|
214
|
+
});
|
|
215
|
+
`;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const ledger = new Map(existingLedger());
|
|
219
|
+
for (const [destination, sources] of lisaOwnedSources()) {
|
|
220
|
+
const known = new Set(ledger.get(destination) ?? []);
|
|
221
|
+
for (const source of sources) {
|
|
222
|
+
for (const hash of historicalHashes(source)) known.add(hash);
|
|
223
|
+
}
|
|
224
|
+
ledger.set(destination, [...known].sort());
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (process.argv.includes("--check")) {
|
|
228
|
+
checkCurrentBytesAreRecorded();
|
|
229
|
+
} else {
|
|
230
|
+
writeFileSync(outputPath, render(ledger));
|
|
231
|
+
process.stdout.write(`Wrote ${ledger.size} ledger entries.\n`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Assert the one property that actually protects refresh: every Lisa-owned file
|
|
236
|
+
* Lisa ships *right now* has its current hash recorded.
|
|
237
|
+
*
|
|
238
|
+
* Deliberately narrower than "the file equals a fresh regeneration". That
|
|
239
|
+
* stricter form looks safer and is not: the history walk depends on clone depth
|
|
240
|
+
* and on merge topology, so a byte-exact check fails whenever CI's view of
|
|
241
|
+
* history differs from the author's. It did exactly that here — `autoupdate`
|
|
242
|
+
* merged `main` into the PR branch, main carried other merged template changes,
|
|
243
|
+
* the walk found hashes the author's run never saw, and a correct ledger was
|
|
244
|
+
* reported out of date. With many PRs in flight it would mean every merge
|
|
245
|
+
* reddens every other open PR.
|
|
246
|
+
*
|
|
247
|
+
* Historical hashes appearing later are purely additive, and being additive they
|
|
248
|
+
* cannot cause harm: an extra known-good hash can only let refresh replace a
|
|
249
|
+
* copy that genuinely came from an older Lisa. What must never happen is the
|
|
250
|
+
* *current* bytes going unrecorded — a guard edited without regenerating would
|
|
251
|
+
* stop being recognised as Lisa's own, and refresh would silently stop
|
|
252
|
+
* delivering it. That is the failure this gate exists to catch, and it is
|
|
253
|
+
* deterministic everywhere.
|
|
254
|
+
*/
|
|
255
|
+
function checkCurrentBytesAreRecorded() {
|
|
256
|
+
const recorded = existingLedger();
|
|
257
|
+
const missing = [];
|
|
258
|
+
for (const [destination, sources] of lisaOwnedSources()) {
|
|
259
|
+
const known = new Set(recorded.get(destination) ?? []);
|
|
260
|
+
for (const source of sources) {
|
|
261
|
+
const current = workingCopy(source);
|
|
262
|
+
if (current === undefined) continue;
|
|
263
|
+
if (!known.has(digest(current))) missing.push(source);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (missing.length > 0) {
|
|
267
|
+
process.stderr.write(
|
|
268
|
+
`Lisa-owned hash ledger does not record the bytes currently shipped for:\n${missing
|
|
269
|
+
.map(source => ` ${source}`)
|
|
270
|
+
.join(
|
|
271
|
+
"\n"
|
|
272
|
+
)}\nRun \`bun run build:lisa-owned-hash-ledger\` and commit the result.\n`
|
|
273
|
+
);
|
|
274
|
+
process.exit(1);
|
|
275
|
+
}
|
|
276
|
+
process.stdout.write(
|
|
277
|
+
`Lisa-owned hash ledger records every shipped artifact (${recorded.size} entries).\n`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Auto-update PR branches (Dispatch Handler)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Auto-update PR branches
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Claude CI Auto-Fix
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Claude Code Review Response
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Claude Deploy Auto-Fix
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Claude Nightly Code Complexity
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Claude Nightly Test Coverage
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
|
|
4
5
|
name: Claude Nightly Test Improvement
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# You can customize this file — Lisa will not overwrite it.
|
|
3
4
|
#
|
|
4
5
|
# Back-syncs merges down the env chain so hotfixes propagate.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
2
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
2
3
|
# -----------------------------------------------------------------------------
|
|
3
4
|
# Required-checks snapshot drift — the REMOTE arm (#2426)
|
|
4
5
|
# -----------------------------------------------------------------------------
|