@codyswann/lisa 4.60.4 → 4.60.6

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 (92) hide show
  1. package/{scripts/check-workflow-load-failures.ts → all/copy-overwrite/scripts/check-workflow-load-failures.mjs} +36 -76
  2. package/all/copy-overwrite/scripts/lib/reusable-workflow-load-adapter.d.mts +21 -0
  3. package/{dist/core/reusable-workflow-load-adapter.js → all/copy-overwrite/scripts/lib/reusable-workflow-load-adapter.mjs} +50 -41
  4. package/all/copy-overwrite/scripts/lib/reusable-workflow-load-failure.d.mts +29 -0
  5. package/all/copy-overwrite/scripts/lib/reusable-workflow-load-failure.mjs +124 -0
  6. package/all/copy-overwrite/scripts/lib/reusable-workflow-load-scan.d.mts +36 -0
  7. package/all/copy-overwrite/scripts/lib/reusable-workflow-load-scan.mjs +102 -0
  8. package/all/create-only/.github/workflows/workflow-load-failure-sweep.yml +42 -0
  9. package/dist/codex/scripts/block-migration-edits.sh +12 -4
  10. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  11. package/dist/core/lisa-owned-hash-ledger.js +64 -0
  12. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  13. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  14. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  15. package/dist/core/upstream-evidence-manifest.js +23 -9
  16. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  17. package/dist/opencode/plugin-templates/lisa-block-migration-edits.ts +10 -2
  18. package/package.json +5 -5
  19. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  21. package/plugins/lisa-agy/plugin.json +1 -1
  22. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  25. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa-expo-agy/plugin.json +1 -1
  32. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  36. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  37. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-nestjs/.codex-plugin/skills/nestjs-rules/SKILL.md +6 -11
  42. package/plugins/lisa-nestjs/hooks/block-migration-edits.sh +14 -18
  43. package/plugins/lisa-nestjs/skills/nestjs-rules/SKILL.md +6 -11
  44. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  45. package/plugins/lisa-nestjs-agy/skills/nestjs-rules/SKILL.md +6 -11
  46. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-copilot/hooks/block-migration-edits.sh +14 -18
  48. package/plugins/lisa-nestjs-copilot/skills/nestjs-rules/SKILL.md +6 -11
  49. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-nestjs-cursor/hooks/block-migration-edits.sh +14 -18
  51. package/plugins/lisa-nestjs-cursor/skills/nestjs-rules/SKILL.md +6 -11
  52. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  55. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  60. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails-agy/plugin.json +1 -1
  65. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  70. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  75. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  77. package/plugins/src/nestjs/hooks/block-migration-edits.sh +14 -18
  78. package/plugins/src/nestjs/skills/nestjs-rules/SKILL.md +6 -11
  79. package/scripts/check-workflow-load-failures.mjs +4 -0
  80. package/scripts/two-channel-couplings.json +1 -1
  81. package/typescript/copy-overwrite/.prettierignore +1 -0
  82. package/dist/core/reusable-workflow-load-adapter.d.ts +0 -78
  83. package/dist/core/reusable-workflow-load-adapter.d.ts.map +0 -1
  84. package/dist/core/reusable-workflow-load-adapter.js.map +0 -1
  85. package/dist/core/reusable-workflow-load-failure.d.ts +0 -144
  86. package/dist/core/reusable-workflow-load-failure.d.ts.map +0 -1
  87. package/dist/core/reusable-workflow-load-failure.js +0 -184
  88. package/dist/core/reusable-workflow-load-failure.js.map +0 -1
  89. package/dist/core/reusable-workflow-load-scan.d.ts +0 -92
  90. package/dist/core/reusable-workflow-load-scan.d.ts.map +0 -1
  91. package/dist/core/reusable-workflow-load-scan.js +0 -108
  92. package/dist/core/reusable-workflow-load-scan.js.map +0 -1
@@ -2,7 +2,9 @@
2
2
  # This file is managed by Lisa.
3
3
  # Do not edit directly — changes will be overwritten on the next `lisa` run.
4
4
 
5
- # PreToolUse hook: block Write/Edit on TypeORM migration files.
5
+ # PreToolUse hook: block Write/Edit on TypeORM migration files by default.
6
+ # This scopes direct edit tools; it does not verify approval or establish the
7
+ # provenance of files written through other tools.
6
8
  # NestJS projects must use `bun run migration:generate` to create migrations
7
9
  # from entity diffs. Hand-written migrations drift from entity metadata and
8
10
  # break the schema/migration contract.
