@codyswann/lisa 4.35.4 → 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.
Files changed (69) hide show
  1. package/all/copy-overwrite/scripts/lib/gate-failure-diagnosis.mjs +296 -3
  2. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  3. package/dist/core/lisa-owned-hash-ledger.js +6 -0
  4. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  5. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  6. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  7. package/dist/core/upstream-evidence-manifest.js +4 -3
  8. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  9. package/package.json +4 -4
  10. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  12. package/plugins/lisa/.codex-plugin/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
  13. package/plugins/lisa/rules/reference/measurement-integrity.md +10 -0
  14. package/plugins/lisa/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
  15. package/plugins/lisa-agy/plugin.json +1 -1
  16. package/plugins/lisa-agy/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
  17. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  20. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-copilot/rules/reference/measurement-integrity.md +10 -0
  24. package/plugins/lisa-copilot/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
  25. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cursor/rules/measurement-integrity-reference.mdc +10 -0
  27. package/plugins/lisa-cursor/skills/lisa-jsdoc-best-practices/SKILL.md +60 -1
  28. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  30. package/plugins/lisa-expo-agy/plugin.json +1 -1
  31. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  36. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  40. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  41. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  45. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  46. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  50. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  51. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  55. package/plugins/lisa-rails-agy/plugin.json +1 -1
  56. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  60. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  61. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  66. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/src/base/rules/reference/measurement-integrity.md +10 -0
  69. 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.4",
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": "cdfd50ffb82cb4a61189aa88ac5079f7191d5af3",
318
- "gitHead": "cdfd50ffb82cb4a61189aa88ac5079f7191d5af3",
319
- "lisaReleaseTag": "v4.35.4"
317
+ "lisaReleaseCommit": "eef625a21fce4a478796cb76926a3c8e03d032b6",
318
+ "gitHead": "eef625a21fce4a478796cb76926a3c8e03d032b6",
319
+ "lisaReleaseTag": "v4.35.5"
320
320
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -348,7 +348,66 @@ In `@example` blocks, use fenced code blocks and escape `@` as `\@`:
348
348
  */
349
349
  ```
350
350
 
351
- ### Quick Reference for Escaping
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
- ### Quick Reference for Escaping
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
  |---------|----------|---------|
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -348,7 +348,66 @@ In `@example` blocks, use fenced code blocks and escape `@` as `\@`:
348
348
  */
349
349
  ```
350
350
 
351
- ### Quick Reference for Escaping
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
  |---------|----------|---------|
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -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
- ### Quick Reference for Escaping
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
  |---------|----------|---------|
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -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
- ### Quick Reference for Escaping
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
  |---------|----------|---------|
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.35.4",
3
+ "version": "4.35.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"