@codyswann/lisa 3.41.1 → 3.43.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.
Files changed (66) hide show
  1. package/all/copy-overwrite/scripts/lisa-environment-prepare.mjs +356 -0
  2. package/all/copy-overwrite/scripts/lisa-work-item.mjs +203 -1
  3. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  4. package/dist/core/lisa-owned-hash-ledger.js +6 -0
  5. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  6. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  7. package/dist/core/upstream-evidence-manifest.js +12 -3
  8. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  9. package/expo/create-only/.github/workflows/playwright-e2e.yml +92 -75
  10. package/package.json +1 -1
  11. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  13. package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  14. package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  15. package/plugins/lisa-agy/plugin.json +1 -1
  16. package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  17. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  20. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  24. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  26. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  28. package/plugins/lisa-expo-agy/plugin.json +1 -1
  29. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  39. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  44. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  49. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails-agy/plugin.json +1 -1
  54. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  59. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  64. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  66. package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
@@ -0,0 +1,356 @@
1
+ #!/usr/bin/env node
2
+ // This file is managed by Lisa and IS replaced on each `lisa` run.
3
+ // Do not edit directly — durable changes belong upstream in Lisa.
4
+
5
+ /**
6
+ * lisa-environment-prepare — the caller the `environment:*` facade never had.
7
+ *
8
+ * Lisa already defines the facade and ships gates that prove a project's reset
9
+ * guard REFUSES. It shipped nothing that actually resets an environment before
10
+ * a suite, so every consumer hand-wired its own: measured 2026-08-19, one
11
+ * frontend resets after its browser suite via `if: always()`, the same repo's
12
+ * native suite resets not at all, and a second repo's shape could not be
13
+ * verified. A native suite had therefore been accumulating data nightly.
14
+ *
15
+ * This module owns three things and deliberately no more:
16
+ *
17
+ * 1. **Sequencing.** Reset before reseed, always, regardless of the order a
18
+ * caller lists them. They are not commutative: reseeding and then emptying
19
+ * leaves an empty environment that reports as prepared.
20
+ * 2. **Failure semantics.** A verb the caller ASKED FOR and that the project
21
+ * does not declare is a failure, never a skip. This is the whole point. A
22
+ * suite that runs against an environment nobody reset, and reports green,
23
+ * is the defect the facade work existed to prevent, and it is exactly what
24
+ * a tolerant "the script wasn't there, carry on" would reintroduce.
25
+ * 3. **Refusing production before invoking anything.**
26
+ *
27
+ * What it does NOT own is what the verbs do. Per the facade contract §3 the
28
+ * verbs are an interface, not a mechanism; a project may implement them with a
29
+ * local script today and a scoped Lambda tomorrow without this file changing.
30
+ *
31
+ * ## On the production refusal, and what it is worth
32
+ *
33
+ * The check here is a CALLER-SIDE refusal on the environment name it was
34
+ * handed. It is not identity verification and must not be read as any: this
35
+ * process has no connection to the target and no way to learn that a name
36
+ * reading `dev` addresses a production database through a tunnel or a copied
37
+ * env file. That gap is closed by layers this file cannot reach — the reset
38
+ * capability not being deployed to production at all, an execution role that
39
+ * cannot invoke it there, the implementation asserting its own resolved stage,
40
+ * and the implementation asserting the database it actually connected to.
41
+ *
42
+ * So this refusal is the cheap outer layer of several, and its value is that
43
+ * it is the one that fires before a single process starts. It is written
44
+ * against the shipped `lisa-destructive-guard` classifier rather than a fresh
45
+ * regex so that "what counts as production" has ONE definition in Lisa — the
46
+ * guard already treats `prod`, `prd` and `live` as production and treats an
47
+ * identity it cannot read exactly as it treats production.
48
+ *
49
+ * @module scripts/lisa-environment-prepare
50
+ */
51
+
52
+ import { existsSync, readFileSync } from "node:fs";
53
+ import { join } from "node:path";
54
+ import { spawnSync } from "node:child_process";
55
+
56
+ import { classifyEnvironment } from "./lisa-destructive-guard.mjs";
57
+ import { invokedAsScript } from "./lib/invoked-as-script.mjs";
58
+ import { readGates } from "./lisa-gates.mjs";
59
+
60
+ /**
61
+ * The facade's verbs, in the only order they may run.
62
+ *
63
+ * Order is a property of the module rather than of the caller's argument list,
64
+ * because a caller that lists them the other way round has made a mistake this
65
+ * module can simply not honour.
66
+ */
67
+ export const FACADE_VERBS = Object.freeze(["reset", "reseed"]);
68
+
69
+ /**
70
+ * Every reason a preparation can refuse or fail.
71
+ *
72
+ * Machine-readable and stable: reports and workflow steps branch on these, and
73
+ * the facade contract §4 obligation 5 requires a refusal to carry the guard's
74
+ * own vocabulary so it is demonstrably a refusal rather than a crash on the
75
+ * way to one.
76
+ */
77
+ export const PREPARE_REASONS = Object.freeze([
78
+ "environment_env_required",
79
+ "environment_name_malformed",
80
+ "environment_runner_malformed",
81
+ "environment_target_forbidden",
82
+ "environment_verb_unknown",
83
+ "environment_verb_missing",
84
+ "environment_verb_failed",
85
+ ]);
86
+
87
+ /**
88
+ * The task name a verb resolves to.
89
+ * @param {string} verb One of {@link FACADE_VERBS}.
90
+ * @returns {string} The npm script name, e.g. `environment:reset`.
91
+ */
92
+ function taskFor(verb) {
93
+ return `environment:${verb}`;
94
+ }
95
+
96
+ /**
97
+ * A usable environment name.
98
+ *
99
+ * An allowlist of shapes, not a denylist of dangerous characters, and that is
100
+ * the whole point — a denylist is a list of the attacks someone thought of.
101
+ * This admits `dev`, `staging`, `us-prod-1`, `preview_2`; it admits nothing
102
+ * carrying a space, a quote, a semicolon, a backtick, or `$(`.
103
+ *
104
+ * Without it, `classifyEnvironment` is not sufficient protection even though it
105
+ * is the right classifier: it splits on non-alphanumerics and inspects the
106
+ * SEGMENTS, so `dev; rm -rf /` yields `dev`, `rm`, `rf` — none of which look
107
+ * like production — and the value passes the refusal. Measured before this
108
+ * existed, `--env='dev; touch /tmp/x'` produced the command
109
+ * `bun run environment:reset -- --env=dev; touch /tmp/x`. The injected half
110
+ * could name production, so the omission defeated the production guard using
111
+ * the very input that guard exists to check.
112
+ */
113
+ const ENVIRONMENT_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/u;
114
+
115
+ /**
116
+ * A usable task-runner prefix.
117
+ *
118
+ * Same reasoning, applied to the other value that reaches the child process.
119
+ * It comes from `.lisa.config.json`, which is a less likely attacker channel
120
+ * than a workflow input — but "less likely" is not a property worth relying on
121
+ * when the check costs one regular expression. Mirrors the plain-command
122
+ * validation `quality.yml` already applies to a resolved gate command.
123
+ */
124
+ const RUNNER_PREFIX = /^[A-Za-z0-9][A-Za-z0-9 ._@:/-]*$/u;
125
+
126
+ /**
127
+ * The argument vector for a verb.
128
+ *
129
+ * A vector rather than a command line, and executed WITHOUT a shell, so no
130
+ * amount of punctuation in any element can become syntax. The name validation
131
+ * above already makes that unreachable; this makes it impossible rather than
132
+ * merely blocked, which is the correct arrangement for the destructive path.
133
+ *
134
+ * The bare `--` is load-bearing and not stylistic. Measured on 2026-08-19:
135
+ * `npm run <task> --env=dev` reaches the script with NO arguments at all,
136
+ * while `bun run <task> --env=dev` forwards it — so the form without `--` is
137
+ * correct on one runner and silently argument-less on the other. Both runners
138
+ * forward correctly with `--`, so that is the only portable form.
139
+ * @param {string} runner Task-runner prefix, e.g. `bun run`.
140
+ * @param {string} verb One of {@link FACADE_VERBS}.
141
+ * @param {string} env The target environment name.
142
+ * @returns {string[]} The argument vector, executable without a shell.
143
+ */
144
+ function argvFor(runner, verb, env) {
145
+ return [...runner.trim().split(/\s+/u), taskFor(verb), "--", `--env=${env}`];
146
+ }
147
+
148
+ /**
149
+ * The default executor: run the vector directly, inheriting stdio.
150
+ *
151
+ * No `shell: true`. stdio is inherited so a failing reset's own output reaches
152
+ * the operator unaltered — a summary reprinted by this module would be strictly
153
+ * less useful than what the project's own tooling already said.
154
+ * @param {string[]} argv The argument vector.
155
+ * @returns {number|null} Exit code, or null when the child was killed.
156
+ */
157
+ function spawnExec(argv) {
158
+ const [file, ...args] = argv;
159
+ const child = spawnSync(file, args, { stdio: "inherit" });
160
+ if (child.error) return null;
161
+ return child.status;
162
+ }
163
+
164
+ /**
165
+ * Prepare an environment by running the requested facade verbs in order.
166
+ *
167
+ * Every refusal happens BEFORE the first invocation. That ordering is
168
+ * deliberate: a run that resets and then discovers the reseed is missing has
169
+ * emptied a shared environment and left it empty, which is a worse state than
170
+ * the one it started in and one no later step can undo.
171
+ * @param {object} options Options.
172
+ * @param {string} [options.env] Target environment name. Mandatory.
173
+ * @param {readonly string[]} [options.verbs] Verbs the caller requires.
174
+ * @param {Record<string, string>} [options.scripts] The project's npm scripts.
175
+ * @param {string} [options.runner] Task-runner prefix, e.g. `bun run`.
176
+ * @param {(command: string) => number|null} [options.exec] Executor.
177
+ * @returns {{ok: boolean, reason: string|null, message: string, ran: string[]}} Outcome.
178
+ */
179
+ export function prepareEnvironment({
180
+ env,
181
+ verbs = FACADE_VERBS,
182
+ scripts = {},
183
+ runner = "npm run",
184
+ exec = spawnExec,
185
+ }) {
186
+ const target = typeof env === "string" ? env.trim() : "";
187
+ if (!target) {
188
+ return {
189
+ ok: false,
190
+ reason: "environment_env_required",
191
+ message:
192
+ "--env is required and has no default. A default that is safe in one repo is the production default in another, so there is no value to fall back to.",
193
+ ran: [],
194
+ };
195
+ }
196
+
197
+ // Shape BEFORE meaning. A name that cannot be a name is refused as
198
+ // malformed rather than classified, because classification of a malformed
199
+ // value is where the injection lived: the classifier reads alphanumeric
200
+ // segments and is blind to the punctuation between them.
201
+ if (!ENVIRONMENT_NAME.test(target)) {
202
+ return {
203
+ ok: false,
204
+ reason: "environment_name_malformed",
205
+ message: `"${target}" is not a usable environment name. Names must start with a letter or digit and contain only letters, digits, dot, underscore and hyphen. Anything else is refused before it is classified, because a value carrying shell punctuation can look non-production segment by segment while naming production in the part that gets executed.`,
206
+ ran: [],
207
+ };
208
+ }
209
+
210
+ if (!RUNNER_PREFIX.test(runner)) {
211
+ return {
212
+ ok: false,
213
+ reason: "environment_runner_malformed",
214
+ message: `the configured task runner "${runner}" is not a plain command. Set gates.runner in .lisa.config.json to something like "bun run".`,
215
+ ran: [],
216
+ };
217
+ }
218
+
219
+ const unknown = verbs.filter(verb => !FACADE_VERBS.includes(verb));
220
+ if (unknown.length > 0) {
221
+ return {
222
+ ok: false,
223
+ reason: "environment_verb_unknown",
224
+ message: `unknown verb(s): ${unknown.join(", ")}. The facade defines exactly ${FACADE_VERBS.join(" and ")}.`,
225
+ ran: [],
226
+ };
227
+ }
228
+
229
+ // Ambiguity resolves to refusal: `classifyEnvironment` reports `unresolved`
230
+ // for anything it cannot read, and this treats that identically to
231
+ // production. "I could not tell" must never be the cheaper answer.
232
+ if (classifyEnvironment(target) !== "non-production") {
233
+ return {
234
+ ok: false,
235
+ reason: "environment_target_forbidden",
236
+ message: `"${target}" is refused as a destructive target. Production is refused with no override, and an environment identity that cannot be classified fails closed exactly as production does.`,
237
+ ran: [],
238
+ };
239
+ }
240
+
241
+ // Resolve every requested verb before running any of them.
242
+ const ordered = FACADE_VERBS.filter(verb => verbs.includes(verb));
243
+ const missing = ordered.filter(verb => !scripts[taskFor(verb)]);
244
+ if (missing.length > 0) {
245
+ return {
246
+ ok: false,
247
+ reason: "environment_verb_missing",
248
+ message: `the caller requires ${missing.map(taskFor).join(" and ")}, which this project does not declare. A required verb that is absent is a failure, not a skip — a suite running against an environment nobody prepared proves nothing. Declare the script, or stop requiring the verb.`,
249
+ ran: [],
250
+ };
251
+ }
252
+
253
+ const ran = [];
254
+ for (const verb of ordered) {
255
+ const argv = argvFor(runner, verb, target);
256
+ ran.push(argv.join(" "));
257
+ const status = exec(argv);
258
+ // A null status is spawnSync's report of a child killed by a signal. Any
259
+ // reading other than "failed" lets an OOM-killed reset clear the suite.
260
+ if (status !== 0) {
261
+ return {
262
+ ok: false,
263
+ reason: "environment_verb_failed",
264
+ message: `${taskFor(verb)} ${status === null ? "was killed before it finished" : `exited ${status}`}. Nothing after it ran: a reseed layered onto a failed reset produces fixture data on top of whatever the last run left behind.`,
265
+ ran,
266
+ };
267
+ }
268
+ }
269
+
270
+ return {
271
+ ok: true,
272
+ reason: null,
273
+ message: `prepared ${target}: ${ordered.map(taskFor).join(", ")}`,
274
+ ran,
275
+ };
276
+ }
277
+
278
+ /**
279
+ * Read a `--name=<value>` flag from the argument list.
280
+ * @param {readonly string[]} argv Arguments after the script name.
281
+ * @param {string} name Flag name, without dashes.
282
+ * @returns {string|null} The value, or null when absent.
283
+ */
284
+ function readFlag(argv, name) {
285
+ const prefix = `--${name}=`;
286
+ const hit = argv.find(arg => arg.startsWith(prefix));
287
+ return hit ? hit.slice(prefix.length) : null;
288
+ }
289
+
290
+ /**
291
+ * The `scripts` block of the project's `package.json`.
292
+ * @param {string} cwd Project root.
293
+ * @returns {Record<string, string>} The scripts, empty when unreadable.
294
+ */
295
+ function readPackageScripts(cwd) {
296
+ const path = join(cwd, "package.json");
297
+ if (!existsSync(path)) return {};
298
+ try {
299
+ return JSON.parse(readFileSync(path, "utf8"))?.scripts ?? {};
300
+ } catch {
301
+ return {};
302
+ }
303
+ }
304
+
305
+ /**
306
+ * CLI entry point.
307
+ * @param {readonly string[]} [argv] Arguments after the script name.
308
+ * @param {string} [cwd] Project root.
309
+ * @returns {number} Process exit code.
310
+ */
311
+ export function runCli(argv = process.argv.slice(2), cwd = process.cwd()) {
312
+ const env = readFlag(argv, "env");
313
+ const verbsFlag = readFlag(argv, "verbs");
314
+ const verbs = verbsFlag
315
+ ? verbsFlag
316
+ .split(",")
317
+ .map(verb => verb.trim())
318
+ .filter(Boolean)
319
+ : FACADE_VERBS;
320
+
321
+ let runner = "npm run";
322
+ try {
323
+ runner = readGates(cwd).runner;
324
+ } catch {
325
+ // An unreadable config falls back to the same default the gate runner
326
+ // uses, so the two never disagree about how to invoke a task. The comment
327
+ // that stood here claimed this was "not a reason to guess a runner and
328
+ // press on", which is the opposite of what the code does — it does press
329
+ // on, deliberately. Pressing on is safe because the fallback is a plain
330
+ // `npm run`: a project whose scripts are not reachable that way fails at
331
+ // the verb, with its own error, rather than here with a guess about why.
332
+ }
333
+
334
+ const result = prepareEnvironment({
335
+ env,
336
+ verbs,
337
+ scripts: readPackageScripts(cwd),
338
+ runner,
339
+ });
340
+
341
+ if (result.ok) {
342
+ console.log(`✅ ${result.message}`);
343
+ return 0;
344
+ }
345
+ console.error(`❌ environment preparation refused: ${result.reason}`);
346
+ console.error(` ${result.message}`);
347
+ return 1;
348
+ }
349
+
350
+ // Realpath-based, for the reason spelled out at the foot of lisa-gates.mjs: a
351
+ // string comparison of module URLs answers "no" through a symlinked checkout,
352
+ // a git worktree, or a macOS /tmp path, and this file would then load, run
353
+ // nothing, and exit 0 — a preparation that never happened, reported as done.
354
+ if (invokedAsScript(import.meta.url)) {
355
+ process.exit(runCli());
356
+ }
@@ -2011,6 +2011,206 @@ function backlink(args) {
2011
2011
  console.log(`work-item backlink ${outcome} on ${ref}: ${MARKER} ${prUrl}`);
2012
2012
  }