@@ -79,8 +81,8 @@ LISA_HOOK_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)"
79
81
  # That is what keeps an undeclared project on exactly the command, and exactly
80
82
  # the exit status, it had before.
81
83
  #
82
- # ONE PROPERTY, so there is no all-or-nothing question here: this hook proves
83
- # `migration-provenance` and nothing else.
84
+ # A project may supply its own `migration-provenance` check for these edits.
85
+ # The built-in only refuses the scoped Write/Edit calls.
84
86
  # ---------------------------------------------------------------------------
85
87
  if [ -n "${CLAUDE_PROJECT_DIR:-}" ] &&
86
88
  [ -f "$LISA_HOOK_DIR/lisa-edit-gate.sh" ] &&
@@ -98,7 +100,7 @@ if [ -n "${CLAUDE_PROJECT_DIR:-}" ] &&
98
100
  fi
99
101
 
100
102
  cat >&2 <<EOF
101
- ❌ Blocked: Direct edits to TypeORM migration files are not allowed.
103
+ ❌ Blocked: This default hook refuses Write/Edit on TypeORM migration files.
102
104
 
103
105
  File: $FILE_PATH
104
106
 
@@ -110,20 +112,14 @@ artifact — generate them from entity diffs:
110
112
  2. Run: bun run migration:generate --name=<DescriptiveName>
111
113
  3. Review the generated migration; commit entity + migration together.
112
114
 
