@codyswann/lisa 4.6.9 → 4.6.11

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 (72) hide show
  1. package/dist/core/anchored-rewrite.d.ts +153 -0
  2. package/dist/core/anchored-rewrite.d.ts.map +1 -0
  3. package/dist/core/anchored-rewrite.js +192 -0
  4. package/dist/core/anchored-rewrite.js.map +1 -0
  5. package/dist/core/index.d.ts +1 -0
  6. package/dist/core/index.d.ts.map +1 -1
  7. package/dist/core/index.js +1 -0
  8. package/dist/core/index.js.map +1 -1
  9. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  10. package/dist/core/upstream-evidence-manifest.js +9 -1
  11. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  12. package/dist/migrations/ensure-lighthouse-collect-options.d.ts +35 -0
  13. package/dist/migrations/ensure-lighthouse-collect-options.d.ts.map +1 -0
  14. package/dist/migrations/ensure-lighthouse-collect-options.js +79 -0
  15. package/dist/migrations/ensure-lighthouse-collect-options.js.map +1 -0
  16. package/dist/migrations/index.d.ts +1 -0
  17. package/dist/migrations/index.d.ts.map +1 -1
  18. package/dist/migrations/index.js +3 -0
  19. package/dist/migrations/index.js.map +1 -1
  20. package/expo/create-only/lighthouserc.js +2 -3
  21. package/package.json +2 -1
  22. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-agy/plugin.json +1 -1
  25. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  28. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-expo-agy/plugin.json +1 -1
  35. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  45. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  50. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  55. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-rails-agy/plugin.json +1 -1
  60. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  65. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  70. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  72. package/scripts/check-whole-output-guards.mjs +620 -0
