@xhulz/nina 0.58.1 → 0.60.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/package.json +1 -1
- package/releases/0.59.0/core/GAPS.md +125 -0
- package/releases/0.59.0/core/answered.json +74 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.59.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.59.0/core/tree/.claude/agents/architect.md +131 -0
- package/releases/0.59.0/core/tree/.claude/agents/dba.md +119 -0
- package/releases/0.59.0/core/tree/.claude/agents/design-reviewer.md +75 -0
- package/releases/0.59.0/core/tree/.claude/agents/devops.md +118 -0
- package/releases/0.59.0/core/tree/.claude/agents/implementer.md +164 -0
- package/releases/0.59.0/core/tree/.claude/agents/integration-tester.md +170 -0
- package/releases/0.59.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.59.0/core/tree/.claude/agents/qa.md +150 -0
- package/releases/0.59.0/core/tree/.claude/agents/reviewer.md +187 -0
- package/releases/0.59.0/core/tree/.claude/agents/secops.md +120 -0
- package/releases/0.59.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.59.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.59.0/core/tree/.claude/agents-overview.md +65 -0
- package/releases/0.59.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.59.0/core/tree/.claude/graph.md +79 -0
- package/releases/0.59.0/core/tree/.claude/patterns.md +251 -0
- package/releases/0.59.0/core/tree/.claude/pills/README.md +150 -0
- package/releases/0.59.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.59.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.59.0/core/tree/.claude/router.md +205 -0
- package/releases/0.59.0/core/tree/.claude/templates/integration.md +48 -0
- package/releases/0.59.0/core/tree/CLAUDE.md +166 -0
- package/releases/0.59.0/core/tree/scripts/cost-watch.mjs +25 -0
- package/releases/0.59.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.59.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.59.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.59.0/core/vocabulary.json +14 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.59.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.59.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.59.0/surfaces/d1/tree/.claude/agents/dba.md +15 -0
- package/releases/0.59.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.59.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.59.0/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.59.0/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.59.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.59.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.59.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.59.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.59.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.59.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.59.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.59.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.59.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.59.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.59.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.59.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.59.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.59.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.59.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.59.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.59.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.59.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.59.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.59.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.59.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.59.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.59.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.59.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.59.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.59.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.59.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/releases/0.60.0/core/GAPS.md +125 -0
- package/releases/0.60.0/core/answered.json +74 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.60.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.60.0/core/tree/.claude/agents/architect.md +132 -0
- package/releases/0.60.0/core/tree/.claude/agents/dba.md +119 -0
- package/releases/0.60.0/core/tree/.claude/agents/design-reviewer.md +76 -0
- package/releases/0.60.0/core/tree/.claude/agents/devops.md +118 -0
- package/releases/0.60.0/core/tree/.claude/agents/implementer.md +164 -0
- package/releases/0.60.0/core/tree/.claude/agents/integration-tester.md +170 -0
- package/releases/0.60.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.60.0/core/tree/.claude/agents/qa.md +150 -0
- package/releases/0.60.0/core/tree/.claude/agents/reviewer.md +187 -0
- package/releases/0.60.0/core/tree/.claude/agents/secops.md +120 -0
- package/releases/0.60.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.60.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.60.0/core/tree/.claude/agents-overview.md +65 -0
- package/releases/0.60.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.60.0/core/tree/.claude/graph.md +79 -0
- package/releases/0.60.0/core/tree/.claude/patterns.md +251 -0
- package/releases/0.60.0/core/tree/.claude/pills/README.md +150 -0
- package/releases/0.60.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.60.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.60.0/core/tree/.claude/router.md +205 -0
- package/releases/0.60.0/core/tree/.claude/templates/integration.md +48 -0
- package/releases/0.60.0/core/tree/CLAUDE.md +166 -0
- package/releases/0.60.0/core/tree/scripts/cost-watch.mjs +25 -0
- package/releases/0.60.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.60.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.60.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.60.0/core/vocabulary.json +14 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.60.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.60.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.60.0/surfaces/d1/tree/.claude/agents/dba.md +15 -0
- package/releases/0.60.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.60.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.60.0/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.60.0/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.60.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.60.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.60.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.60.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.60.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.60.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.60.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.60.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.60.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.60.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.60.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.60.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.60.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.60.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.60.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.60.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.60.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.60.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.60.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.60.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.60.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.60.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.60.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.60.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.60.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.60.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.60.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/src/commands/learn.mjs +42 -11
- package/src/commands/upgrade.mjs +23 -1
- package/src/dashboard.html +15 -8
- package/src/dashboard.mjs +1 -1
- package/src/office.html +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!-- nina:slot money.1 -->
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Monetary values & percentages
|
|
6
|
+
|
|
7
|
+
- **Money is an integer of the currency's minor unit**, end to end — {{MINOR_UNIT}}, never a float, never a type that can hold a fraction of one. Source of precision: `{{MONEY_MODULE}}`.
|
|
8
|
+
- **Percentages are basis points** (`40% → 4000`, `100% → 10000`) so a distribution is exact without floating point.
|
|
9
|
+
- **Parsing, formatting and percentage arithmetic live in one module and nowhere else.** A second place that turns a string into money is a second rounding rule, and the two will disagree on a value somebody is owed.
|
|
10
|
+
- **Never** convert to a floating-point type before formatting, and never let a display format round a stored value.
|
|
11
|
+
- Monetary database columns are integer. JSON responses serialize them as **strings**, not numbers, so no client parses them into a float. The service owns the conversion.
|
|
12
|
+
|
|
13
|
+
<!-- nina:slot money.2 -->
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Distribution invariants (enforced by reviewer + unit tests)
|
|
18
|
+
|
|
19
|
+
The distribution engine lives in `{{CORE_PKG}}`. It is pure and total over integer {{MINOR_UNIT}}:
|
|
20
|
+
|
|
21
|
+
- A destination is either a percentage (basis points of the amount) or a fixed value.
|
|
22
|
+
- `total = Σ destinations`, computed in {{MINOR_UNIT}}.
|
|
23
|
+
- `total > amount` → **reject.** Never clamp, never distribute what is not there.
|
|
24
|
+
- `total < amount` → **allow**, surface the shortfall, and leave the remainder **parked**. Silence is the defect here: an unexplained remainder is indistinguishable from a bug.
|
|
25
|
+
- `total = amount` → OK.
|
|
26
|
+
- A retention is just another destination — the same arithmetic applies to it, with no special case.
|
|
27
|
+
|
|
28
|
+
<!-- nina:slot money.3 -->
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## State machines & idempotency (enforced by reviewer)
|
|
33
|
+
|
|
34
|
+
- **Every money-moving entity is a state machine.** Its states and legal transitions are declared in `.claude/architecture.md`; the code follows the declaration, not the other way round. Illegal transitions throw; they are never silently coerced.
|
|
35
|
+
- **Every transition writes an audit row** (entity type, entity id, from, to, actor). No transition without a trail — the trail is what makes a money bug diagnosable after the money has moved.
|
|
36
|
+
- **Outbound transfers are idempotent.** Each carries a unique key, and dedupe happens before the side effect, at the serialization point.
|
|
37
|
+
- **One serialization point per balance.** Whatever computes and dispatches against a single balance never runs concurrently with itself. Two concurrent runs over one balance is how a double send happens even when every individual write is correct.
|
|
38
|
+
|
|
39
|
+
<!-- nina:slot money.4 -->
|
|
40
|
+
- **Money computation and dispatch go through the serialization point.** Routes, queue consumers and tools never run a distribution or a transfer synchronously in the request path.
|
|
41
|
+
|
|
42
|
+
<!-- nina:slot money.5 -->
|
|
43
|
+
- **The distribution engine lives in `{{CORE_PKG}}`.** Services call it as a pure function; they do not embed money logic inline.
|
|
44
|
+
|
|
45
|
+
<!-- nina:slot money.6 -->
|
|
46
|
+
- Idempotency on money-moving writes: the record carries an idempotency key, and the serialization point refuses the second attempt *before* the side effect.
|
|
47
|
+
|
|
48
|
+
<!-- nina:slot money.7 -->
|
|
49
|
+
- `{{CORE_PKG}}` is the most-tested package — pure functions over fixtures. Cover the distribution invariants exhaustively: over, under, exact, mixed percentage and fixed, and rounding.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!-- nina:slot money.1 -->
|
|
2
|
+
3. **An outbound transfer is idempotent — it is NEVER sent twice.** Every transfer carries an idempotency key, and deduplication happens at a single serialization point **before** the side effect, never after it. A retry, a re-delivered queue message, a double-click and a replayed webhook must all collapse to one transfer. This is the highest-blast-radius invariant in the system: almost everything else can be corrected afterwards, and a duplicated transfer cannot.
|
|
3
|
+
|
|
4
|
+
<!-- nina:slot money.2 -->
|
|
5
|
+
4. **Conservation — what comes in equals what goes out plus what is retained.** A distribution may NEVER exceed the amount it distributes → **block**. If it is **less**, **alert** and leave the remainder **parked** and visible — never silently distributed, never silently absorbed. All arithmetic is integer {{MINOR_UNIT}}; percentages are basis points. The LLM never computes a monetary value.
|
|
6
|
+
|
|
7
|
+
<!-- nina:slot money.3 -->
|
|
8
|
+
5. **State-machine integrity.** Every money-moving entity has an explicit set of states and legal transitions, declared in `.claude/architecture.md` § *State machines* — not inferred from whatever code happens to exist. Only declared transitions are legal; an illegal one throws and is never silently coerced. **Every transition writes an audit row** (entity, id, from → to, actor, when). Skipping a state, inventing one, or landing a transition with no audit row is a hard reject.
|
|
9
|
+
|
|
10
|
+
<!-- nina:slot money.4 -->
|
|
11
|
+
- **money movement**: anything that creates, moves, settles or records a balance
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- nina:slot pii.1 -->
|
|
2
|
+
- **Privacy.** No sensitive value in clear text where it must not be. The categories are declared in `.claude/architecture.md` § *Privacy* — they are not decided per query, and not decided by you. **Document bytes live only in the object store, referenced by key: the column holds the key, never the bytes.** Any column the architect's spec flagged for masking must be encrypted at rest. Reject a schema that widens what is stored in the clear.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<!-- nina:slot pii.1 -->
|
|
2
|
+
|
|
3
|
+
**Point it at an UNAUTHENTICATED route — a sign-in page is the right one.** Never sign in, and never
|
|
4
|
+
screenshot a signed-in page. Accounts on deployed environments hold real personal data, and a
|
|
5
|
+
screenshot or a console dump pulls it into agent transcripts and logs, where it persists and nobody
|
|
6
|
+
ever looks for it again. That is a privacy leak with no upside here: the sign-in page proves
|
|
7
|
+
everything this check is for. It renders from the same bundle, it exercises the same build-time env
|
|
8
|
+
inlining (a missing variable blanks it identically), and it needs no session.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<!-- nina:slot pii.1 -->
|
|
2
|
+
- Check for privacy regressions: **no sensitive value in a log, an error message — a library's own included — a URL or a test fixture**, per the categories in `.claude/architecture.md` § *Privacy*; document bytes only in the object store, never plaintext in the database; no leaked secret.
|
|
3
|
+
|
|
4
|
+
<!-- nina:slot pii.2 -->
|
|
5
|
+
- **privacy** — the privacy check above, in full: no sensitive value in a log, an error message, a
|
|
6
|
+
URL or a test fixture; document bytes only in the object store; no leaked secret. Where
|
|
7
|
+
**tenant-and-privacy** is dispatched, its reviewer owns this too and there is no separate one; where
|
|
8
|
+
it is not, this is a dimension of its own. Either way it is never nobody's.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<!-- nina:slot pii.1 -->
|
|
2
|
+
- **Privacy (Hard Rule #8)** — the categories declared in `.claude/architecture.md` § *Privacy* must never appear in logs, in responses that do not need them, in error paths, or in the database in clear text. Check every endpoint that returns a person's record for fields it includes by accident: a `select` that quietly grew a column is the usual way this leaks. Check the error paths too — they are written last and reviewed least — and what the libraries on them print or carry in their own errors, bound values included.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<!-- nina:slot pii.1 -->
|
|
2
|
+
- **Nothing personal reaches the chain.** What is written on-chain is public, permanent, and beyond
|
|
3
|
+
deletion by anyone — including by you, and including after a subject asks. A hash of a personal
|
|
4
|
+
identifier is not a protection: it is a lookup table for whoever holds the input set. Reject a
|
|
5
|
+
personal datum stored in state, emitted in an event, or passed as calldata.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<!-- nina:slot pii.1 -->
|
|
2
|
+
8. **Sensitive personal data is classified, and the classification is enforced.** What counts as sensitive here — identity documents, financial identifiers, anything a person would not expect to be readable by whoever can read a log — is declared in `.claude/architecture.md` § *Privacy*, along with the regime that governs it ({{PRIVACY_REGIME}}). Encrypted at rest. **No sensitive value in a log, an error message, a URL, an analytics event, or an agent transcript** — the places nobody thinks about are exactly the ones that persist. That includes what a library puts in its own errors and prints itself: a database client's error can carry the query and every bound value, and a framework can log a whole error past the logger it was given. A database error is mapped at the data layer to a typed error from a closed list before anything logs or returns it, and a test proves that a bound value it writes reaches no thrown error. Document bytes live only in the object store, referenced by key, never in the database in clear text.
|
|
3
|
+
|
|
4
|
+
<!-- nina:slot pii.2 -->
|
|
5
|
+
- **personal data**: where it is collected, stored, logged or sent
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!-- nina:slot prisma.1 -->
|
|
2
|
+
| `prisma-cli` | **before ANY `prisma` CLI command** — `validate`, `format`, `migrate dev`, `migrate diff`, `migrate deploy`. Flags differ between versions, and one of them (`migrate diff --shadow-database-url` against a live database) destroys the database it points at |
|
|
3
|
+
| `prisma-client-api` | auditing a new or changed query — filters, operators, `$transaction` semantics. Through a driver adapter, cite the adapter's installed source for what a transaction does: the skill describes the default engine, and an adapter can roll back less |
|
|
4
|
+
|
|
5
|
+
<!-- nina:slot prisma.2 -->
|
|
6
|
+
Neither skill covers a **caching or edge layer sitting on top of the client** — cache strategy,
|
|
7
|
+
edge-client behaviour and the rule about never caching a read that authorizes a write belong to that
|
|
8
|
+
layer's own integration doc, declared like any other integration. A skill does not replace it.
|
|
9
|
+
|
|
10
|
+
<!-- nina:slot prisma.3 -->
|
|
11
|
+
- **With Prisma, both offline.** Run `pnpm --filter {{DB_PKG_NAME}} exec prisma validate`; it must pass. Then run `prisma migrate diff` in its **offline, file-only form** and read the generated SQL, not just the Prisma delta. Its flags changed in Prisma 7, so read the installed major (`prisma --version`) before writing the command:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
# Prisma 6. Compare the PREVIOUS schema against the working one — pure file-to-file, no database.
|
|
15
|
+
git show HEAD:{{DB_PKG}}/prisma/schema.prisma > /tmp/schema-head.prisma
|
|
16
|
+
pnpm --filter {{DB_PKG_NAME}} exec prisma migrate diff \
|
|
17
|
+
--from-schema-datamodel /tmp/schema-head.prisma \
|
|
18
|
+
--to-schema-datamodel prisma/schema.prisma \
|
|
19
|
+
--script
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
From Prisma 7 the two flags are `--from-schema` and `--to-schema`, and the schema engine starts from the
|
|
23
|
+
datasource in `prisma.config.ts` even for this diff: with none there, it prints nothing and exits 0. For
|
|
24
|
+
SQLite a placeholder the diff never opens is enough, a `file:` URL under a gitignored directory; for any
|
|
25
|
+
other provider, find out what the diff opens before you give it one. Never a real database's URL. A first schema has nothing at `HEAD`: diff it `--from-empty`. Compare the output against the
|
|
26
|
+
hand-written `migration.sql` to confirm the declarative parts match.
|
|
27
|
+
|
|
28
|
+
⚠️ **Do NOT reach for `--from-migrations`.** It looks like the natural choice and it is a trap:
|
|
29
|
+
Prisma refuses it without a shadow database (`--shadow-database-url`, or from Prisma 7 a
|
|
30
|
+
`shadowDatabaseUrl` in `prisma.config.ts`), which pushes you toward supplying a database URL — the exact move that destroys databases (below). The file-to-file form above answers the
|
|
31
|
+
same question with no database involved.
|
|
32
|
+
|
|
33
|
+
⛔ **NEVER point `--shadow-database-url`, `--from-url`, `--to-url`, `--from-schema-datasource` — or, from Prisma 7, a `shadowDatabaseUrl` or the config datasource behind `--from-config-datasource` — at a real database, most of all not the one `{{SECRETS_LOCAL}}` names.** Prisma **executes** the entire migration history against whatever database those flags name, which **DESTROYS ALL DATA** in it. A shadow database must be a disposable, empty database and nothing else. It does not announce itself: the command completes with a reassuring "empty migration" result and no error, having already destroyed everything in the database it was pointed at. If the offline form above cannot answer your question, **STOP and report that to the orchestrator** instead of reaching for a database URL.
|
|
34
|
+
|
|
35
|
+
<!-- nina:slot prisma.4 -->
|
|
36
|
+
- **Where reads are cached through Prisma Accelerate,** every `findUnique` / `findMany` on a hot read path names its `cacheStrategy` (`ttl` / `swr`), and one that feeds a correctness-critical write names none.
|
|
37
|
+
|
|
38
|
+
<!-- nina:slot prisma.5 -->
|
|
39
|
+
- **On an edge runtime,** new Prisma code paths use the edge client of the installed major: `@prisma/client/edge` up to Prisma 6; from 7, the client the `prisma-client` generator writes with the platform's `runtime` set, imported from where it is generated — `@prisma/client/edge` fails there with `MODULE_NOT_FOUND`.
|
|
40
|
+
|
|
41
|
+
<!-- nina:slot prisma.6 -->
|
|
42
|
+
- Run a Prisma command that writes to a real database — `prisma migrate dev`, `migrate deploy`, `migrate reset`, `migrate resolve`, `db push`, `db execute`, `$executeRaw*` — or **any `prisma migrate diff` variant carrying a database URL**, which silently wipes the database it points at.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!-- nina:slot prisma.1 -->
|
|
2
|
+
- **`prisma-cli`** — before `migrate deploy` or any other Prisma CLI command against a real database.
|
|
3
|
+
|
|
4
|
+
<!-- nina:slot prisma.2 -->
|
|
5
|
+
- **Prisma migrations go out with `prisma migrate deploy`**, and nothing else changes a shared database's schema.
|
|
6
|
+
|
|
7
|
+
<!-- nina:slot prisma.3 -->
|
|
8
|
+
- Run `prisma migrate diff --shadow-database-url <url>` against any live database. It **executes** the migration history against that database, destroying everything in it, and reports success. Use a disposable shadow database or don't run it.
|
|
9
|
+
|
|
10
|
+
<!-- nina:slot prisma.4 -->
|
|
11
|
+
- Run `prisma migrate reset` against a shared database, ever.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!-- nina:slot prisma.1 -->
|
|
2
|
+
- **Database table/column names** (Prisma `@map` / `@@map`): `snake_case` in SQL, `camelCase` in TS.
|
|
3
|
+
|
|
4
|
+
<!-- nina:slot prisma.2 -->
|
|
5
|
+
- Where Prisma reads are cached through Accelerate, `cacheStrategy` lives in `{{DB_PKG}}`: services do not add, strip, or override cache policies.
|
|
6
|
+
|
|
7
|
+
<!-- nina:slot prisma.3 -->
|
|
8
|
+
|
|
9
|
+
### Prisma
|
|
10
|
+
|
|
11
|
+
- Schema lives in `{{DB_PKG}}/prisma/schema.prisma`. Nowhere else.
|
|
12
|
+
- **Never write raw SQL** unless justified in a code comment with perf data.
|
|
13
|
+
- N+1 is solved with `include` / `select`, chosen deliberately.
|
|
14
|
+
- Where reads are cached through Accelerate, every `findUnique` / `findMany` on a hot path defines its `cacheStrategy`, and no direct connection string is embedded in code.
|
|
15
|
+
- Tests run a real Prisma client against a real database; the client is never mocked.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<!-- nina:slot prisma.1 -->
|
|
2
|
+
| Run any `prisma` CLI command (the database gate, devops, and the integration gate where there is one) | `prisma-cli` | flags differ between versions; `migrate diff --shadow-database-url` against a live DB wiped dev/staging once |
|
|
3
|
+
|
|
4
|
+
<!-- nina:slot prisma.2 -->
|
|
5
|
+
| Write or audit a Prisma query (architect, implementer, the database gate, reviewer) | `prisma-client-api` | filters, operators, `$transaction` semantics. a caching or edge layer on top of the client is **NOT covered** — its cache strategy belongs to that layer's own integration doc |
|
package/src/commands/learn.mjs
CHANGED
|
@@ -281,14 +281,26 @@ function wilson(k, n) {
|
|
|
281
281
|
*
|
|
282
282
|
* A round is counted sent back once, however many loop-backs sent it: the checkers that run beside each other
|
|
283
283
|
* each reject the same work, and one project's architect had 14 loop-backs on a day it ran 7 rounds, which the
|
|
284
|
-
* share read as 100% sent back where 5 of the 7 were.
|
|
284
|
+
* share read as 100% sent back where 5 of the 7 were. Each loop-back is charged to the round its work came from:
|
|
285
|
+
* the stage's newest round before it, in its session.
|
|
286
|
+
*
|
|
287
|
+
* The change is read on first attempts: the rounds that did not take back work sent back to the stage. A fix is
|
|
288
|
+
* sent back far more often than new work, and how many of a stage's rounds are fixes moves with the work — one
|
|
289
|
+
* project's architect wrote first specs the week before its lessons and corrected hard ones the week after, 22 of
|
|
290
|
+
* 23 rounds, and its share went from 14% to 84%, read as the lessons making it worse, while its corrections were
|
|
291
|
+
* sent back as often as before (60% and 55%). Nor can the two be read side by side: a fix exists because a round
|
|
292
|
+
* before it failed, so a lesson that works leaves fewer of them, and a comparison that waited on both read the
|
|
293
|
+
* lessons that worked as unclear. The fixes are shown, not judged.
|
|
285
294
|
*
|
|
286
295
|
* @param {object[]} records - Recorded dispatches.
|
|
287
296
|
* @param {Awaited<ReturnType<typeof lessons>>} known - The project's pills.
|
|
288
297
|
* @param {{owners?: ReturnType<typeof sentBackTo>, targets?: Set<string>|null}} [graph] - Who each loop-back sent
|
|
289
298
|
* work back to, and the stages the graph sends work back to at all.
|
|
290
299
|
* @returns {{rel: string, date: string, role: string, comparable: boolean, why?: string, on?: string|null,
|
|
291
|
-
* was?: string, before?: Side, after?: Side,
|
|
300
|
+
* was?: string, before?: Side, after?: Side, first?: {before: Side, after: Side}, fixes?: {before: Side, after: Side},
|
|
301
|
+
* thin?: boolean, change?: 'lower'|'higher'|'unclear', control?: {before: Side, after: Side}}[]}
|
|
302
|
+
* `before` and `after` are all its rounds, `first` its first attempts, `fixes` the rounds that took back its work;
|
|
303
|
+
* `thin` says the first attempts were too few either side to read a change, which is then `unclear`.
|
|
292
304
|
* A `Side` is `{n, loops, span}`: the stage's rounds, how many were sent back, and the first and last day a round
|
|
293
305
|
* of it was recorded on, since a project younger than the window has fewer days than fourteen to show.
|
|
294
306
|
*/
|
|
@@ -296,6 +308,8 @@ export function verified(records, known, { owners = new Map(), targets = null }
|
|
|
296
308
|
const out = [];
|
|
297
309
|
const ownerOf = (r) => chargedTo(owners, r);
|
|
298
310
|
const sentBack = records.filter((r) => readable(r.verdict) && isLoopBack(r.verdict));
|
|
311
|
+
const fixes = new Set([...owners.values()].map((o) => o.fix).filter(Boolean));
|
|
312
|
+
const byTime = (a, b) => String(a.ts).localeCompare(String(b.ts));
|
|
299
313
|
const sideOf = (these, backs) => {
|
|
300
314
|
const days = these.map((r) => day(r.ts)).sort();
|
|
301
315
|
return { n: these.length, loops: Math.min(these.length, sendings(owners, backs)), span: [days[0] ?? null, days.at(-1) ?? null] };
|
|
@@ -312,8 +326,21 @@ export function verified(records, known, { owners = new Map(), targets = null }
|
|
|
312
326
|
out.push({ ...base, comparable: false, why: `nothing in the graph sends work back to ${role}` });
|
|
313
327
|
continue;
|
|
314
328
|
}
|
|
315
|
-
const rounds = records.filter((r) => r.role === role && readable(r.verdict));
|
|
329
|
+
const rounds = records.filter((r) => r.role === role && readable(r.verdict)).sort(byTime);
|
|
316
330
|
const backs = sentBack.filter((r) => ownerOf(r) === role);
|
|
331
|
+
// The round a loop-back sent back: its own record, where the graph routes it nowhere and it is charged to the stage
|
|
332
|
+
// that gave it; else the stage's round that had finished, in its session, when the loop-back's stage began — read
|
|
333
|
+
// over every round of it, so one whose verdict cannot be read takes the charge, uncounted, rather than an older one.
|
|
334
|
+
const all = records.filter((r) => r.role === role).sort(byTime);
|
|
335
|
+
const sourceOf = (b) => {
|
|
336
|
+
if (!owners.has(b)) return b;
|
|
337
|
+
return all.findLast((r) => r.session && r.session === b.session && String(r.result_ts ?? r.ts) <= String(b.ts)) ?? null;
|
|
338
|
+
};
|
|
339
|
+
const sentRounds = new Set(backs.map(sourceOf).filter(Boolean));
|
|
340
|
+
const counted = (these) => {
|
|
341
|
+
const days = these.map((r) => day(r.ts)).sort();
|
|
342
|
+
return { n: these.length, loops: these.filter((r) => sentRounds.has(r)).length, span: [days[0] ?? null, days.at(-1) ?? null] };
|
|
343
|
+
};
|
|
317
344
|
const side = (pick, mine) => sideOf(mine.filter(pick), backs.filter(pick));
|
|
318
345
|
if (side(pre, rounds).n < VERIFY_MIN || side(post, rounds).n < VERIFY_MIN) {
|
|
319
346
|
const [b, a] = [side(pre, rounds).n, side(post, rounds).n];
|
|
@@ -326,21 +353,24 @@ export function verified(records, known, { owners = new Map(), targets = null }
|
|
|
326
353
|
for (const r of rounds.filter(post)) if (ranOn(r)) tally.set(ranOn(r), (tally.get(ranOn(r)) ?? 0) + 1);
|
|
327
354
|
const on = [...tally].sort((x, y) => y[1] - x[1])[0]?.[0] ?? null;
|
|
328
355
|
const mine = on ? rounds.filter((r) => ranOn(r) === on) : rounds;
|
|
329
|
-
const before =
|
|
330
|
-
const after =
|
|
356
|
+
const before = counted(mine.filter(pre));
|
|
357
|
+
const after = counted(mine.filter(post));
|
|
331
358
|
if (before.n < VERIFY_MIN || after.n < VERIFY_MIN) {
|
|
332
359
|
const was = [...new Set(rounds.filter(pre).map(ranOn).filter(Boolean))].join(', ') || 'no recorded model';
|
|
333
360
|
out.push({ ...base, on, was, comparable: false, why: `${role} ran on ${on} after it, and before it on ${was}` });
|
|
334
361
|
continue;
|
|
335
362
|
}
|
|
336
|
-
const
|
|
337
|
-
const
|
|
338
|
-
const
|
|
363
|
+
const first = { before: counted(mine.filter((r) => pre(r) && !fixes.has(r))), after: counted(mine.filter((r) => post(r) && !fixes.has(r))) };
|
|
364
|
+
const fixed = { before: counted(mine.filter((r) => pre(r) && fixes.has(r))), after: counted(mine.filter((r) => post(r) && fixes.has(r))) };
|
|
365
|
+
const thin = first.before.n < VERIFY_MIN || first.after.n < VERIFY_MIN;
|
|
366
|
+
const [bLo, bHi] = wilson(first.before.loops, first.before.n);
|
|
367
|
+
const [aLo, aHi] = wilson(first.after.loops, first.after.n);
|
|
368
|
+
const change = thin ? 'unclear' : aHi < bLo ? 'lower' : aLo > bHi ? 'higher' : 'unclear';
|
|
339
369
|
const others = [...(targets ?? new Set(sentBack.map(ownerOf)))].filter((x) => x && x !== role);
|
|
340
370
|
const theirs = records.filter((r) => others.includes(r.role) && readable(r.verdict));
|
|
341
371
|
const otherBacks = sentBack.filter((r) => others.includes(ownerOf(r)));
|
|
342
372
|
const control = (pick) => sideOf(theirs.filter(pick), otherBacks.filter(pick));
|
|
343
|
-
out.push({ ...base, comparable: true, on, before, after, change, control: { before: control(pre), after: control(post) } });
|
|
373
|
+
out.push({ ...base, comparable: true, on, before, after, first, fixes: fixed, thin, change, control: { before: control(pre), after: control(post) } });
|
|
344
374
|
}
|
|
345
375
|
}
|
|
346
376
|
return out;
|
|
@@ -1184,10 +1214,11 @@ export async function learn(argv, ctx) {
|
|
|
1184
1214
|
const unmeasured = checks.filter((c) => !c.comparable);
|
|
1185
1215
|
if (measured.length === 0) console.log(` verify no lesson could be measured yet — ${VERIFY_MIN}+ rounds of its stage on the same model are needed in the ${VERIFY_DAYS} days either side of its date`);
|
|
1186
1216
|
measured.forEach((c, i) => {
|
|
1187
|
-
const said = { lower: 'sent back less since', higher: 'sent back more since', unclear: 'no clear change' }[c.change];
|
|
1217
|
+
const said = c.thin ? 'too few first attempts to tell' : { lower: 'sent back less since', higher: 'sent back more since', unclear: 'no clear change' }[c.change];
|
|
1188
1218
|
console.log(
|
|
1189
1219
|
` ${i === 0 ? 'verify ' : ' '} ${c.rel.replace(/^\.claude\/pills\//, '')} (${c.date}) · ${c.role}${c.on ? `, on ${c.on}` : ''}: ` +
|
|
1190
|
-
`${pct(c.before.loops, c.before.n)} → ${pct(c.after.loops, c.after.n)} of its
|
|
1220
|
+
`${pct(c.first.before.loops, c.first.before.n)} → ${pct(c.first.after.loops, c.first.after.n)} of its first attempts sent back (n ${c.first.before.n} → ${c.first.after.n}) — ${said}; ` +
|
|
1221
|
+
`its fixes ${pct(c.fixes.before.loops, c.fixes.before.n)} → ${pct(c.fixes.after.loops, c.fixes.after.n)}; ` +
|
|
1191
1222
|
`the other stages ${pct(c.control.before.loops, c.control.before.n)} → ${pct(c.control.after.loops, c.control.after.n)}`,
|
|
1192
1223
|
);
|
|
1193
1224
|
});
|
package/src/commands/upgrade.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import { readFile } from 'node:fs/promises';
|
|
|
13
13
|
import { spawnSync } from 'node:child_process';
|
|
14
14
|
import { describeMove, HARNESS, interruptedMove, movedFrom, moveJournal, readProfile, surfacesIn } from '../paths.mjs';
|
|
15
15
|
import { existsSync, lstatSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
16
|
-
import { dirname, join, resolve } from 'node:path';
|
|
16
|
+
import { dirname, join, resolve, sep } from 'node:path';
|
|
17
17
|
import { REMOVED, composeProject, composedPaths, defaultedSlots, layerRootFor, walk } from './compose.mjs';
|
|
18
18
|
import { detected, missingNeeds } from '../surfaces.mjs';
|
|
19
19
|
import { filledSlots, projectSlots, referencedVocabulary } from './check.mjs';
|
|
@@ -22,6 +22,7 @@ import { closeAnswered } from './learn.mjs';
|
|
|
22
22
|
import { tidyRetired } from './pills.mjs';
|
|
23
23
|
import { lacksPackage, missingFragment, missingWiring, shippedScripts } from '../wiring.mjs';
|
|
24
24
|
import { runSteps } from '../steps.mjs';
|
|
25
|
+
import { granted } from '../tools.mjs';
|
|
25
26
|
import { defaultVocabulary } from '../vocabulary.mjs';
|
|
26
27
|
|
|
27
28
|
/** What stops a move from outside it: Ctrl-C, a `kill`, the terminal closing. */
|
|
@@ -641,6 +642,27 @@ export async function upgrade(argv, ctx) {
|
|
|
641
642
|
console.log(`\n ${newVocab.length} vocabulary name(s) ${to} asks for and this profile does not answer — fill each, or defer it with why:`);
|
|
642
643
|
console.log(` ${newVocab.join(', ')}`);
|
|
643
644
|
}
|
|
645
|
+
// Claude Code reads which agents exist, and each one's tools, when a session starts, and an agent's body on every
|
|
646
|
+
// dispatch. A session left open runs the new specs with the old tools, and a rule that asks for a tool its stage was
|
|
647
|
+
// only now given goes unfollowed without a word.
|
|
648
|
+
const restaged = [];
|
|
649
|
+
for (const p of [...pathsAfter].sort()) {
|
|
650
|
+
const rel = p.split(sep).join('/');
|
|
651
|
+
if (!/^\.claude\/agents\/[^/]+\.md$/.test(rel) || !entryAt(p)) continue;
|
|
652
|
+
const role = rel.slice('.claude/agents/'.length, -'.md'.length);
|
|
653
|
+
if (!pathsBefore.has(p) || !saved.has(p)) {
|
|
654
|
+
restaged.push(`${role}: a new stage`);
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
657
|
+
const was = granted(saved.get(p).toString('utf8'));
|
|
658
|
+
const now = granted(readFileSync(join(target, p), 'utf8'));
|
|
659
|
+
const change = [...now.filter((t) => !was.includes(t)).map((t) => `+${t}`), ...was.filter((t) => !now.includes(t)).map((t) => `-${t}`)];
|
|
660
|
+
if (change.length > 0) restaged.push(`${role}: ${change.join(', ')}`);
|
|
661
|
+
}
|
|
662
|
+
if (restaged.length > 0) {
|
|
663
|
+
console.log(`\n ${restaged.length} stage(s) a session already open does not have as ${to} composes them — Claude Code reads which agents exist, and their tools, when a session starts. Open a new one before the next dispatch:`);
|
|
664
|
+
for (const r of restaged) console.log(` ${r}`);
|
|
665
|
+
}
|
|
644
666
|
console.log('');
|
|
645
667
|
return 0;
|
|
646
668
|
}
|
package/src/dashboard.html
CHANGED
|
@@ -232,7 +232,8 @@ const RENDER = {
|
|
|
232
232
|
// Lessons written the same day for the same stage are read over the same rounds, so they are one comparison, not
|
|
233
233
|
// a row each repeating its numbers.
|
|
234
234
|
const groups = [];
|
|
235
|
-
for
|
|
235
|
+
// A payload from before first attempts were read: its rounds stand in for them, and none is marked a fix.
|
|
236
|
+
for (const c of d.checks.filter((x) => x.before).map((x) => ({ fixes: { before: { n: 0, loops: 0, span: [null, null] }, after: { n: 0, loops: 0, span: [null, null] } }, first: { before: x.before, after: x.after }, ...x }))) {
|
|
236
237
|
const same = groups.find((g) => g.role === c.role && g.date === c.date && g.on === c.on);
|
|
237
238
|
if (same) same.lessons.push(c.rel);
|
|
238
239
|
else groups.push({ ...c, lessons: [c.rel] });
|
|
@@ -247,11 +248,14 @@ const RENDER = {
|
|
|
247
248
|
// The share is of work sent back, so up is worse. A move the rounds are too few to tell from chance still says
|
|
248
249
|
// which way it went: "could be chance" alone read, beside 33% → 67%, as if the larger number were the better one.
|
|
249
250
|
const share = (side) => (side.n ? Math.round((100 * side.loops) / side.n) : 0);
|
|
251
|
+
// Read on first attempts: a fix is sent back more often than new work, and a week of fixes after a week of first
|
|
252
|
+
// specs read as a lesson making its stage worse.
|
|
250
253
|
const verdict = (g) =>
|
|
251
|
-
g.
|
|
254
|
+
g.thin ? ['faint', '≈ too few first attempts to tell']
|
|
255
|
+
: g.change === 'lower' ? ['ok', '▼ better: sent back less']
|
|
252
256
|
: g.change === 'higher' ? ['bad', '▲ worse: sent back more']
|
|
253
|
-
: share(g.after) > share(g.before) ? ['faint', '▲ sent back more, but could be chance']
|
|
254
|
-
: share(g.after) < share(g.before) ? ['faint', '▼ sent back less, but could be chance']
|
|
257
|
+
: share(g.first.after) > share(g.first.before) ? ['faint', '▲ sent back more, but could be chance']
|
|
258
|
+
: share(g.first.after) < share(g.first.before) ? ['faint', '▼ sent back less, but could be chance']
|
|
255
259
|
: ['faint', '≈ no change'];
|
|
256
260
|
|
|
257
261
|
const answer = !groups.length
|
|
@@ -277,9 +281,12 @@ const RENDER = {
|
|
|
277
281
|
g.on ? el('span', { class: 'faint mono' }, g.on) : null,
|
|
278
282
|
el('span', { class: `verdict ${verdict(g)[0]}` }, verdict(g)[1]),
|
|
279
283
|
),
|
|
280
|
-
el('div', { class: 'faint', style: 'font-size:12px;margin:0 0 2px' }, `share of the ${g.role}'s
|
|
281
|
-
|
|
282
|
-
meter('after', g.after),
|
|
284
|
+
el('div', { class: 'faint', style: 'font-size:12px;margin:0 0 2px' }, `share of the ${g.role}'s first attempts sent back to it · lower is better`),
|
|
285
|
+
// Too few to tell is drawn faint, so a 100% of one round does not read as a result.
|
|
286
|
+
el('div', { style: g.thin ? 'opacity:.45' : '' }, meter('before', g.first.before), meter('after', g.first.after)),
|
|
287
|
+
el('div', { class: 'faint', style: 'font-size:12px;margin:6px 0 0' },
|
|
288
|
+
`its fixes of work sent back, shown, not judged: ${pct(g.fixes.before.loops, g.fixes.before.n)} of ${g.fixes.before.n} → ${pct(g.fixes.after.loops, g.fixes.after.n)} of ${g.fixes.after.n}. ` +
|
|
289
|
+
'A fix is sent back more often than new work, and a lesson that works leaves fewer of them.'),
|
|
283
290
|
el('div', { class: 'faint', style: 'margin:6px 0 8px' }, `for reference, the other stages over the same days: ${pct(g.control.before.loops, g.control.before.n)} → ${pct(g.control.after.loops, g.control.after.n)}`),
|
|
284
291
|
el('div', { class: 'chips' }, g.lessons.map(lessonChip)),
|
|
285
292
|
);
|
|
@@ -310,7 +317,7 @@ const RENDER = {
|
|
|
310
317
|
),
|
|
311
318
|
d.late.length ? [el('h3', {}, 'capture · sent back with nothing written down'), d.late.map((o) => el('div', { class: 'note' }, el('span', { class: 'role' }, o.role), ` sent back ${o.count} time(s) ${o.since ? `since its newest lesson (${o.since})` : 'and no lesson at all'}`, el('ul', { class: 'list soft' }, o.recent.map((r) => el('li', {}, `${when(r.ts)} · ${r.desc ?? '(no description)'}`)))))] : null,
|
|
312
319
|
el('h3', {}, 'verify · is each stage sent back less since its lessons?'),
|
|
313
|
-
el('p', { class: 'note soft', style: 'margin-bottom:12px' }, `For each lesson, the share of its stage's
|
|
320
|
+
el('p', { class: 'note soft', style: 'margin-bottom:12px' }, `For each lesson, the share of its stage's first attempts that a later stage sent back, in the ${d.window} days before it was written and the ${d.window} after — lower is better. First attempts, because a fix of work already sent back is sent back more often, and a week of fixes after a week of new work would read as the lesson making things worse. A change is called only when it is larger than chance moves a share at that many rounds. The other stages, over the same days, say whether everything moved at once: then it was the work that changed, not the lesson.`),
|
|
314
321
|
groups.length ? groups.map(comparison) : el('p', { class: 'note faint' }, 'No lesson could be measured yet.'),
|
|
315
322
|
d.owed.length ? [el('h3', {}, 'to graduate · here or in the harness'), d.owed.map((o) => el('p', { class: 'note' }, el('span', { class: 'mono' }, o.rel), o.declined ? el('span', { class: 'soft' }, ` — declined by the harness${o.declined.in ? ` in ${o.declined.in}` : ''}: ${o.declined.why}`) : el('span', { class: 'soft' }, ` — recurred ${o.occurrences} times`)))] : null,
|
|
316
323
|
d.open.length ? [el('h3', {}, 'requests open in the harness'), table(['since', 'pill', 'proposed for'], d.open.map((r) => [el('span', { class: 'mono soft' }, r.date), el('span', { class: 'mono' }, r.pill), r.target]))] : null,
|
package/src/dashboard.mjs
CHANGED
|
@@ -87,7 +87,7 @@ export function dashboardTabs(target, ctx) {
|
|
|
87
87
|
madeHere: d.madeHere,
|
|
88
88
|
relapses: d.relapses.map(({ lesson, request, recurred, due }) => ({ rel: lesson.rel, recurred, due, target: request.target, rule_in: request.rule_in, answered_in: request.answered_in })),
|
|
89
89
|
use: d.use,
|
|
90
|
-
checks: d.checks.map((c) => (c.comparable ? { rel: c.rel, role: c.role, date: c.date, on: c.on ?? null, before: c.before, after: c.after, change: c.change, control: c.control } : { rel: c.rel, role: c.role, why: c.why })),
|
|
90
|
+
checks: d.checks.map((c) => (c.comparable ? { rel: c.rel, role: c.role, date: c.date, on: c.on ?? null, before: c.before, after: c.after, first: c.first, fixes: c.fixes, thin: c.thin, change: c.change, control: c.control } : { rel: c.rel, role: c.role, why: c.why })),
|
|
91
91
|
activity: d.activity,
|
|
92
92
|
gated: d.gated,
|
|
93
93
|
};
|
package/src/office.html
CHANGED
|
@@ -1196,7 +1196,7 @@ function drawScreen(now) {
|
|
|
1196
1196
|
}
|
|
1197
1197
|
{
|
|
1198
1198
|
const [x, y] = at(COUNTER.x + COUNTER.w / 2, COUNTER.y + 6);
|
|
1199
|
-
plate('
|
|
1199
|
+
plate('orchestrator', x, y, label, '#fff8e8', (COUNTER.w - 8) * scale);
|
|
1200
1200
|
// NINA's name goes with her, beside her head, wherever she carries the work.
|
|
1201
1201
|
const [ninaX, ninaY] = at(boss.x + 7, boss.y - 9);
|
|
1202
1202
|
s.font = `600 ${label}px ${SANS}`;
|