@xhulz/nina 0.48.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/bin/nina.mjs +10 -1
- package/package.json +1 -1
- package/releases/0.49.0/core/GAPS.md +125 -0
- package/releases/0.49.0/core/answered.json +53 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.49.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.49.0/core/tree/.claude/agents/architect.md +129 -0
- package/releases/0.49.0/core/tree/.claude/agents/dba.md +117 -0
- package/releases/0.49.0/core/tree/.claude/agents/devops.md +118 -0
- package/releases/0.49.0/core/tree/.claude/agents/implementer.md +162 -0
- package/releases/0.49.0/core/tree/.claude/agents/integration-tester.md +168 -0
- package/releases/0.49.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.49.0/core/tree/.claude/agents/qa.md +150 -0
- package/releases/0.49.0/core/tree/.claude/agents/reviewer.md +184 -0
- package/releases/0.49.0/core/tree/.claude/agents/secops.md +120 -0
- package/releases/0.49.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.49.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.49.0/core/tree/.claude/agents-overview.md +64 -0
- package/releases/0.49.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.49.0/core/tree/.claude/graph.md +75 -0
- package/releases/0.49.0/core/tree/.claude/patterns.md +251 -0
- package/releases/0.49.0/core/tree/.claude/pills/README.md +147 -0
- package/releases/0.49.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.49.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.49.0/core/tree/.claude/router.md +202 -0
- package/releases/0.49.0/core/tree/.claude/templates/integration.md +45 -0
- package/releases/0.49.0/core/tree/CLAUDE.md +164 -0
- package/releases/0.49.0/core/tree/scripts/cost-watch.mjs +25 -0
- package/releases/0.49.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.49.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.49.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.49.0/core/vocabulary.json +13 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.49.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.49.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.49.0/surfaces/d1/tree/.claude/agents/dba.md +13 -0
- package/releases/0.49.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.49.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.49.0/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.49.0/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.49.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.49.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.49.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.49.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.49.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.49.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.49.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.49.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.49.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.49.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.49.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.49.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.49.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.49.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.49.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.49.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.49.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.49.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.49.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.49.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.49.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.49.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.49.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.49.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.49.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.49.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.49.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/releases/0.50.0/core/GAPS.md +125 -0
- package/releases/0.50.0/core/answered.json +53 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.50.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.50.0/core/tree/.claude/agents/architect.md +129 -0
- package/releases/0.50.0/core/tree/.claude/agents/dba.md +117 -0
- package/releases/0.50.0/core/tree/.claude/agents/devops.md +118 -0
- package/releases/0.50.0/core/tree/.claude/agents/implementer.md +162 -0
- package/releases/0.50.0/core/tree/.claude/agents/integration-tester.md +168 -0
- package/releases/0.50.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.50.0/core/tree/.claude/agents/qa.md +150 -0
- package/releases/0.50.0/core/tree/.claude/agents/reviewer.md +184 -0
- package/releases/0.50.0/core/tree/.claude/agents/secops.md +120 -0
- package/releases/0.50.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.50.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.50.0/core/tree/.claude/agents-overview.md +64 -0
- package/releases/0.50.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.50.0/core/tree/.claude/graph.md +75 -0
- package/releases/0.50.0/core/tree/.claude/patterns.md +251 -0
- package/releases/0.50.0/core/tree/.claude/pills/README.md +147 -0
- package/releases/0.50.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.50.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.50.0/core/tree/.claude/router.md +202 -0
- package/releases/0.50.0/core/tree/.claude/templates/integration.md +46 -0
- package/releases/0.50.0/core/tree/CLAUDE.md +164 -0
- package/releases/0.50.0/core/tree/scripts/cost-watch.mjs +25 -0
- package/releases/0.50.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.50.0/core/tree/scripts/harness-check.mjs +71 -0
- package/releases/0.50.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.50.0/core/vocabulary.json +13 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.50.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.50.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.50.0/surfaces/d1/tree/.claude/agents/dba.md +15 -0
- package/releases/0.50.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.50.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.50.0/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.50.0/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.50.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.50.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.50.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.50.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.50.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.50.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.50.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.50.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.50.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.50.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.50.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.50.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.50.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.50.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.50.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.50.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.50.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.50.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.50.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.50.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.50.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.50.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.50.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.50.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.50.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.50.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.50.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/src/commands/check.mjs +146 -1
- package/src/commands/gate.mjs +5 -11
- package/src/commands/pipeline.mjs +22 -1
- package/src/commands/upgrade.mjs +8 -0
- package/src/gate.mjs +48 -3
- package/src/office.html +1069 -0
- package/src/office.mjs +434 -0
- package/src/wiring.mjs +11 -1
|
@@ -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/check.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import { expectedUnfilled } from '../expected.mjs';
|
|
|
14
14
|
import { parseGraph, validateGraph } from '../graph.mjs';
|
|
15
15
|
import { frontmatterFindings, installedSkills, modelFindings, toolFindings } from '../tools.mjs';
|
|
16
16
|
import { HOOK_SCRIPTS, missingWiring, shippedScripts } from '../wiring.mjs';
|
|
17
|
-
import { existsSync } from 'node:fs';
|
|
17
|
+
import { existsSync, readdirSync, realpathSync } from 'node:fs';
|
|
18
18
|
import { join, resolve, sep } from 'node:path';
|
|
19
19
|
import { SLOT, closedGate, defaultedSlots, layerRootFor, noticeOf, readLayerText, stripWhy, walk } from './compose.mjs';
|
|
20
20
|
import { PLACEHOLDER, defaultVocabulary } from '../vocabulary.mjs';
|
|
@@ -182,6 +182,138 @@ export async function unwiredScripts(layerRoot, surfaces, target) {
|
|
|
182
182
|
.sort();
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
const STORE = 'node_modules/.pnpm/';
|
|
186
|
+
const PATH_CHAR = /[\w.@+\-/]/;
|
|
187
|
+
const STORE_DIR = `${sep}node_modules${sep}.pnpm${sep}`;
|
|
188
|
+
|
|
189
|
+
/** The project's root and every directory two levels down holding a package.json: where a package links its deps. */
|
|
190
|
+
function packageDirs(target) {
|
|
191
|
+
const dirs = [target];
|
|
192
|
+
const visit = (dir, depth) => {
|
|
193
|
+
let entries = [];
|
|
194
|
+
try {
|
|
195
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
196
|
+
} catch {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
for (const entry of entries) {
|
|
200
|
+
if (!entry.isDirectory() || entry.name === 'node_modules' || entry.name.startsWith('.')) continue;
|
|
201
|
+
const sub = join(dir, entry.name);
|
|
202
|
+
if (existsSync(join(sub, 'package.json'))) dirs.push(sub);
|
|
203
|
+
if (depth > 1) visit(sub, depth - 1);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
visit(target, 2);
|
|
207
|
+
return dirs;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** The libraries a `node_modules` directory links, scoped ones included. */
|
|
211
|
+
function linksIn(modules) {
|
|
212
|
+
const out = [];
|
|
213
|
+
let entries = [];
|
|
214
|
+
try {
|
|
215
|
+
entries = readdirSync(modules);
|
|
216
|
+
} catch {
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
for (const name of entries.filter((entry) => !entry.startsWith('.'))) {
|
|
220
|
+
if (!name.startsWith('@')) out.push(join(modules, name));
|
|
221
|
+
else {
|
|
222
|
+
try {
|
|
223
|
+
for (const inner of readdirSync(join(modules, name))) out.push(join(modules, name, inner));
|
|
224
|
+
} catch {
|
|
225
|
+
// Not a scope after all.
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return out;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Each store's directories the install uses: those a package links, and every one they link in turn. What is left
|
|
234
|
+
* is what a peer change renamed away, kept on disk and linked by nothing.
|
|
235
|
+
*
|
|
236
|
+
* @param {string} target - The project directory.
|
|
237
|
+
* @returns {Map<string, Set<string>>} Store directory (real path) → the names in it still in use.
|
|
238
|
+
*/
|
|
239
|
+
function liveStoreDirs(target) {
|
|
240
|
+
const live = new Map();
|
|
241
|
+
const queue = [];
|
|
242
|
+
const reach = (link) => {
|
|
243
|
+
let real;
|
|
244
|
+
try {
|
|
245
|
+
real = realpathSync(link);
|
|
246
|
+
} catch {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const at = real.indexOf(STORE_DIR);
|
|
250
|
+
if (at === -1) return;
|
|
251
|
+
const store = real.slice(0, at + STORE_DIR.length - 1);
|
|
252
|
+
const name = real.slice(at + STORE_DIR.length).split(sep)[0];
|
|
253
|
+
if (!live.has(store)) live.set(store, new Set());
|
|
254
|
+
if (live.get(store).has(name)) return;
|
|
255
|
+
live.get(store).add(name);
|
|
256
|
+
queue.push(join(store, name, 'node_modules'));
|
|
257
|
+
};
|
|
258
|
+
for (const dir of packageDirs(target)) for (const link of linksIn(join(dir, 'node_modules'))) reach(link);
|
|
259
|
+
while (queue.length > 0) for (const link of linksIn(queue.pop())) reach(link);
|
|
260
|
+
return live;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* The paths into the package manager's store that a text cites and the install no longer uses. Only the store: its
|
|
265
|
+
* directory names carry a suffix per peer, renamed when an unrelated dependency changes one, and the old directory
|
|
266
|
+
* stays on disk, linked by nothing — so a citation still opens on the machine that wrote it. A store path is stale
|
|
267
|
+
* when its file is gone, or when its directory is not among those the install reaches from the packages' own links
|
|
268
|
+
* (the root and packages two levels down); a store nothing reaches is judged by the file alone. A path through a
|
|
269
|
+
* package's own link, or one written from some package's directory, cannot be told stale from here. A line number
|
|
270
|
+
* after a path is not part of it; an elision (`...`, `…`), a template and a URL are not citations. Each occurrence of
|
|
271
|
+
* the store is read outwards, and the next is looked for past it, so the text is read once.
|
|
272
|
+
*
|
|
273
|
+
* @param {string} text
|
|
274
|
+
* @param {string} target - The project directory.
|
|
275
|
+
* @param {Map<string, Map<string, Set<string>>>} [reached] - What the install reaches, by project, kept between
|
|
276
|
+
* the docs of one run so the store is walked once.
|
|
277
|
+
* @returns {string[]} Each stale path once, in the order cited.
|
|
278
|
+
*/
|
|
279
|
+
export function unresolvedCitations(text, target, reached = new Map()) {
|
|
280
|
+
const cited = new Set();
|
|
281
|
+
let at = text.indexOf(STORE);
|
|
282
|
+
while (at !== -1) {
|
|
283
|
+
let start = at;
|
|
284
|
+
while (start > 0 && PATH_CHAR.test(text[start - 1])) start -= 1;
|
|
285
|
+
let end = at + STORE.length;
|
|
286
|
+
while (end < text.length && PATH_CHAR.test(text[end])) end += 1;
|
|
287
|
+
const path = text.slice(start, end).replace(/[/.]+$/, '');
|
|
288
|
+
const url = text[start - 1] === ':' && path.startsWith('//');
|
|
289
|
+
const elided = text[start - 1] === '…' || text[end] === '…' || path.split('/').includes('...');
|
|
290
|
+
const template = text[end] === '<';
|
|
291
|
+
if (!url && !elided && !template && !path.endsWith('.pnpm')) cited.add(path);
|
|
292
|
+
at = text.indexOf(STORE, end);
|
|
293
|
+
}
|
|
294
|
+
if (cited.size === 0) return [];
|
|
295
|
+
if (!reached.has(target)) reached.set(target, liveStoreDirs(target));
|
|
296
|
+
const live = reached.get(target);
|
|
297
|
+
const stale = (path) => {
|
|
298
|
+
const from = path.indexOf(STORE);
|
|
299
|
+
const [dir, ...rest] = path.slice(from + STORE.length).split('/');
|
|
300
|
+
// The store the citation names: the one under the directory it is written in (a spike's own), else the
|
|
301
|
+
// project's — an absolute path from another machine, or `../../` from a package's directory, leads there.
|
|
302
|
+
const prefix = path.startsWith('/') ? '' : path.slice(0, from).replace(/^(?:\.\.?\/)+/, '');
|
|
303
|
+
const named = join(target, prefix, 'node_modules', '.pnpm');
|
|
304
|
+
if (!existsSync(join(named, dir, ...rest))) return true;
|
|
305
|
+
let store;
|
|
306
|
+
try {
|
|
307
|
+
store = realpathSync(named);
|
|
308
|
+
} catch {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
const used = live.get(store);
|
|
312
|
+
return Boolean(used) && !used.has(dir);
|
|
313
|
+
};
|
|
314
|
+
return [...cited].filter(stale);
|
|
315
|
+
}
|
|
316
|
+
|
|
185
317
|
/**
|
|
186
318
|
* `nina check`.
|
|
187
319
|
*
|
|
@@ -307,6 +439,19 @@ export async function check(argv, ctx) {
|
|
|
307
439
|
if (why) deferredUsed.add(key);
|
|
308
440
|
notes.push(why ? `deferred: ${key} — ${why}` : `${key} documents no declared integration — declare it, or say under "deferred" why not: retired, or waiting for its boundary`);
|
|
309
441
|
}
|
|
442
|
+
// A premise cites installed source by its path, and a path into the package manager's store dies when a peer
|
|
443
|
+
// change renames the directory: the version and the file unchanged, the citation pointing where no fresh install
|
|
444
|
+
// looks. Said per doc, so each premise is re-cited before anyone trusts it.
|
|
445
|
+
const reached = new Map();
|
|
446
|
+
for (const doc of docs.filter((name) => name.endsWith('.md')).sort()) {
|
|
447
|
+
const key = `.claude/integrations/${doc}`;
|
|
448
|
+
const gone = unresolvedCitations(await readFile(join(target, key), 'utf8').catch(() => ''), target, reached);
|
|
449
|
+
if (gone.length > 0) {
|
|
450
|
+
notes.push(
|
|
451
|
+
`${key} cites ${gone.length} path(s) in the package manager's store that the install no longer uses — ${gone[0]}${gone.length > 1 ? ', …' : ''}: a peer change renames those directories, and the old one stays on disk linked by nothing; re-cite each from the depending package's own node_modules link, with its version beside it`,
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
310
455
|
|
|
311
456
|
const slots = await projectSlots(resolved.dir, surfaces);
|
|
312
457
|
const filled = await filledSlots(target);
|
package/src/commands/gate.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import { tmpdir } from 'node:os';
|
|
|
21
21
|
import { join, resolve } from 'node:path';
|
|
22
22
|
import { readProfile, slugFor } from '../paths.mjs';
|
|
23
23
|
import { GATE, hookCommand, missingWiring, shippedScripts } from '../wiring.mjs';
|
|
24
|
-
import { LEDGER_TAIL, ledgerPath, loadProject, loopState, projectGateDir, readLedger, runGate } from '../gate.mjs';
|
|
24
|
+
import { LEDGER_TAIL, ledgerPath, loadProject, loopState, projectGateDir, readLedger, runGate, sessionLedgers } from '../gate.mjs';
|
|
25
25
|
import { projectRecords } from '../store.mjs';
|
|
26
26
|
import { layerRootFor } from './compose.mjs';
|
|
27
27
|
import { handsToModel } from '../detectors.mjs';
|
|
@@ -286,24 +286,18 @@ function loopStatus(target, wanted) {
|
|
|
286
286
|
console.error(' .claude/graph.md is not composed, so the gate has no loops to hold — run `nina compose`\n');
|
|
287
287
|
return 2;
|
|
288
288
|
}
|
|
289
|
-
const dir =
|
|
290
|
-
const ledgers = (existsSync(dir) ? readdirSync(dir) : [])
|
|
291
|
-
.filter((f) => f.endsWith('.jsonl') && f !== 'errors.jsonl')
|
|
292
|
-
.map((f) => ({ session: f.slice(0, -'.jsonl'.length), written: statSync(join(dir, f)).mtime }))
|
|
293
|
-
.sort((a, b) => b.written - a.written);
|
|
289
|
+
const { dir, ledgers, picked, why } = sessionLedgers(target, wanted);
|
|
294
290
|
if (ledgers.length === 0 && !wanted) {
|
|
295
291
|
console.log(` the gate has no ledger here yet: no session has dispatched a stage since it was wired (${dir})`);
|
|
296
292
|
console.log('gate: no open loop');
|
|
297
293
|
return 0;
|
|
298
294
|
}
|
|
299
|
-
|
|
300
|
-
if (matching.length !== 1) {
|
|
301
|
-
const why = matching.length === 0 ? `no session starts with "${wanted}"` : `${matching.length} sessions start with "${wanted}" — give more of the id`;
|
|
295
|
+
if (!picked) {
|
|
302
296
|
console.error(` ${why} (${dir})\n`);
|
|
303
297
|
return 2;
|
|
304
298
|
}
|
|
305
|
-
const { session, written } =
|
|
306
|
-
const state = loopState(project, readLedger(
|
|
299
|
+
const { session, written, path } = picked;
|
|
300
|
+
const state = loopState(project, readLedger(path));
|
|
307
301
|
const others = ledgers.length > 1 ? `; ${ledgers.length - 1} other session(s) kept here, --session <id> for one` : '';
|
|
308
302
|
console.log(` session ${session}, its ledger last written ${written.toISOString().slice(0, 16).replace('T', ' ')} UTC${others}`);
|
|
309
303
|
for (const line of state.lines) console.log(` ${line}`);
|
|
@@ -168,7 +168,8 @@ export function historyOf(records, since) {
|
|
|
168
168
|
/**
|
|
169
169
|
* Runs the command.
|
|
170
170
|
*
|
|
171
|
-
* @param {string[]} argv - `[--project <dir>] [--for <number or words>] [--since <YYYY-MM-DD>]
|
|
171
|
+
* @param {string[]} argv - `[--project <dir>] [--for <number or words>] [--since <YYYY-MM-DD>]`, or `--view [--session <id>]
|
|
172
|
+
* [--replay] [--port <n>] [--open]` for the office.
|
|
172
173
|
* @returns {Promise<number>} Process exit code.
|
|
173
174
|
*/
|
|
174
175
|
export async function pipeline(argv) {
|
|
@@ -179,6 +180,26 @@ export async function pipeline(argv) {
|
|
|
179
180
|
console.error(` no .claude/graph.md in ${dir} — this draws a composed pipeline: \`nina compose\` writes one`);
|
|
180
181
|
return 1;
|
|
181
182
|
}
|
|
183
|
+
// The office: the same graph as a room, its agents at their desks, live or replayed (src/office.mjs).
|
|
184
|
+
const viewOnly = ['--session', '--replay', '--port', '--open'].filter((flag) => argv.includes(flag));
|
|
185
|
+
if (viewOnly.length > 0 && !argv.includes('--view')) {
|
|
186
|
+
console.error(` ${viewOnly.join(', ')} ${viewOnly.length > 1 ? 'belong' : 'belongs'} to the office, and mean${viewOnly.length > 1 ? '' : 's'} nothing without --view`);
|
|
187
|
+
return 2;
|
|
188
|
+
}
|
|
189
|
+
if (argv.includes('--view')) {
|
|
190
|
+
const drawingOnly = ['--for', '--since'].filter((flag) => argv.includes(flag));
|
|
191
|
+
if (drawingOnly.length > 0) {
|
|
192
|
+
console.error(` ${drawingOnly.join(', ')} ${drawingOnly.length > 1 ? 'are' : 'is'} for the drawing, not the office`);
|
|
193
|
+
return 2;
|
|
194
|
+
}
|
|
195
|
+
const { viewOffice } = await import('../office.mjs');
|
|
196
|
+
const port = arg('--port');
|
|
197
|
+
if (port !== null && !(/^\d+$/.test(port) && Number(port) <= 65535)) {
|
|
198
|
+
console.error(` --port takes a port number, 0 to 65535, and was given ${port}`);
|
|
199
|
+
return 2;
|
|
200
|
+
}
|
|
201
|
+
return viewOffice({ target: dir, wanted: arg('--session') || undefined, replay: argv.includes('--replay'), port: port === null ? undefined : Number(port), open: argv.includes('--open') });
|
|
202
|
+
}
|
|
182
203
|
const graphText = readFileSync(graphPath, 'utf8');
|
|
183
204
|
const graph = parseGraph(graphText);
|
|
184
205
|
const words = stageWords(graphText);
|
package/src/commands/upgrade.mjs
CHANGED
|
@@ -364,6 +364,14 @@ export async function upgrade(argv, ctx) {
|
|
|
364
364
|
const scriptsBefore = await shippedScripts(from.dir, surfaces);
|
|
365
365
|
const newScripts = new Set([...(await shippedScripts(onto.dir, kept))].filter((s) => !scriptsBefore.has(s)));
|
|
366
366
|
const unwired = newScripts.size > 0 ? await missingWiring(target, newScripts) : [];
|
|
367
|
+
// A script already run whose hooks this NINA needs more of — a matcher that grew — holds what it held, so it does
|
|
368
|
+
// not stop the move; it is said, with what fixes it.
|
|
369
|
+
const stillRun = new Set([...(await shippedScripts(onto.dir, kept))].filter((s) => scriptsBefore.has(s)));
|
|
370
|
+
const widened = stillRun.size > 0 ? (await missingWiring(target, stillRun)).filter((w) => / hook running `[^`]+` does not match /.test(w)) : [];
|
|
371
|
+
if (widened.length > 0) {
|
|
372
|
+
for (const w of widened) console.log(` · ${w}`);
|
|
373
|
+
console.log('');
|
|
374
|
+
}
|
|
367
375
|
if (unwired.length > 0) {
|
|
368
376
|
console.log(` ✗ ${unwired.length} hook(s) or script(s) that ${to}'s new ${[...newScripts].join(', ')} need(s) are not wired:`);
|
|
369
377
|
for (const w of unwired) console.log(` ${w}`);
|
package/src/gate.mjs
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
* PreToolUse / PostToolUse on Agent, Task, SendMessage
|
|
19
19
|
* a dispatch launched, and the agent it launched
|
|
20
20
|
* UserPromptSubmit (human text only) the owner spoke, and every open loop gets one round more
|
|
21
|
+
* PreToolUse / PostToolUse on AskUserQuestion
|
|
22
|
+
* the orchestrator asked the owner, and was answered: when, for the office
|
|
21
23
|
* PreToolUse on Agent, Task, SendMessage
|
|
22
24
|
* the decision: let it through, or send the round past the cap to
|
|
23
25
|
* the owner to confirm
|
|
@@ -606,6 +608,10 @@ function onPost(input, project, path, at) {
|
|
|
606
608
|
}
|
|
607
609
|
// A dispatch made inside a subagent is not the pipeline's: its stages are dispatched by the orchestrator.
|
|
608
610
|
if (input.agent_id) return null;
|
|
611
|
+
if (tool === 'AskUserQuestion') {
|
|
612
|
+
append(path, { k: 'answered', at });
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
609
615
|
if (!DISPATCH.has(tool)) return null;
|
|
610
616
|
const response = input.tool_response && typeof input.tool_response === 'object' ? input.tool_response : {};
|
|
611
617
|
let role;
|
|
@@ -659,13 +665,23 @@ function confirmation(r) {
|
|
|
659
665
|
|
|
660
666
|
/** A dispatch is about to go out: note when, and send the round past its edge's cap to the owner to confirm. */
|
|
661
667
|
function onPre(input, project, path, at) {
|
|
668
|
+
// The orchestrator asking the owner, as it asks: when it was, and nothing it said. Nothing counts it; the office
|
|
669
|
+
// (`nina pipeline --view`) draws the question over its head until the answer, which `onPost` records.
|
|
670
|
+
if (!input.agent_id && input.tool_name === 'AskUserQuestion') {
|
|
671
|
+
append(path, { k: 'question', at });
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
662
674
|
if (input.agent_id || !DISPATCH.has(input.tool_name)) return null;
|
|
663
675
|
const entries = readLedger(path);
|
|
664
|
-
const
|
|
676
|
+
const to = input.tool_name === 'SendMessage' ? recipient(entries, project, input.tool_input?.to) : null;
|
|
677
|
+
const role = to ? to.role : input.tool_input?.subagent_type;
|
|
665
678
|
if (!role || !project.graph.stages.has(role)) return null;
|
|
666
679
|
// When it went out, whatever the owner decides: joined to its `dispatch` entry by the tool_use id,
|
|
667
|
-
// it is the moment the fixer was sent — which is what a later review has to begin after.
|
|
668
|
-
|
|
680
|
+
// it is the moment the fixer was sent — which is what a later review has to begin after. A message says so, and
|
|
681
|
+
// names its agent when the ledger already knows it — never a name the model wrote that nothing launched — so the
|
|
682
|
+
// office can tell a message to a running agent from a resume before the `dispatch` entry is written.
|
|
683
|
+
const known = to?.agent && entries.some((e) => e.k === 'dispatch' && e.agent === to.agent);
|
|
684
|
+
append(path, { k: 'pre', at, role, id: input.tool_use_id ?? null, ...(to ? { via: 'SendMessage', ...(known ? { agent: to.agent } : {}) } : {}) });
|
|
669
685
|
const over = roundsFor(entries, role, project.loops, project.forward)
|
|
670
686
|
.filter((r) => excess(r) > 0)
|
|
671
687
|
.sort((a, b) => excess(b) - excess(a));
|
|
@@ -686,6 +702,35 @@ function onPre(input, project, path, at) {
|
|
|
686
702
|
return confirmation(worst);
|
|
687
703
|
}
|
|
688
704
|
|
|
705
|
+
/**
|
|
706
|
+
* A project's session ledgers, the newest first, and the one asked for: the latest, or the one whose id starts
|
|
707
|
+
* with `wanted`. `nina gate --status` and the office (`nina pipeline --view`) pick a session through this, so
|
|
708
|
+
* the two never show different ones.
|
|
709
|
+
*
|
|
710
|
+
* @param {string} root - The project directory.
|
|
711
|
+
* @param {string} [wanted] - The start of a session id; absent, the session whose ledger was written last.
|
|
712
|
+
* @returns {{dir: string, ledgers: {session: string, written: Date, path: string}[], picked: {session: string, written: Date, path: string}|null, why: string|null}}
|
|
713
|
+
* `why` says why nothing was picked, and is null when there is simply no ledger yet.
|
|
714
|
+
*/
|
|
715
|
+
export function sessionLedgers(root, wanted) {
|
|
716
|
+
const dir = projectGateDir(root);
|
|
717
|
+
const ledgers = (existsSync(dir) ? readdirSync(dir) : [])
|
|
718
|
+
.filter((f) => f.endsWith('.jsonl') && f !== 'errors.jsonl')
|
|
719
|
+
.flatMap((f) => {
|
|
720
|
+
// Pruned between the listing and here, by another session: gone, and not a failure.
|
|
721
|
+
try {
|
|
722
|
+
return [{ session: f.slice(0, -'.jsonl'.length), written: statSync(join(dir, f)).mtime, path: join(dir, f) }];
|
|
723
|
+
} catch {
|
|
724
|
+
return [];
|
|
725
|
+
}
|
|
726
|
+
})
|
|
727
|
+
.sort((a, b) => b.written - a.written);
|
|
728
|
+
const matching = wanted ? ledgers.filter((l) => l.session.startsWith(wanted)) : ledgers.slice(0, 1);
|
|
729
|
+
if (matching.length === 1) return { dir, ledgers, picked: matching[0], why: null };
|
|
730
|
+
const why = !wanted ? null : matching.length === 0 ? `no session starts with "${wanted}"` : `${matching.length} sessions start with "${wanted}" — give more of the id`;
|
|
731
|
+
return { dir, ledgers, picked: null, why };
|
|
732
|
+
}
|
|
733
|
+
|
|
689
734
|
/** Stages as a sentence lists them: `qa`, `implementer or architect`, `a, b or c`. */
|
|
690
735
|
const either = (stages) => (stages.length < 2 ? stages.join('') : `${stages.slice(0, -1).join(', ')} or ${stages.at(-1)}`);
|
|
691
736
|
|