@codyswann/lisa 4.35.4 → 4.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/all/copy-overwrite/scripts/check-third-party-action-pins.mjs +554 -0
- package/all/copy-overwrite/scripts/lib/gate-failure-diagnosis.mjs +296 -3
- package/dist/core/downstream-references.d.ts.map +1 -1
- package/dist/core/downstream-references.js +4 -0
- package/dist/core/downstream-references.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +16 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/third-party-action-pins.d.ts +84 -0
- package/dist/core/third-party-action-pins.d.ts.map +1 -0
- package/dist/core/third-party-action-pins.js +153 -0
- package/dist/core/third-party-action-pins.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +15 -7
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/migrations/ensure-third-party-action-pins.d.ts +123 -0
- package/dist/migrations/ensure-third-party-action-pins.d.ts.map +1 -0
- package/dist/migrations/ensure-third-party-action-pins.js +238 -0
- package/dist/migrations/ensure-third-party-action-pins.js.map +1 -0
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +3 -0
- package/dist/migrations/index.js.map +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
- package/plugins/lisa/rules/reference/measurement-integrity.md +10 -0
- package/plugins/lisa/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-jsdoc-best-practices/SKILL.md +60 -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/rules/reference/measurement-integrity.md +10 -0
- package/plugins/lisa-copilot/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/measurement-integrity-reference.mdc +10 -0
- package/plugins/lisa-cursor/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/reference/measurement-integrity.md +10 -0
- package/plugins/src/base/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
- package/scripts/check-third-party-action-pins.mjs +111 -14
- package/scripts/two-channel-couplings.json +1 -1
- package/typescript/copy-overwrite/.prettierignore +1 -0
- package/typescript/package-lisa/package.lisa.json +1 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Migration, MigrationContext, MigrationResult } from "./migration.interface.js";
|
|
2
|
+
/** Resolve the commit a ref points at, or null when it cannot be determined. */
|
|
3
|
+
export type ShaResolver = (owner: string, repo: string, ref: string) => Promise<string | null>;
|
|
4
|
+
/**
|
|
5
|
+
* Ask GitHub what a ref resolves to right now.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately resolves live rather than reading a table shipped inside Lisa.
|
|
8
|
+
* A shipped table pins every consumer to whatever those refs meant on the night
|
|
9
|
+
* it was generated, which converts a mutable-ref problem into a stale-ref
|
|
10
|
+
* problem and calls it fixed. Resolving live also satisfies the harder half of
|
|
11
|
+
* the requirement: the SHA written is the one THAT repository's ref resolves to
|
|
12
|
+
* at migration time, so pinning never silently upgrades anything.
|
|
13
|
+
*
|
|
14
|
+
* Returns null rather than throwing on every failure path. The caller turns a
|
|
15
|
+
* null into a reported skip; an exception here would turn a missing network
|
|
16
|
+
* into a failed `lisa` run, which is not what an unreachable API means.
|
|
17
|
+
*
|
|
18
|
+
* Unauthenticated on purpose. Every action being resolved is public — a private
|
|
19
|
+
* one could not be `uses:`-ed by a consumer's runner either — and the endpoint's
|
|
20
|
+
* anonymous allowance is far above the handful of distinct refs one repository
|
|
21
|
+
* has. Reading a token here would mean reaching into the environment from
|
|
22
|
+
* `src/`, and buying a higher rate limit is not worth that: being rate-limited
|
|
23
|
+
* lands on the same reported-skip path as being offline, which is a correct
|
|
24
|
+
* outcome rather than a failure. A caller that wants authenticated lookups
|
|
25
|
+
* injects its own resolver.
|
|
26
|
+
* @param owner - Action owner
|
|
27
|
+
* @param repo - Action repository
|
|
28
|
+
* @param ref - The mutable ref to resolve
|
|
29
|
+
* @returns The 40-character commit SHA, or null when it cannot be resolved
|
|
30
|
+
*/
|
|
31
|
+
export declare const resolveViaGitHub: ShaResolver;
|
|
32
|
+
/**
|
|
33
|
+
* Pin the third-party actions in an already-seeded consumer's workflows.
|
|
34
|
+
*
|
|
35
|
+
* #3585 pinned Lisa's own workflows and its `create-only` templates. Those
|
|
36
|
+
* templates are seeded once and never overwritten, so that fix reaches new
|
|
37
|
+
* adoptions and no repository that already exists. This migration is the
|
|
38
|
+
* surface that reaches the installed base — the same role, and the same
|
|
39
|
+
* reasoning, as `ensure-nightly-e2e-workflow-pins` (#3476, #3485, #3588).
|
|
40
|
+
*
|
|
41
|
+
* It rewrites matched `uses:` lines only, never the file, so a host that has
|
|
42
|
+
* edited its seeded workflow keeps every other edit.
|
|
43
|
+
*/
|
|
44
|
+
export declare class EnsureThirdPartyActionPinsMigration implements Migration {
|
|
45
|
+
private readonly resolve;
|
|
46
|
+
readonly name = "ensure-third-party-action-pins";
|
|
47
|
+
readonly description = "Pin third-party GitHub Actions in this project's workflows to the commit SHA their ref resolves to today";
|
|
48
|
+
/**
|
|
49
|
+
* Create the migration.
|
|
50
|
+
* @param resolve - SHA resolver, injectable so tests never touch the network
|
|
51
|
+
*/
|
|
52
|
+
constructor(resolve?: ShaResolver);
|
|
53
|
+
/**
|
|
54
|
+
* Whether any workflow in this project carries a mutable third-party ref.
|
|
55
|
+
*
|
|
56
|
+
* Never touches the network: an offline machine must still get a truthful
|
|
57
|
+
* answer about whether there is anything to do.
|
|
58
|
+
* @param ctx - Migration context
|
|
59
|
+
* @returns True when at least one reference needs pinning
|
|
60
|
+
*/
|
|
61
|
+
applies(ctx: MigrationContext): Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* Resolve every mutable ref and rewrite the ones that resolved.
|
|
64
|
+
* @param ctx - Migration context
|
|
65
|
+
* @returns Applied, skipped, or no-op result
|
|
66
|
+
*/
|
|
67
|
+
apply(ctx: MigrationContext): Promise<MigrationResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Read every workflow file and collect its mutable third-party refs.
|
|
70
|
+
* @param projectDir - Destination project directory
|
|
71
|
+
* @returns One entry per workflow file that has at least one finding
|
|
72
|
+
*/
|
|
73
|
+
private scan;
|
|
74
|
+
/**
|
|
75
|
+
* Resolve each distinct reference, dropping the ones that do not resolve.
|
|
76
|
+
* @param found - Every finding across the scanned files
|
|
77
|
+
* @returns The references that resolved to a commit SHA
|
|
78
|
+
*/
|
|
79
|
+
private resolveAll;
|
|
80
|
+
/**
|
|
81
|
+
* Decline during a package manager's install, and say what was declined.
|
|
82
|
+
*
|
|
83
|
+
* A workflow file is not a generated artifact — it is a reviewed,
|
|
84
|
+
* checked-in declaration of what runs against this repository, and nobody
|
|
85
|
+
* types `bun install` meaning to change that. The same rule, and the same
|
|
86
|
+
* incident behind it, as `ensure-seeded-gates` (#3574).
|
|
87
|
+
*
|
|
88
|
+
* It reports rather than going quiet, because a migration that silently
|
|
89
|
+
* skipped here would be this codebase's signature defect: work that stops
|
|
90
|
+
* happening with nothing anywhere saying so.
|
|
91
|
+
* @param ctx - Migration context
|
|
92
|
+
* @param found - Every finding across the scanned files
|
|
93
|
+
* @returns A skipped result carrying the operator-readable explanation
|
|
94
|
+
*/
|
|
95
|
+
private refuse;
|
|
96
|
+
/**
|
|
97
|
+
* Report that nothing could be resolved, without claiming to have applied.
|
|
98
|
+
*
|
|
99
|
+
* No network and no credentials are ordinary conditions on a developer
|
|
100
|
+
* machine, so neither is a failure. What matters is that the result says
|
|
101
|
+
* `skipped`: a migration that reported `applied` here would be recorded as
|
|
102
|
+
* done and never run again, leaving the references mutable forever.
|
|
103
|
+
* @param ctx - Migration context
|
|
104
|
+
* @param found - Every finding across the scanned files
|
|
105
|
+
* @returns A skipped result carrying the operator-readable explanation
|
|
106
|
+
*/
|
|
107
|
+
private declineUnresolved;
|
|
108
|
+
/**
|
|
109
|
+
* One operator-readable line per distinct reference.
|
|
110
|
+
* @param found - Every finding across the scanned files
|
|
111
|
+
* @returns Indented description lines
|
|
112
|
+
*/
|
|
113
|
+
private describe;
|
|
114
|
+
/**
|
|
115
|
+
* Summarize what was pinned, naming anything that was left alone.
|
|
116
|
+
* @param pins - References that resolved
|
|
117
|
+
* @param found - Every finding across the scanned files
|
|
118
|
+
* @param changedFiles - Files that were rewritten
|
|
119
|
+
* @returns Operator-readable summary
|
|
120
|
+
*/
|
|
121
|
+
private summarize;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=ensure-third-party-action-pins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-third-party-action-pins.d.ts","sourceRoot":"","sources":["../../src/migrations/ensure-third-party-action-pins.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAKlC,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,KACR,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAU5B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,gBAAgB,EAAE,WAmB9B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,qBAAa,mCAAoC,YAAW,SAAS;IASvD,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,QAAQ,CAAC,IAAI,oCAAoC;IACjD,QAAQ,CAAC,WAAW,8GACyF;IAE7G;;;OAGG;gBAC0B,OAAO,GAAE,WAA8B;IAEpE;;;;;;;OAOG;IACG,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAItD;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAqC5D;;;;OAIG;YACW,IAAI;IAqBlB;;;;OAIG;YACW,UAAU;IAcxB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,MAAM;IAmBd;;;;;;;;;;OAUG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAIhB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;CAalB"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { readFile, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as fse from "fs-extra";
|
|
4
|
+
import { applyPins, distinctRefs, findUnpinnedRefs, } from "../core/third-party-action-pins.js";
|
|
5
|
+
const WORKFLOW_DIR = path.join(".github", "workflows");
|
|
6
|
+
const WORKFLOW_FILE = /\.ya?ml$/;
|
|
7
|
+
/**
|
|
8
|
+
* Ask GitHub what a ref resolves to right now.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately resolves live rather than reading a table shipped inside Lisa.
|
|
11
|
+
* A shipped table pins every consumer to whatever those refs meant on the night
|
|
12
|
+
* it was generated, which converts a mutable-ref problem into a stale-ref
|
|
13
|
+
* problem and calls it fixed. Resolving live also satisfies the harder half of
|
|
14
|
+
* the requirement: the SHA written is the one THAT repository's ref resolves to
|
|
15
|
+
* at migration time, so pinning never silently upgrades anything.
|
|
16
|
+
*
|
|
17
|
+
* Returns null rather than throwing on every failure path. The caller turns a
|
|
18
|
+
* null into a reported skip; an exception here would turn a missing network
|
|
19
|
+
* into a failed `lisa` run, which is not what an unreachable API means.
|
|
20
|
+
*
|
|
21
|
+
* Unauthenticated on purpose. Every action being resolved is public — a private
|
|
22
|
+
* one could not be `uses:`-ed by a consumer's runner either — and the endpoint's
|
|
23
|
+
* anonymous allowance is far above the handful of distinct refs one repository
|
|
24
|
+
* has. Reading a token here would mean reaching into the environment from
|
|
25
|
+
* `src/`, and buying a higher rate limit is not worth that: being rate-limited
|
|
26
|
+
* lands on the same reported-skip path as being offline, which is a correct
|
|
27
|
+
* outcome rather than a failure. A caller that wants authenticated lookups
|
|
28
|
+
* injects its own resolver.
|
|
29
|
+
* @param owner - Action owner
|
|
30
|
+
* @param repo - Action repository
|
|
31
|
+
* @param ref - The mutable ref to resolve
|
|
32
|
+
* @returns The 40-character commit SHA, or null when it cannot be resolved
|
|
33
|
+
*/
|
|
34
|
+
export const resolveViaGitHub = async (owner, repo, ref) => {
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/commits/${encodeURIComponent(ref)}`, {
|
|
37
|
+
headers: {
|
|
38
|
+
Accept: "application/vnd.github.sha",
|
|
39
|
+
"User-Agent": "lisa-third-party-action-pins",
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const sha = (await response.text()).trim();
|
|
46
|
+
return /^[0-9a-f]{40}$/.test(sha) ? sha : null;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Pin the third-party actions in an already-seeded consumer's workflows.
|
|
54
|
+
*
|
|
55
|
+
* #3585 pinned Lisa's own workflows and its `create-only` templates. Those
|
|
56
|
+
* templates are seeded once and never overwritten, so that fix reaches new
|
|
57
|
+
* adoptions and no repository that already exists. This migration is the
|
|
58
|
+
* surface that reaches the installed base — the same role, and the same
|
|
59
|
+
* reasoning, as `ensure-nightly-e2e-workflow-pins` (#3476, #3485, #3588).
|
|
60
|
+
*
|
|
61
|
+
* It rewrites matched `uses:` lines only, never the file, so a host that has
|
|
62
|
+
* edited its seeded workflow keeps every other edit.
|
|
63
|
+
*/
|
|
64
|
+
export class EnsureThirdPartyActionPinsMigration {
|
|
65
|
+
resolve;
|
|
66
|
+
name = "ensure-third-party-action-pins";
|
|
67
|
+
description = "Pin third-party GitHub Actions in this project's workflows to the commit SHA their ref resolves to today";
|
|
68
|
+
/**
|
|
69
|
+
* Create the migration.
|
|
70
|
+
* @param resolve - SHA resolver, injectable so tests never touch the network
|
|
71
|
+
*/
|
|
72
|
+
constructor(resolve = resolveViaGitHub) {
|
|
73
|
+
this.resolve = resolve;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Whether any workflow in this project carries a mutable third-party ref.
|
|
77
|
+
*
|
|
78
|
+
* Never touches the network: an offline machine must still get a truthful
|
|
79
|
+
* answer about whether there is anything to do.
|
|
80
|
+
* @param ctx - Migration context
|
|
81
|
+
* @returns True when at least one reference needs pinning
|
|
82
|
+
*/
|
|
83
|
+
async applies(ctx) {
|
|
84
|
+
return (await this.scan(ctx.projectDir)).length > 0;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve every mutable ref and rewrite the ones that resolved.
|
|
88
|
+
* @param ctx - Migration context
|
|
89
|
+
* @returns Applied, skipped, or no-op result
|
|
90
|
+
*/
|
|
91
|
+
async apply(ctx) {
|
|
92
|
+
const scanned = await this.scan(ctx.projectDir);
|
|
93
|
+
if (scanned.length === 0) {
|
|
94
|
+
return { name: this.name, action: "noop" };
|
|
95
|
+
}
|
|
96
|
+
const found = scanned.flatMap(file => file.refs);
|
|
97
|
+
if (ctx.postinstallSafe === true) {
|
|
98
|
+
return this.refuse(ctx, found);
|
|
99
|
+
}
|
|
100
|
+
const pins = await this.resolveAll(found);
|
|
101
|
+
if (pins.length === 0) {
|
|
102
|
+
return this.declineUnresolved(ctx, found);
|
|
103
|
+
}
|
|
104
|
+
const updates = scanned
|
|
105
|
+
.map(file => ({ file, source: applyPins(file.source, pins) }))
|
|
106
|
+
.filter(update => update.source !== update.file.source);
|
|
107
|
+
if (updates.length === 0) {
|
|
108
|
+
return { name: this.name, action: "noop" };
|
|
109
|
+
}
|
|
110
|
+
const changedFiles = updates.map(update => update.file.relative);
|
|
111
|
+
const message = this.summarize(pins, found, changedFiles);
|
|
112
|
+
if (ctx.dryRun) {
|
|
113
|
+
ctx.logger.dry(`Would pin ${pins.length} reference(s) in ${changedFiles.join(", ")}`);
|
|
114
|
+
return { name: this.name, action: "applied", changedFiles, message };
|
|
115
|
+
}
|
|
116
|
+
for (const update of updates) {
|
|
117
|
+
await writeFile(update.file.absolute, update.source);
|
|
118
|
+
}
|
|
119
|
+
ctx.logger.success(message);
|
|
120
|
+
return { name: this.name, action: "applied", changedFiles, message };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Read every workflow file and collect its mutable third-party refs.
|
|
124
|
+
* @param projectDir - Destination project directory
|
|
125
|
+
* @returns One entry per workflow file that has at least one finding
|
|
126
|
+
*/
|
|
127
|
+
async scan(projectDir) {
|
|
128
|
+
const dir = path.join(projectDir, WORKFLOW_DIR);
|
|
129
|
+
if (!(await fse.pathExists(dir))) {
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
const names = (await readdir(dir)).filter(name => WORKFLOW_FILE.test(name));
|
|
133
|
+
const files = await Promise.all(names.map(async (name) => {
|
|
134
|
+
const absolute = path.join(dir, name);
|
|
135
|
+
const source = await readFile(absolute, "utf8");
|
|
136
|
+
return {
|
|
137
|
+
relative: path.join(WORKFLOW_DIR, name),
|
|
138
|
+
absolute,
|
|
139
|
+
source,
|
|
140
|
+
refs: findUnpinnedRefs(source),
|
|
141
|
+
};
|
|
142
|
+
}));
|
|
143
|
+
return files.filter(file => file.refs.length > 0);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve each distinct reference, dropping the ones that do not resolve.
|
|
147
|
+
* @param found - Every finding across the scanned files
|
|
148
|
+
* @returns The references that resolved to a commit SHA
|
|
149
|
+
*/
|
|
150
|
+
async resolveAll(found) {
|
|
151
|
+
const resolutions = await Promise.all(distinctRefs(found).map(async (ref) => ({
|
|
152
|
+
ref,
|
|
153
|
+
sha: await this.resolve(ref.owner, ref.repo, ref.ref),
|
|
154
|
+
})));
|
|
155
|
+
return resolutions.flatMap(({ ref, sha }) => sha === null ? [] : [{ action: ref.action, ref: ref.ref, sha }]);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Decline during a package manager's install, and say what was declined.
|
|
159
|
+
*
|
|
160
|
+
* A workflow file is not a generated artifact — it is a reviewed,
|
|
161
|
+
* checked-in declaration of what runs against this repository, and nobody
|
|
162
|
+
* types `bun install` meaning to change that. The same rule, and the same
|
|
163
|
+
* incident behind it, as `ensure-seeded-gates` (#3574).
|
|
164
|
+
*
|
|
165
|
+
* It reports rather than going quiet, because a migration that silently
|
|
166
|
+
* skipped here would be this codebase's signature defect: work that stops
|
|
167
|
+
* happening with nothing anywhere saying so.
|
|
168
|
+
* @param ctx - Migration context
|
|
169
|
+
* @param found - Every finding across the scanned files
|
|
170
|
+
* @returns A skipped result carrying the operator-readable explanation
|
|
171
|
+
*/
|
|
172
|
+
refuse(ctx, found) {
|
|
173
|
+
const message = [
|
|
174
|
+
"Left this project's workflows unchanged: an install must not rewrite what runs against this repository.",
|
|
175
|
+
"",
|
|
176
|
+
` ${found.length} third-party action reference(s) resolve at job start to whatever their owner has pushed:`,
|
|
177
|
+
"",
|
|
178
|
+
...this.describe(found),
|
|
179
|
+
"",
|
|
180
|
+
" To pin them deliberately, so the change lands in a commit somebody reviews:",
|
|
181
|
+
"",
|
|
182
|
+
" npx @codyswann/lisa@latest .",
|
|
183
|
+
].join("\n");
|
|
184
|
+
ctx.logger.warn(message);
|
|
185
|
+
return { name: this.name, action: "skipped", changedFiles: [], message };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Report that nothing could be resolved, without claiming to have applied.
|
|
189
|
+
*
|
|
190
|
+
* No network and no credentials are ordinary conditions on a developer
|
|
191
|
+
* machine, so neither is a failure. What matters is that the result says
|
|
192
|
+
* `skipped`: a migration that reported `applied` here would be recorded as
|
|
193
|
+
* done and never run again, leaving the references mutable forever.
|
|
194
|
+
* @param ctx - Migration context
|
|
195
|
+
* @param found - Every finding across the scanned files
|
|
196
|
+
* @returns A skipped result carrying the operator-readable explanation
|
|
197
|
+
*/
|
|
198
|
+
declineUnresolved(ctx, found) {
|
|
199
|
+
const message = [
|
|
200
|
+
"Could not reach GitHub to look up what these action references point at, so nothing was changed.",
|
|
201
|
+
"",
|
|
202
|
+
` ${found.length} third-party action reference(s) are still resolved at job start by their owner:`,
|
|
203
|
+
"",
|
|
204
|
+
...this.describe(found),
|
|
205
|
+
"",
|
|
206
|
+
" Nothing is broken and nothing has changed. Re-run once this machine can",
|
|
207
|
+
" reach github.com; if the lookups were rate-limited, a few minutes is enough:",
|
|
208
|
+
"",
|
|
209
|
+
" npx @codyswann/lisa@latest .",
|
|
210
|
+
].join("\n");
|
|
211
|
+
ctx.logger.warn(message);
|
|
212
|
+
return { name: this.name, action: "skipped", changedFiles: [], message };
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* One operator-readable line per distinct reference.
|
|
216
|
+
* @param found - Every finding across the scanned files
|
|
217
|
+
* @returns Indented description lines
|
|
218
|
+
*/
|
|
219
|
+
describe(found) {
|
|
220
|
+
return distinctRefs(found).map(ref => ` • ${ref.action}@${ref.ref}`);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Summarize what was pinned, naming anything that was left alone.
|
|
224
|
+
* @param pins - References that resolved
|
|
225
|
+
* @param found - Every finding across the scanned files
|
|
226
|
+
* @param changedFiles - Files that were rewritten
|
|
227
|
+
* @returns Operator-readable summary
|
|
228
|
+
*/
|
|
229
|
+
summarize(pins, found, changedFiles) {
|
|
230
|
+
const distinct = distinctRefs(found).length;
|
|
231
|
+
const unresolved = distinct - pins.length;
|
|
232
|
+
const tail = unresolved > 0
|
|
233
|
+
? ` ${unresolved} reference(s) could not be looked up and were left as they are.`
|
|
234
|
+
: "";
|
|
235
|
+
return `Pinned ${pins.length} third-party action reference(s) to commit SHAs in ${changedFiles.join(", ")}.${tail}`;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=ensure-third-party-action-pins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-third-party-action-pins.js","sourceRoot":"","sources":["../../src/migrations/ensure-third-party-action-pins.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ export { EnsurePushDefaultSafeMigration } from "./ensure-push-default-safe.js";
|
|
|
13
13
|
export { EnsureQualityCallerScopesMigration } from "./ensure-quality-caller-scopes.js";
|
|
14
14
|
export { EnsureSeededGatesMigration } from "./ensure-seeded-gates.js";
|
|
15
15
|
export { EnsureSonarExcludesLisaHarnessMigration } from "./ensure-sonar-excludes-lisa-harness.js";
|
|
16
|
+
export { EnsureThirdPartyActionPinsMigration } from "./ensure-third-party-action-pins.js";
|
|
16
17
|
export { EnsureTsconfigLocalFilesFallbackMigration } from "./ensure-tsconfig-local-files-fallback.js";
|
|
17
18
|
export { EnsureWikiSourceDeclaredMigration } from "./ensure-wiki-source-declared.js";
|
|
18
19
|
export { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,6CAA6C,EAAE,MAAM,gDAAgD,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,qCAAqC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,EAAE,uCAAuC,EAAE,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,qCAAqC,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,wCAAwC,EAAE,MAAM,yCAAyC,CAAC;AACnG,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,EAAE,mCAAmC,EAAE,MAAM,qCAAqC,CAAC;AAC1F,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,oCAAoC,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAElF;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAElD;;;OAGG;gBACS,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE;IAyB7C;;;OAGG;IACH,MAAM,IAAI,SAAS,SAAS,EAAE;IAI9B;;;;OAIG;IACG,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/D;;;;OAIG;IACG,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;CAazE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D"}
|
package/dist/migrations/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { EnsurePushDefaultSafeMigration } from "./ensure-push-default-safe.js";
|
|
|
11
11
|
import { EnsureQualityCallerScopesMigration } from "./ensure-quality-caller-scopes.js";
|
|
12
12
|
import { EnsureSeededGatesMigration } from "./ensure-seeded-gates.js";
|
|
13
13
|
import { EnsureSonarExcludesLisaHarnessMigration } from "./ensure-sonar-excludes-lisa-harness.js";
|
|
14
|
+
import { EnsureThirdPartyActionPinsMigration } from "./ensure-third-party-action-pins.js";
|
|
14
15
|
import { EnsureTsconfigLocalFilesFallbackMigration } from "./ensure-tsconfig-local-files-fallback.js";
|
|
15
16
|
import { EnsureWikiSourceDeclaredMigration } from "./ensure-wiki-source-declared.js";
|
|
16
17
|
import { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
|
|
@@ -30,6 +31,7 @@ export { EnsurePushDefaultSafeMigration } from "./ensure-push-default-safe.js";
|
|
|
30
31
|
export { EnsureQualityCallerScopesMigration } from "./ensure-quality-caller-scopes.js";
|
|
31
32
|
export { EnsureSeededGatesMigration } from "./ensure-seeded-gates.js";
|
|
32
33
|
export { EnsureSonarExcludesLisaHarnessMigration } from "./ensure-sonar-excludes-lisa-harness.js";
|
|
34
|
+
export { EnsureThirdPartyActionPinsMigration } from "./ensure-third-party-action-pins.js";
|
|
33
35
|
export { EnsureTsconfigLocalFilesFallbackMigration } from "./ensure-tsconfig-local-files-fallback.js";
|
|
34
36
|
export { EnsureWikiSourceDeclaredMigration } from "./ensure-wiki-source-declared.js";
|
|
35
37
|
export { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
|
|
@@ -62,6 +64,7 @@ export class MigrationRegistry {
|
|
|
62
64
|
new EnsureQualityCallerScopesMigration(),
|
|
63
65
|
new EnsureSeededGatesMigration(),
|
|
64
66
|
new EnsureSonarExcludesLisaHarnessMigration(),
|
|
67
|
+
new EnsureThirdPartyActionPinsMigration(),
|
|
65
68
|
new EnsureWikiSourceDeclaredMigration(),
|
|
66
69
|
new PruneRetiredClaudeDenyRulesMigration(),
|
|
67
70
|
new ReconcileClaudeStackPluginsMigration(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
"zod-validation-error": "^4.0.0"
|
|
167
167
|
},
|
|
168
168
|
"name": "@codyswann/lisa",
|
|
169
|
-
"version": "4.
|
|
169
|
+
"version": "4.36.0",
|
|
170
170
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
171
171
|
"main": "dist/index.js",
|
|
172
172
|
"exports": {
|
|
@@ -314,7 +314,7 @@
|
|
|
314
314
|
"test": "tests"
|
|
315
315
|
},
|
|
316
316
|
"types": "./dist/index.d.ts",
|
|
317
|
-
"lisaReleaseCommit": "
|
|
318
|
-
"gitHead": "
|
|
319
|
-
"lisaReleaseTag": "v4.
|
|
317
|
+
"lisaReleaseCommit": "e680357faafbc7d19a410bc517bd6fb48e3c5929",
|
|
318
|
+
"gitHead": "e680357faafbc7d19a410bc517bd6fb48e3c5929",
|
|
319
|
+
"lisaReleaseTag": "v4.36.0"
|
|
320
320
|
}
|
|
@@ -348,7 +348,66 @@ In `@example` blocks, use fenced code blocks and escape `@` as `\@`:
|
|
|
348
348
|
*/
|
|
349
349
|
```
|
|
350
350
|
|
|
351
|
-
###
|
|
351
|
+
### Path Examples Must Not Contain the Block Terminator
|
|
352
|
+
|
|
353
|
+
A path written as an example inside a doc comment **ends the comment** if it
|
|
354
|
+
contains `*/` — a glob such as `sandbox-*/`, or any real directory whose
|
|
355
|
+
name ends in an asterisk. Everything below that point is then parsed as source:
|
|
356
|
+
path segments become identifiers, and the separator between them becomes
|
|
357
|
+
division.
|
|
358
|
+
|
|
359
|
+
**Write the wildcard as a placeholder, not a glob:**
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// WRONG — the comment ends inside the path, mid-line
|
|
363
|
+
/**
|
|
364
|
+
* Debris lands at `.stryker-tmp/bite-guard-intact/sandbox-*/rails/scripts/foo.sh`
|
|
365
|
+
* and this line is no longer a comment.
|
|
366
|
+
*/
|
|
367
|
+
|
|
368
|
+
// RIGHT — a placeholder cannot terminate the block
|
|
369
|
+
/**
|
|
370
|
+
* Debris lands at `.stryker-tmp/bite-guard-intact/sandbox-<id>/rails/scripts/foo.sh`
|
|
371
|
+
* and this line is still a comment.
|
|
372
|
+
*/
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
`<id>`, `<name>`, `<n>` — the same placeholder convention used everywhere else
|
|
376
|
+
in Lisa's docs. Escaping (`*\/`) also works but produces an example nobody can
|
|
377
|
+
copy and paste, which defeats the point of writing one.
|
|
378
|
+
|
|
379
|
+
### What it looks like when you get it wrong
|
|
380
|
+
|
|
381
|
+
The build goes red immediately — `bun run typecheck`, `bun run lint` and the
|
|
382
|
+
test run all fail — but **none of them mentions a comment**, and every line
|
|
383
|
+
they report sits *below* the real cause. Measured, with the true cause on
|
|
384
|
+
line 89:
|
|
385
|
+
|
|
386
|
+
```text
|
|
387
|
+
src/configs/repo-scan.ts(90,9): error TS1005: ';' expected.
|
|
388
|
+
src/configs/repo-scan.ts(90,20): error TS1443: Module declaration names may only use ' or " quoted strings.
|
|
389
|
+
src/configs/repo-scan.ts(94,1): error TS1160: Unterminated template literal.
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Errors naming identifiers you never wrote — `Cannot find name 'mutation'`,
|
|
393
|
+
`Cannot find name 'src'` — are the giveaway: those are backtick contents from
|
|
394
|
+
inside the comment, now being read as code. **Look upward for a doc comment
|
|
395
|
+
before looking for a missing import.**
|
|
396
|
+
|
|
397
|
+
Lisa's gate runner says this for you. When a gate fails, it scans the files the
|
|
398
|
+
failure named and reports the closed comment by name:
|
|
399
|
+
|
|
400
|
+
```text
|
|
401
|
+
a doc comment in src/configs/repo-scan.ts ends early, on line 89 — every error
|
|
402
|
+
reported below that line is downstream of it, not a fault of its own
|
|
403
|
+
↳ src/configs/repo-scan.ts:89 — the block opened on line 87 ends at the
|
|
404
|
+
terminator INSIDE this line, not on line 92
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
It is a text scan rather than a lint rule on purpose: the file does not parse,
|
|
408
|
+
so ESLint reports `Parsing error` and runs zero rules on it.
|
|
409
|
+
|
|
410
|
+
## Quick Reference for Escaping
|
|
352
411
|
|
|
353
412
|
| Context | Approach | Example |
|
|
354
413
|
|---------|----------|---------|
|
|
@@ -33,6 +33,16 @@ An entire corpus sits outside the query's scope and nothing says so. `gh search
|
|
|
33
33
|
|
|
34
34
|
**Catch it:** validate the detector against known-true items before believing any count.
|
|
35
35
|
|
|
36
|
+
#### A second domain, which is what makes this a category rather than a quirk
|
|
37
|
+
|
|
38
|
+
The same mode, on a filesystem rather than a tracker. A survey of agent worktrees enumerating `.claude/worktrees/` and `.worktrees/` returns a well-formed list — and omits every worktree created outside the repository tree, under the per-user temporary directory. Four such worktrees existed, three of them with uncommitted changes; none appeared.
|
|
39
|
+
|
|
40
|
+
Run it through the membership test and it qualifies on all three counts: the list is **well formed** (no error, no warning, no partial marker); the omission is **invisible from the list itself**, which looks exactly like a complete survey of a machine with fewer worktrees on it; and **a mechanical step would have caught it** — the same one A1 already prescribes, validating the enumeration against a worktree you know exists.
|
|
41
|
+
|
|
42
|
+
This example is here rather than folded into the paragraph above because **a second domain tests whether the category is real or just a description of one tool's behaviour.** A mode observed only through `gh search` could be a fact about GitHub's search semantics; the same shape in a `find` over directories says the failure belongs to *enumeration with an unstated boundary*, whichever substrate is enumerating. When extending this document, a new domain for an existing mode is worth as much as a new mode.
|
|
43
|
+
|
|
44
|
+
**The consequence in that instance was not academic.** Uncommitted work outside the repository tree is invisible to every query anyone would run before deciding what to clean up, and looks identical to abandoned scratch — so a survey feeding a deletion decision under-reports precisely the thing that must not be deleted. See the worktree-and-binding hazards for the separate question of a mitigation whose cost is invisibility; the measurement half is this mode.
|
|
45
|
+
|
|
36
46
|
### A2. Truncation — under, enumeration
|
|
37
47
|
|
|
38
48
|
Real members past the first page are dropped with no truncation signal. `gh issue list` and `gh pr list` default to 30 and cap silently at whatever `--limit` is passed: one audit reported **37 items where the answer was 513**, a 14× undercount. A paging API returning **249 of 845 rows with `hasNextPage: false`** is the same mode on another substrate.
|
|
@@ -348,7 +348,66 @@ In `@example` blocks, use fenced code blocks and escape `@` as `\@`:
|
|
|
348
348
|
*/
|
|
349
349
|
```
|
|
350
350
|
|
|
351
|
-
###
|
|
351
|
+
### Path Examples Must Not Contain the Block Terminator
|
|
352
|
+
|
|
353
|
+
A path written as an example inside a doc comment **ends the comment** if it
|
|
354
|
+
contains `*/` — a glob such as `sandbox-*/`, or any real directory whose
|
|
355
|
+
name ends in an asterisk. Everything below that point is then parsed as source:
|
|
356
|
+
path segments become identifiers, and the separator between them becomes
|
|
357
|
+
division.
|
|
358
|
+
|
|
359
|
+
**Write the wildcard as a placeholder, not a glob:**
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// WRONG — the comment ends inside the path, mid-line
|
|
363
|
+
/**
|
|
364
|
+
* Debris lands at `.stryker-tmp/bite-guard-intact/sandbox-*/rails/scripts/foo.sh`
|
|
365
|
+
* and this line is no longer a comment.
|
|
366
|
+
*/
|
|
367
|
+
|
|
368
|
+
// RIGHT — a placeholder cannot terminate the block
|
|
369
|
+
/**
|
|
370
|
+
* Debris lands at `.stryker-tmp/bite-guard-intact/sandbox-<id>/rails/scripts/foo.sh`
|
|
371
|
+
* and this line is still a comment.
|
|
372
|
+
*/
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
`<id>`, `<name>`, `<n>` — the same placeholder convention used everywhere else
|
|
376
|
+
in Lisa's docs. Escaping (`*\/`) also works but produces an example nobody can
|
|
377
|
+
copy and paste, which defeats the point of writing one.
|
|
378
|
+
|
|
379
|
+
### What it looks like when you get it wrong
|
|
380
|
+
|
|
381
|
+
The build goes red immediately — `bun run typecheck`, `bun run lint` and the
|
|
382
|
+
test run all fail — but **none of them mentions a comment**, and every line
|
|
383
|
+
they report sits *below* the real cause. Measured, with the true cause on
|
|
384
|
+
line 89:
|
|
385
|
+
|
|
386
|
+
```text
|
|
387
|
+
src/configs/repo-scan.ts(90,9): error TS1005: ';' expected.
|
|
388
|
+
src/configs/repo-scan.ts(90,20): error TS1443: Module declaration names may only use ' or " quoted strings.
|
|
389
|
+
src/configs/repo-scan.ts(94,1): error TS1160: Unterminated template literal.
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Errors naming identifiers you never wrote — `Cannot find name 'mutation'`,
|
|
393
|
+
`Cannot find name 'src'` — are the giveaway: those are backtick contents from
|
|
394
|
+
inside the comment, now being read as code. **Look upward for a doc comment
|
|
395
|
+
before looking for a missing import.**
|
|
396
|
+
|
|
397
|
+
Lisa's gate runner says this for you. When a gate fails, it scans the files the
|
|
398
|
+
failure named and reports the closed comment by name:
|
|
399
|
+
|
|
400
|
+
```text
|
|
401
|
+
a doc comment in src/configs/repo-scan.ts ends early, on line 89 — every error
|
|
402
|
+
reported below that line is downstream of it, not a fault of its own
|
|
403
|
+
↳ src/configs/repo-scan.ts:89 — the block opened on line 87 ends at the
|
|
404
|
+
terminator INSIDE this line, not on line 92
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
It is a text scan rather than a lint rule on purpose: the file does not parse,
|
|
408
|
+
so ESLint reports `Parsing error` and runs zero rules on it.
|
|
409
|
+
|
|
410
|
+
## Quick Reference for Escaping
|
|
352
411
|
|
|
353
412
|
| Context | Approach | Example |
|
|
354
413
|
|---------|----------|---------|
|