@codyswann/lisa 4.47.0 → 4.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/configs/vitest/base.d.ts +71 -1
  2. package/dist/configs/vitest/base.d.ts.map +1 -1
  3. package/dist/configs/vitest/base.js +141 -23
  4. package/dist/configs/vitest/base.js.map +1 -1
  5. package/dist/configs/vitest/fleet-admission-global-setup.d.ts +34 -0
  6. package/dist/configs/vitest/fleet-admission-global-setup.d.ts.map +1 -0
  7. package/dist/configs/vitest/fleet-admission-global-setup.js +123 -0
  8. package/dist/configs/vitest/fleet-admission-global-setup.js.map +1 -0
  9. package/dist/configs/vitest/fleet-admission.d.ts +129 -0
  10. package/dist/configs/vitest/fleet-admission.d.ts.map +1 -0
  11. package/dist/configs/vitest/fleet-admission.js +239 -0
  12. package/dist/configs/vitest/fleet-admission.js.map +1 -0
  13. package/dist/configs/vitest/synthesis-scratch-reclaim.d.ts +86 -0
  14. package/dist/configs/vitest/synthesis-scratch-reclaim.d.ts.map +1 -0
  15. package/dist/configs/vitest/synthesis-scratch-reclaim.js +226 -0
  16. package/dist/configs/vitest/synthesis-scratch-reclaim.js.map +1 -0
  17. package/dist/core/host-rules-pointer.d.ts.map +1 -1
  18. package/dist/core/host-rules-pointer.js +30 -22
  19. package/dist/core/host-rules-pointer.js.map +1 -1
  20. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  21. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  22. package/dist/core/upstream-evidence-manifest.js +9 -1
  23. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  24. package/package.json +4 -4
  25. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-agy/plugin.json +1 -1
  28. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  30. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  31. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-expo-agy/plugin.json +1 -1
  38. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  43. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  48. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  53. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  58. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails-agy/plugin.json +1 -1
  63. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  68. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  73. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  75. package/scripts/cleanup-worktrees.sh +69 -16
package/package.json CHANGED
@@ -176,7 +176,7 @@
176
176
  "zod-validation-error": "^4.0.0"
177
177
  },
178
178
  "name": "@codyswann/lisa",
179
- "version": "4.47.0",
179
+ "version": "4.49.0",
180
180
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
181
181
  "main": "dist/index.js",
182
182
  "exports": {
@@ -324,7 +324,7 @@
324
324
  "test": "tests"
325
325
  },
326
326
  "types": "./dist/index.d.ts",
327
- "lisaReleaseCommit": "fcf2333d7daa6e6616891fa279dc9d2573718960",
328
- "gitHead": "fcf2333d7daa6e6616891fa279dc9d2573718960",
329
- "lisaReleaseTag": "v4.47.0"
327
+ "lisaReleaseCommit": "13f6d114d64862b46c149e9aae4ec77a671145e0",
328
+ "gitHead": "13f6d114d64862b46c149e9aae4ec77a671145e0",
329
+ "lisaReleaseTag": "v4.49.0"
330
330
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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-cdk",
3
- "version": "4.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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-expo",
3
- "version": "4.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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-openclaw",
3
- "version": "4.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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.47.0",
3
+ "version": "4.49.0",
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"
@@ -10,7 +10,12 @@
10
10
  # ~/.codex/worktrees, .lisa-worktrees, /tmp) OR its branch matches an
11
11
  # agent naming pattern (claude/*, worktree-*, codex/*) OR its branch is
12
12
  # fully merged into an environment branch (main/dev/staging).
13
- # 3. No modified/staged TRACKED files ("real work" is never deleted).
13
+ # 3. Git could actually REPORT on it, and reported no modified/staged TRACKED
14
+ # files ("real work" is never deleted). "I looked and it was clean" and "I
15
+ # could not look" are different answers: a `git status` that FAILS is kept
16
+ # in its own bucket, never treated as clean. This mirrors the TypeScript
17
+ # entitlement rule (src/cli/worktree-prune-policy.ts), which blocks on
18
+ # `unreadable` rather than defaulting an unproven worktree to eligible.
14
19
  # 4. Its HEAD commit is reachable from some remote ref (nothing unpushed).
