@xhulz/nina 0.79.0 → 0.81.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 +3 -0
- package/package.json +1 -1
- package/releases/0.80.0/core/GAPS.md +125 -0
- package/releases/0.80.0/core/answered.json +128 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.80.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.80.0/core/tree/.claude/agents/architect.md +140 -0
- package/releases/0.80.0/core/tree/.claude/agents/dba.md +123 -0
- package/releases/0.80.0/core/tree/.claude/agents/design-reviewer.md +82 -0
- package/releases/0.80.0/core/tree/.claude/agents/devops.md +122 -0
- package/releases/0.80.0/core/tree/.claude/agents/implementer.md +208 -0
- package/releases/0.80.0/core/tree/.claude/agents/integration-tester.md +174 -0
- package/releases/0.80.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.80.0/core/tree/.claude/agents/qa.md +154 -0
- package/releases/0.80.0/core/tree/.claude/agents/reviewer.md +191 -0
- package/releases/0.80.0/core/tree/.claude/agents/secops.md +124 -0
- package/releases/0.80.0/core/tree/.claude/agents/solidity-auditor.md +130 -0
- package/releases/0.80.0/core/tree/.claude/agents/solidity-dev.md +127 -0
- package/releases/0.80.0/core/tree/.claude/agents-overview.md +65 -0
- package/releases/0.80.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.80.0/core/tree/.claude/graph.md +79 -0
- package/releases/0.80.0/core/tree/.claude/patterns.md +256 -0
- package/releases/0.80.0/core/tree/.claude/pills/README.md +150 -0
- package/releases/0.80.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.80.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.80.0/core/tree/.claude/router.md +224 -0
- package/releases/0.80.0/core/tree/.claude/templates/integration.md +48 -0
- package/releases/0.80.0/core/tree/CLAUDE.md +167 -0
- package/releases/0.80.0/core/tree/scripts/cost-watch.mjs +27 -0
- package/releases/0.80.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.80.0/core/tree/scripts/harness-check.mjs +84 -0
- package/releases/0.80.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.80.0/core/vocabulary.json +15 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.80.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.80.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.80.0/surfaces/d1/tree/.claude/agents/dba.md +15 -0
- package/releases/0.80.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.80.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.80.0/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.80.0/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.80.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.80.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.80.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.80.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.80.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.80.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.80.0/surfaces/edge-cf/tree/CLAUDE.md +29 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.80.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.80.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.80.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.80.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.80.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.80.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.80.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.80.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.80.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.80.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.80.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.80.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.80.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.80.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.80.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.80.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.80.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.80.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.80.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.80.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/releases/0.81.0/core/GAPS.md +125 -0
- package/releases/0.81.0/core/answered.json +128 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.81.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.81.0/core/tiers.json +5 -0
- package/releases/0.81.0/core/tree/.claude/agents/architect.md +140 -0
- package/releases/0.81.0/core/tree/.claude/agents/dba.md +123 -0
- package/releases/0.81.0/core/tree/.claude/agents/design-reviewer.md +82 -0
- package/releases/0.81.0/core/tree/.claude/agents/devops.md +122 -0
- package/releases/0.81.0/core/tree/.claude/agents/implementer.md +208 -0
- package/releases/0.81.0/core/tree/.claude/agents/integration-tester.md +174 -0
- package/releases/0.81.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.81.0/core/tree/.claude/agents/qa.md +154 -0
- package/releases/0.81.0/core/tree/.claude/agents/reviewer.md +191 -0
- package/releases/0.81.0/core/tree/.claude/agents/secops.md +124 -0
- package/releases/0.81.0/core/tree/.claude/agents/solidity-auditor.md +130 -0
- package/releases/0.81.0/core/tree/.claude/agents/solidity-dev.md +127 -0
- package/releases/0.81.0/core/tree/.claude/agents-overview.md +65 -0
- package/releases/0.81.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.81.0/core/tree/.claude/graph.md +79 -0
- package/releases/0.81.0/core/tree/.claude/patterns.md +256 -0
- package/releases/0.81.0/core/tree/.claude/pills/README.md +150 -0
- package/releases/0.81.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.81.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.81.0/core/tree/.claude/router.md +224 -0
- package/releases/0.81.0/core/tree/.claude/templates/integration.md +48 -0
- package/releases/0.81.0/core/tree/CLAUDE.md +167 -0
- package/releases/0.81.0/core/tree/scripts/cost-watch.mjs +27 -0
- package/releases/0.81.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.81.0/core/tree/scripts/harness-check.mjs +84 -0
- package/releases/0.81.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.81.0/core/vocabulary.json +18 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.81.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.81.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.81.0/surfaces/d1/tree/.claude/agents/dba.md +15 -0
- package/releases/0.81.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.81.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.81.0/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.81.0/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.81.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.81.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.81.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.81.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.81.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.81.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.81.0/surfaces/edge-cf/tree/CLAUDE.md +29 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.81.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.81.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.81.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.81.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.81.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.81.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.81.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.81.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.81.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.81.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.81.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.81.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.81.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.81.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.81.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.81.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.81.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.81.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.81.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.81.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/src/commands/check.mjs +4 -2
- package/src/commands/compose.mjs +58 -4
- package/src/commands/eval.mjs +35 -24
- package/src/commands/init.mjs +14 -4
- package/src/commands/status.mjs +11 -1
- package/src/commands/upgrade.mjs +17 -2
- package/src/vocabulary.mjs +76 -2
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Agent Router
|
|
2
|
+
|
|
3
|
+
Decides which subagent (or chain) to dispatch for a given task. Subagent definitions live in `.claude/agents/`.
|
|
4
|
+
|
|
5
|
+
<!-- nina:slot project.1 track-summary -->
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Decision tree
|
|
10
|
+
|
|
11
|
+
The stages and edges are in `.claude/graph.md`. What follows is this project's own way of sizing a
|
|
12
|
+
task into a chain over them.
|
|
13
|
+
|
|
14
|
+
<!-- nina:slot project.2 decision-tree -->
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Track flow
|
|
19
|
+
|
|
20
|
+
<!-- nina:slot project.3 track-flow-diagram -->
|
|
21
|
+
|
|
22
|
+
The stages, and the edges between them, are in `.claude/graph.md` — the one place they are stated. Every gate the diff triggers runs beside the reviewer, and `qa` goes out once all of them approved. The reviewer's `Gates` line names the gates the diff triggers: send any you did not. When the architect's report says `Design review: needed`, says nothing of it, or the change builds a check, scanner, parser or filter, send the spec to the `design-reviewer` before the implementer, once per spec, before its first step: a design flaw found in the spec costs one correction, found in the diff a whole round.
|
|
23
|
+
|
|
24
|
+
**Every loop has a cap.** Before dispatching a loop-back, count the rounds the SAME issue has already made on that edge. At the cap `.claude/graph.md` gives it, do not dispatch again: stop and hand {{OWNER}} the report from every round. A third attempt at a fix that failed twice is rarely different from the second, each round costs minutes to hours<!-- nina:why -->, and until this rule existed nothing in the pipeline could stop a loop at all<!-- /nina:why -->. A different issue on the same edge starts its own count. A stage that sends work back names each issue on the `ISSUES` line under its verdict; when you dispatch a round — the fix, and the check of the fix — copy that line into both dispatches, so the stage that checks can keep the id of an issue that is still open. That id is what your count is of.
|
|
25
|
+
|
|
26
|
+
Where the project wires the **loop gate** (`scripts/loop-gate.mjs`, run by hooks — `nina wire` puts them
|
|
27
|
+
in place), the cap is held for you. It counts a round when a dispatch acts on a loop-back a stage
|
|
28
|
+
declared on its `VERDICT` line — per issue while every round's reports named theirs on the `ISSUES` line,
|
|
29
|
+
per loop from the first that did not until it closes — whichever stage the fix went to; several dispatches
|
|
30
|
+
acting on the same verdicts are one round; and each message from {{OWNER}} gives every open loop one round
|
|
31
|
+
more — your own `AskUserQuestion` does not. A loop closes when a review launched after the latest fix passes
|
|
32
|
+
with no rejection beside it — a resumed one too, and a pass needs no `ISSUES` line — or when the next stage,
|
|
33
|
+
sent out after the last review, passes. Work run side by side shares one count per stage and verdict: a rejection still open in
|
|
34
|
+
one task keeps another's pass from closing it. The dispatch past the cap goes to {{OWNER}} to confirm. If they refuse it, do
|
|
35
|
+
what the graph says — hand them each round's report and ask how to proceed — and do not route around the
|
|
36
|
+
refusal by resuming the fixer or making the fix yourself.
|
|
37
|
+
|
|
38
|
+
The gate trusts the ids it is given: an issue renamed between rounds starts its count over, so an edge
|
|
39
|
+
still goes to {{OWNER}} once it has gone round more than twice its cap with no approval between. It does
|
|
40
|
+
not see a fix you make without a subagent — so keep your own count as well, gate or no gate. When you
|
|
41
|
+
dispatch a second round on an edge, say "round 2 of max 2 on <edge>" in the dispatch itself, so the
|
|
42
|
+
count is in the transcript for whoever reads it next. After a compaction the gate hands you its open loops
|
|
43
|
+
and the documents to read again, and a new session begins with the loops the one before it left open, said on
|
|
44
|
+
its first prompt; `nina gate --status` lists them, and what closes each, at any time.
|
|
45
|
+
|
|
46
|
+
### Milestone gate
|
|
47
|
+
|
|
48
|
+
**secops** is a milestone gate, not a per-sub-step stage: when the LAST sub-step of a numbered set (`6.*`)
|
|
49
|
+
or phase passes qa, dispatch it beside devops to audit the whole assembled surface. The set is not done
|
|
50
|
+
until it returns `SECURE`; a `BLOCKED` goes back to the architect or implementer, then to a re-audit.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Rules
|
|
55
|
+
<!-- nina:slot db.1 -->
|
|
56
|
+
<!-- nina:slot integrations.1 -->
|
|
57
|
+
<!-- nina:slot blockchain.1 -->
|
|
58
|
+
|
|
59
|
+
### Planner only for ambiguous, multi-step, or multi-package work
|
|
60
|
+
If the task fits in one head and lives in a single package, skip to architect (or implementer for trivial things).
|
|
61
|
+
One package is not one step, though: the architect still splits a long file list into steps (see *A spec's steps are passes of their own*).
|
|
62
|
+
|
|
63
|
+
### Architect output is a spec, not code
|
|
64
|
+
Architect produces a TS spec; implementer consumes the spec; they do not re-read the original user message.
|
|
65
|
+
|
|
66
|
+
### A chain with no architect: the dispatch is the spec
|
|
67
|
+
When a chain starts at the implementer, your dispatch is its spec: the goal, the files it may touch and
|
|
68
|
+
what must hold when it is done. The reviewer reviews against it and asks none of what only an architect's
|
|
69
|
+
spec carries — an Obsolescence list, a preview-deploy plan, a skill citation, integration premises. A
|
|
70
|
+
change that needs one of those needs an architect. Say in it whether the change touches a critical path
|
|
71
|
+
(`CLAUDE.md` § *Critical paths*): one that touches none, and builds no check whose refusing is the feature, is a
|
|
72
|
+
simple change, and the implementer leaves its tests' mutations to qa rather than running each twice.
|
|
73
|
+
|
|
74
|
+
### A spec is corrected in place
|
|
75
|
+
A spec sent back is corrected where it is wrong; new work comes as a new step file or spec. Never ask for
|
|
76
|
+
a `Revision N` section, and correct a spec yourself only in place, searching it and its steps for what you contradict. Point a dispatch at the sections and steps
|
|
77
|
+
that changed, by number: a history at a spec's head is read first by every stage and applies to
|
|
78
|
+
nothing.<!-- nina:why --> The architect was told to correct in place, and the
|
|
79
|
+
orchestrator went on asking for revisions. The first new project's second spike spec opened with four
|
|
80
|
+
revision sections, one of them written by the orchestrator, and every dispatch told the stage to read them
|
|
81
|
+
first. Its first spec reached an eighth revision, which had become the way new work was asked for.<!-- /nina:why -->
|
|
82
|
+
|
|
83
|
+
### A spike answers one question
|
|
84
|
+
A spike is an experiment: it answers a question about a service, a library or the data before anything is
|
|
85
|
+
designed on it, and its code is evidence, kept in a directory of its own outside the product's packages.
|
|
86
|
+
The architect writes a spike plan, one page, not a spec: the question, what to run and observe, the
|
|
87
|
+
answer that settles it, with the run that prints each token that would refuse it, and when to stop. The
|
|
88
|
+
reviewer checks that it measures what it says it measures.
|
|
89
|
+
No qa, devops or secops. A plan in steps runs them as a spec's (§ *A spec's steps are passes of their own*), without qa:
|
|
90
|
+
a step that builds on another goes out once every review of that one approved, whatever the plan says. Its plan is
|
|
91
|
+
corrected at most twice, counting a correction you make in place; past that, or when its answer raises a new
|
|
92
|
+
question, stop and ask {{OWNER}}: a new question is a new spike, and a spike revised past its question is
|
|
93
|
+
the product being designed without a spec.
|
|
94
|
+
|
|
95
|
+
### Reviewer audits; QA runs tests
|
|
96
|
+
Reviewer runs `{{TYPECHECK_CMD}}` / `{{LINT_CMD}}` (and `{{BUILD_CMD}}` for frontend) and verifies clean, confirms guardrails ran, but **does not run vitest**. QA runs vitest once after approval.
|
|
97
|
+
|
|
98
|
+
### A stage that returns no verdict
|
|
99
|
+
A report with no `VERDICT` line, a run that stopped, or one out of context is not a pass. Resume it once
|
|
100
|
+
with `SendMessage` for its report; failing that, dispatch the stage again, saying what the first run left
|
|
101
|
+
in the tree. Nothing builds on its work until a verdict does.
|
|
102
|
+
|
|
103
|
+
### A round of work goes to a fresh run
|
|
104
|
+
A resumed run is billed its whole history again on every turn. Resume one only for something short: its missing report, or a re-check of a few files. A fix, a revised spec or a re-run of flows goes to a new run of the stage, dispatched with what it needs: the spec's path, the findings with their `ISSUES` line, and the files and probes they name.<!-- nina:why --> In the project this was learned in, a resumed fix began at a 526k-token context and re-read 60M tokens, twice a first round, and resumed rounds held three quarters of everything the pipeline read.<!-- /nina:why -->
|
|
105
|
+
|
|
106
|
+
### A dispatch is named for whoever watches
|
|
107
|
+
The `description` of a dispatch, and the `summary` of a message resuming a run, are what {{OWNER}} reads beside each agent at work, in Claude Code and in `nina dashboard`, where a task takes its first dispatch's name. Say what the agent will do, in words someone who has not read the plan understands, then the step's id: `Fix the export spec · M2 15b`, not `M2 15b/15c spec fix`. The words come first, since a long one is cut at its end; the whole stays near eight words.<!-- nina:why --> In the two projects this was learned in, the descriptions were the plan's ids — `M2 15b/15c spec fix`, `10e round 2: controls and rows` — and the owner, watching the agents at work, could not tell what any of them was doing.<!-- /nina:why -->
|
|
108
|
+
|
|
109
|
+
### Notes ride with the work
|
|
110
|
+
A report's **Notes** send nothing back (Hard Rule #20). Carry them into the next dispatch of the same work — the fix round when there is one, else the next step's spec — and list those still open when you report the step to {{OWNER}}. A rejection whose every issue is a note goes back to the stage that gave it, to give its verdict again under that rule, not to a fix.
|
|
111
|
+
|
|
112
|
+
### A report that sends work two ways
|
|
113
|
+
When one report names issues for the architect and for the implementer, the architect goes first, and the
|
|
114
|
+
implementer fixes against the corrected spec.
|
|
115
|
+
|
|
116
|
+
### Pipeline is not sacred
|
|
117
|
+
If reviewer finds a design flaw, loop back to the architect. Don't paper over with implementation hacks.
|
|
118
|
+
|
|
119
|
+
### Plugin skills are part of the pipeline
|
|
120
|
+
The mandatory triggers are the table in `CLAUDE.md` and each spec's own § *Skills you MUST consult*; every
|
|
121
|
+
stage invokes them through the `Skill` tool. The architect cites which skill informed the spec, and the
|
|
122
|
+
reviewer rejects a spec touching a surface with a mandatory skill that cites none and says nothing of why.
|
|
123
|
+
|
|
124
|
+
### Devops owns the deploy
|
|
125
|
+
Invoke **devops** after **qa PASS** on any step that changes a deployed surface (API, frontend, schema, deploy config, secrets, platform bindings). It is the stage that executes Hard Rule #14 — the reviewer only checks that the spec *has* a preview-deploy plan. Skip it for steps that touch only tests, docs, or the harness, and while the project has no preview target yet. **Preview and staging it deploys on its own; production needs an explicit go from {{OWNER}} for that specific change, quoted in the dispatch.**
|
|
126
|
+
<!-- nina:slot frontend.2 -->
|
|
127
|
+
|
|
128
|
+
### Look at every loop-back for a lesson
|
|
129
|
+
|
|
130
|
+
When a stage loops back (qa → implementer on a test failure, reviewer rejects a diff, a gate blocks) **or** the user corrects something, the orchestrator asks one question: **would this happen again?** If it would, the lesson goes into a pill under `.claude/pills/<role>/` (or `shared/` if it spans roles) so the responsible agent does not repeat it. If it would not — a typo, a flake, a one-off — say so in one line and move on. The question is not optional; the pill is its answer when the answer is yes. <!-- nina:why -->The rule used to be "a pill on every loop-back", and it was followed 3% of the time. <!-- /nina:why -->A rule that demands a lesson from a typo trains everyone to skip the ones that were lessons. `harness:check` watches the outcome<!-- nina:why --> instead of the ritual<!-- /nina:why --> — a role sent back three times since its newest lesson is reported every turn until one is written (`nina learn`). Skip it only if the lesson is really a code convention (→ `patterns.md`/`CLAUDE.md`, through `.nina/project/tree/`) or a library premise (→ `integrations/<lib>.md`): write it there. If the lesson already has a pill, do **not** write a second one — increment its `occurrences` and set `last_seen` to today. At three, `harness:check` asks every turn where it graduates: a convention of this codebase becomes a rule here, and `nina learn --graduate <pill> --here <file>` retires the pill; a rule any project of this shape needs goes to the harness with `nina learn --graduate <pill>` — commit the request with the pill. Each subagent reads its own pills before acting, and `nina pills` checks they are well formed and filed where their audience reads them (see `.claude/pills/README.md`).
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Parallelization
|
|
135
|
+
|
|
136
|
+
**The rule that decides everything here: a stage that only reads can always run beside another
|
|
137
|
+
stage that only reads. A stage that writes files owns those files alone.** Most of this pipeline is
|
|
138
|
+
read-only, so most of it can overlap — the default of running every stage nose-to-tail is a
|
|
139
|
+
habit, not a constraint.
|
|
140
|
+
|
|
141
|
+
Dispatch concurrent agents **in a single message with multiple Agent tool calls**. Separate messages
|
|
142
|
+
run them one after another and buy nothing.
|
|
143
|
+
|
|
144
|
+
### Run these in parallel
|
|
145
|
+
|
|
146
|
+
| Together | Why it is safe | What it buys |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| **`reviewer` ∥ every gate the diff triggered** after the implementer | all read-only + Bash | the gates stop being a serial prefix to the review |
|
|
149
|
+
| **`reviewer` fanned out by dimension** — one per axis of risk the diff carries, such as tenant isolation, patterns and spec-scope | read-only; they never touch the same output | **the biggest single win.** One reviewer carrying ~15 checklists over a 500-line diff misses things; three narrow ones do not. Faster *and* better |
|
|
150
|
+
| **`architect` across the sibling specs of one milestone** (`<feature>-spec1..N`) | each writes its own file under `.claude/plans/specs/` | the specs share context, so designing them together is more coherent than one-at-a-time, and the whole milestone is specced in one pass |
|
|
151
|
+
| **`devops` ∥ `secops`** at the end of a milestone | devops only reads code; what it writes is a deploy target, not the tree | the audit and the preview deploy stop being sequential |
|
|
152
|
+
| **`Explore` fan-out** for "where does X live" | read-only | one search instead of every stage re-grepping the tree |
|
|
153
|
+
|
|
154
|
+
### Implementers side by side
|
|
155
|
+
|
|
156
|
+
Two implementers write at once only on work that shares no file and builds on nothing the other writes:
|
|
157
|
+
the planner's `PARALLEL-SAFE`, a step's `Builds on` and the binding file lists say which. Where decides how:
|
|
158
|
+
|
|
159
|
+
- **In different packages, each checked on its own** (typecheck, lint and build scoped to it, and none of
|
|
160
|
+
them building the other package first): side by side in this checkout.
|
|
161
|
+
- **In one package, or where a check spans packages:** each with **`isolation: "worktree"`**. A worktree
|
|
162
|
+
holds only what is committed — every closed pass is (§ *Commits*) — and lacks what git does not track,
|
|
163
|
+
such as dependencies or a virtual environment, until its implementer sets it up.
|
|
164
|
+
- You merge a worktree's work, in step order. Never let two agents merge.<!-- nina:why --> The rule
|
|
165
|
+
used to be one implementer per package, always in a worktree. The first new project had no commit for a
|
|
166
|
+
worktree to hold, so it ran two implementers side by side in one checkout, one per spike directory, and
|
|
167
|
+
neither disturbed the other. It also ran two steps of one spec one after the other that built on the
|
|
168
|
+
same two steps and nothing else, only because they shared a package and both edited its README.<!-- /nina:why -->
|
|
169
|
+
|
|
170
|
+
### A spec's steps are passes of their own
|
|
171
|
+
|
|
172
|
+
When the architect splits a spec into steps, each step is its own pass from the implementer on: an
|
|
173
|
+
implementer for that step alone, then the reviewer and every gate its diff triggers, then qa. A step's
|
|
174
|
+
implementer goes out only once every step it builds on has closed its pass, so no step is built on one
|
|
175
|
+
that was sent back. Steps whose turn comes together and share no file go out together, as § *Implementers side by side*
|
|
176
|
+
says; their reviews go out together too, and their qa runs one after the other. Parallel steps save
|
|
177
|
+
time, not tokens: each run builds its own context, and a step that builds on another is never one of
|
|
178
|
+
them. Never hand one implementer several steps, or a spec that lists more than {{STEP_FILES}} files or forecasts more
|
|
179
|
+
than {{STEP_LINES}} lines with no steps: that spec goes back to the architect to be split. The planner's `ONE-SPEC` and `ONE-REVIEW` group
|
|
180
|
+
its own sibling steps into one spec and one review; they never put two of an architect's steps in one
|
|
181
|
+
implementer run.
|
|
182
|
+
|
|
183
|
+
Each step's commit is measured against the forecast it was built to (`nina sizes`, and `harness:check` after every
|
|
184
|
+
turn). When a step took more than one implementer round, write `First round: ~N lines` in its step file with its
|
|
185
|
+
commit, the count its implementer's first report gave: the rounds after it are the review's, not the forecast's, and
|
|
186
|
+
the rate is measured by the first. One that landed more than a quarter over says the steps forecast with it are short
|
|
187
|
+
by as much: forecast each again at its turn, before it goes out — a `Size:` line that opens with its number, at the rate
|
|
188
|
+
`nina sizes` prints for it, from the steps of its `Kind:` where any landed — and send the architect only a step the new
|
|
189
|
+
number puts past {{STEP_LINES}} lines, to be split. A forecast that already carries a rate measured on steps of another
|
|
190
|
+
kind is restated from its own count at its kind's, never multiplied again: `nina sizes` shows what a step carries over
|
|
191
|
+
its first forecast beside what its kind's steps missed by. The rest wait for their turn, when the steps before them will have measured the
|
|
192
|
+
rate again.
|
|
193
|
+
|
|
194
|
+
### Commits
|
|
195
|
+
|
|
196
|
+
When a pass closes — `qa` returns `PASS`, or the reviewer approves a chain that ends there — commit what
|
|
197
|
+
it changed, with a message naming the step and its spec as its step file does (`<spec> step <n>`), which is how
|
|
198
|
+
`nina sizes` finds it. Commit on a working branch: never on the
|
|
199
|
+
project's default branch, so before a piece of work's first commit there, create a branch named for its
|
|
200
|
+
spec. Never push, amend, rebase or force; {{OWNER}} merges. A pass sent back is not committed. You are
|
|
201
|
+
the only one who commits (Hard Rule #18): a commit is what a worktree holds, what `secops` audits a
|
|
202
|
+
milestone by, and what `qa` checks a "pre-existing" failure against.
|
|
203
|
+
|
|
204
|
+
### Keep these serial
|
|
205
|
+
|
|
206
|
+
- **`qa`.** Vitest is ~2–3 GB per worker; concurrent invocations take the machine down. One run, at
|
|
207
|
+
the end of each pass. This is not negotiable and is not a speed problem — the suites are seconds, except those
|
|
208
|
+
`CLAUDE.md` names as slow.
|
|
209
|
+
- **The merge**, always.
|
|
210
|
+
- **A loop-back.** When a stage rejects, fix and re-run that stage; do not fan out around a failure.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Examples
|
|
215
|
+
|
|
216
|
+
| User request | Pipeline |
|
|
217
|
+
|---|---|
|
|
218
|
+
<!-- nina:slot project.5 dispatch-examples -->
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Quick triage
|
|
223
|
+
|
|
224
|
+
When the doubt is whether a critical path is touched, take the heavier chain; when it is only how much ceremony, the lighter one (`CLAUDE.md` § *If you are uncertain which chain applies*).
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!-- nina:requires integrations -->
|
|
2
|
+
# <Name> — premises
|
|
3
|
+
|
|
4
|
+
> One integration, one doc. The **integration-tester** creates it on first contact with the
|
|
5
|
+
> dependency and appends to it whenever it observes behavior this file does not yet carry.
|
|
6
|
+
> Everything below is evidence. A claim you cannot cite belongs in *Open questions*, not in a
|
|
7
|
+
> premise — a premise that turns out to be a guess is how an integration regression ships.
|
|
8
|
+
|
|
9
|
+
- **Kind:** `installed-library` · `live-api` · `platform-binding` — each that applies (a client library over a platform binding is both); a premise's kind decides what counts as its evidence.
|
|
10
|
+
- **Boundary:** the one module that speaks to this dependency. Nothing else may.
|
|
11
|
+
- **Skill:** the installed skill covering it, or *none* — do not invent one.
|
|
12
|
+
|
|
13
|
+
## Premise index
|
|
14
|
+
|
|
15
|
+
Read this table and the sections your task actually cites. Not the whole file.
|
|
16
|
+
|
|
17
|
+
| Premise | Evidence | Claim |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| P1 | `<citation>` | one sentence |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## P1 — <the claim, as a sentence>
|
|
24
|
+
|
|
25
|
+
**Claim.** What the dependency does, in one sentence, stated specifically enough to be wrong.
|
|
26
|
+
|
|
27
|
+
**Evidence.** The form depends on the kind:
|
|
28
|
+
|
|
29
|
+
- `installed-library` — `<package dir>/node_modules/<lib>/<file>:<line>`, with the lines that prove it
|
|
30
|
+
quoted and the version beside it. From the version actually installed here, not the latest release,
|
|
31
|
+
and through the package's own link: the store directory behind it is renamed by a peer change. A library
|
|
32
|
+
no package links, a dependency of a dependency, has no link of its own: cite it through the one that depends
|
|
33
|
+
on it, `<package dir>/node_modules/<parent> → <lib>@<version>/<file>:<line>`, which `nina check` resolves from where that link leads.
|
|
34
|
+
- `live-api` — the request sent and the response received, verbatim, or the contract-test case that
|
|
35
|
+
pins it. The vendor's documentation is not evidence: it describes what they intend, and you are
|
|
36
|
+
depending on what they do.
|
|
37
|
+
- `platform-binding` — what the local emulator did when driven, plus the platform's installed types.
|
|
38
|
+
|
|
39
|
+
**Why it matters here.** Which code depends on this being true, and what breaks if it is not.
|
|
40
|
+
|
|
41
|
+
**Checked.** `<date>` against `<version / environment>`.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Open questions
|
|
46
|
+
|
|
47
|
+
Behavior this doc does not settle yet, and what would settle it. A question here is honest work;
|
|
48
|
+
the same uncertainty written as a premise is a defect waiting for a deploy.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<!-- nina:slot project.1 title -->
|
|
2
|
+
|
|
3
|
+
<!-- nina:slot project.2 mission -->
|
|
4
|
+
|
|
5
|
+
<!-- nina:slot project.3 stack -->
|
|
6
|
+
<!-- nina:slot edge-cf.1 -->
|
|
7
|
+
|
|
8
|
+
> **A subagent can only invoke a skill if `Skill` is in its `tools:` list.** That field is an allowlist, not a hint.<!-- nina:why --> An earlier version of this harness omitted `Skill` on every role, so every mandatory-skill rule was unenforceable, and the skills were measured at 2 invocations in 743 runs — both from built-in agents that carry the full tool set.<!-- /nina:why --> Any new role that binds a skill must grant `Skill`. The `tools:` field is read when the agent is registered, so a change to it needs a new session; the spec body is re-read on every dispatch.
|
|
9
|
+
|
|
10
|
+
Mandatory triggers:
|
|
11
|
+
|
|
12
|
+
| When you are about to… | Invoke skill | Why |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
<!-- nina:slot edge-cf.2 -->
|
|
15
|
+
<!-- nina:slot edge-cf.3 -->
|
|
16
|
+
<!-- nina:slot edge-cf.4 -->
|
|
17
|
+
<!-- nina:slot edge-cf.5 -->
|
|
18
|
+
<!-- nina:slot frontend.1 -->
|
|
19
|
+
| Run the **secops** milestone gate | `security-audit` | the attack-class corpus; guidance mode — its full six-phase workflow is for an explicit whole-tree audit only |
|
|
20
|
+
<!-- nina:slot edge-cf.6 -->
|
|
21
|
+
<!-- nina:slot prisma.1 -->
|
|
22
|
+
<!-- nina:slot prisma.2 -->
|
|
23
|
+
<!-- nina:slot d1.1 -->
|
|
24
|
+
|
|
25
|
+
**Each agent spec now carries its own binding table** (`.claude/agents/<role>.md` § *Skills you MUST consult*), because a rule that lives only here is not in front of a stage when it acts.<!-- nina:why --> It was invoked 2 times in 743 subagent runs.<!-- /nina:why --> `qa` and `planner` have no skill bound — none of the installed skills covers running tests or decomposition, and an invented binding is worse than none.
|
|
26
|
+
<!-- nina:slot edge-cf.7 -->
|
|
27
|
+
|
|
28
|
+
Reviewer rejects any architect spec that touches the platform runtime or its deploy config without citing which skill it consulted, OR explaining why the skill was not needed. Same standard as the premise rule below: retrieval beats recall.
|
|
29
|
+
|
|
30
|
+
## Where things live
|
|
31
|
+
- Full architecture → `.claude/architecture.md`
|
|
32
|
+
- Code conventions → `.claude/patterns.md`
|
|
33
|
+
- Pipeline graph — stages, edges, loop caps → `.claude/graph.md`
|
|
34
|
+
- Agent dispatch rules → `.claude/router.md`
|
|
35
|
+
- Which docs to load per task → `.claude/retrieval.md`
|
|
36
|
+
- Agent pipeline overview → `.claude/agents-overview.md`
|
|
37
|
+
- Stage contracts + examples → `.claude/pipeline.md`
|
|
38
|
+
- Subagent role specs → `.claude/agents/` (dispatchable via Agent tool)
|
|
39
|
+
<!-- nina:slot project.4 product-docs -->
|
|
40
|
+
|
|
41
|
+
**Where a memory goes.** How a stage should work → a pill under `.claude/pills/`, which the stage reads and `nina learn` measures. How a dependency behaves → its `.claude/integrations/` doc. A decision about this system → `.claude/architecture.md`. A rule every project needs → a request to the harness (`nina learn --graduate`). Only a preference of the owner's goes in Claude Code's own memory: it is this machine's alone, no stage reads it, and nothing measures it.
|
|
42
|
+
|
|
43
|
+
**Generated files — edit the layer, not the output.** A file that opens with a
|
|
44
|
+
`<!-- nina:generated -->` comment was composed by `nina compose` from the harness core, the
|
|
45
|
+
surfaces this project declares in `.nina/profile.json`, and this project's own fragments in
|
|
46
|
+
`.nina/project/tree/`. Most of the docs above open with one, and so does this file. The
|
|
47
|
+
comment names the layer to edit instead — or says the text belongs to the harness and cannot
|
|
48
|
+
be changed from this project, in which case **report it rather than editing it**. A hand edit
|
|
49
|
+
is reported as drift by `pnpm harness:check` and overwritten by the next compose, which is
|
|
50
|
+
how a correction written in the wrong place disappears without anyone being told.
|
|
51
|
+
|
|
52
|
+
**The rule is the marker, not the directory.** Most of `.claude/` is yours to write and is
|
|
53
|
+
never composed: `architecture.md`, the code map, `integrations/*`, everything under
|
|
54
|
+
`plans/**`, and the pills under `pills/<role>/`. Do not stop writing those.
|
|
55
|
+
|
|
56
|
+
**A generated line you cannot fix here is a change made upstream.** The harness lives in its own
|
|
57
|
+
repository; this project composes a *frozen* version of it, pinned as `core` in `.nina/profile.json`.
|
|
58
|
+
So a wrong composed line has one of two addresses, and saying which is part of reporting it. **This
|
|
59
|
+
project's own fact** — a path, a provider, a duration, a package name — belongs in a fragment under
|
|
60
|
+
`.nina/project/tree/`, and you can fix it now. **The harness's rule** — what a role must do, what a
|
|
61
|
+
stage hands off, what a report must contain — cannot be changed from this project at all: report it as
|
|
62
|
+
a request against the pinned version, quoting the composed file and line, and it arrives back through
|
|
63
|
+
`nina upgrade`. A correction that names no layer is not actionable by anyone, however right it is.
|
|
64
|
+
|
|
65
|
+
## ⚠️ Agent pipeline — MANDATORY
|
|
66
|
+
|
|
67
|
+
> **Dispatch the subagent chain that fits the task's size and blast radius — before executing anything non-trivial.**
|
|
68
|
+
> The pipeline is **proportional, not one-size-fits-all.** A change on a **critical path** (below) and a substantial multi-file feature get the full chain. Small read-only / display / UI-copy changes get a light chain — or a direct edit. **Under-gating a change on a critical path is a protocol violation. Over-gating a one-file label or list change wastes hours — that is also a failure.**
|
|
69
|
+
|
|
70
|
+
**Critical paths.** A change that touches one is gated in full, and when it is unclear whether a change touches one, it does:
|
|
71
|
+
|
|
72
|
+
- **auth**: how a credential is issued, checked or revoked, and who may do what
|
|
73
|
+
<!-- nina:slot db.8 -->
|
|
74
|
+
<!-- nina:slot integrations.7 -->
|
|
75
|
+
<!-- nina:slot money.4 -->
|
|
76
|
+
<!-- nina:slot pii.2 -->
|
|
77
|
+
<!-- nina:slot blockchain.4 -->
|
|
78
|
+
|
|
79
|
+
### Procedure — follow this every time
|
|
80
|
+
|
|
81
|
+
1. **Classify the task** using the table below *before* touching any file — and before a session's first dispatch, read `.claude/graph.md` and `.claude/router.md`.
|
|
82
|
+
2. **Dispatch the first subagent** in the required chain via the Agent tool.
|
|
83
|
+
3. Each stage hands off a written artifact (spec / diff / review) to the next.
|
|
84
|
+
4. **Run the read-only stages concurrently.** A stage that only reads can run beside any other stage that only reads, so the `reviewer` and every gate the diff triggers go out together after the implementer — in ONE message with multiple Agent calls — and `secops` runs beside `devops` at a milestone's end, once its last `qa` passed. For a diff over ~200 lines, fan the reviewer out by dimension — one reviewer per axis of risk the diff actually carries — instead of asking one agent to carry every checklist. Concurrent **implementers** are the exception: they write, so they run together only on work that shares no file and builds on nothing the other writes — side by side in different packages, each in `isolation: "worktree"` within one. `qa` is always alone (vitest memory). Full rules: `.claude/router.md` § *Parallelization*.
|
|
85
|
+
5. The **reviewer** names every gate the diff triggers — the database gate when the schema or a query was touched — and `qa` goes out only once the reviewer and each of those gates approved.
|
|
86
|
+
6. **Honor the planner's `ONE-SPEC` / `ONE-REVIEW` grouping.** Sibling steps that change no observable behavior on their own get **one** architect spec and **one** reviewer pass over the combined diff, while still being implemented one step at a time. Small steps are good; eight full pipelines to ship one feature are not. This never relaxes a gate — the gates in `.claude/graph.md` fire on the surface touched, however the specs were grouped.
|
|
87
|
+
7. **Right-size before dispatching.** Match the chain to blast radius (see table). A change that touches no critical path and ≤2 files takes the light chain — or a direct edit when a subagent adds nothing (a label, a copy tweak, a list render). Do NOT run planner/architect/secops on that. The gates on a critical path are never optional.
|
|
88
|
+
8. **Commit each pass that closes**, on a working branch — never on the default branch, never pushed (`.claude/router.md` § *Commits*).
|
|
89
|
+
9. **At the END of a spec-SET / milestone** (e.g. all of `6.*`), after the last sub-step's qa, dispatch **secops**. The milestone is not done until secops returns `SECURE`. This is a milestone gate, NOT a per-sub-step stage. **Scope secops to the milestone's diff by default.** A whole-tree sweep surfaces pre-existing debt mid-task and causes scope-creep — run it ONLY when explicitly requested, as a deliberate choice, never as the default.
|
|
90
|
+
|
|
91
|
+
### Required chain by task shape
|
|
92
|
+
|
|
93
|
+
| Task shape | Required dispatch |
|
|
94
|
+
|---|---|
|
|
95
|
+
| Question / exploration / Q&A | none — answer directly |
|
|
96
|
+
| Trivial edit (rename, typo, 1-line log fix) | none — edit directly |
|
|
97
|
+
| **Small read-only / display / UI-copy change** (≤2 files, no critical path) | **implementer → reviewer** — or a direct edit if a subagent adds no value; qa runs ONLY the affected test file, and not at all when no test covers the change. No planner, no secops. |
|
|
98
|
+
| **Spike** — an experiment that answers a question about a service, a library or the data before anything is designed on it | **architect (spike plan) → implementer → reviewer** — no qa, devops or secops; `.claude/router.md` § *A spike answers one question* |
|
|
99
|
+
| Single-file bug fix (TS) | **implementer → reviewer → qa** |
|
|
100
|
+
| Refactor TS (no new behavior) | **architect → implementer → reviewer → qa** |
|
|
101
|
+
| New TS feature / multi-file change (a critical path, or ≥3 files with logic) | **planner → architect → implementer → reviewer → qa** |
|
|
102
|
+
<!-- nina:slot db.3 -->
|
|
103
|
+
<!-- nina:slot integrations.1 -->
|
|
104
|
+
<!-- nina:slot blockchain.2 -->
|
|
105
|
+
| **ANY step that changes a deployed surface** (API, frontend, schema, deploy config, secrets, bindings) | **+ devops after qa** — preview deploy + smoke; prod only on an explicit go; with no preview target yet, the step ends at qa |
|
|
106
|
+
<!-- nina:slot frontend.2 -->
|
|
107
|
+
| **END of a spec-SET / milestone** (a numbered set like `6.*`, or a phase like one package's build-out) | **+ secops after the last sub-step's qa** — milestone security gate; `SECURE` required before the milestone is declared done |
|
|
108
|
+
|
|
109
|
+
**Sizes, and what each decides.** ≤2 files and no critical path: the light chain. Past 4 files or ~400 new lines, the planner decomposes a subtask. One implementer run writes at most {{STEP_FILES}} files and about {{STEP_LINES}} lines: the architect forecasts both and splits a longer step. A `ONE-SPEC` group stays under ~400 lines of diff. Past ~200 lines, the reviewer fans out by dimension. Each size decides only its own thing.
|
|
110
|
+
|
|
111
|
+
**Test execution policy:** vitest is **only** invoked by the **qa** stage, which runs once at the end of the pipeline (after reviewer approves). Implementer writes tests but does NOT execute them. Reviewer does NOT run tests. This prevents the workspace-machine memory blowups from concurrent vitest invocations (vitest is ~2–3 GB per worker). Configs enforce single-fork; the root `pnpm test` uses `turbo run test --concurrency=1`.
|
|
112
|
+
|
|
113
|
+
**Test scoping (speed — this is the single biggest time sink).** qa runs ONLY the test files / packages the diff actually touches during the build→fix loop — never the full suite per cycle. Run it targeted per file while iterating; run the **full** package suite exactly ONCE, right before opening the PR / merging, as the final gate. Vitest stays single-fork and non-concurrent.
|
|
114
|
+
|
|
115
|
+
<!-- nina:slot project.8 slow-suites -->
|
|
116
|
+
|
|
117
|
+
### If you are uncertain which chain applies
|
|
118
|
+
→ If the doubt is whether a **critical path** is touched → treat it as the heavier shape and gate it. If the task clearly touches no critical path and the only question is "how much ceremony" → take the **lighter** chain; an extra planner/secops pass on a display change costs hours, not minutes.
|
|
119
|
+
|
|
120
|
+
<!-- nina:slot project.5 roles-heading -->
|
|
121
|
+
|
|
122
|
+
- **planner** → decompose ambiguous or multi-step tasks into ordered subtasks
|
|
123
|
+
- **architect** → design the TS technical approach AND cite external-library premises (`<package dir>/node_modules/<lib>/<file>:<line>` + version); write a spec before code exists
|
|
124
|
+
- **design-reviewer** → read the spec before any code when the architect's report says the design is the question; back to the architect on a design flaw
|
|
125
|
+
- **implementer** → write TS code AND test files strictly to spec; runs typecheck/lint/build only (NOT vitest)
|
|
126
|
+
<!-- nina:slot db.4 -->
|
|
127
|
+
<!-- nina:slot integrations.3 -->
|
|
128
|
+
<!-- nina:slot blockchain.3 -->
|
|
129
|
+
- **reviewer** → verify diff matches spec, run typecheck/lint/build (NOT vitest), name every gate the diff triggers, confirm spec has a preview-deploy plan
|
|
130
|
+
- **qa** → runs vitest once at the END of the pipeline (after the reviewer and every gate approve) for the affected packages; loops back to implementer on failures
|
|
131
|
+
- **devops** → **deploy owner.** Runs after **qa PASS** on any step that changes a deployed surface, once the project has a preview target. Deploys to preview or staging first; production needs an explicit go. Smokes the deployed preview for a blank page and a clean console — judging whether the screen is *right* is the reviewer's job, not his. Executes Hard Rule #14: clean build, every deploy target, build-time env, migrations in order against the right DB, secret parity, **smoke against preview**, named rollback. Deploys preview/staging on its own; **a production deploy requires an explicit go from {{OWNER}} for that change.** Read-only on code — a failed deploy caused by bad code loops back, it does not get patched here.
|
|
132
|
+
- **secops** → **milestone security gate.** Runs once at the END of a completed spec-SET (a numbered milestone like `6.*`, or a phase like one package's build-out), after the last sub-step's qa — NOT per sub-step. Audits as an attacker and a privacy auditor (auth/session, tenant isolation, secrets and config exposure, PII leakage, abuse of any irreversible operation and its idempotency seams, injection/SSRF, dependency and binding posture). **Scoped to the milestone diff by default; a whole-tree sweep runs only on explicit request** (it surfaces pre-existing debt mid-task → scope-creep). Read-only; CRITICAL/HIGH findings in the milestone's own surface BLOCK it and loop back until re-audited.
|
|
133
|
+
|
|
134
|
+
<!-- nina:slot project.6 doc-pointers -->
|
|
135
|
+
|
|
136
|
+
## Hard rules (non-negotiable)
|
|
137
|
+
|
|
138
|
+
A rule keeps its number in every project, because other documents cite it as `Hard Rule #N`. A rule this project does not have leaves a gap in the numbers — it was not lost, and the list is not renumbered.
|
|
139
|
+
|
|
140
|
+
1. **Run the subagent chain proportional to the task (see the pipeline table).** Under-gating a change on a critical path is a protocol violation — those gates are never skipped, and when uncertain whether one is touched, gate it. But small read-only / display / UI-copy changes (≤2 files, no critical path) take the light chain or a direct edit — over-gating them wastes hours and is also a failure.
|
|
141
|
+
<!-- nina:slot db.5 -->
|
|
142
|
+
<!-- nina:slot money.1 -->
|
|
143
|
+
<!-- nina:slot money.2 -->
|
|
144
|
+
<!-- nina:slot money.3 -->
|
|
145
|
+
<!-- nina:slot db.6 -->
|
|
146
|
+
<!-- nina:slot db.7 -->
|
|
147
|
+
<!-- nina:slot pii.1 -->
|
|
148
|
+
9. **TSDoc is mandatory on every TS declaration** (function, type, interface, class, method, enum) — exported or not, and members are declarations: the fields of an interface, a type alias or an inline type literal, class members, constructors, an object literal's methods and accessors — a hand-built fake's too — and a local whose value is a function, a mock's included. A data local, a literal typed by a documented declaration and a property descriptor passed as an argument need none. Enforced in review, by a sweep of every file touched, not a sample.
|
|
149
|
+
<!-- nina:slot edge-cf.8 -->
|
|
150
|
+
<!-- nina:slot integrations.4 -->
|
|
151
|
+
<!-- nina:slot integrations.5 -->
|
|
152
|
+
<!-- nina:slot integrations.6 -->
|
|
153
|
+
14. **Preview-first deploy. Smoke runs against preview, NEVER prod first.** The **devops** stage owns executing this; the reviewer only verifies the plan exists. Any change that culminates in a production deploy must name a preview URL (a preview deployment for `{{APP_DIR}}`; a staging route for the API) in the architect's spec. Smoke runs against preview FIRST. A spec without a preview-deploy plan is rejected by the reviewer. Until the project has a preview target, a change deploys nowhere: it ends at qa, and the first deploy is a step of its own whose spec names the target.
|
|
154
|
+
15. **Relative imports use the `.js` extension in `.ts`/`.tsx` source — this is intentional ESM, NOT a mistake.** `import { x } from './client.js'` (never `'./client'` or `'./client.ts'`). TypeScript does not rewrite specifiers; emitting packages ({{EMITTING_PKGS}}) ship real `dist/*.js`, so the `.js` form is the only one that resolves at runtime, and the bundlers map it back to `.ts` source transparently. Stripping or `.ts`-ifying the extension breaks the build — do not "fix" it. Full rationale: `.claude/patterns.md` § *Relative imports carry a `.js` extension*.
|
|
155
|
+
<!-- nina:slot blockchain.1 -->
|
|
156
|
+
17. **Every artifact you are handed is a hypothesis; the tree is the truth.** A file list, a line range, a test filter, a cited premise — each was derived by an earlier stage from a tree that may have moved since, so **the part you are about to rely on** is checked against the tree before you act on it. Where it diverges, **report the divergence, naming the stage that produced it**: a stage that quietly works around a wrong input hides the defect from the only stage that can fix it, and the next task inherits it intact. Acting on what the tree says **never widens what you were authorized to touch** — a wrong range inside a file you own is corrected and reported; a divergence that would take you outside your authorized files stops the work and goes back to the stage that drew the boundary. <!-- nina:why -->This is not diligence for its own sake. On one milestone three consecutive stages each found the artifact above them wrong — a test filter that covered two of six blocks gated on a live credential, a line range that missed a second block of orphaned mocks, a spec that named the wrong test as the one blocking a removal — and every one of the three found it only by going to look.<!-- /nina:why -->
|
|
157
|
+
18. **Only the orchestrator commits, and no stage moves the checkout.** A stage reads history (`git diff`, `log`, `show`, `status`, `blame`) and builds or tests another revision in a `git worktree` it removes afterwards. It never stashes, checks out, switches, resets, restores, cleans, commits, merges or rebases in the tree it was dispatched into: the work in flight lives there, uncommitted, and a stash or a checkout takes it from every stage beside it. Its scratch directories are its own as well: each in the session's scratchpad, named for its stage and step and made so that an existing path fails (`mktemp -d "<scratchpad>/<role>-<step>-XXXX"`), before its first write there. Every file it writes goes inside one — a log, a captured output, a note of a path — and none at the scratchpad's root, not even for a moment. A shell variable does not outlive its call, so the call that makes the directory prints its path (`echo "$S"`), and each later call writes that path out in full. Before it ends, it lists the root to see that none of its files is there.<!-- nina:why --> In one project, a qa wrote a path note at the root, and a reviewer whose dispatch named its `mktemp -d` directory wrote a capture and a log there. In the third, three of one step's four stages did, an implementer to keep its directory's path from one call to the next.<!-- /nina:why --> Its scratch work creates, links and deletes only paths inside those, checked before each `ln -s`, `cp` or `rm -rf`; runs a probe another stage named from a copy in one of them; and removes them when it ends, except what its report names for a later run. A gate keeps the harness it built — its generators, fuzz and differential drivers — and names each with the command that runs it: the re-check of the fix runs them first, rebuilds any no longer there and says so, and writes only what the fix added. The report names every directory it made. A probe that needs a package's module resolution runs in a scratch copy of the package, never in the tree.<!-- nina:why --> In the third project, five stages ran side by side in one session's scratchpad: a reviewer set up in another stage's `pkg`, overwrote four of its files, linked onto a link and so left a stray link inside the repository's `node_modules`, then removed the directory the dba had named as holding its harness. Another wrote a probe into a test directory four stages were reading.<!-- /nina:why -->
|
|
158
|
+
19. **Every turn re-reads the whole context, so take each thing in once.** Tool calls that do not depend on each other go out in one message. A file you wrote or edited is in your context already: read it again only once something else changed it. Find before you open (`grep -l`, `grep -c`), then read the range you need; output longer than a screen goes to a file in your scratch directory (Hard Rule #18), which you grep. A battery, a fuzz or a differential check of many light cases, run as a script of your own, goes side by side: a worker per core less two (`os.availableParallelism() - 2`), a quarter of that when you are one of the gates that run together, each worker on its own scratch copy of what it changes and in its own process group, killed when it ends or times out. A case that starts a process — the script under test, a compiler — is as light as its memory: measure one case's peak resident memory first, its processes summed, and run no more workers than fit at that peak in a quarter of the machine's memory, a sixteenth when you are one of the gates; the script holds its pool to the smaller of that count and the cores'. A case that boots a runtime, a database or a browser runs alone, and so does the suite. No case waits out a real timeout or delay of the code it tests: that code takes it from the case — an argument, an environment variable, a clock passed in — and the spec of such code says how. Wait in calls that each end within three minutes — your context is cached five minutes, and the turn after a longer call writes all of it again at twelve times a re-read's price: run the rest in shares, or in the background checked by calls of up to three minutes, never a short `sleep` a turn, which re-reads your context only to learn it is not done.<!-- nina:why --> In the project this was learned in, 99% of an implementer's ~350 turns sent a single call, and runs re-read files they had just written 534 times.<!-- /nina:why --><!-- nina:why --> In the third project, one step's stages each ran theirs one case at a time: an implementer round spent 66 of its 92 minutes in `sleep` on 2,536 mutants, an integration-tester 43 of 81 in fuzz commands of nine and ten minutes, and the reviewers that had rejected the change by 11:02 waited until 12:10 on it.<!-- /nina:why --><!-- nina:why --> Later in that project, a task's five implementer rounds spent three quarters of nine hours waiting on mutation batteries run one case at a time: each case started the script under test, 200 to 450 MB, on a machine of ten cores, and some waited out a real timeout of a minute.<!-- /nina:why --><!-- nina:why --> In that project too, 142 calls waited five to ten minutes in one, and writing the context again on the turn after each came to a quarter of what its stages spent on input.<!-- /nina:why -->
|
|
159
|
+
20. **Send work back only for what blocks it.** A finding blocks when shipping it would be wrong: a defect in behavior, security, data or a contract; a requirement of the spec unmet, or a file written outside the ones it authorized; a test that cannot fail, or a case the spec requires left untested; a claim a later stage will act on that is false. The rest is a **note**: wording, naming or style, a claim imprecise but not false, an improvement, a step longer than its forecast, an evasion the spec ruled out in writing — never a hole in security, isolation or data, which blocks however the spec scoped it. Nor is a question for the design a note: a form a check, guard or scanner accepts that its design's intent refuses without saying so — what the spec ruled out in writing stays a note — or a choice the spec left open that a later stage will act on, blocks and goes to the architect, even when the code does what its spec says: a note reaches no one who can decide it. A failure that fails closed is not safe for the change when it fails at a size the design did not choose and no test reaches: that one fails in production.<!-- nina:why --> In two steps replayed without the full pipeline, the replay's reviewers saw both design flaws the pipeline had caught, in 3 of 5 reviews and in 4 of 5, and blocked the first in two and the second in none: one wrote that the architect might refuse the form and approved, the others called a chunk sized for another table safe because it throws before any query — which it does only at a size no test reaches.<!-- /nina:why --> A note never sends work back and never goes on the `ISSUES` line: list it in a **Notes** section of your report, with `path:line`, whatever the verdict.<!-- nina:why --> In one step's second round, 7 to 9 of its 19 issues were wording or evasions its spec had scoped out, and with the rest they bought a third round of every stage.<!-- /nina:why -->
|
|
160
|
+
21. **A run proved local is proved by a refusal, and no control leaves the machine.** A guard that keeps a run off the network — a sandbox profile, a preload, a refusing proxy — works only if it refuses at once, an error within milliseconds (`EPERM`, curl's exit 7): a timeout is what a packet that left looks like, and proves nothing. Check each guard with its own control, never one an earlier pass ran: inside it, connect to a listener the probe started on `127.0.0.1` and to `192.0.2.1`, and record each outcome and its time; one that allows loopback answers the first and refuses the second, one that denies all refuses both. A control never runs outside the guard, nor reaches a real host: a guard that cannot be checked without one is reported unchecked, never checked by the call. A redirect the claim rests on — a registry variable, a proxy, a base URL — is a premise, not a guard: it runs under the guard too, so one that does not take is refused, not sent.<!-- nina:why --> Learned three times in the third project: a control fetch that reached the npm registry to show a sandbox worked; a loopback-only profile that let a connect time out where it should have refused, so every pass that trusted it rested on nothing; and controls of a registry variable that wrangler does not read, run outside the guard, which reached the registry three times.<!-- /nina:why -->
|
|
161
|
+
|
|
162
|
+
## Common commands
|
|
163
|
+
|
|
164
|
+
<!-- nina:slot project.7 common-commands -->
|
|
165
|
+
|
|
166
|
+
## When in doubt
|
|
167
|
+
Consult `.claude/retrieval.md` to decide which docs to load before acting.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The cost watch, run by this project's Claude Code hooks on every tool call a subagent makes.
|
|
4
|
+
*
|
|
5
|
+
* A run re-reads its whole context on every turn, so what it costs grows faster than what it does. When the
|
|
6
|
+
* tokens a run has re-read pass {{RUN_READ_WARN}}M, and again at each doubling, this tells the run what a
|
|
7
|
+
* turn now costs and to hand back what is left if it is more than one run should carry, and tells the
|
|
8
|
+
* person in one line. A shell output longer than {{OUTPUT_CLIP}} characters goes to a file, and the run sees
|
|
9
|
+
* its first and last lines and where the rest is; a call that ran past the five minutes the run's cache
|
|
10
|
+
* lives is named to it. It keeps counts only, under ~/.nina/gate/, and lets every call through if anything
|
|
11
|
+
* goes wrong.
|
|
12
|
+
*
|
|
13
|
+
* The mechanism lives in the NINA package; this file only says which project it watches, and from what.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { dirname, resolve } from 'node:path';
|
|
17
|
+
import { Readable } from 'node:stream';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
// Read before the package is loaded: every tool call passes this hook, and the orchestrator's — which it does
|
|
21
|
+
// not watch — go through without paying for it.
|
|
22
|
+
const chunks = [];
|
|
23
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
24
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
25
|
+
if (!/"agent_id"\s*:\s*"[^"]/.test(raw)) process.exit(0);
|
|
26
|
+
const { runCostWatch } = await import('@xhulz/nina/cost');
|
|
27
|
+
process.exitCode = await runCostWatch({ root: resolve(dirname(dirname(fileURLToPath(import.meta.url)))), warnAt: Number('{{RUN_READ_WARN}}') * 1e6, clipAt: Number('{{OUTPUT_CLIP}}'), stdin: Readable.from([raw]) });
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The edit guard, run by this project's `PreToolUse` hook on the edit tools and the shell.
|
|
4
|
+
*
|
|
5
|
+
* A file this harness composes is changed in its layer, never in place: the next compose would
|
|
6
|
+
* overwrite the edit. This refuses an edit to a file carrying the `nina:generated` notice, and the
|
|
7
|
+
* refusal quotes the notice, which names where the change goes. And it refuses a stage the git that
|
|
8
|
+
* would move the checkout its work in flight lives in — Hard Rule #18. The mechanism lives in the NINA
|
|
9
|
+
* package; this file only says which project it guards. It lets every call through if anything goes
|
|
10
|
+
* wrong.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { dirname, resolve } from 'node:path';
|
|
14
|
+
import { Readable } from 'node:stream';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
|
|
17
|
+
// Read before the package is loaded: every shell command passes this hook, and the orchestrator's — the one
|
|
18
|
+
// that commits — go through without paying for it.
|
|
19
|
+
const chunks = [];
|
|
20
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
21
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
22
|
+
if (/"tool_name"\s*:\s*"Bash"/.test(raw) && !/"agent_id"\s*:\s*"[^"]/.test(raw)) process.exit(0);
|
|
23
|
+
const { runGuard } = await import('@xhulz/nina/guard');
|
|
24
|
+
process.exitCode = await runGuard({ root: resolve(dirname(dirname(fileURLToPath(import.meta.url)))), stdin: Readable.from([raw]) });
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Runs this project's harness drift detectors.
|
|
4
|
+
*
|
|
5
|
+
* The mechanism lives in the NINA package — what counts as drift, what counts as a check
|
|
6
|
+
* that could not run, and how either reaches a Claude Code hook. Only the LIST is here,
|
|
7
|
+
* because only this project knows which detectors it has and what to do when one fires.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node scripts/harness-check.mjs human-readable; exit 1 on drift, 2 on error
|
|
11
|
+
* node scripts/harness-check.mjs --hook JSON for a Stop hook — shown to the person; always exit 0
|
|
12
|
+
* node scripts/harness-check.mjs --context JSON for a UserPromptSubmit hook — read by the model
|
|
13
|
+
* before it answers; always exit 0
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { dirname, resolve } from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
import { runDetectors } from '@xhulz/nina/detectors';
|
|
19
|
+
|
|
20
|
+
const ROOT = resolve(dirname(dirname(fileURLToPath(import.meta.url))));
|
|
21
|
+
|
|
22
|
+
process.exit(
|
|
23
|
+
runDetectors(
|
|
24
|
+
[
|
|
25
|
+
// Every composed project has this one, so the core carries it rather than asking each
|
|
26
|
+
// project to write the same nine lines. It disables itself where the project does not
|
|
27
|
+
// declare the npm script, like any other detector.
|
|
28
|
+
{
|
|
29
|
+
name: 'agent specs',
|
|
30
|
+
declaredBy: 'harness:compose:check',
|
|
31
|
+
bin: 'nina',
|
|
32
|
+
args: ['compose', '--check', '--drift', '--quiet'],
|
|
33
|
+
hint: 'these files are generated — run `nina where <file>` to see which layer owns it, then `nina compose`',
|
|
34
|
+
ignore: /^compose: current$/,
|
|
35
|
+
},
|
|
36
|
+
// What the project has not declared yet: vocabulary, its own layer, the documents the layers
|
|
37
|
+
// read, the wiring. On a new project this is the whole to-do list, and it reaches the model
|
|
38
|
+
// before its first answer — so the first conversation starts by filling it, unasked.
|
|
39
|
+
{
|
|
40
|
+
name: 'declaration',
|
|
41
|
+
bin: 'nina',
|
|
42
|
+
args: ['check', '--detector', '--quiet'],
|
|
43
|
+
hint: 'each line says what is missing — `.nina/TODO.md` lists the project’s own items, and `.nina/BRIEF.md`, where the interview wrote one, says what the project is; fill them, then `nina compose`',
|
|
44
|
+
ignore: /^check: declaration is sound/,
|
|
45
|
+
},
|
|
46
|
+
// The one link of the learning cycle that fails in silence: a role keeps being sent back
|
|
47
|
+
// and nothing is written down. It fires on the event — sent back three times since that role's
|
|
48
|
+
// newest lesson — not on a rate, so it says something new when it speaks. A lesson learned
|
|
49
|
+
// a third time it sends to the harness itself, and says so once.
|
|
50
|
+
{
|
|
51
|
+
name: 'lessons',
|
|
52
|
+
bin: 'nina',
|
|
53
|
+
args: ['learn', '--check', '--quiet'],
|
|
54
|
+
hint: 'each line above says what it needs — `nina learn` shows the whole cycle',
|
|
55
|
+
ignore: /^learn: current$/,
|
|
56
|
+
},
|
|
57
|
+
// The loop gate holds the caps in .claude/graph.md from this project's hooks, and it lets every
|
|
58
|
+
// call through when it fails — so a gate that stopped working looks exactly like a pipeline with
|
|
59
|
+
// no loops. This asks it, every turn, whether it is wired and would still hold one.
|
|
60
|
+
{
|
|
61
|
+
name: 'loop gate',
|
|
62
|
+
bin: 'nina',
|
|
63
|
+
args: ['gate', '--selftest', '--quiet'],
|
|
64
|
+
hint: 'the caps in .claude/graph.md are not being held — `nina wire --apply` wires the gate; `nina gate --selftest` says what else is wrong',
|
|
65
|
+
ignore: /^gate: current$/,
|
|
66
|
+
},
|
|
67
|
+
// A step that landed well past its forecast says the steps forecast with it are short by as much, and it took
|
|
68
|
+
// a reviewer noticing, then a whole architect run, to work the rate out. It speaks until the next of them is
|
|
69
|
+
// forecast again; the rest are forecast at their turn. And for a step to land whose `Size:` line it cannot read,
|
|
70
|
+
// which no rate would count.
|
|
71
|
+
{
|
|
72
|
+
name: 'step sizes',
|
|
73
|
+
bin: 'nina',
|
|
74
|
+
args: ['sizes', '--check', '--quiet'],
|
|
75
|
+
hint: 'forecast the next of those steps again before it goes out — a `Size:` line, the number `nina sizes` lists for it — and send the architect only a step the new number puts past the limit, to split; the rest at their turn. A `Size:` line it cannot read is written `Size: ~N lines in M files`, the forecast followed by `lines`',
|
|
76
|
+
ignore: /^sizes: current$/,
|
|
77
|
+
},
|
|
78
|
+
// A detector of the project's own compares and never writes. A reviewer runs this check read-only, and one
|
|
79
|
+
// that regenerates what it checks reports a clean tree it has just changed.
|
|
80
|
+
<!-- nina:slot project.1 detectors -->
|
|
81
|
+
],
|
|
82
|
+
{ root: ROOT, hook: process.argv.includes('--hook'), context: process.argv.includes('--context') },
|
|
83
|
+
),
|
|
84
|
+
);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The loop gate, run by this project's Claude Code hooks.
|
|
4
|
+
*
|
|
5
|
+
* `.claude/graph.md` caps every loop-back edge. This holds the cap: it records the verdict each stage
|
|
6
|
+
* reports, each dispatch that goes out and each time the owner speaks, and sends the dispatch that would
|
|
7
|
+
* make a round past its edge's cap to the owner to confirm — the graph's `human`. The owner's next
|
|
8
|
+
* message starts every count over. It keeps metadata only, under ~/.nina/gate/.
|
|
9
|
+
*
|
|
10
|
+
* The mechanism lives in the NINA package; this file only says which project it guards. It prints
|
|
11
|
+
* nothing unless it has a decision to report, and it lets every call through if anything goes wrong —
|
|
12
|
+
* `nina gate --selftest`, run by `pnpm harness:check`, is what says so.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { dirname, resolve } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { runGate } from '@xhulz/nina/gate';
|
|
18
|
+
|
|
19
|
+
process.exitCode = await runGate({ root: resolve(dirname(dirname(fileURLToPath(import.meta.url)))) });
|