113
- If a schema change cannot be expressed via the entity model, the entity
114
- model is wrong — fix the entity, do not hand-write the migration.
115
+ Out-of-band migrations (backfills, seed data, maintenance) cannot always
116
+ come from entity diffs. A project that supports these edits can declare a
117
+ \`migration-provenance\` check at \`pre-tool\` in .lisa.config.json. The hook
118
+ runs that check and uses its result to permit or refuse the edit.
115
119
 
116
- OUT-OF-BAND MIGRATIONS (seed data, backfills, data transformations,
117
- one-off cleanup): these genuinely cannot come from entity diffs. They
118
- are legitimate but they bypass the entity-as-source-of-truth contract.
119
-
120
- If you believe this edit is an out-of-band migration:
121
- 1. STOP and tell the user what change is needed and why it cannot
122
- be expressed via the entity model.
123
- 2. Get explicit approval before proceeding.
124
- 3. Document the rationale in the migration's class comment.
125
-
126
- Do NOT silently hand-write a migration. See the nestjs-rules skill
127
- for the full rationale.
120
+ Document the migration's rationale and verification in its class comment.
121
+ This default hook cannot verify human approval and does not inspect Bash
122
+ writes. Do not switch tools to evade its refusal. See the nestjs-rules skill
123
+ for the supported project-check path.
128
124
  EOF
129
125
  exit 2
@@ -51,11 +51,9 @@ In this project, **entity files (`src/database/entities/*.ts`) are the single so
51
51
  2. Run `bun run migration:generate --name=<DescriptiveName>` to produce the migration from the diff.
52
52
  3. Review the generated migration, then commit both the entity change and the migration together.
53
53
 
54
- If a schema change cannot be expressed via the entity model, the entity model is wrong — fix the entity, do not hand-write the migration.
54
+ ### Generate Schema Migrations
55
55
 
56
- ### Never Create Migration Files Manually
57
-
58
- Never create or modify a TypeORM migration file directly. Use `migration:generate` from `package.json`:
56
+ Use `migration:generate` from `package.json` for changes represented by entity metadata:
59
57
 
60
58
  ```bash
61
59
  bun run migration:generate --name=<DescriptiveName>
@@ -69,18 +67,15 @@ Some changes genuinely cannot be derived from entity diffs:
69
67
  - **Data backfills** (populating a new column from existing rows)
70
68
  - **Data transformations** (splitting a column, normalizing values)
71
69
  - **One-off cleanup** (deleting orphaned rows before a constraint is added)
70
+ - **Database maintenance** (refreshing planner statistics with `ANALYZE`)
72
71
 
73
- These are legitimate cases for a hand-written migration, but they are **out-of-band** — they bypass the entity-as-source-of-truth contract. When you encounter one:
74
-
75
- 1. **Stop and tell the user.** Explain what change is needed and why it cannot be expressed via the entity model.
76
- 2. **Get explicit approval** before writing the migration by hand.
77
- 3. Document the rationale in the migration's class comment so future readers understand why this one was not generated.
72
+ Use the project's established migration process for these cases. Document the rationale and verification in the migration's class comment so future readers understand why it was not generated. Apply the authorization already given for the work; the default edit hook does not record or verify human approval.
78
73
 
79
- Do not silently hand-write a migration for a backfill or seed-data change. The user must know that the entity-as-source-of-truth contract is being intentionally bypassed for this case.
74
+ A project that supports direct migration edits can declare its own `migration-provenance` check at `pre-tool` in `.lisa.config.json`. The Claude and Codex hooks run that check for the targeted migration and permit the edit only when it passes. The check must validate the project's migration policy; an unconditional success command proves nothing. Without a declared check, the built-in still refuses the edit. OpenCode's migration adapter currently does not support this exception path and continues to refuse it.
80
75
 
81
76
  ### Enforcement
82
77
 
83
- The `lisa-nestjs` plugin ships a `PreToolUse` hook (`block-migration-edits.sh`) that blocks `Write`/`Edit` on any path matching `**/migrations/*.ts` or `**/migrations/*.js`. The block surfaces this rule's guidance to remind you to either (a) edit the entity instead, or (b) ask the user before proceeding with an out-of-band migration.
78
+ The `lisa-nestjs` plugin's default `PreToolUse` hook (`block-migration-edits.sh`) refuses `Write`/`Edit` on paths matching `**/migrations/*.ts` or `**/migrations/*.js`. Codex also inspects `apply_patch`; its migration matcher and OpenCode's matcher cover numbered TypeScript migration filenames. These are direct-edit checks, not an audit of migration authorship: they do not inspect Bash writes. Do not switch tools to evade a refusal. Use the supported project check where available.
84
79
 
85
80
  ### Why Auto-Generation
86
81
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.60.4",
3
+ "version": "4.60.6",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -2,7 +2,9 @@
2
2
  # This file is managed by Lisa.
3
3
  # Do not edit directly — changes will be overwritten on the next `lisa` run.
4
4
 
5
- # PreToolUse hook: block Write/Edit on TypeORM migration files.
5
+ # PreToolUse hook: block Write/Edit on TypeORM migration files by default.
6
+ # This scopes direct edit tools; it does not verify approval or establish the
7
+ # provenance of files written through other tools.
6
8
  # NestJS projects must use `bun run migration:generate` to create migrations
7
9
  # from entity diffs. Hand-written migrations drift from entity metadata and
8
10
  # break the schema/migration contract.
@@ -79,8 +81,8 @@ LISA_HOOK_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)"
79
81
  # That is what keeps an undeclared project on exactly the command, and exactly
80
82
  # the exit status, it had before.
81
83
  #
82
- # ONE PROPERTY, so there is no all-or-nothing question here: this hook proves
83
- # `migration-provenance` and nothing else.
84
+ # A project may supply its own `migration-provenance` check for these edits.
85
+ # The built-in only refuses the scoped Write/Edit calls.
84
86
  # ---------------------------------------------------------------------------
85
87
  if [ -n "${CLAUDE_PROJECT_DIR:-}" ] &&
86
88
  [ -f "$LISA_HOOK_DIR/lisa-edit-gate.sh" ] &&
@@ -98,7 +100,7 @@ if [ -n "${CLAUDE_PROJECT_DIR:-}" ] &&
98
100
  fi
99
101
 
100
102
  cat >&2 <<EOF
101
- ❌ Blocked: Direct edits to TypeORM migration files are not allowed.
103
+ ❌ Blocked: This default hook refuses Write/Edit on TypeORM migration files.
102
104
 
103
105
  File: $FILE_PATH
104
106
 
@@ -110,20 +112,14 @@ artifact — generate them from entity diffs:
110
112
  2. Run: bun run migration:generate --name=<DescriptiveName>
111
113
  3. Review the generated migration; commit entity + migration together.
112
114
 
113
- If a schema change cannot be expressed via the entity model, the entity
114
- model is wrong — fix the entity, do not hand-write the migration.
115
+ Out-of-band migrations (backfills, seed data, maintenance) cannot always
116
+ come from entity diffs. A project that supports these edits can declare a
117
+ \`migration-provenance\` check at \`pre-tool\` in .lisa.config.json. The hook
118
+ runs that check and uses its result to permit or refuse the edit.
115
119
 
116
- OUT-OF-BAND MIGRATIONS (seed data, backfills, data transformations,
117
- one-off cleanup): these genuinely cannot come from entity diffs. They
118
- are legitimate but they bypass the entity-as-source-of-truth contract.
119
-
120
- If you believe this edit is an out-of-band migration:
121
- 1. STOP and tell the user what change is needed and why it cannot
122
- be expressed via the entity model.
123
- 2. Get explicit approval before proceeding.
124
- 3. Document the rationale in the migration's class comment.
125
-
126
- Do NOT silently hand-write a migration. See the nestjs-rules skill
127
- for the full rationale.
120
+ Document the migration's rationale and verification in its class comment.
121
+ This default hook cannot verify human approval and does not inspect Bash
122
+ writes. Do not switch tools to evade its refusal. See the nestjs-rules skill
123
+ for the supported project-check path.
128
124
  EOF
129
125
  exit 2
@@ -51,11 +51,9 @@ In this project, **entity files (`src/database/entities/*.ts`) are the single so
51
51
  2. Run `bun run migration:generate --name=<DescriptiveName>` to produce the migration from the diff.
52
52
  3. Review the generated migration, then commit both the entity change and the migration together.
53
53
 
54
- If a schema change cannot be expressed via the entity model, the entity model is wrong — fix the entity, do not hand-write the migration.
54
+ ### Generate Schema Migrations
55
55
 
56
- ### Never Create Migration Files Manually
57
-
58
- Never create or modify a TypeORM migration file directly. Use `migration:generate` from `package.json`:
56
+ Use `migration:generate` from `package.json` for changes represented by entity metadata:
59
57
 
60
58
  ```bash
61
59
  bun run migration:generate --name=<DescriptiveName>
@@ -69,18 +67,15 @@ Some changes genuinely cannot be derived from entity diffs:
69
67
  - **Data backfills** (populating a new column from existing rows)
70
68
  - **Data transformations** (splitting a column, normalizing values)
71
69
  - **One-off cleanup** (deleting orphaned rows before a constraint is added)
70
+ - **Database maintenance** (refreshing planner statistics with `ANALYZE`)
72
71
 
73
- These are legitimate cases for a hand-written migration, but they are **out-of-band** — they bypass the entity-as-source-of-truth contract. When you encounter one:
74
-
75
- 1. **Stop and tell the user.** Explain what change is needed and why it cannot be expressed via the entity model.
76
- 2. **Get explicit approval** before writing the migration by hand.
77
- 3. Document the rationale in the migration's class comment so future readers understand why this one was not generated.
72
+ Use the project's established migration process for these cases. Document the rationale and verification in the migration's class comment so future readers understand why it was not generated. Apply the authorization already given for the work; the default edit hook does not record or verify human approval.
78
73
 
79
- Do not silently hand-write a migration for a backfill or seed-data change. The user must know that the entity-as-source-of-truth contract is being intentionally bypassed for this case.
74
+ A project that supports direct migration edits can declare its own `migration-provenance` check at `pre-tool` in `.lisa.config.json`. The Claude and Codex hooks run that check for the targeted migration and permit the edit only when it passes. The check must validate the project's migration policy; an unconditional success command proves nothing. Without a declared check, the built-in still refuses the edit. OpenCode's migration adapter currently does not support this exception path and continues to refuse it.
80
75
 
81
76
  ### Enforcement
82
77
 
83
- The `lisa-nestjs` plugin ships a `PreToolUse` hook (`block-migration-edits.sh`) that blocks `Write`/`Edit` on any path matching `**/migrations/*.ts` or `**/migrations/*.js`. The block surfaces this rule's guidance to remind you to either (a) edit the entity instead, or (b) ask the user before proceeding with an out-of-band migration.
78
+ The `lisa-nestjs` plugin's default `PreToolUse` hook (`block-migration-edits.sh`) refuses `Write`/`Edit` on paths matching `**/migrations/*.ts` or `**/migrations/*.js`. Codex also inspects `apply_patch`; its migration matcher and OpenCode's matcher cover numbered TypeScript migration filenames. These are direct-edit checks, not an audit of migration authorship: they do not inspect Bash writes. Do not switch tools to evade a refusal. Use the supported project check where available.
84
79
 
85
80
  ### Why Auto-Generation
86
81
 
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from "../all/copy-overwrite/scripts/check-workflow-load-failures.mjs";
3
+
4
+ runCli();
@@ -97,7 +97,7 @@
97
97
  "workflows": 23,
98
98
  "steps": 781,
99
99
  "couplings": 33,
100
- "inventory": 80
100
+ "inventory": 87
101
101
  },
102
102
  "counts": {
103
103
  "package-backed": 10,
@@ -77,6 +77,7 @@ scripts/check-third-party-action-pins.mjs
77
77
  scripts/check-third-party-review-evidence.mjs
78
78
  scripts/check-threshold-ratchet.mjs
79
79
  scripts/check-verification-coverage.mjs
80
+ scripts/check-workflow-load-failures.mjs
80
81
  scripts/classify-maestro-failures.mjs
81
82
  scripts/lisa-command-envelope.mjs
82
83
  scripts/lisa-commit-msg-gates.mjs
@@ -1,78 +0,0 @@
1
- /**
2
- * Turn GitHub's run endpoints into the pages `core/reusable-workflow-load-scan`
3
- * expects (CodySwannGT/lisa#3581).
4
- *
5
- * The HTTP request is injected. That keeps the endpoint shapes, the paging
6
- * parameters and the response handling under test against a stub, which is the
7
- * only way to prove this wiring without a live call whose rate limit decides
8
- * whether the suite passes — the lesson a sibling lane paid twenty minutes of
9
- * held-dirty tree to learn.
10
- *
11
- * ## Why this needs three endpoints and not one
12
- *
13
- * The run LIST gives id, caller path, timestamp and conclusion. It does not
14
- * give the two facts the verdict actually turns on: `referenced_workflows`
15
- * comes from the single-run endpoint, and the job count from the run's jobs
16
- * endpoint. So a full scan is inherently N+1, and reading every run's detail
17
- * across a wide window is the kind of request volume that gets a scheduled job
18
- * rate-limited into a false green.
19
- *
20
- * The narrowing that makes it affordable is sound rather than convenient: a
21
- * load failure is only reachable from a conclusion GitHub can produce BEFORE
22
- * creating a job. Detail is therefore fetched only for those, and a run with
23
- * any other conclusion keeps zeroes it never fetched.
24
- *
25
- * **Those zeroes are not measurements.** For a `success` run they are simply
26
- * absent evidence, and the classifier's label for such a run is not meaningful
27
- * — the only verdict this adapter's output supports is `load-failure`, which
28
- * is the one the scan filters for. Anything that starts reporting per-verdict
29
- * counts from these pages must fetch detail unconditionally first.
30
- * @module core/reusable-workflow-load-adapter
31
- */
32
- import type { RunPage } from "./reusable-workflow-load-scan.js";
33
- /** GitHub's default and maximum page size for the runs endpoint. */
34
- export declare const RUNS_PER_PAGE = 100;
35
- /** Performs one authenticated GET and returns the decoded JSON body. */
36
- export type GithubRequest = (path: string) => Promise<unknown>;
37
- /** What the fetcher needs to address a repository. */
38
- export interface AdapterOptions {
39
- /** Repository in `owner/name` form. */
40
- readonly repo: string;
41
- /** The injected request function. */
42
- readonly request: GithubRequest;
43
- /** Page size; defaults to `RUNS_PER_PAGE`. */
44
- readonly perPage?: number;
45
- }
46
- /**
47
- * Path for one page of run history, newest first.
48
- * @param repo - Repository in `owner/name` form
49
- * @param page - 1-based page number
50
- * @param perPage - Page size
51
- * @returns The API path to request
52
- */
53
- export declare function runsPath(repo: string, page: number, perPage: number): string;
54
- /**
55
- * Path for one run's detail, which is where `referenced_workflows` lives.
56
- * @param repo - Repository in `owner/name` form
57
- * @param id - The run id
58
- * @returns The API path to request
59
- */
60
- export declare function runPath(repo: string, id: number): string;
61
- /**
62
- * Path for one run's jobs, read only for its `total_count`.
63
- * @param repo - Repository in `owner/name` form
64
- * @param id - The run id
65
- * @returns The API path to request
66
- */
67
- export declare function jobsPath(repo: string, id: number): string;
68
- /**
69
- * Build the page fetcher `scanForLoadFailures` consumes.
70
- *
71
- * `hasMore` is derived from a full page rather than from `total_count`,
72
- * because a run created while the scan is paging shifts `total_count` under
73
- * it. A full page means "ask again"; a short page means the history ended.
74
- * @param options - Repository, request function and page size
75
- * @returns A fetcher for one 1-based page of run history
76
- */
77
- export declare function createRunPageFetcher(options: AdapterOptions): (page: number) => Promise<RunPage>;
78
- //# sourceMappingURL=reusable-workflow-load-adapter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reusable-workflow-load-adapter.d.ts","sourceRoot":"","sources":["../../src/core/reusable-workflow-load-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,kCAAkC,CAAC;AAY5E,oEAAoE;AACpE,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/D,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAEzD;AA8ED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,cAAc,GACtB,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAqBpC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"reusable-workflow-load-adapter.js","sourceRoot":"","sources":["../../src/core/reusable-workflow-load-adapter.ts"],"names":[],"mappings":"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"}