2013
2013
 
2014
+ /**
2015
+ * Cross-references on a work item that are MERGED pull requests in one repo.
2016
+ *
2017
+ * Repo-scoped deliberately. A cross-reference carries no repository constraint,
2018
+ * so a downstream consumer's pull request mentioning an upstream issue appears
2019
+ * here exactly like a local one. Measured while building this: a sweep that
2020
+ * ignored `repository_url` credited two issues with fixes that lived in other
2021
+ * repositories entirely, which is the difference between "shipped" and
2022
+ * "somebody mentioned it".
2023
+ *
2024
+ * Exported so it can be asserted against fixture payloads without a network —
2025
+ * a permissive filter returns MORE numbers rather than throwing, so nothing
2026
+ * observable changes unless something asserts on the returned list.
2027
+ * @param {unknown[]} events Timeline events for the work item.
2028
+ * @param {string} repository `owner/name` the pull request must belong to.
2029
+ * @returns {number[]} Merged pull-request numbers, de-duplicated.
2030
+ */
2031
+ export function mergedPullRequestsIn(events, repository) {
2032
+ const suffix = `/${repository}`;
2033
+ const numbers = (Array.isArray(events) ? events : [])
2034
+ .filter(event => event?.event === "cross-referenced")
2035
+ .map(event => event?.source?.issue)
2036
+ .filter(issue => issue?.pull_request?.merged_at)
2037
+ .filter(issue => String(issue?.repository_url ?? "").endsWith(suffix))
2038
+ .map(issue => issue?.number)
2039
+ .filter(number => typeof number === "number");
2040
+ return [...new Set(numbers)];
2041
+ }
2042
+
2043
+ function githubTimeline(ref) {
2044
+ const [repository, number] = ref.split("#");
2045
+ const result = run(
2046
+ "gh",
2047
+ ["api", `repos/${repository}/issues/${number}/timeline?per_page=100`],
2048
+ { allowFailure: true }
2049
+ );
2050
+ if (result.status !== 0) throw githubFailure(result, ref);
2051
+ const events = safeJson(result.stdout, `GitHub timeline for ${ref}`);
2052
+ return Array.isArray(events) ? events : [];
2053
+ }
2054
+
2055
+ /**
2056
+ * Move a work item to its configured terminal role and close it.
2057
+ *
2058
+ * The terminal role is RESOLVED from configuration, never assumed. Lisa's own
2059
+ * repository maps `production` to `status:done`, but the map is environment
2060
+ * aware — a project whose target is `dev` has a different terminal role, and a
2061
+ * hardcoded label would silently apply the wrong one there while looking
2062
+ * correct here. `lifecycleContract` already computes this for every provider.
2063
+ *
2064
+ * **It refuses without evidence.** A completion command that closes whatever it
2065
+ * is pointed at is a way to make unfinished work disappear, which is the same
2066
+ * defect class as a gate that passes because it found nothing. Evidence is a
2067
+ * merged pull request in this repository.
2068
+ * @param {string} ref Canonical work-item reference.
2069
+ * @param {object} contract The resolved tracker contract.
2070
+ * @returns {{merged: number[], terminal: string}} What was applied, and why.
2071
+ */
2072
+ function completeWorkItem(ref, contract) {
2073
+ if (contract.provider !== "github") {
2074
+ throw new TrackingError(
2075
+ `no completion writer for tracker '${contract.provider}'; only github is supported so far.\n` +
2076
+ `Add one rather than closing by hand — a lifecycle step performed by hand is one nothing can verify happened.`
2077
+ );
2078
+ }
2079
+ const [repository, number] = ref.split("#");
2080
+ const merged = mergedPullRequestsIn(githubTimeline(ref), repository);
2081
+ if (merged.length === 0) {
2082
+ throw new TrackingError(
2083
+ `refusing to complete ${ref}: no merged pull request in ${repository} references it.\n` +
2084
+ `Completion is evidence-based on purpose. A command that closes whatever it is pointed at\n` +
2085
+ `is a way to make unfinished work disappear, and the closure would be indistinguishable\n` +
2086
+ `from a real one afterwards. If the work shipped some other way, say so on the item and close it deliberately.`
2087
+ );
2088
+ }
2089
+ const terminal = contract.lifecycle.terminal;
2090
+ const claimed = contract.lifecycle.claimed;
2091
+ const edit = [
2092
+ "issue",
2093
+ "edit",
2094
+ String(number),
2095
+ "--repo",
2096
+ repository,
2097
+ "--add-label",
2098
+ terminal,
2099
+ ];
2100
+ // Removing the claimed role is what makes the claimed lane mean something.
2101
+ // Leaving it produces the exact drift this command exists to end: an item
2102
+ // that is closed AND still reports as in progress.
2103
+ if (claimed && claimed !== terminal) {
2104
+ edit.push("--remove-label", claimed);
2105
+ }
2106
+ const edited = run("gh", edit, { allowFailure: true });
2107
+ if (edited.status !== 0) throw githubFailure(edited, ref);
2108
+ const closed = run(
2109
+ "gh",
2110
+ [
2111
+ "issue",
2112
+ "close",
2113
+ String(number),
2114
+ "--repo",
2115
+ repository,
2116
+ "--reason",
2117
+ "completed",
2118
+ ],
2119
+ { allowFailure: true }
2120
+ );
2121
+ if (closed.status !== 0) throw githubFailure(closed, ref);
2122
+ return { merged, terminal };
2123
+ }
2124
+
2125
+ function complete(args) {
2126
+ const contract = trackerContract();
2127
+ const supplied = option(args, "--ref", "LISA_WORK_ITEM_REF");
2128
+ const bound = readState(true)?.ref;
2129
+ if (!supplied && !bound) {
2130
+ throw new TrackingError(
2131
+ "complete requires --ref <work-item>, or a worktree binding from `lisa-work-item.mjs link`"
2132
+ );
2133
+ }
2134
+ const ref = canonicalizeRef(supplied ?? bound, contract);
2135
+ const { merged, terminal } = completeWorkItem(ref, contract);
2136
+ console.log(
2137
+ `work-item completed: ${ref} -> ${terminal} (merged: ${merged
2138
+ .map(number => `#${number}`)
2139
+ .join(", ")})`
2140
+ );
2141
+ }
2142
+
2143
+ /**
2144
+ * Report every claimed work item that already has a merged pull request.
2145
+ *
2146
+ * The drift detector. Closing at merge time is the fix; this is what catches
2147
+ * the ones that slipped, and what proves whether the fix is holding. Measured
2148
+ * before either existed: 27 of 27 claimed items in this repository had a merged
2149
+ * pull request, so the claimed lane reported 27 things in flight when the real
2150
+ * number was one.
2151
+ *
2152
+ * Reports by default and only acts under `--apply`, because a sweep that closes
2153
+ * things as a side effect of being run is not something anyone will run twice.
2154
+ */
2155
+ function sweep(args) {
2156
+ const contract = trackerContract();
2157
+ if (contract.provider !== "github") {
2158
+ throw new TrackingError(
2159
+ `no sweep for tracker '${contract.provider}'; only github is supported so far.`
2160
+ );
2161
+ }
2162
+ const repository = currentRepository();
2163
+ if (!repository)
2164
+ throw new TrackingError("could not resolve the current GitHub repository");
2165
+ const claimed = contract.lifecycle.claimed;
2166
+ const listing = run(
2167
+ "gh",
2168
+ [
2169
+ "issue",
2170
+ "list",
2171
+ "--repo",
2172
+ repository,
2173
+ "--state",
2174
+ "open",
2175
+ "--label",
2176
+ claimed,
2177
+ "--limit",
2178
+ "200",
2179
+ "--json",
2180
+ "number,title",
2181
+ ],
2182
+ { allowFailure: true }
2183
+ );
2184
+ if (listing.status !== 0) throw githubFailure(listing, repository);
2185
+ const issues = safeJson(listing.stdout, "GitHub issue listing");
2186
+ const apply = args.includes("--apply");
2187
+ let drifted = 0;
2188
+ for (const issue of Array.isArray(issues) ? issues : []) {
2189
+ const ref = `${repository}#${issue.number}`;
2190
+ const merged = mergedPullRequestsIn(githubTimeline(ref), repository);
2191
+ if (merged.length === 0) continue;
2192
+ drifted += 1;
2193
+ const evidence = merged.map(number => `#${number}`).join(", ");
2194
+ if (!apply) {
2195
+ console.log(`DRIFT ${ref} merged: ${evidence} ${issue.title}`);
2196
+ continue;
2197
+ }
2198
+ const { terminal } = completeWorkItem(ref, contract);
2199
+ console.log(`completed ${ref} -> ${terminal} (merged: ${evidence})`);
2200
+ }
2201
+ if (drifted === 0) {
2202
+ console.log(
2203
+ `No drift: every item carrying "${claimed}" is genuinely in flight.`
2204
+ );
2205
+ return;
2206
+ }
2207
+ if (!apply) {
2208
+ console.log(
2209
+ `\n${drifted} claimed item(s) already have a merged pull request. Re-run with --apply to complete them.`
2210
+ );
2211
+ }
2212
+ }
2213
+
2014
2214
  function prepareCommitMessage(args) {
2015
2215
  const [file, source = ""] = args;
2016
2216
  if (!file)
@@ -2159,6 +2359,8 @@ function main() {
2159
2359
  return console.log("work-item binding cleared");
2160
2360
  }
2161
2361
  if (command === "backlink") return backlink(args);
2362
+ if (command === "complete") return complete(args);
2363
+ if (command === "sweep") return sweep(args);
2162
2364
  // One place resolves the level, and everything else asks. The CI job needs
2163
2365
  // it to decide whether a missing tracker credential is a problem, and a
2164
2366
  // second implementation of the precedence rules in shell is exactly the
@@ -2169,7 +2371,7 @@ function main() {
2169
2371
  if (command === "validate-push") return validatePush(args);
2170
2372
  if (command === "validate-pr") return validatePr(args);
2171
2373
  throw new TrackingError(
2172
- "Usage: lisa-work-item.mjs link|current|attach-branch|clear|verify-level|backlink|prepare-commit-msg|validate-commit|validate-push|validate-pr" +
2374
+ "Usage: lisa-work-item.mjs link|current|attach-branch|clear|verify-level|backlink|complete|sweep|prepare-commit-msg|validate-commit|validate-push|validate-pr" +
2173
2375
  "\n(`bind` is accepted as an alias for `link`, but some agent harnesses refuse the token `bind` in a command line.)"
2174
2376
  );
2175
2377
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lisa-owned-hash-ledger.d.ts","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AACA,6EAA6E;AAE7E;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAwYjC,CAAC"}
1
+ {"version":3,"file":"lisa-owned-hash-ledger.d.ts","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AACA,6EAA6E;AAE7E;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CA8YjC,CAAC"}
@@ -207,6 +207,10 @@ export const LISA_OWNED_HASH_LEDGER = Object.freeze({
207
207
  "d7d88e44763694bed5eae998cd3663922c957e49f9f9621d9201f0417a4128ad",
208
208
  "e17c45f7cadf0fb55dd07270776caf211af99b7d4771a4fde75aafe5919e8dbe",
209
209
  ]),
210
+ "scripts/lisa-environment-prepare.mjs": Object.freeze([
211
+ "c765c7a44ea81d54c7820f2068c8811fb73ca3e5f063cb55a8c30391d1326323",
212
+ "f8c8e276fa6d68ed661f07882f20ee095d18a5e8a90136f78f1ed2b032ce33d4",
213
+ ]),
210
214
  "scripts/lisa-floor-collisions.mjs": Object.freeze([
211
215
  "2d11968f6852ab745cba939de03c6d6cb5f413975d2cfc8fc447bdd0b218e91a",
212
216
  "3c7a0234b4f5609fce49e44711d2ec86af8cf7fb82b0831e4450e3347ecefe45",
@@ -351,7 +355,9 @@ export const LISA_OWNED_HASH_LEDGER = Object.freeze({
351
355
  "2d9ca0841db9e75ddfd95e3a4d485fd01aa639a512ef648996f565b7991d8e2b",
352
356
  "4c263fef48c03b3b6c623ea8a6cd55505bfaf28197e5072226ea35f9f3d26885",
353
357
  "5eb31c284e820a51312d4484f0669128007326af55ee515923fec33700d003a1",
358
+ "637741a9e5d2904aed24d48efd6bec1326c5573f718a13152807aa0e4b42f0a1",
354
359
  "6a8be8577242588f14ab52b25b2a22b6def53aefa9513b4d3d7c49f4d8027079",
360
+ "71ff42c2cb8ac7022e0066132476764dd745fb92bf19ccd395000b1fe319abc7",
355
361
  "83e7f1257bfee293bcdcdafef4272f40fcdca2d9e43ceb9df647c13c8277423d",
356
362
  "8cd8d102d4b3276f92bb4706274d280c302269fb2f564ca93b1d79cb3ff26841",
357
363
  "9223856be4618fb1e3e731b259ae5bf5328decc322f0b4a0d0fd18d6b12cd45a",
@@ -1 +1 @@
1
- {"version":3,"file":"lisa-owned-hash-ledger.js","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lisa-owned-hash-ledger.js","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,6EAA6E;AAE7E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAE/B,MAAM,CAAC,MAAM,CAAC;IAChB,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,+BAA+B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC7C,kEAAkE;KACnE,CAAC;IACF,uBAAuB,EAAE,MAAM,CAAC,MAAM,CAAC;QACrC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,0BAA0B,EAAE,MAAM,CAAC,MAAM,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,yBAAyB,EAAE,MAAM,CAAC,MAAM,CAAC;QACvC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gCAAgC,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gCAAgC,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC;QACpD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,2CAA2C,EAAE,MAAM,CAAC,MAAM,CAAC;QACzD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,qCAAqC,EAAE,MAAM,CAAC,MAAM,CAAC;QACnD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,yCAAyC,EAAE,MAAM,CAAC,MAAM,CAAC;QACvD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,uCAAuC,EAAE,MAAM,CAAC,MAAM,CAAC;QACrD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,+BAA+B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC7C,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,oCAAoC,EAAE,MAAM,CAAC,MAAM,CAAC;QAClD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC;QACpD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC;QACpD,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,iDAAiD,EAAE,MAAM,CAAC,MAAM,CAAC;QAC/D,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,oDAAoD,EAAE,MAAM,CAAC,MAAM,CAAC;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gDAAgD,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9D,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,uCAAuC,EAAE,MAAM,CAAC,MAAM,CAAC;QACrD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,gDAAgD,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9D,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,yCAAyC,EAAE,MAAM,CAAC,MAAM,CAAC;QACvD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,qCAAqC,EAAE,MAAM,CAAC,MAAM,CAAC;QACnD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;KACnE,CAAC;IACF,2BAA2B,EAAE,MAAM,CAAC,MAAM,CAAC;QACzC,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,mCAAmC,EAAE,MAAM,CAAC,MAAM,CAAC;QACjD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,kCAAkC,EAAE,MAAM,CAAC,MAAM,CAAC;QAChD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1C,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1C,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,sDAAsD,EAAE,MAAM,CAAC,MAAM,CAAC;QACpE,kEAAkE;KACnE,CAAC;IACF,oDAAoD,EAAE,MAAM,CAAC,MAAM,CAAC;QAClE,kEAAkE;KACnE,CAAC;IACF,uCAAuC,EAAE,MAAM,CAAC,MAAM,CAAC;QACrD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;IACF,wCAAwC,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;KACnE,CAAC;CACH,CAAC,CAAC;AACH,sEAAsE"}
@@ -1 +1 @@
1
- {"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAs1EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CA2uOjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
1
+ {"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAw1EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAmvOjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}