@codyswann/lisa 4.35.3 → 4.35.5
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/lib/gate-failure-diagnosis.mjs +296 -3
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +6 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +4 -3
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.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/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.35.
|
|
169
|
+
"version": "4.35.5",
|
|
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.35.
|
|
317
|
+
"lisaReleaseCommit": "eef625a21fce4a478796cb76926a3c8e03d032b6",
|
|
318
|
+
"gitHead": "eef625a21fce4a478796cb76926a3c8e03d032b6",
|
|
319
|
+
"lisaReleaseTag": "v4.35.5"
|
|
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
|
|---------|----------|---------|
|
|
@@ -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
|
|---------|----------|---------|
|
|
@@ -38,6 +38,16 @@ An entire corpus sits outside the query's scope and nothing says so. `gh search
|
|
|
38
38
|
|
|
39
39
|
**Catch it:** validate the detector against known-true items before believing any count.
|
|
40
40
|
|
|
41
|
+
#### A second domain, which is what makes this a category rather than a quirk
|
|
42
|
+
|
|
43
|
+
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.
|
|
44
|
+
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
49
|
+
**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.
|
|
50
|
+
|
|
41
51
|
### A2. Truncation — under, enumeration
|
|
42
52
|
|
|
43
53
|
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
|
|---------|----------|---------|
|