@codyswann/lisa 4.4.3 → 4.4.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 (67) hide show
  1. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  2. package/dist/core/lisa-owned-hash-ledger.js +5 -0
  3. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  4. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  5. package/dist/core/upstream-evidence-manifest.js +8 -7
  6. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  7. package/expo/copy-overwrite/scripts/bdd/baseline.mjs +2 -2
  8. package/package.json +1 -1
  9. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  11. package/plugins/lisa/hooks/threshold-ratchet.mjs +17 -0
  12. package/plugins/lisa-agy/plugin.json +1 -1
  13. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  15. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  16. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-copilot/hooks/threshold-ratchet.mjs +17 -0
  20. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +17 -0
  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/plugins/src/base/hooks/threshold-ratchet.mjs +17 -0
  63. package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +17 -0
  64. package/scripts/plugin-parity-drift.mjs +66 -11
  65. package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +3 -3
  66. package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +17 -0
  67. package/typescript/copy-overwrite/scripts/check-verification-coverage.mjs +24 -2
@@ -29,10 +29,10 @@
29
29
  *
30
30
  * @module scripts/bdd/baseline
31
31
  */
32
- import { spawnSync } from "node:child_process";
33
32
  import * as fs from "node:fs";
34
33
  import * as path from "node:path";
35
34
 
35
+ import { boundedSpawnSync } from "../lib/bounded-spawn.mjs";
36
36
  import { byCodeUnit, declaredPlatforms } from "./contract.mjs";
37
37
  import { parseFeatureSource, scenarioIdsIn } from "./parse.mjs";
38
38
 