15
20
  # 5. It is older than --min-age-days (default 7) by directory mtime.
16
21
  # 6. Its uncommitted content is reachable from some commit — asked of the
@@ -70,7 +75,7 @@ fi
70
75
 
71
76
  NOW=$(date +%s)
72
77
  MIN_AGE_SECS=$((MIN_AGE_DAYS * 86400))
73
- REMOVED=0 KEPT_DIRTY=0 KEPT_UNPUSHED=0 KEPT_YOUNG=0 KEPT_UNTRACKED=0 ORPHANS=0 ERRORS=0
78
+ REMOVED=0 KEPT_DIRTY=0 KEPT_UNPUSHED=0 KEPT_YOUNG=0 KEPT_UNTRACKED=0 KEPT_UNREADABLE=0 ORPHANS=0 ERRORS=0
74
79
  KEPT_UNREACHABLE=0
75
80
 
76
81
  # Content-reachability guard. Absent node or an unresolvable script leaves the
@@ -162,7 +167,23 @@ process_worktree() {
162
167
  return
163
168
  fi
164
169
 
165
- if [ -n "$(git -C "$wt" status --porcelain --untracked-files=no 2>/dev/null)" ]; then
170
+ # Capture the OUTPUT and the EXIT STATUS separately. Written as
171
+ # `[ -n "$(git ... 2>/dev/null)" ]` — the way this and the untracked check
172
+ # below both used to be — a FAILED git collapses to the empty string, `-n ""`
173
+ # is false, and an unreadable worktree takes the same branch as a spotless
174
+ # one: it falls through every KEEP predicate to removal. A short/corrupt index
175
+ # (what a SIGKILLed git leaves behind, and the ordinary outcome of the
176
+ # concurrency pressure this script exists to relieve) reaches exactly that
177
+ # state: `git status` exits 128 while the ref queries below still answer.
178
+ local tracked_status tracked_rc
179
+ tracked_status=$(git -C "$wt" status --porcelain --untracked-files=no 2>/dev/null)
180
+ tracked_rc=$?
181
+ if [ "$tracked_rc" -ne 0 ]; then
182
+ KEPT_UNREADABLE=$((KEPT_UNREADABLE + 1))
183
+ log "KEEP (git could not report on it — unreadable, so nothing was proven) $wt"
184
+ return
185
+ fi
186
+ if [ -n "$tracked_status" ]; then
166
187
  KEPT_DIRTY=$((KEPT_DIRTY + 1))
167
188
  log "KEEP (modified tracked files) $wt"
168
189
  return
@@ -183,7 +204,15 @@ process_worktree() {
183
204
  fi
184
205
 
185
206
  local force_flag=()
186
- if [ -n "$(git -C "$wt" status --porcelain 2>/dev/null)" ]; then
207
+ local full_status full_rc
208
+ full_status=$(git -C "$wt" status --porcelain 2>/dev/null)
209
+ full_rc=$?
210
+ if [ "$full_rc" -ne 0 ]; then
211
+ KEPT_UNREADABLE=$((KEPT_UNREADABLE + 1))
212
+ log "KEEP (git could not report on it — unreadable, so nothing was proven) $wt"
213
+ return
214
+ fi
215
+ if [ -n "$full_status" ]; then
187
216
  if [ "$FORCE_UNTRACKED" = 1 ]; then
188
217
  force_flag=(--force)
189
218
  else
@@ -195,7 +224,12 @@ process_worktree() {
195
224
 
196
225
  act "$wt [branch: ${branch:-detached}]"
197
226
  if [ "$APPLY" = 1 ]; then
198
- if git -C "$REPO" worktree remove "${force_flag[@]}" "$wt" 2>/dev/null; then
227
+ # `${arr[@]+"${arr[@]}"}` rather than a plain `"${force_flag[@]}"`. Under
228
+ # `set -u`, bash before 4.4 — which includes the 3.2.57 that ships as
229
+ # /bin/bash on macOS, where this script mostly runs — treats an EMPTY array
230
+ # expansion as an unbound variable and aborts. The abort landed on the first
231
+ # removal candidate, so `--apply` exited 1 with no summary at all.
232
+ if git -C "$REPO" worktree remove ${force_flag[@]+"${force_flag[@]}"} "$wt" 2>/dev/null; then
199
233
  REMOVED=$((REMOVED + 1))
200
234
  if [ "$DELETE_BRANCHES" = 1 ] && [ -n "$branch" ] && ! is_env_branch "$branch"; then
201
235
  git -C "$REPO" branch -D "$branch" >/dev/null 2>&1 || true
@@ -232,24 +266,43 @@ while IFS= read -r line; do
232
266
  done < <(git -C "$REPO" worktree list --porcelain; echo)
233
267
 
234
268
  # Orphan directories under .claude/worktrees that git no longer tracks.
269
+ #
270
+ # This is the same "a failed read looks like a benign answer" hazard the status
271
+ # guards above fix, with a worse ending: the removal here is `rm -rf`, which
272
+ # bypasses `git worktree remove`'s own refusal to delete a dirty worktree. So
273
+ # the enumeration is done ONCE, up front, with its exit status checked. An empty
274
+ # result from a FAILED `git worktree list` would make `grep` match nothing, `!`
275
+ # invert to true, and a live registered worktree be deleted outright — and empty
276
+ # output from a killed git is the ordinary outcome of the very concurrency
277
+ # pressure this script exists to relieve. Nothing proven means nothing swept.
235
278
  wtroot="$REPO/.claude/worktrees"
236
279
  if [ -d "$wtroot" ]; then
237
- for d in "$wtroot"/*/; do
238
- d=${d%/}
239
- [ -d "$d" ] || continue
240
- if ! git -C "$REPO" worktree list --porcelain | grep -qF "worktree $d"; then
241
- if dir_age_ok "$d"; then
242
- ORPHANS=$((ORPHANS + 1))
243
- act "(orphan dir, not a registered worktree) $d"
244
- [ "$APPLY" = 1 ] && rm -rf "$d"
280
+ registered=$(git -C "$REPO" worktree list --porcelain 2>/dev/null)
281
+ registered_rc=$?
282
+ if [ "$registered_rc" -ne 0 ]; then
283
+ log "SKIP orphan sweep (git could not enumerate worktrees — nothing was proven)"
284
+ else
285
+ for d in "$wtroot"/*/; do
286
+ d=${d%/}
287
+ [ -d "$d" ] || continue
288
+ # `-x` anchors the whole line. A substring match let a registered
289
+ # `…/wt-280` mark a genuine orphan `…/wt-28` as registered forever; that
290
+ # direction only ever keeps too much, but the prefix collision is real and
291
+ # this repository has that collision class on record.
292
+ if ! printf '%s\n' "$registered" | grep -qxF "worktree $d"; then
293
+ if dir_age_ok "$d"; then
294
+ ORPHANS=$((ORPHANS + 1))
295
+ act "(orphan dir, not a registered worktree) $d"
296
+ [ "$APPLY" = 1 ] && rm -rf "$d"
297
+ fi
245
298
  fi
246
- fi
247
- done
299
+ done
300
+ fi
248
301
  fi
249
302
 
250
303
  log ""
251
304
  log "=== summary ==="
252
305
  log "removed (or would remove): $REMOVED orphan dirs: $ORPHANS"
253
- log "kept: $KEPT_DIRTY modified-tracked, $KEPT_UNPUSHED unpushed, $KEPT_UNTRACKED untracked-only, $KEPT_UNREACHABLE uncommitted-content, $KEPT_YOUNG too-young errors: $ERRORS"
306
+ log "kept: $KEPT_DIRTY modified-tracked, $KEPT_UNPUSHED unpushed, $KEPT_UNTRACKED untracked-only, $KEPT_UNREACHABLE uncommitted-content, $KEPT_YOUNG too-young, $KEPT_UNREADABLE unreadable errors: $ERRORS"
254
307
  [ "$APPLY" = 0 ] && log "(dry run — rerun with --apply to delete)"
255
308
  exit 0