@@ -0,0 +1,153 @@
1
+ /**
2
+ * anchored-rewrite — make every step of a multi-step text transform
3
+ * individually accountable (CodySwannGT/lisa#3081).
4
+ *
5
+ * @remarks
6
+ * ## The defect this removes
7
+ *
8
+ * A transform with N anchored rewrites, guarded by comparing its finished
9
+ * output to its input, passes as soon as **any one** step lands:
10
+ *
11
+ * ```ts
12
+ * const out = source.replace(A, A2).replace(B, B2);
13
+ * if (out === source) throw new Error("the rewrite no longer applies");
14
+ * ```
15
+ *
16
+ * That guard asks "did something change". It cannot answer "did everything I
17
+ * asked for happen". The N−1 other steps can silently stop matching and it
18
+ * stays green — and it degrades in the direction nobody watches, because it was
19
+ * written when N was 1, where the check is sound, and became unsound the moment
20
+ * a second step was added without anyone noticing the question had changed
21
+ * underneath them.
22
+ *
23
+ * It has already bitten this repository. CodySwannGT/lisa#2980 deleted the
24
+ * import line that the FIRST rewrite of a test fixture anchored on. The second
25
+ * rewrite still matched, so `out !== source`, so the guard passed — and the
26
+ * fixture built a module referencing `fileURLToPath` without importing it.
27
+ * Every case downstream then failed inside a module-resolution error, in a test
28
+ * about repository layout, for a reason that had nothing to do with what it was
29
+ * testing. The partially-applied output was not merely incomplete, it was
30
+ * **invalid**, and it surfaced far from the guard that let it through.
31
+ *
32
+ * ## Why a helper rather than a convention
33
+ *
34
+ * The remedy — assert each anchor is present before replacing — is uniform and
35
+ * cheap, and writing it by hand is three lines per step that read like noise.
36
+ * An idiom is adopted when the safe form is the SHORTEST one to write, so this
37
+ * module exists to make `replaceOrThrow(text, anchor, replacement, context)`
38
+ * shorter than the unguarded `text.replace(anchor, replacement)` plus the
39
+ * hand-rolled assertion it needs to be correct.
40
+ *
41
+ * ## The failure names the step
42
+ *
43
+ * "Something did not apply" is barely better than the guard it replaces: the
44
+ * reader still has to find which of the N steps it means. Every failure here
45
+ * names the anchor verbatim (truncated for legibility, never elided to a
46
+ * count), the caller-supplied `context`, and the step's `label` or ordinal when
47
+ * one is available. The replaced guard in #2980 said "the root default moved",
48
+ * which was not what had happened and sent its reader to the wrong file.
49
+ *
50
+ * ## Optional steps are declared, not implied
51
+ *
52
+ * Some rewrites genuinely may or may not apply — reconciling a block that a
53
+ * given host file may simply not have, for instance. A mechanism with no way to
54
+ * say that is a mechanism people route around, and a routed-around guard
55
+ * protects nothing. So `optional: true` is a first-class part of the rewrite
56
+ * shape: it says "this step is allowed to find nothing", it is visible in
57
+ * review, and it is visible to the `check:whole-output-guards` sweep, which
58
+ * reads a declared-optional step as accounted for rather than as a finding.
59
+ *
60
+ * `optional` never suppresses a REQUIRED step's failure — each entry carries
61
+ * its own flag, so one optional step in a list of four leaves the other three
62
+ * fully enforced.
63
+ * @module core/anchored-rewrite
64
+ */
65
+ /** One anchored step of a multi-step transform. */
66
+ export interface Rewrite {
67
+ /**
68
+ * The text (or pattern) the step replaces. A string anchor replaces its
69
+ * FIRST occurrence, matching `String.prototype.replace`; a regular
70
+ * expression replaces according to its own flags.
71
+ */
72
+ readonly anchor: string | RegExp;
73
+ /** What the anchor is replaced with. */
74
+ readonly replacement: string;
75
+ /**
76
+ * Whether this step is allowed to find nothing. Defaults to `false` — a step
77
+ * is REQUIRED unless it says otherwise, so forgetting the flag fails loudly
78
+ * rather than silently weakening the guard.
79
+ */
80
+ readonly optional?: boolean;
81
+ /**
82
+ * Human-readable name for this step, quoted in the failure. Without one the
83
+ * failure names the step by its 1-based position, which is usable but worse:
84
+ * a position shifts when someone inserts a step above it.
85
+ */
86
+ readonly label?: string;
87
+ }
88
+ /**
89
+ * A required anchored rewrite whose anchor was not present.
90
+ *
91
+ * Carries the anchor, label and context as fields as well as in the message so
92
+ * a caller that wants to report the miss its own way does not have to parse
93
+ * prose back out of a string.
94
+ */
95
+ export declare class MissingAnchorError extends Error {
96
+ /** The anchor that was not found, verbatim. */
97
+ readonly anchor: string;
98
+ /** The step's label, or its 1-based position when it had none. */
99
+ readonly step: string;
100
+ /** What the caller said it was transforming. */
101
+ readonly context: string;
102
+ /**
103
+ * Build the failure, naming the step and quoting the anchor verbatim.
104
+ * @param anchor - The anchor that was not found.
105
+ * @param step - The step's label or 1-based position.
106
+ * @param context - What the caller said it was transforming.
107
+ */
108
+ constructor(anchor: string, step: string, context: string);
109
+ }
110
+ /**
111
+ * Replace an anchor, failing when it is not there.
112
+ *
113
+ * The shortest correct spelling of one step of a multi-step transform. Use it
114
+ * everywhere a rewrite is REQUIRED to land; for a step that may legitimately
115
+ * find nothing use {@link replaceOptional}, which says so in the source.
116
+ * @param text - The text to transform.
117
+ * @param anchor - The text or pattern to replace.
118
+ * @param replacement - What to put in its place.
119
+ * @param context - What is being transformed, quoted in the failure (e.g. the
120
+ * file path, or the name of the fixture being built).
121
+ * @param step - Optional name for this step, quoted in the failure.
122
+ * @returns The transformed text.
123
+ * @throws {MissingAnchorError} When the anchor is not present.
124
+ */
125
+ export declare function replaceOrThrow(text: string, anchor: string | RegExp, replacement: string, context: string, step?: string): string;
126
+ /**
127
+ * Replace an anchor that is allowed not to be there.
128
+ *
129
+ * The declared escape hatch. It does exactly what a bare `.replace` does — the
130
+ * value is that it SAYS the step is optional, which a reader can see and the
131
+ * `check:whole-output-guards` sweep can read. A transform mixing required and
132
+ * optional steps stays fully enforced on the required ones.
133
+ * @param text - The text to transform.
134
+ * @param anchor - The text or pattern to replace, if present.
135
+ * @param replacement - What to put in its place.
136
+ * @returns The transformed text, or the input unchanged when absent.
137
+ */
138
+ export declare function replaceOptional(text: string, anchor: string | RegExp, replacement: string): string;
139
+ /**
140
+ * Apply an ordered list of anchored rewrites, each individually accountable.
141
+ *
142
+ * Steps run in order against the running text, so a later step may anchor on
143
+ * text an earlier one produced. The first REQUIRED step whose anchor is absent
144
+ * throws, naming that step — nothing partially applied is ever returned,
145
+ * because the throw happens before the caller receives anything.
146
+ * @param text - The text to transform.
147
+ * @param rewrites - The steps, in order.
148
+ * @param context - What is being transformed, quoted in any failure.
149
+ * @returns The transformed text.
150
+ * @throws {MissingAnchorError} On the first required step that does not apply.
151
+ */
152
+ export declare function applyRewrites(text: string, rewrites: readonly Rewrite[], context: string): string;
153
+ //# sourceMappingURL=anchored-rewrite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchored-rewrite.d.ts","sourceRoot":"","sources":["../../src/core/anchored-rewrite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAKH,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACtB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAY1D;AAyCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CASR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,WAAW,EAAE,MAAM,GAClB,MAAM,CAER;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,OAAO,EAAE,MAAM,GACd,MAAM,CAaR"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * anchored-rewrite — make every step of a multi-step text transform
3
+ * individually accountable (CodySwannGT/lisa#3081).
4
+ *
5
+ * @remarks
6
+ * ## The defect this removes
7
+ *
8
+ * A transform with N anchored rewrites, guarded by comparing its finished
9
+ * output to its input, passes as soon as **any one** step lands:
10
+ *
11
+ * ```ts
12
+ * const out = source.replace(A, A2).replace(B, B2);
13
+ * if (out === source) throw new Error("the rewrite no longer applies");
14
+ * ```
15
+ *
16
+ * That guard asks "did something change". It cannot answer "did everything I
17
+ * asked for happen". The N−1 other steps can silently stop matching and it
18
+ * stays green — and it degrades in the direction nobody watches, because it was
19
+ * written when N was 1, where the check is sound, and became unsound the moment
20
+ * a second step was added without anyone noticing the question had changed
21
+ * underneath them.
22
+ *
23
+ * It has already bitten this repository. CodySwannGT/lisa#2980 deleted the
24
+ * import line that the FIRST rewrite of a test fixture anchored on. The second
25
+ * rewrite still matched, so `out !== source`, so the guard passed — and the
26
+ * fixture built a module referencing `fileURLToPath` without importing it.
27
+ * Every case downstream then failed inside a module-resolution error, in a test
28
+ * about repository layout, for a reason that had nothing to do with what it was
29
+ * testing. The partially-applied output was not merely incomplete, it was
30
+ * **invalid**, and it surfaced far from the guard that let it through.
31
+ *
32
+ * ## Why a helper rather than a convention
33
+ *
34
+ * The remedy — assert each anchor is present before replacing — is uniform and
35
+ * cheap, and writing it by hand is three lines per step that read like noise.
36
+ * An idiom is adopted when the safe form is the SHORTEST one to write, so this
37
+ * module exists to make `replaceOrThrow(text, anchor, replacement, context)`
38
+ * shorter than the unguarded `text.replace(anchor, replacement)` plus the
39
+ * hand-rolled assertion it needs to be correct.
40
+ *
41
+ * ## The failure names the step
42
+ *
43
+ * "Something did not apply" is barely better than the guard it replaces: the
44
+ * reader still has to find which of the N steps it means. Every failure here
45
+ * names the anchor verbatim (truncated for legibility, never elided to a
46
+ * count), the caller-supplied `context`, and the step's `label` or ordinal when
47
+ * one is available. The replaced guard in #2980 said "the root default moved",
48
+ * which was not what had happened and sent its reader to the wrong file.
49
+ *
50
+ * ## Optional steps are declared, not implied
51
+ *
52
+ * Some rewrites genuinely may or may not apply — reconciling a block that a
53
+ * given host file may simply not have, for instance. A mechanism with no way to
54
+ * say that is a mechanism people route around, and a routed-around guard
55
+ * protects nothing. So `optional: true` is a first-class part of the rewrite
56
+ * shape: it says "this step is allowed to find nothing", it is visible in
57
+ * review, and it is visible to the `check:whole-output-guards` sweep, which
58
+ * reads a declared-optional step as accounted for rather than as a finding.
59
+ *
60
+ * `optional` never suppresses a REQUIRED step's failure — each entry carries
61
+ * its own flag, so one optional step in a list of four leaves the other three
62
+ * fully enforced.
63
+ * @module core/anchored-rewrite
64
+ */
65
+ /** Longest anchor text quoted verbatim in a failure before truncation. */
66
+ const ANCHOR_EXCERPT_LIMIT = 120;
67
+ /**
68
+ * A required anchored rewrite whose anchor was not present.
69
+ *
70
+ * Carries the anchor, label and context as fields as well as in the message so
71
+ * a caller that wants to report the miss its own way does not have to parse
72
+ * prose back out of a string.
73
+ */
74
+ export class MissingAnchorError extends Error {
75
+ /** The anchor that was not found, verbatim. */
76
+ anchor;
77
+ /** The step's label, or its 1-based position when it had none. */
78
+ step;
79
+ /** What the caller said it was transforming. */
80
+ context;
81
+ /**
82
+ * Build the failure, naming the step and quoting the anchor verbatim.
83
+ * @param anchor - The anchor that was not found.
84
+ * @param step - The step's label or 1-based position.
85
+ * @param context - What the caller said it was transforming.
86
+ */
87
+ constructor(anchor, step, context) {
88
+ super(`${context}: rewrite ${step} did not apply — the text does not contain ` +
89
+ `${excerpt(anchor)}. Re-anchor the rewrite on text that is still ` +
90
+ `there, or mark the step \`optional: true\` if it is allowed to find ` +
91
+ `nothing.`);
92
+ this.name = "MissingAnchorError";
93
+ this.anchor = anchor;
94
+ this.step = step;
95
+ this.context = context;
96
+ }
97
+ }
98
+ /**
99
+ * Quote an anchor for a failure message, truncating a long one.
100
+ * @param anchor - The anchor's source text.
101
+ * @returns A quoted, length-bounded excerpt.
102
+ */
103
+ function excerpt(anchor) {
104
+ const quoted = JSON.stringify(anchor);
105
+ return quoted.length <= ANCHOR_EXCERPT_LIMIT
106
+ ? quoted
107
+ : `${quoted.slice(0, ANCHOR_EXCERPT_LIMIT)}…"`;
108
+ }
109
+ /**
110
+ * The anchor's source text, for reporting.
111
+ * @param anchor - A string or regular-expression anchor.
112
+ * @returns The text to quote in a failure.
113
+ */
114
+ function anchorText(anchor) {
115
+ return typeof anchor === "string" ? anchor : String(anchor);
116
+ }
117
+ /**
118
+ * Whether an anchor is present in the text.
119
+ *
120
+ * A global regular expression is tested with a FRESH copy rather than the
121
+ * caller's: `RegExp.prototype.test` advances `lastIndex` on a `/g` pattern, so
122
+ * testing the caller's object first would leave it mid-string and make the
123
+ * `replace` that follows start from the wrong offset. That is a defect the
124
+ * presence check would have INTRODUCED, which is the worst kind for a guard to
125
+ * carry.
126
+ * @param text - The text being transformed.
127
+ * @param anchor - The anchor to look for.
128
+ * @returns Whether the anchor matches at least once.
129
+ */
130
+ function anchorPresent(text, anchor) {
131
+ if (typeof anchor === "string")
132
+ return text.includes(anchor);
133
+ return new RegExp(anchor.source, anchor.flags.replace("g", "")).test(text);
134
+ }
135
+ /**
136
+ * Replace an anchor, failing when it is not there.
137
+ *
138
+ * The shortest correct spelling of one step of a multi-step transform. Use it
139
+ * everywhere a rewrite is REQUIRED to land; for a step that may legitimately
140
+ * find nothing use {@link replaceOptional}, which says so in the source.
141
+ * @param text - The text to transform.
142
+ * @param anchor - The text or pattern to replace.
143
+ * @param replacement - What to put in its place.
144
+ * @param context - What is being transformed, quoted in the failure (e.g. the
145
+ * file path, or the name of the fixture being built).
146
+ * @param step - Optional name for this step, quoted in the failure.
147
+ * @returns The transformed text.
148
+ * @throws {MissingAnchorError} When the anchor is not present.
149
+ */
150
+ export function replaceOrThrow(text, anchor, replacement, context, step) {
151
+ if (!anchorPresent(text, anchor)) {
152
+ throw new MissingAnchorError(anchorText(anchor), step === undefined ? "(unnamed)" : `"${step}"`, context);
153
+ }
154
+ return text.replace(anchor, replacement);
155
+ }
156
+ /**
157
+ * Replace an anchor that is allowed not to be there.
158
+ *
159
+ * The declared escape hatch. It does exactly what a bare `.replace` does — the
160
+ * value is that it SAYS the step is optional, which a reader can see and the
161
+ * `check:whole-output-guards` sweep can read. A transform mixing required and
162
+ * optional steps stays fully enforced on the required ones.
163
+ * @param text - The text to transform.
164
+ * @param anchor - The text or pattern to replace, if present.
165
+ * @param replacement - What to put in its place.
166
+ * @returns The transformed text, or the input unchanged when absent.
167
+ */
168
+ export function replaceOptional(text, anchor, replacement) {
169
+ return text.replace(anchor, replacement);
170
+ }
171
+ /**
172
+ * Apply an ordered list of anchored rewrites, each individually accountable.
173
+ *
174
+ * Steps run in order against the running text, so a later step may anchor on
175
+ * text an earlier one produced. The first REQUIRED step whose anchor is absent
176
+ * throws, naming that step — nothing partially applied is ever returned,
177
+ * because the throw happens before the caller receives anything.
178
+ * @param text - The text to transform.
179
+ * @param rewrites - The steps, in order.
180
+ * @param context - What is being transformed, quoted in any failure.
181
+ * @returns The transformed text.
182
+ * @throws {MissingAnchorError} On the first required step that does not apply.
183
+ */
184
+ export function applyRewrites(text, rewrites, context) {
185
+ return rewrites.reduce((current, rewrite, index) => {
186
+ if (rewrite.optional === true) {
187
+ return replaceOptional(current, rewrite.anchor, rewrite.replacement);
188
+ }
189
+ return replaceOrThrow(current, rewrite.anchor, rewrite.replacement, context, rewrite.label ?? `#${index + 1}`);
190
+ }, text);
191
+ }
192
+ //# sourceMappingURL=anchored-rewrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchored-rewrite.js","sourceRoot":"","sources":["../../src/core/anchored-rewrite.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  export * from "./config.js";
2
2
  export * from "./bootstrap-environment.js";
3
3
  export { Lisa, type LisaDependencies } from "./lisa.js";
4
+ export * from "./anchored-rewrite.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACxD,cAAc,uBAAuB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from "./config.js";
2
2
  export * from "./bootstrap-environment.js";
3
3
  export { Lisa } from "./lisa.js";
4
+ export * from "./anchored-rewrite.js";
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAyB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAyB,MAAM,WAAW,CAAC;AACxD,cAAc,uBAAuB,CAAC"}
@@ -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,CA84EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CA6kPjE,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,CAg5EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAolPjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
@@ -139,7 +139,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
139
139
  "expo/create-only/jest.setup.local.ts": "f0266cf872f41b6599e476e135f0b8947c3d226abe5bc4e02fb4087c836abac0",
140
140
  "expo/create-only/jest.setup.pre.local.js": "92d24da88f69ac3d5325d2221b570308d13e81d02deaa936c24866ed1acd8363",
141
141
  "expo/create-only/lighthouserc-config.json": "48637345034564923cefc96ea8192d807b7d64f4f94a6daa63625ca71e1bea5b",
142
- "expo/create-only/lighthouserc.js": "8e6fb0a37cd2884cec32378fcd8e213bc7489d2b9e9ad862e61c90435b2679a7",
142
+ "expo/create-only/lighthouserc.js": "5686fb51020edab301abe612b467b082c5d80580e78437914f0d6cbd434d905d",
143
143
  "expo/create-only/scripts/zap-baseline.sh": "7ecfcb911f2f2284eb672c9eb960a1588792a984a713cb2e5f5d9963b32af910",
144
144
  "expo/create-only/stryker.conf.json": "a49c9563b2a3337a7b4bc198e259cd06e681ed043b194506a90f9fe0e8eb6ab3",
145
145
  "expo/create-only/tsconfig.json": "fdb99e32d1588e75735755d7b5caab406ad8387c21a3d820cd3b40cb9218a191",
@@ -1085,6 +1085,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
1085
1085
  "scripts/check-security-floors.mjs": "6122404ea247c7d70718472e44bb007c0c5dad2fcc064c8a2d797cd9d0f85b29",
1086
1086
  "scripts/check-state-classification.mjs": "26baaa85c0758fa41f1f66257f7d3a31ea4dd5cf17a9c0acaa3e89caaaf6265a",
1087
1087
  "scripts/check-template-workflow-refs.mjs": "f784a822ae82f41b7501d61e45a1badeecb84f118083f4c53c66402d6c50ffa2",
1088
+ "scripts/check-whole-output-guards.mjs": "bb3c959fe67a6f481a9b8442a5a9a51a49599b4efd8fbefe3329fdf5c96b9c02",
1088
1089
  "scripts/check-workflow-package-paths.mjs": "d057c7666ad048cfbd11a1ef83ad1e13fb1c61a9d399ec83221c99c4256728a1",
1089
1090
  "scripts/claude-remote-setup.sh": "0e33accf8aa057c70497f01c38bef9f9f3801d649272f583578d89201b242655",
1090
1091
  "scripts/clean-dist.mjs": "04970d768464acbf96ebeb77c16a6a3b3da56c744eef0da64c573c6152ee0dc7",
@@ -7075,6 +7076,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7075
7076
  "scripts/check-security-floors.mjs": true,
7076
7077
  "scripts/check-state-classification.mjs": true,
7077
7078
  "scripts/check-template-workflow-refs.mjs": true,
7079
+ "scripts/check-whole-output-guards.mjs": true,
7078
7080
  "scripts/check-workflow-package-paths.mjs": true,
7079
7081
  "scripts/claude-remote-setup.sh": true,
7080
7082
  "scripts/clean-dist.mjs": true,
@@ -7345,6 +7347,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7345
7347
  "src/configs/worktrees.ts": true,
7346
7348
  "src/copilot/copilot-instructions-installer.ts": true,
7347
7349
  "src/copilot/plugin-installer.ts": true,
7350
+ "src/core/anchored-rewrite.ts": true,
7348
7351
  "src/core/apply-receipt.ts": true,
7349
7352
  "src/core/bootstrap-environment.ts": true,
7350
7353
  "src/core/config.ts": true,
@@ -7438,6 +7441,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7438
7441
  "src/migrations/ensure-jest-rn-mock-accessibility-manager.ts": true,
7439
7442
  "src/migrations/ensure-learnings-gitattributes.ts": true,
7440
7443
  "src/migrations/ensure-learnings-merge-driver.ts": true,
7444
+ "src/migrations/ensure-lighthouse-collect-options.ts": true,
7441
7445
  "src/migrations/ensure-lisa-postinstall.ts": true,
7442
7446
  "src/migrations/ensure-oxlint-base-configs.ts": true,
7443
7447
  "src/migrations/ensure-playwright-dedicated-caller.ts": true,
@@ -7987,7 +7991,9 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7987
7991
  "tests/unit/config/work-item-traceability-scope-gate.test.ts": true,
7988
7992
  "tests/unit/config/workspace-suite-collection.test.ts": true,
7989
7993
  "tests/unit/config/worktree-exclusion-anchoring.test.ts": true,
7994
+ "tests/unit/configs/lighthouse-collect-config.test.ts": true,
7990
7995
  "tests/unit/configs/lintstaged-matcher-ordering.test.ts": true,
7996
+ "tests/unit/core/anchored-rewrite.test.ts": true,
7991
7997
  "tests/unit/core/bootstrap-environment.test.ts": true,
7992
7998
  "tests/unit/core/fs-extra-namespace-callsites.test.ts": true,
7993
7999
  "tests/unit/core/fs-extra-namespace-members.test.ts": true,
@@ -8132,6 +8138,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
8132
8138
  "tests/unit/migrations/ensure-jest-rn-mock-accessibility-manager.test.ts": true,
8133
8139
  "tests/unit/migrations/ensure-learnings-gitattributes.test.ts": true,
8134
8140
  "tests/unit/migrations/ensure-learnings-merge-driver.test.ts": true,
8141
+ "tests/unit/migrations/ensure-lighthouse-collect-options.test.ts": true,
8135
8142
  "tests/unit/migrations/ensure-lisa-postinstall.test.ts": true,
8136
8143
  "tests/unit/migrations/ensure-oxlint-base-configs.test.ts": true,
8137
8144
  "tests/unit/migrations/ensure-playwright-dedicated-caller.test.ts": true,
@@ -8192,6 +8199,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
8192
8199
  "tests/unit/scripts/check-orphan-test-processes.test.ts": true,
8193
8200
  "tests/unit/scripts/check-pipeline-status-reads.test.ts": true,
8194
8201
  "tests/unit/scripts/check-template-workflow-refs.test.ts": true,
8202
+ "tests/unit/scripts/check-whole-output-guards.test.ts": true,
8195
8203
  "tests/unit/scripts/check-workflow-package-contracts.test.ts": true,
8196
8204
  "tests/unit/scripts/check-workflow-package-paths.test.ts": true,
8197
8205
  "tests/unit/scripts/codex-hook-filter.test.ts": true,