@@ -121,7 +121,7 @@ export function resolveGit() {
121
121
  function git(root, args) {
122
122
  const binary = resolveGit();
123
123
  if (!binary) return { ok: false, stdout: "" };
124
- const result = spawnSync(binary, [...args], {
124
+ const result = boundedSpawnSync(binary, [...args], {
125
125
  cwd: root,
126
126
  encoding: "utf8",
127
127
  maxBuffer: 64 * 1024 * 1024,
package/package.json CHANGED
@@ -145,7 +145,7 @@
145
145
  "zod-validation-error": "^4.0.0"
146
146
  },
147
147
  "name": "@codyswann/lisa",
148
- "version": "4.4.3",
148
+ "version": "4.4.5",
149
149
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
150
150
  "main": "dist/index.js",
151
151
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.5",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -92,6 +92,20 @@ const NO_RENAMES = "--no-renames";
92
92
 
93
93
  /**
94
94
  * Run git, returning stdout or null on any failure.
95
+ *
96
+ * The swallow is CORRECT here and is kept, because #2777 already made the
97
+ * consumer fail closed: a null change set reaches `threshold-ratchet: failing
98
+ * closed — an enforcement gate that cannot read the change set has not verified
99
+ * it`. That comment names the original defect exactly — "git() swallows every
100
+ * failure, so the ratchet passed exactly when it had no evidence" — so a killed
101
+ * child now joins the failures that already refuse. This call site needed the
102
+ * DEADLINE and nothing else.
103
+ *
104
+ * The deadline is written inline rather than imported. This file is
105
+ * materialized from `plugins/src/base/hooks/` into two stack lanes AND runs as
106
+ * an agent-time hook inside a plugin payload, which has no `./lib/` to import
107
+ * from — the same accommodation `preflight-secrets.mjs` makes, and the same one
108
+ * the entry guard below is written out for.
95
109
  * @param {string[]} args Git arguments
96
110
  * @param {string} [cwd] Working directory
97
111
  * @returns {string | null} Captured stdout, or null when git failed
@@ -102,6 +116,9 @@ function git(args, cwd) {
102
116
  cwd,
103
117
  encoding: "utf-8",
104
118
  stdio: ["ignore", "pipe", "ignore"],
119
+ // A hang detector, not a budget. `git` reached through PATH on macOS goes
120
+ // via Apple's xcrun shim, measured over 20s under load in #2887.
121
+ timeout: 30_000,
105
122
  });
106
123
  } catch {
107
124
  return null;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.5",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -92,6 +92,20 @@ const NO_RENAMES = "--no-renames";
92
92
 
93
93
  /**
94
94
  * Run git, returning stdout or null on any failure.
95
+ *
96
+ * The swallow is CORRECT here and is kept, because #2777 already made the
97
+ * consumer fail closed: a null change set reaches `threshold-ratchet: failing
98
+ * closed — an enforcement gate that cannot read the change set has not verified
99
+ * it`. That comment names the original defect exactly — "git() swallows every
100
+ * failure, so the ratchet passed exactly when it had no evidence" — so a killed
101
+ * child now joins the failures that already refuse. This call site needed the
102
+ * DEADLINE and nothing else.
103
+ *
104
+ * The deadline is written inline rather than imported. This file is
105
+ * materialized from `plugins/src/base/hooks/` into two stack lanes AND runs as
106
+ * an agent-time hook inside a plugin payload, which has no `./lib/` to import
107
+ * from — the same accommodation `preflight-secrets.mjs` makes, and the same one
108
+ * the entry guard below is written out for.
95
109
  * @param {string[]} args Git arguments
96
110
  * @param {string} [cwd] Working directory
97
111
  * @returns {string | null} Captured stdout, or null when git failed
@@ -102,6 +116,9 @@ function git(args, cwd) {
102
116
  cwd,
103
117
  encoding: "utf-8",
104
118
  stdio: ["ignore", "pipe", "ignore"],
119
+ // A hang detector, not a budget. `git` reached through PATH on macOS goes
120
+ // via Apple's xcrun shim, measured over 20s under load in #2887.
121
+ timeout: 30_000,
105
122
  });
106
123
  } catch {
107
124
  return null;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.4.3",
3
+ "version": "4.4.5",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -92,6 +92,20 @@ const NO_RENAMES = "--no-renames";
92
92
 
93
93
  /**
94
94
  * Run git, returning stdout or null on any failure.
95
+ *
96
+ * The swallow is CORRECT here and is kept, because #2777 already made the
97
+ * consumer fail closed: a null change set reaches `threshold-ratchet: failing
98
+ * closed — an enforcement gate that cannot read the change set has not verified
99
+ * it`. That comment names the original defect exactly — "git() swallows every
100
+ * failure, so the ratchet passed exactly when it had no evidence" — so a killed
101
+ * child now joins the failures that already refuse. This call site needed the
102
+ * DEADLINE and nothing else.
103
+ *
104
+ * The deadline is written inline rather than imported. This file is
105
+ * materialized from `plugins/src/base/hooks/` into two stack lanes AND runs as
106
+ * an agent-time hook inside a plugin payload, which has no `./lib/` to import
107
+ * from — the same accommodation `preflight-secrets.mjs` makes, and the same one
108
+ * the entry guard below is written out for.
95
109
  * @param {string[]} args Git arguments
96
110
  * @param {string} [cwd] Working directory
97
111
  * @returns {string | null} Captured stdout, or null when git failed
@@ -102,6 +116,9 @@ function git(args, cwd) {
102
116
  cwd,
103
117
  encoding: "utf-8",
104
118
  stdio: ["ignore", "pipe", "ignore"],
119
+ // A hang detector, not a budget. `git` reached through PATH on macOS goes
120
+ // via Apple's xcrun shim, measured over 20s under load in #2887.
121
+ timeout: 30_000,
105
122
  });
106
123
  } catch {
107
124
  return null;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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.4.3",
3
+ "version": "4.4.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"
@@ -92,6 +92,20 @@ const NO_RENAMES = "--no-renames";
92
92
 
93
93
  /**
94
94
  * Run git, returning stdout or null on any failure.
95
+ *
96
+ * The swallow is CORRECT here and is kept, because #2777 already made the
97
+ * consumer fail closed: a null change set reaches `threshold-ratchet: failing
98
+ * closed — an enforcement gate that cannot read the change set has not verified
99
+ * it`. That comment names the original defect exactly — "git() swallows every
100
+ * failure, so the ratchet passed exactly when it had no evidence" — so a killed
101
+ * child now joins the failures that already refuse. This call site needed the
102
+ * DEADLINE and nothing else.
103
+ *
104
+ * The deadline is written inline rather than imported. This file is
105
+ * materialized from `plugins/src/base/hooks/` into two stack lanes AND runs as
106
+ * an agent-time hook inside a plugin payload, which has no `./lib/` to import
107
+ * from — the same accommodation `preflight-secrets.mjs` makes, and the same one
108
+ * the entry guard below is written out for.
95
109
  * @param {string[]} args Git arguments
96
110
  * @param {string} [cwd] Working directory
97
111
  * @returns {string | null} Captured stdout, or null when git failed
@@ -102,6 +116,9 @@ function git(args, cwd) {
102
116
  cwd,
103
117
  encoding: "utf-8",
104
118
  stdio: ["ignore", "pipe", "ignore"],
119
+ // A hang detector, not a budget. `git` reached through PATH on macOS goes
120
+ // via Apple's xcrun shim, measured over 20s under load in #2887.
121
+ timeout: 30_000,
105
122
  });
106
123
  } catch {
107
124
  return null;