@codyswann/lisa 4.73.4 → 4.73.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 (64) hide show
  1. package/README.md +13 -0
  2. package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +102 -3
  3. package/all/copy-overwrite/scripts/lisa-enforcement-freshness.mjs +3 -0
  4. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  5. package/dist/core/lisa-owned-hash-ledger.js +10 -0
  6. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  7. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  8. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  9. package/dist/core/upstream-evidence-manifest.js +17 -5
  10. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  11. package/package.json +4 -4
  12. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  14. package/plugins/lisa-agy/plugin.json +1 -1
  15. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  17. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  18. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-expo-agy/plugin.json +1 -1
  25. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  35. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  40. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  45. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails-agy/plugin.json +1 -1
  50. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  55. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  60. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  62. package/scripts/lisa-enforcement-fallback.sh +102 -3
  63. package/scripts/lisa-enforcement-freshness.mjs +3 -0
  64. package/scripts/two-channel-couplings.json +1 -1
package/package.json CHANGED
@@ -189,7 +189,7 @@
189
189
  "qs": "^6.16.0"
190
190
  },
191
191
  "name": "@codyswann/lisa",
192
- "version": "4.73.4",
192
+ "version": "4.73.5",
193
193
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
194
194
  "main": "dist/index.js",
195
195
  "exports": {
@@ -345,7 +345,7 @@
345
345
  "test": "tests"
346
346
  },
347
347
  "types": "./dist/index.d.ts",
348
- "lisaReleaseCommit": "1ee980d2b49cee63024ac8c221d0affcb26da1c5",
349
- "gitHead": "1ee980d2b49cee63024ac8c221d0affcb26da1c5",
350
- "lisaReleaseTag": "v4.73.4"
348
+ "lisaReleaseCommit": "c2f416b4787953f49a663a5d91d197041bca6ce9",
349
+ "gitHead": "c2f416b4787953f49a663a5d91d197041bca6ce9",
350
+ "lisaReleaseTag": "v4.73.5"
351
351
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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-cdk",
3
- "version": "4.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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-expo",
3
- "version": "4.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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.73.4",
3
+ "version": "4.73.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-openclaw",
3
- "version": "4.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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.73.4",
3
+ "version": "4.73.5",
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"
@@ -208,6 +208,103 @@ note_version() {
208
208
 
209
209
  plugin_tree_version=""
210
210
 
211
+ # Node cannot supervise its own stalled startup. Bash owns a live group anchor
212
+ # and an independent builtin-read timer instead. The real child Bash has its own
213
+ # $$, waits for group qualification before starting Node, and drains its OWN
214
+ # group. No remembered PID receives a later external signal. Its live anchor
215
+ # pins the group even after Node returns, until all descendants are terminated.
216
+ # Only this optional subprocess is bounded; enforcement below is unchanged.
217
+ run_optional_freshness() (
218
+ command -v mkfifo >/dev/null 2>&1 && command -v ps >/dev/null 2>&1 || exit 1
219
+ ps -o pid= -p "$$" >/dev/null 2>&1 || exit 1
220
+ # Bash 3.2 unwinds function locals before EXIT on an explicit exit inside
221
+ # command substitution. This function already isolates all state in a subshell.
222
+ scratch="" anchor="" scratch_identity="" current_identity="" helper_status=1
223
+ [ -n "$notice_temp_base" ] && notice_parent_chain_trusted "$notice_temp_base" || exit 1
224
+ scratch="$(umask 077 && mktemp -d "$notice_temp_base/lisa-freshness.XXXXXX")" || exit 1
225
+ case "$scratch" in "$notice_temp_base"/lisa-freshness.*) ;; *) exit 1 ;; esac
226
+ [ -d "$scratch" ] && [ ! -L "$scratch" ] && [ -O "$scratch" ] || exit 1
227
+ scratch_identity="$(stat -f '%d:%i:%Lp' "$scratch" 2>/dev/null)" ||
228
+ scratch_identity="$(stat -c '%d:%i:%a' "$scratch" 2>/dev/null)" || exit 1
229
+ [ "${scratch_identity##*:}" = 700 ] || exit 1
230
+ cleanup_diagnostic() {
231
+ if [ -n "$anchor" ]; then
232
+ printf 'stop\n' >&8
233
+ wait "$anchor" 2>/dev/null || true
234
+ fi
235
+ exec 8>&- 9>&-
236
+ current_identity="$(stat -f '%d:%i:%Lp' "$scratch" 2>/dev/null)" ||
237
+ current_identity="$(stat -c '%d:%i:%a' "$scratch" 2>/dev/null)" || current_identity=""
238
+ if [ "$current_identity" = "$scratch_identity" ] &&
239
+ [ -d "$scratch" ] && [ ! -L "$scratch" ] && [ -O "$scratch" ] &&
240
+ notice_parent_chain_trusted "$notice_temp_base"; then
241
+ rm -rf "$scratch"
242
+ fi
243
+ }
244
+ trap cleanup_diagnostic EXIT
245
+ trap 'exit 1' HUP INT TERM
246
+ mkfifo "$scratch/start" "$scratch/done" || exit 1
247
+ exec 8<>"$scratch/start" 9<>"$scratch/done" || exit 1
248
+ set -m
249
+ /bin/bash -c '
250
+ set +m
251
+ scratch="$1"
252
+ shift
253
+ # This live anchor qualifies its own group before launching any Node work.
254
+ # Native qualification must not race a separate parent/start countdown.
255
+ [ "$(ps -o pgid= -p "$$" 2>/dev/null | tr -d " ")" = "$$" ] || exit 1
256
+ (
257
+ node "$@" </dev/null >"$scratch/output" 2>/dev/null
258
+ printf "%s\n" "$?" >"$scratch/status"
259
+ printf "done\n" >&9
260
+ ) &
261
+ # Bash 3.2 accepts integer timeouts. One second leaves headroom beneath
262
+ # the two-second diagnostic ceiling without delaying real enforcement.
263
+ if read -r -t 1 -u 9 done && [ "$done" = done ]; then
264
+ printf "complete\n" >"$scratch/complete"
265
+ # Parent acceptance or its bounded absence both terminate the group.
266
+ read -r -t 1 -u 8 stop || true
267
+ fi
268
+ kill -KILL -- -"$$"
269
+ ' lisa-freshness "$scratch" "$@" &
270
+ anchor=$!
271
+ while [ ! -f "$scratch/status" ] && [ "$(jobs -pr)" = "$anchor" ]; do sleep 0.01; done
272
+ printf 'stop\n' >&8
273
+ wait "$anchor" 2>/dev/null || true
274
+ anchor=""
275
+ [ -f "$scratch/complete" ] && [ -f "$scratch/status" ] || exit 1
276
+ read -r helper_status <"$scratch/status"
277
+ [ "$helper_status" = 0 ] || exit 1
278
+ cat "$scratch/output"
279
+ )
280
+
281
+ # Do not promote even one partial fact. Successful exit plus a terminal protocol
282
+ # row and every requested guard result are required before globals are changed.
283
+ valid_freshness_result() {
284
+ local line key value seen="|" complete=0 count=0
285
+ while IFS= read -r line; do
286
+ [ "$complete" -eq 0 ] || return 1
287
+ case "$line" in *$'\t'*) ;; *) return 1 ;; esac
288
+ key="${line%%$'\t'*}"
289
+ value="${line#*$'\t'}"
290
+ case "$value" in ''|*$'\t'*|*$'\r'*) return 1 ;; esac
291
+ case "$seen" in *"|$key|"*) return 1 ;; esac
292
+ seen="$seen$key|"
293
+ case "$key" in
294
+ installed|applied|plugin|marketplace|channel)
295
+ [[ "$value" =~ ^[0-9]{1,6}\.[0-9]{1,6}\.[0-9]{1,6}([-+][A-Za-z0-9.-]{1,48})?$ ]] || return 1 ;;
296
+ channel_path) ;;
297
+ guard[0-7])
298
+ [ "${key#guard}" -lt "$guard_count" ] || return 1
299
+ case "$value" in matching|different|unknown) ;; *) return 1 ;; esac
300
+ count=$((count + 1)) ;;
301
+ complete) [ "$value" = 1 ] || return 1; complete=1 ;;
302
+ *) return 1 ;;
303
+ esac
304
+ done <<< "$1"
305
+ [ "$complete" -eq 1 ] && [ "$count" -eq "$guard_count" ]
306
+ }
307
+
211
308
  # Resolve once PER PROCESS at the existing lazy diagnostic boundary. A later
