@xhulz/nina 0.33.0 → 0.35.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/README.md +4 -2
- package/bin/nina.mjs +219 -48
- package/package.json +1 -1
- package/releases/0.34.0/core/GAPS.md +125 -0
- package/releases/0.34.0/core/answered.json +29 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/qa.md +2 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.34.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.34.0/core/tree/.claude/agents/architect.md +127 -0
- package/releases/0.34.0/core/tree/.claude/agents/dba.md +110 -0
- package/releases/0.34.0/core/tree/.claude/agents/devops.md +114 -0
- package/releases/0.34.0/core/tree/.claude/agents/implementer.md +156 -0
- package/releases/0.34.0/core/tree/.claude/agents/integration-tester.md +168 -0
- package/releases/0.34.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.34.0/core/tree/.claude/agents/qa.md +148 -0
- package/releases/0.34.0/core/tree/.claude/agents/reviewer.md +183 -0
- package/releases/0.34.0/core/tree/.claude/agents/secops.md +121 -0
- package/releases/0.34.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.34.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.34.0/core/tree/.claude/agents-overview.md +64 -0
- package/releases/0.34.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.34.0/core/tree/.claude/graph.md +75 -0
- package/releases/0.34.0/core/tree/.claude/patterns.md +213 -0
- package/releases/0.34.0/core/tree/.claude/pills/README.md +146 -0
- package/releases/0.34.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.34.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.34.0/core/tree/.claude/router.md +198 -0
- package/releases/0.34.0/core/tree/.claude/templates/integration.md +45 -0
- package/releases/0.34.0/core/tree/CLAUDE.md +161 -0
- package/releases/0.34.0/core/tree/scripts/cost-watch.mjs +18 -0
- package/releases/0.34.0/core/tree/scripts/edit-guard.mjs +16 -0
- package/releases/0.34.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.34.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.34.0/core/vocabulary.json +13 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.34.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.34.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/dba.md +50 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/patterns.md +19 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.34.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.34.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/devops.md +32 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.34.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.34.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.34.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.34.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.34.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.34.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.34.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.34.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.34.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.34.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.34.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.34.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.34.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.34.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.34.0/surfaces/prisma/tree/.claude/agents/dba.md +39 -0
- package/releases/0.34.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.34.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.34.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.34.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.34.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.34.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- 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/src/agentrun.mjs +91 -12
- package/src/commands/check.mjs +12 -8
- package/src/commands/compose.mjs +85 -9
- package/src/commands/export.mjs +9 -7
- package/src/commands/init.mjs +13 -4
- package/src/commands/langfuse.mjs +25 -10
- package/src/commands/learn.mjs +12 -3
- package/src/commands/release.mjs +21 -3
- package/src/commands/stats.mjs +64 -12
- package/src/commands/upgrade.mjs +131 -25
- package/src/guard.mjs +7 -37
- package/src/langfuse.mjs +31 -11
- package/src/paths.mjs +50 -1
- package/src/prices.mjs +7 -7
- package/src/transcripts.mjs +27 -1
- package/src/vocabulary.mjs +12 -1
- package/src/wiring.mjs +106 -41
package/src/transcripts.mjs
CHANGED
|
@@ -632,7 +632,7 @@ async function attachAgentDetail(projectDir, dispatches) {
|
|
|
632
632
|
if (
|
|
633
633
|
run.agent_read_bytes === size &&
|
|
634
634
|
!('resumes' in run) &&
|
|
635
|
-
[...records, ...later].every((r) => settled(r) && 'round' in r && 'lessons_read' in r && 'tokens' in r && 'files_touched' in r && 'effort' in r && 'turns' in r)
|
|
635
|
+
[...records, ...later].every((r) => settled(r) && 'round' in r && 'lessons_read' in r && 'tokens' in r && 'files_touched' in r && 'effort' in r && 'turns' in r && 'prompt_chars' in r)
|
|
636
636
|
) {
|
|
637
637
|
continue;
|
|
638
638
|
}
|
|
@@ -662,6 +662,8 @@ async function attachAgentDetail(projectDir, dispatches) {
|
|
|
662
662
|
written: new Set(),
|
|
663
663
|
/** The tool calls the round made, by id: over its turns, how many calls each turn sent at once. */
|
|
664
664
|
calls: new Set(),
|
|
665
|
+
/** How long the prompt that opened the round was, in characters; never the prompt. */
|
|
666
|
+
promptChars: null,
|
|
665
667
|
});
|
|
666
668
|
const rounds = [fresh()];
|
|
667
669
|
const roundOf = roundsOf();
|
|
@@ -681,6 +683,14 @@ async function attachAgentDetail(projectDir, dispatches) {
|
|
|
681
683
|
}
|
|
682
684
|
}
|
|
683
685
|
const round = rounds[n - 1];
|
|
686
|
+
if (round.promptChars === null && line.includes('"type":"user"')) {
|
|
687
|
+
try {
|
|
688
|
+
const said = promptOf(JSON.parse(line), n);
|
|
689
|
+
if (said !== null) round.promptChars = said.length;
|
|
690
|
+
} catch {
|
|
691
|
+
// A torn line is not the prompt.
|
|
692
|
+
}
|
|
693
|
+
}
|
|
684
694
|
const hasSkill = line.includes('"Skill"');
|
|
685
695
|
const hasHandback = line.includes('SubagentHandback');
|
|
686
696
|
for (const m of line.matchAll(/"type":"tool_use","id":"([^"]+)"/g)) round.calls.add(m[1]);
|
|
@@ -770,6 +780,7 @@ async function attachAgentDetail(projectDir, dispatches) {
|
|
|
770
780
|
record.tool_calls = round.calls.size;
|
|
771
781
|
record.context_start = shape.start;
|
|
772
782
|
record.context_peak = shape.peak;
|
|
783
|
+
record.prompt_chars = round.promptChars;
|
|
773
784
|
record.usage_model = spent.model;
|
|
774
785
|
record.effort = spent.effort;
|
|
775
786
|
record.files_touched = round.written.size;
|
|
@@ -802,6 +813,21 @@ async function attachAgentDetail(projectDir, dispatches) {
|
|
|
802
813
|
}
|
|
803
814
|
}
|
|
804
815
|
|
|
816
|
+
/**
|
|
817
|
+
* What a round was told, from one transcript row, or null when the row is not it. The dispatch's prompt
|
|
818
|
+
* opens the first round; a later round opens with the message that resumed the run, which Claude Code
|
|
819
|
+
* marks as meta, while a meta row in the first round is a reminder. The snapshot measures it and the
|
|
820
|
+
* Langfuse export sends it, so both read it here.
|
|
821
|
+
*
|
|
822
|
+
* @param {object} row - A parsed transcript row.
|
|
823
|
+
* @param {number} round - The round the row is in, from 1.
|
|
824
|
+
* @returns {string|null}
|
|
825
|
+
*/
|
|
826
|
+
export function promptOf(row, round) {
|
|
827
|
+
const content = row?.message?.content;
|
|
828
|
+
return row?.type === 'user' && (round > 1 || !row.isMeta) && typeof content === 'string' ? content : null;
|
|
829
|
+
}
|
|
830
|
+
|
|
805
831
|
/**
|
|
806
832
|
* How a round spent its context: how many turns it took, and how large the context each turn re-read was
|
|
807
833
|
* when the round began and at its largest. Every turn is billed the whole context again, so a round that
|
package/src/vocabulary.mjs
CHANGED
|
@@ -16,6 +16,17 @@
|
|
|
16
16
|
import { readFileSync } from 'node:fs';
|
|
17
17
|
import { join } from 'node:path';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* A vocabulary name: capitals, digits and `_`, from a letter — `{{S3_BUCKET}}` as much as `{{OWNER}}`. Every
|
|
21
|
+
* reader of a placeholder reads it with this one grammar. Compose took any name the profile declared while
|
|
22
|
+
* `check`, `init` and `upgrade` looked only for capitals and `_`, so `{{S3_BUCKET}}` was reported as declared
|
|
23
|
+
* and referenced by nothing, and deleting it on that advice composed the placeholder raw, with nobody saying so.
|
|
24
|
+
*/
|
|
25
|
+
export const NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
26
|
+
|
|
27
|
+
/** A placeholder in a text, its name captured. */
|
|
28
|
+
export const PLACEHOLDER = /\{\{([A-Z][A-Z0-9_]*)\}\}/g;
|
|
29
|
+
|
|
19
30
|
/**
|
|
20
31
|
* The defaults a layer root supplies, name → value. Anything that is not a string under an
|
|
21
32
|
* upper-case name is ignored rather than trusted: a default reaches every project that pins it.
|
|
@@ -26,7 +37,7 @@ import { join } from 'node:path';
|
|
|
26
37
|
export function defaultVocabulary(layerRoot) {
|
|
27
38
|
try {
|
|
28
39
|
const parsed = JSON.parse(readFileSync(join(layerRoot, 'core', 'vocabulary.json'), 'utf8'));
|
|
29
|
-
return Object.fromEntries(Object.entries(parsed).filter(([name, value]) =>
|
|
40
|
+
return Object.fromEntries(Object.entries(parsed).filter(([name, value]) => NAME.test(name) && typeof value === 'string'));
|
|
30
41
|
} catch {
|
|
31
42
|
return {};
|
|
32
43
|
}
|
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.
|