@xhulz/nina 0.34.0 → 0.36.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.
- package/bin/nina.mjs +222 -48
- package/package.json +1 -1
- package/releases/0.35.0/core/GAPS.md +125 -0
- package/releases/0.35.0/core/answered.json +29 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/qa.md +2 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.35.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.35.0/core/tree/.claude/agents/architect.md +127 -0
- package/releases/0.35.0/core/tree/.claude/agents/dba.md +110 -0
- package/releases/0.35.0/core/tree/.claude/agents/devops.md +114 -0
- package/releases/0.35.0/core/tree/.claude/agents/implementer.md +156 -0
- package/releases/0.35.0/core/tree/.claude/agents/integration-tester.md +168 -0
- package/releases/0.35.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.35.0/core/tree/.claude/agents/qa.md +153 -0
- package/releases/0.35.0/core/tree/.claude/agents/reviewer.md +183 -0
- package/releases/0.35.0/core/tree/.claude/agents/secops.md +121 -0
- package/releases/0.35.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.35.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.35.0/core/tree/.claude/agents-overview.md +64 -0
- package/releases/0.35.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.35.0/core/tree/.claude/graph.md +75 -0
- package/releases/0.35.0/core/tree/.claude/patterns.md +213 -0
- package/releases/0.35.0/core/tree/.claude/pills/README.md +146 -0
- package/releases/0.35.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.35.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.35.0/core/tree/.claude/router.md +198 -0
- package/releases/0.35.0/core/tree/.claude/templates/integration.md +45 -0
- package/releases/0.35.0/core/tree/CLAUDE.md +161 -0
- package/releases/0.35.0/core/tree/scripts/cost-watch.mjs +18 -0
- package/releases/0.35.0/core/tree/scripts/edit-guard.mjs +16 -0
- package/releases/0.35.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.35.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.35.0/core/vocabulary.json +13 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.35.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.35.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/dba.md +50 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/patterns.md +19 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.35.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.35.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/devops.md +32 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.35.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.35.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.35.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.35.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.35.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.35.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.35.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.35.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.35.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.35.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.35.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.35.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.35.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/dba.md +39 -0
- package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.35.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.35.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/releases/0.36.0/core/GAPS.md +125 -0
- package/releases/0.36.0/core/answered.json +29 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/qa.md +2 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.36.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.36.0/core/tree/.claude/agents/architect.md +127 -0
- package/releases/0.36.0/core/tree/.claude/agents/dba.md +110 -0
- package/releases/0.36.0/core/tree/.claude/agents/devops.md +114 -0
- package/releases/0.36.0/core/tree/.claude/agents/implementer.md +156 -0
- package/releases/0.36.0/core/tree/.claude/agents/integration-tester.md +168 -0
- package/releases/0.36.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.36.0/core/tree/.claude/agents/qa.md +153 -0
- package/releases/0.36.0/core/tree/.claude/agents/reviewer.md +183 -0
- package/releases/0.36.0/core/tree/.claude/agents/secops.md +121 -0
- package/releases/0.36.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.36.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.36.0/core/tree/.claude/agents-overview.md +64 -0
- package/releases/0.36.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.36.0/core/tree/.claude/graph.md +75 -0
- package/releases/0.36.0/core/tree/.claude/patterns.md +213 -0
- package/releases/0.36.0/core/tree/.claude/pills/README.md +146 -0
- package/releases/0.36.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.36.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.36.0/core/tree/.claude/router.md +198 -0
- package/releases/0.36.0/core/tree/.claude/templates/integration.md +45 -0
- package/releases/0.36.0/core/tree/CLAUDE.md +161 -0
- package/releases/0.36.0/core/tree/scripts/cost-watch.mjs +18 -0
- package/releases/0.36.0/core/tree/scripts/edit-guard.mjs +16 -0
- package/releases/0.36.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.36.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.36.0/core/vocabulary.json +13 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.36.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.36.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/dba.md +50 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/patterns.md +19 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.36.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.36.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/devops.md +32 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.36.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.36.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.36.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.36.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.36.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.36.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.36.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.36.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.36.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.36.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.36.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.36.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.36.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/dba.md +39 -0
- package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.36.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.36.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/src/agentrun.mjs +89 -9
- package/src/commands/check.mjs +12 -8
- package/src/commands/compose.mjs +85 -9
- package/src/commands/export.mjs +8 -16
- package/src/commands/gate.mjs +19 -13
- package/src/commands/init.mjs +13 -4
- package/src/commands/learn.mjs +17 -18
- package/src/commands/pipeline.mjs +4 -4
- package/src/commands/release.mjs +21 -3
- package/src/commands/runs.mjs +14 -8
- package/src/commands/snapshot.mjs +63 -64
- package/src/commands/stats.mjs +98 -30
- package/src/commands/status.mjs +2 -2
- package/src/commands/upgrade.mjs +131 -25
- package/src/guard.mjs +7 -37
- package/src/paths.mjs +50 -1
- package/src/prices.mjs +7 -7
- package/src/store.mjs +158 -0
- package/src/transcripts.mjs +15 -4
- package/src/vocabulary.mjs +12 -1
- package/src/wiring.mjs +106 -41
package/src/wiring.mjs
CHANGED
|
@@ -205,21 +205,77 @@ function groupsFor(hooks, event) {
|
|
|
205
205
|
return Array.isArray(hooks[event]) ? hooks[event] : null;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/** Whether one hook command runs a hook's script, recognised by what it runs, not by its exact text. */
|
|
209
|
+
function runsCommand(x, h) {
|
|
210
|
+
const cmd = String(x?.command ?? '');
|
|
211
|
+
return cmd.includes(h.script) && (!h.mode || cmd.includes(h.mode));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Whether a settings group runs a hook's script. */
|
|
215
|
+
function runs(g, h) {
|
|
216
|
+
return Boolean(g) && typeof g === 'object' && Array.isArray(g.hooks) && g.hooks.some((x) => runsCommand(x, h));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** A matcher that reaches every tool: none, empty, or `*`. */
|
|
220
|
+
const everyTool = (m) => m === undefined || m === null || m === '' || m === '*';
|
|
221
|
+
|
|
222
|
+
/** A matcher this can read and rewrite: every tool, or a list of exact names. A regular expression is its owner's. */
|
|
223
|
+
const plainMatcher = (m) => everyTool(m) || (typeof m === 'string' && /^[A-Za-z0-9_|]+$/.test(m));
|
|
224
|
+
|
|
225
|
+
/** Whether two matchers reach a tool in common — unknown for a regular expression, taken as no. */
|
|
226
|
+
function overlaps(a, b) {
|
|
227
|
+
if (everyTool(a) || everyTool(b)) return true;
|
|
228
|
+
if (!plainMatcher(a) || !plainMatcher(b)) return false;
|
|
229
|
+
const names = new Set(a.split('|'));
|
|
230
|
+
return b.split('|').some((n) => names.has(n));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Whether two of these groups run on a tool they share, so the hook runs once per group there. */
|
|
234
|
+
const doubled = (groups) => groups.some((g, i) => groups.slice(i + 1).some((other) => overlaps(g.matcher, other.matcher)));
|
|
235
|
+
|
|
208
236
|
/**
|
|
209
237
|
* Whether settings already run a hook. Recognised by what the command runs, not by its exact text —
|
|
210
238
|
* a project may have written its own — and by a matcher that reaches every tool the hook needs.
|
|
211
239
|
*/
|
|
212
240
|
function covered(hooks, h) {
|
|
213
|
-
const groups = groupsFor(hooks, h.event) ?? [];
|
|
214
241
|
const need = h.matcher ? h.matcher.split('|') : [];
|
|
215
|
-
return
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
242
|
+
return (groupsFor(hooks, h.event) ?? []).some((g) => runs(g, h) && need.every((tool) => matcherReaches(g.matcher, tool)));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* The hooks a project runs, from both settings files merged by event — Claude Code runs both, so a hook
|
|
247
|
+
* kept in the local file counts. Every reader asks this one: `wire` used to read the shared file alone,
|
|
248
|
+
* and appended a second copy of each hook a project kept in its local file, which then ran twice.
|
|
249
|
+
*
|
|
250
|
+
* @param {string} target - The project directory.
|
|
251
|
+
* @param {(event: string) => boolean} [wanted] - Events whose malformed lists are worth a problem.
|
|
252
|
+
* @returns {Promise<{merged: Record<string, object[]>, problems: string[]}>} Each merged group says `from` which file.
|
|
253
|
+
*/
|
|
254
|
+
async function projectHooks(target, wanted = () => false) {
|
|
255
|
+
const merged = {};
|
|
256
|
+
const problems = [];
|
|
257
|
+
for (const rel of SETTINGS_FILES) {
|
|
258
|
+
const path = join(target, rel);
|
|
259
|
+
if (!existsSync(path)) continue;
|
|
260
|
+
let settings;
|
|
261
|
+
try {
|
|
262
|
+
settings = JSON.parse(await readFile(path, 'utf8'));
|
|
263
|
+
} catch (error) {
|
|
264
|
+
problems.push(`${rel} is not valid JSON — ${error.message}`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const shape = settings?.hooks;
|
|
268
|
+
if (shape === undefined || shape === null) continue;
|
|
269
|
+
if (typeof shape !== 'object' || Array.isArray(shape)) {
|
|
270
|
+
problems.push(`${rel} has a "hooks" that is not an object of event lists — no hook in it can run`);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
for (const [event, groups] of Object.entries(shape)) {
|
|
274
|
+
if (Array.isArray(groups)) (merged[event] ??= []).push(...groups.map((g) => (g && typeof g === 'object' ? { ...g, from: rel } : g)));
|
|
275
|
+
else if (wanted(event)) problems.push(`${rel}'s hooks.${event} is not a list — no hook in it can run`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return { merged, problems };
|
|
223
279
|
}
|
|
224
280
|
|
|
225
281
|
/** The command settings run for a hook, when they run one — the selftest runs it the same way. */
|
|
@@ -299,29 +355,16 @@ export async function missingWiring(target, shipped) {
|
|
|
299
355
|
}
|
|
300
356
|
const wanted = HOOKS.filter((h) => shipped.has(h.script));
|
|
301
357
|
if (wanted.length === 0) return out;
|
|
302
|
-
const merged =
|
|
303
|
-
|
|
304
|
-
const path = join(target, rel);
|
|
305
|
-
if (!existsSync(path)) continue;
|
|
306
|
-
let settings;
|
|
307
|
-
try {
|
|
308
|
-
settings = JSON.parse(await readFile(path, 'utf8'));
|
|
309
|
-
} catch (error) {
|
|
310
|
-
out.push(`${rel} is not valid JSON — ${error.message}`);
|
|
311
|
-
continue;
|
|
312
|
-
}
|
|
313
|
-
const shape = settings?.hooks;
|
|
314
|
-
if (shape === undefined || shape === null) continue;
|
|
315
|
-
if (typeof shape !== 'object' || Array.isArray(shape)) {
|
|
316
|
-
out.push(`${rel} has a "hooks" that is not an object of event lists — no hook in it can run`);
|
|
317
|
-
continue;
|
|
318
|
-
}
|
|
319
|
-
for (const [event, groups] of Object.entries(shape)) {
|
|
320
|
-
if (Array.isArray(groups)) (merged[event] ??= []).push(...groups);
|
|
321
|
-
else if (wanted.some((h) => h.event === event)) out.push(`${rel}'s hooks.${event} is not a list — no hook in it can run`);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
358
|
+
const { merged, problems } = await projectHooks(target, (event) => wanted.some((h) => h.event === event));
|
|
359
|
+
out.push(...problems);
|
|
324
360
|
for (const h of wanted) {
|
|
361
|
+
const running = (merged[h.event] ?? []).filter((g) => runs(g, h));
|
|
362
|
+
if (doubled(running)) {
|
|
363
|
+
out.push(
|
|
364
|
+
`${running.length} ${h.event} groups run \`${h.script}${h.mode ? ` ${h.mode}` : ''}\` for tools they share, so it runs once per group there — ` +
|
|
365
|
+
'`nina wire --apply` makes them one',
|
|
366
|
+
);
|
|
367
|
+
}
|
|
325
368
|
if (covered(merged, h)) continue;
|
|
326
369
|
out.push(
|
|
327
370
|
`.claude/settings.json has no ${h.event} hook${h.matcher ? ` for ${h.matcher}` : ''} running \`${h.script}${h.mode ? ` ${h.mode}` : ''}\` — without it ${h.why}`,
|
|
@@ -359,13 +402,9 @@ export async function staleHooks(target, shipped) {
|
|
|
359
402
|
* @returns {Promise<string|null>} Null when nothing is missing.
|
|
360
403
|
*/
|
|
361
404
|
export async function missingFragment(target, shipped) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
} catch {
|
|
366
|
-
// Absent or unreadable: everything is missing, and `missingWiring` says which.
|
|
367
|
-
}
|
|
368
|
-
const lacking = HOOKS.filter((h) => shipped.has(h.script) && !covered(settings?.hooks, h));
|
|
405
|
+
// Absent or unreadable files hold nothing: everything they would have held is missing, and `missingWiring` says why.
|
|
406
|
+
const { merged } = await projectHooks(target);
|
|
407
|
+
const lacking = HOOKS.filter((h) => shipped.has(h.script) && !covered(merged, h));
|
|
369
408
|
return lacking.length === 0 ? null : JSON.stringify({ hooks: settingsHooks(lacking) }, null, 2);
|
|
370
409
|
}
|
|
371
410
|
|
|
@@ -405,10 +444,36 @@ export async function applyWiring(target, shipped, { settings: editSettings = tr
|
|
|
405
444
|
if (readable) {
|
|
406
445
|
const hooks = settings.hooks ?? {};
|
|
407
446
|
const added = [];
|
|
447
|
+
const { merged } = await projectHooks(target);
|
|
408
448
|
for (const h of HOOKS.filter((h) => shipped.has(h.script))) {
|
|
409
|
-
|
|
410
|
-
(
|
|
411
|
-
|
|
449
|
+
const running = (merged[h.event] ?? []).filter((g) => runs(g, h));
|
|
450
|
+
if (covered(merged, h) && !doubled(running)) continue;
|
|
451
|
+
const named = `${h.event}${h.matcher ? ` (${h.matcher})` : ''} → ${h.script}${h.mode ? ` ${h.mode}` : ''}`;
|
|
452
|
+
if (running.length === 0) {
|
|
453
|
+
(hooks[h.event] ??= []).push(group(h));
|
|
454
|
+
added.push(named);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
// The groups that already run the script become one that reaches every tool it needs. A second group
|
|
458
|
+
// beside a narrower one — or two left as they were — runs it on the tools they share once per group, and
|
|
459
|
+
// the gate counts each of those events twice. A group in the local file, or one matched by a regular
|
|
460
|
+
// expression, is its owner's to change: said, and not doubled.
|
|
461
|
+
const foreign = running.find((g) => g.from !== '.claude/settings.json' || !plainMatcher(g.matcher));
|
|
462
|
+
if (foreign) {
|
|
463
|
+
problems.push(
|
|
464
|
+
`${foreign.from} runs ${h.script} for "${foreign.matcher ?? ''}" — make every group that runs it there one, reaching ${h.matcher ?? 'every tool'}; ` +
|
|
465
|
+
'another group beside it would run it twice',
|
|
466
|
+
);
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
const mine = (hooks[h.event] ?? []).filter((g) => runs(g, h));
|
|
470
|
+
const keep = mine.find((g) => everyTool(g.matcher)) ?? mine[0];
|
|
471
|
+
if (!everyTool(keep.matcher)) {
|
|
472
|
+
keep.matcher = [...new Set([...mine.flatMap((g) => g.matcher.split('|')), ...(h.matcher ? h.matcher.split('|') : [])])].join('|');
|
|
473
|
+
}
|
|
474
|
+
for (const g of mine) if (g !== keep) g.hooks = g.hooks.filter((x) => !runsCommand(x, h));
|
|
475
|
+
hooks[h.event] = hooks[h.event].filter((g) => !Array.isArray(g?.hooks) || g.hooks.length > 0);
|
|
476
|
+
added.push(`${named} (${mine.length > 1 ? `${mine.length} groups made one, ` : ''}reaching ${everyTool(keep.matcher) ? 'every tool' : keep.matcher})`);
|
|
412
477
|
}
|
|
413
478
|
// An old command, exactly as it was written, learns to say when its script cannot start, and how to
|
|
414
479
|
// install NINA as it is installed now.
|