212
309
  # refusal in the same session gets fresh content evidence in its new process;
213
310
  # an already-noticed permitted call invokes neither Node nor a comparison.
@@ -217,13 +314,15 @@ resolve_vintages() {
217
314
  local config_dir="${CLAUDE_CONFIG_DIR-}"
218
315
  [ -n "$config_dir" ] || config_dir="${HOME-}/.claude"
219
316
  local helper="${BASH_SOURCE[0]%/*}/lisa-enforcement-freshness.mjs"
220
- local key value state_index
317
+ local key value state_index result
221
318
  local state_count=0
222
319
  while [ "$state_count" -lt "$guard_count" ]; do
223
320
  host_guard_states+=("unknown")
224
321
  state_count=$((state_count + 1))
225
322
  done
226
- if [ -f "$helper" ] && [ -r "$helper" ] && command -v node >/dev/null 2>&1; then
323
+ if [ -f "$helper" ] && [ -r "$helper" ] && command -v node >/dev/null 2>&1 &&
324
+ result="$(run_optional_freshness "$helper" "$repo_root" "$config_dir" "${guard_evidence_names[@]}" 2>/dev/null)" &&
325
+ valid_freshness_result "$result"; then
227
326
  while IFS=$'\t' read -r key value; do
228
327
  case "$key" in
229
328
  installed) installed_version="$value" ;;
@@ -237,7 +336,7 @@ resolve_vintages() {
237
336
  case "$value" in matching|different|unknown) host_guard_states[$state_index]="$value" ;; esac
238
337
  ;;
239
338
  esac
240
- done < <(node "$helper" "$repo_root" "$config_dir" "${guard_evidence_names[@]}" 2>/dev/null)
339
+ done <<< "$result"
241
340
  fi
242
341
  note_version "$installed_version" "$repo_root/node_modules/@codyswann/lisa/package.json"
243
342
  note_version "$plugin_tree_version" "$plugin_tree"
@@ -174,4 +174,7 @@ if (
174
174
  emit("channel_path", entry.installPath);
175
175
  }
176
176
  }
177
+ // Bash stages all facts until this terminal row and successful process exit;
178
+ // a killed or failed helper must not lend authority to its earlier output.
179
+ emit("complete", "1");
177
180
  }