@xhulz/nina 0.67.0 → 0.68.1
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.68.0/core/GAPS.md +125 -0
- package/releases/0.68.0/core/answered.json +80 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.68.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.68.0/core/tree/.claude/agents/architect.md +134 -0
- package/releases/0.68.0/core/tree/.claude/agents/dba.md +119 -0
- package/releases/0.68.0/core/tree/.claude/agents/design-reviewer.md +76 -0
- package/releases/0.68.0/core/tree/.claude/agents/devops.md +118 -0
- package/releases/0.68.0/core/tree/.claude/agents/implementer.md +178 -0
- package/releases/0.68.0/core/tree/.claude/agents/integration-tester.md +170 -0
- package/releases/0.68.0/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.68.0/core/tree/.claude/agents/qa.md +150 -0
- package/releases/0.68.0/core/tree/.claude/agents/reviewer.md +187 -0
- package/releases/0.68.0/core/tree/.claude/agents/secops.md +120 -0
- package/releases/0.68.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.68.0/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.68.0/core/tree/.claude/agents-overview.md +65 -0
- package/releases/0.68.0/core/tree/.claude/frontend.md +10 -0
- package/releases/0.68.0/core/tree/.claude/graph.md +79 -0
- package/releases/0.68.0/core/tree/.claude/patterns.md +252 -0
- package/releases/0.68.0/core/tree/.claude/pills/README.md +150 -0
- package/releases/0.68.0/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.68.0/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.68.0/core/tree/.claude/router.md +218 -0
- package/releases/0.68.0/core/tree/.claude/templates/integration.md +48 -0
- package/releases/0.68.0/core/tree/CLAUDE.md +166 -0
- package/releases/0.68.0/core/tree/scripts/cost-watch.mjs +25 -0
- package/releases/0.68.0/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.68.0/core/tree/scripts/harness-check.mjs +81 -0
- package/releases/0.68.0/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.68.0/core/vocabulary.json +14 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.68.0/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.68.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.68.0/surfaces/d1/tree/.claude/agents/dba.md +15 -0
- package/releases/0.68.0/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.68.0/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.0/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.68.0/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.68.0/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.68.0/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.68.0/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.68.0/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.68.0/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.0/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.68.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.68.0/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.68.0/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.68.0/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.68.0/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.68.0/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.68.0/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.68.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.68.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.68.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.68.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.68.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.68.0/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.68.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.68.0/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.68.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.68.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.68.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.68.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.68.0/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/releases/0.68.1/core/GAPS.md +125 -0
- package/releases/0.68.1/core/answered.json +80 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/architect.md +1 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/dba.md +3 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/devops.md +1 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/implementer.md +1 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/qa.md +7 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/reviewer.md +3 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/secops.md +3 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
- package/releases/0.68.1/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
- package/releases/0.68.1/core/tree/.claude/agents/architect.md +134 -0
- package/releases/0.68.1/core/tree/.claude/agents/dba.md +119 -0
- package/releases/0.68.1/core/tree/.claude/agents/design-reviewer.md +76 -0
- package/releases/0.68.1/core/tree/.claude/agents/devops.md +118 -0
- package/releases/0.68.1/core/tree/.claude/agents/implementer.md +178 -0
- package/releases/0.68.1/core/tree/.claude/agents/integration-tester.md +170 -0
- package/releases/0.68.1/core/tree/.claude/agents/planner.md +132 -0
- package/releases/0.68.1/core/tree/.claude/agents/qa.md +150 -0
- package/releases/0.68.1/core/tree/.claude/agents/reviewer.md +187 -0
- package/releases/0.68.1/core/tree/.claude/agents/secops.md +120 -0
- package/releases/0.68.1/core/tree/.claude/agents/solidity-auditor.md +126 -0
- package/releases/0.68.1/core/tree/.claude/agents/solidity-dev.md +123 -0
- package/releases/0.68.1/core/tree/.claude/agents-overview.md +65 -0
- package/releases/0.68.1/core/tree/.claude/frontend.md +10 -0
- package/releases/0.68.1/core/tree/.claude/graph.md +79 -0
- package/releases/0.68.1/core/tree/.claude/patterns.md +252 -0
- package/releases/0.68.1/core/tree/.claude/pills/README.md +150 -0
- package/releases/0.68.1/core/tree/.claude/pipeline.md +101 -0
- package/releases/0.68.1/core/tree/.claude/retrieval.md +103 -0
- package/releases/0.68.1/core/tree/.claude/router.md +218 -0
- package/releases/0.68.1/core/tree/.claude/templates/integration.md +48 -0
- package/releases/0.68.1/core/tree/CLAUDE.md +166 -0
- package/releases/0.68.1/core/tree/scripts/cost-watch.mjs +25 -0
- package/releases/0.68.1/core/tree/scripts/edit-guard.mjs +24 -0
- package/releases/0.68.1/core/tree/scripts/harness-check.mjs +81 -0
- package/releases/0.68.1/core/tree/scripts/loop-gate.mjs +19 -0
- package/releases/0.68.1/core/vocabulary.json +14 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/graph.md +11 -0
- package/releases/0.68.1/surfaces/blockchain/tree/.claude/router.md +6 -0
- package/releases/0.68.1/surfaces/blockchain/tree/CLAUDE.md +12 -0
- package/releases/0.68.1/surfaces/d1/tree/.claude/agents/dba.md +15 -0
- package/releases/0.68.1/surfaces/d1/tree/.claude/agents/devops.md +2 -0
- package/releases/0.68.1/surfaces/d1/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.1/surfaces/d1/tree/.claude/patterns.md +8 -0
- package/releases/0.68.1/surfaces/d1/tree/CLAUDE.md +2 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/architect.md +5 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/dba.md +54 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/devops.md +5 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/planner.md +2 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents/secops.md +2 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/agents-overview.md +5 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/graph.md +8 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/patterns.md +22 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/pipeline.md +13 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/retrieval.md +5 -0
- package/releases/0.68.1/surfaces/db/tree/.claude/router.md +4 -0
- package/releases/0.68.1/surfaces/db/tree/CLAUDE.md +17 -0
- package/releases/0.68.1/surfaces/drizzle/tree/.claude/agents/dba.md +9 -0
- package/releases/0.68.1/surfaces/drizzle/tree/.claude/agents/devops.md +5 -0
- package/releases/0.68.1/surfaces/drizzle/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.1/surfaces/drizzle/tree/.claude/patterns.md +7 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/devops.md +29 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
- package/releases/0.68.1/surfaces/edge-cf/tree/CLAUDE.md +27 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/patterns.md +8 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/retrieval.md +2 -0
- package/releases/0.68.1/surfaces/frontend/tree/.claude/router.md +14 -0
- package/releases/0.68.1/surfaces/frontend/tree/CLAUDE.md +5 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/graph.md +10 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/patterns.md +38 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/pipeline.md +16 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/retrieval.md +16 -0
- package/releases/0.68.1/surfaces/integrations/tree/.claude/router.md +6 -0
- package/releases/0.68.1/surfaces/integrations/tree/CLAUDE.md +17 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/architect.md +12 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/dba.md +14 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/implementer.md +11 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/secops.md +5 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/graph.md +2 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/patterns.md +49 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/pipeline.md +2 -0
- package/releases/0.68.1/surfaces/money/tree/.claude/retrieval.md +2 -0
- package/releases/0.68.1/surfaces/money/tree/CLAUDE.md +11 -0
- package/releases/0.68.1/surfaces/pii/tree/.claude/agents/dba.md +2 -0
- package/releases/0.68.1/surfaces/pii/tree/.claude/agents/devops.md +8 -0
- package/releases/0.68.1/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
- package/releases/0.68.1/surfaces/pii/tree/.claude/agents/secops.md +2 -0
- package/releases/0.68.1/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
- package/releases/0.68.1/surfaces/pii/tree/CLAUDE.md +5 -0
- package/releases/0.68.1/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
- package/releases/0.68.1/surfaces/prisma/tree/.claude/agents/dba.md +42 -0
- package/releases/0.68.1/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
- package/releases/0.68.1/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
- package/releases/0.68.1/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
- package/releases/0.68.1/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
- package/releases/0.68.1/surfaces/prisma/tree/.claude/patterns.md +15 -0
- package/releases/0.68.1/surfaces/prisma/tree/CLAUDE.md +5 -0
- package/src/commands/gate.mjs +1 -1
- package/src/commands/learn.mjs +2 -1
- package/src/commands/sizes.mjs +72 -30
- package/src/gate.mjs +114 -8
- package/src/office.html +212 -96
- package/src/office.mjs +2 -1
package/src/office.html
CHANGED
|
@@ -152,22 +152,36 @@ function disc(ctx, cx, cy, r, color) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
// ─── the floor plan ───────────────────────────────────────────────────────────────────────────
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
/*
|
|
156
|
+
* Two rows of rooms either side of one corridor that runs across the building, the garden below. The floor is laid
|
|
157
|
+
* out for the window it is drawn in: a room's desks go in as many rows as make the whole office come out largest, so
|
|
158
|
+
* a wide window gets long rooms side by side and a narrow one deeper rooms. Rooms used to stand in two columns, three
|
|
159
|
+
* deep, off a corridor down the middle, four desks a row: once a stage got as many desks as it ever ran at once, a
|
|
160
|
+
* project's office grew taller than wide, fitted whole it stood small in the middle of a wide window, and people
|
|
161
|
+
* watching it asked whether it worked at all.
|
|
162
|
+
*/
|
|
159
163
|
const FACE = 24;
|
|
160
164
|
const DESK_STEP = 52;
|
|
161
165
|
const DESK_ROW = 46;
|
|
166
|
+
const CORRIDOR_H = 32;
|
|
162
167
|
const GARDEN = 52;
|
|
168
|
+
/** The reception's own floor: its counter, the waiting chairs, the vending machine. */
|
|
169
|
+
const LOBBY_W = 224;
|
|
170
|
+
const LOBBY_H = 116;
|
|
171
|
+
/** A room below the corridor is entered through the wall it faces, and walked down a strip by its right wall to its lane. */
|
|
172
|
+
const STRIP = 22;
|
|
173
|
+
/** The column a room's shelf or rack stands in, past its last desk. */
|
|
174
|
+
const CORNER = 28;
|
|
175
|
+
/** An empty room is somewhere to sit, as wide as four desks. */
|
|
176
|
+
const EMPTY_W = 224;
|
|
163
177
|
|
|
164
178
|
/** The rooms, by phase, in the order the work moves through them. A stage not named here works in build. */
|
|
165
179
|
const PHASES = [
|
|
166
|
-
{ key: 'design', name: 'design',
|
|
167
|
-
{ key: 'build', name: 'build',
|
|
168
|
-
{ key: 'review', name: 'review & gates',
|
|
169
|
-
{ key: 'lab', name: 'test lab',
|
|
170
|
-
{ key: 'release', name: 'release',
|
|
180
|
+
{ key: 'design', name: 'design', band: 'top', roles: ['planner', 'architect', 'design-reviewer'] },
|
|
181
|
+
{ key: 'build', name: 'build', band: 'top', roles: ['implementer', 'solidity-dev'] },
|
|
182
|
+
{ key: 'review', name: 'review & gates', band: 'top', roles: ['reviewer', 'dba', 'integration-tester', 'solidity-auditor'] },
|
|
183
|
+
{ key: 'lab', name: 'test lab', band: 'bottom', roles: ['qa'] },
|
|
184
|
+
{ key: 'release', name: 'release', band: 'bottom', roles: ['devops', 'secops'] },
|
|
171
185
|
];
|
|
172
186
|
|
|
173
187
|
const rooms = new Map(PHASES.map((ph) => [ph.key, { ...ph, stages: [] }]));
|
|
@@ -177,71 +191,167 @@ ROOM.stages.forEach((role, i) => {
|
|
|
177
191
|
// declares `× many` in a page served before it was.
|
|
178
192
|
rooms.get(phase).stages.push({ role, index: i, seats: ROOM.seats?.[role] ?? (ROOM.many.includes(role) ? 2 : 1) });
|
|
179
193
|
});
|
|
180
|
-
const lobby = { key: 'lobby', name: 'reception',
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
194
|
+
const lobby = { key: 'lobby', name: 'reception', band: 'bottom', stages: [] };
|
|
195
|
+
const bands = {
|
|
196
|
+
top: [rooms.get('design'), rooms.get('build'), rooms.get('review')],
|
|
197
|
+
bottom: [lobby, rooms.get('lab'), rooms.get('release')],
|
|
184
198
|
};
|
|
185
199
|
for (const room of [...rooms.values(), lobby]) {
|
|
186
|
-
|
|
187
|
-
room.
|
|
188
|
-
room.rows = Math.max(1, Math.ceil(desks / 4));
|
|
189
|
-
room.h = room === lobby ? 116 : FACE + 8 + room.rows * DESK_ROW + 26;
|
|
200
|
+
room.deskCount = room.stages.reduce((n, st) => n + st.seats, 0);
|
|
201
|
+
room.corner = room.key === 'lab' || room.key === 'release';
|
|
190
202
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
203
|
+
|
|
204
|
+
/** How wide a room's name plate is, so what hangs beside it starts after it. */
|
|
205
|
+
const signWidth = (room) => Math.max(40, room.name.length * 4 + 8);
|
|
206
|
+
/** Where a room's shelf or rack stands: in its column, before the strip of a room below the corridor. */
|
|
207
|
+
const cornerX = (room) => room.x + room.w - (room.band === 'bottom' ? STRIP : 0) - CORNER + 3;
|
|
208
|
+
/** Desks a row in a room whose band has `rows` rows of them. */
|
|
209
|
+
const perRow = (room, rows) => Math.ceil(room.deskCount / rows);
|
|
210
|
+
/** How wide a room is with its desks in `rows` rows. */
|
|
211
|
+
function roomWidth(room, rows) {
|
|
212
|
+
if (room === lobby) return LOBBY_W + STRIP;
|
|
213
|
+
const desks = room.deskCount ? 12 + perRow(room, rows) * DESK_STEP + 4 + (room.corner ? CORNER : 0) : EMPTY_W;
|
|
214
|
+
return Math.max(desks, signWidth(room) + 24) + (room.band === 'bottom' ? STRIP : 0);
|
|
199
215
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
216
|
+
/** How tall a band of rooms is with their desks in at most `rows` rows. */
|
|
217
|
+
function bandHeight(list, rows) {
|
|
218
|
+
const most = Math.max(1, ...list.filter((r) => r.deskCount).map((r) => Math.ceil(r.deskCount / perRow(r, rows))));
|
|
219
|
+
return Math.max(list.includes(lobby) ? LOBBY_H : 0, FACE + 8 + most * DESK_ROW + 26);
|
|
220
|
+
}
|
|
221
|
+
/** The office's size with each band's desks in so many rows. */
|
|
222
|
+
function measure(arrangement) {
|
|
223
|
+
const wide = (band) => bands[band].reduce((x, room) => x + roomWidth(room, arrangement[band]), 0);
|
|
224
|
+
return { w: Math.max(wide('top'), wide('bottom')), h: bandHeight(bands.top, arrangement.top) + CORRIDOR_H + bandHeight(bands.bottom, arrangement.bottom) + GARDEN };
|
|
225
|
+
}
|
|
226
|
+
/** The rows for each band that make the whole office come out largest in a space `width` by `height`. */
|
|
227
|
+
function arrange(width, height) {
|
|
228
|
+
// A page loaded hidden, as the dashboard's frame is until its tab is opened, has no size yet: it lays out for a common
|
|
229
|
+
// window, and again when it is shown.
|
|
230
|
+
const [W, H] = width > 0 && height > 0 ? [width, height] : [1200, 800];
|
|
231
|
+
const most = (band) => Math.max(1, ...bands[band].map((r) => r.deskCount));
|
|
232
|
+
let best = null;
|
|
233
|
+
for (let top = 1; top <= most('top'); top += 1) {
|
|
234
|
+
for (let bottom = 1; bottom <= most('bottom'); bottom += 1) {
|
|
235
|
+
const size = measure({ top, bottom });
|
|
236
|
+
const zoom = Math.min(W / size.w, H / size.h);
|
|
237
|
+
if (!best || zoom > best.zoom + 1e-9) best = { top, bottom, zoom };
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return best;
|
|
207
241
|
}
|
|
208
242
|
|
|
209
|
-
/** Each stage's desks and the places to stand by them
|
|
243
|
+
/** Each stage's desks and the places to stand by them, placed by `layout`; and the stage of a role. */
|
|
210
244
|
const stages = new Map();
|
|
211
245
|
for (const room of rooms.values()) {
|
|
212
|
-
let n = 0;
|
|
213
246
|
for (const st of room.stages) {
|
|
214
|
-
const stage = { role: st.role, room, shirt: SHIRTS[st.index % SHIRTS.length], desks: [], slots: [], folder: null };
|
|
215
|
-
for (let k = 0; k < st.seats; k += 1
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const aisle = dx + 44;
|
|
219
|
-
const seatY = dy + 34;
|
|
220
|
-
const exit = [{ x: aisle, y: seatY }, { x: aisle, y: room.laneY }];
|
|
221
|
-
stage.desks.push({ dx, dy });
|
|
222
|
-
stage.slots.push({ x: dx + 18, y: seatY, room, exit, kind: 'seat', who: null, desk: stage.desks.at(-1) });
|
|
247
|
+
const stage = { role: st.role, room, shirt: SHIRTS[st.index % SHIRTS.length], desks: [], slots: [], folder: null, drop: { room }, spare: { room, kind: 'stand', role: st.role } };
|
|
248
|
+
for (let k = 0; k < st.seats; k += 1) {
|
|
249
|
+
stage.desks.push({});
|
|
250
|
+
stage.slots.push({ room, kind: 'seat', who: null, desk: stage.desks.at(-1) });
|
|
223
251
|
}
|
|
224
|
-
const first = stage.desks[0];
|
|
225
|
-
stage.drop = { x: first.dx + 44, y: first.dy + 30, room, exit: [{ x: first.dx + 44, y: room.laneY }] };
|
|
226
|
-
stage.spare = { x: first.dx + 44, y: first.dy + 40, room, exit: [{ x: first.dx + 44, y: room.laneY }], kind: 'stand' };
|
|
227
252
|
stages.set(st.role, stage);
|
|
228
253
|
}
|
|
229
254
|
}
|
|
230
|
-
const COUNTER = {
|
|
255
|
+
const COUNTER = { w: 104 };
|
|
231
256
|
// NINA stands at the end of the counter, facing the room: behind it, only her head showed.
|
|
232
|
-
const BOSS_HOME = {
|
|
257
|
+
const BOSS_HOME = { room: lobby, kind: 'stand' };
|
|
233
258
|
// The owner is not drawn: they are the phone on the counter, where the gate's calls ring and their answers come in.
|
|
234
|
-
const PHONE = {
|
|
235
|
-
const OWNER_HOME = {
|
|
236
|
-
const ENTRANCE = {
|
|
259
|
+
const PHONE = {};
|
|
260
|
+
const OWNER_HOME = { room: lobby, kind: 'line' };
|
|
261
|
+
const ENTRANCE = { room: lobby, kind: 'stand' };
|
|
262
|
+
const RECEPTION = {};
|
|
263
|
+
|
|
264
|
+
let LW = 0;
|
|
265
|
+
let LH = 0;
|
|
266
|
+
let FLOOR_H = 0;
|
|
267
|
+
let HALL_Y = 0;
|
|
268
|
+
/** The rows each band's desks are in now. */
|
|
269
|
+
let arranged = null;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Lays the floor out with each band's desks in so many rows. Every place someone can be is the same object before and
|
|
273
|
+
* after, moved, so whoever sits, stands or walks keeps it.
|
|
274
|
+
*/
|
|
275
|
+
function layout(arrangement) {
|
|
276
|
+
arranged = arrangement;
|
|
277
|
+
const [wasW, wasH] = [LW, LH];
|
|
278
|
+
LW = measure(arrangement).w;
|
|
279
|
+
const topH = bandHeight(bands.top, arrangement.top);
|
|
280
|
+
const bottomH = bandHeight(bands.bottom, arrangement.bottom);
|
|
281
|
+
HALL_Y = topH + CORRIDOR_H / 2;
|
|
282
|
+
FLOOR_H = topH + CORRIDOR_H + bottomH;
|
|
283
|
+
LH = FLOOR_H + GARDEN;
|
|
284
|
+
for (const [band, list] of Object.entries(bands)) {
|
|
285
|
+
let x = 0;
|
|
286
|
+
for (const room of list) {
|
|
287
|
+
room.per = perRow(room, arrangement[band]);
|
|
288
|
+
room.x = x;
|
|
289
|
+
room.w = roomWidth(room, arrangement[band]);
|
|
290
|
+
room.y = band === 'top' ? 0 : topH + CORRIDOR_H;
|
|
291
|
+
room.h = band === 'top' ? topH : bottomH;
|
|
292
|
+
x += room.w;
|
|
293
|
+
}
|
|
294
|
+
// The narrower band's last room takes up the difference, so both reach the end wall together.
|
|
295
|
+
list.at(-1).w += LW - x;
|
|
296
|
+
}
|
|
297
|
+
for (const room of [...rooms.values(), lobby]) {
|
|
298
|
+
room.laneY = room.y + room.h - 14;
|
|
299
|
+
// A room above the corridor opens onto it through its bottom wall; one below, through the wall it faces, at its strip.
|
|
300
|
+
room.doorX = room.band === 'top' ? room.x + room.w - 14 : room.x + room.w - STRIP / 2;
|
|
301
|
+
}
|
|
302
|
+
for (const room of rooms.values()) {
|
|
303
|
+
let n = 0;
|
|
304
|
+
for (const st of room.stages) {
|
|
305
|
+
const stage = stages.get(st.role);
|
|
306
|
+
stage.slots.forEach((slot, k) => {
|
|
307
|
+
const dx = room.x + 12 + (n % room.per) * DESK_STEP;
|
|
308
|
+
const dy = room.y + FACE + 6 + Math.floor(n / room.per) * DESK_ROW;
|
|
309
|
+
const aisle = dx + 44;
|
|
310
|
+
const seatY = dy + 34;
|
|
311
|
+
n += 1;
|
|
312
|
+
Object.assign(stage.desks[k], { dx, dy });
|
|
313
|
+
Object.assign(slot, { x: dx + 18, y: seatY, exit: [{ x: aisle, y: seatY }, { x: aisle, y: room.laneY }] });
|
|
314
|
+
});
|
|
315
|
+
const first = stage.desks[0];
|
|
316
|
+
Object.assign(stage.drop, { x: first.dx + 44, y: first.dy + 30, exit: [{ x: first.dx + 44, y: room.laneY }] });
|
|
317
|
+
Object.assign(stage.spare, { x: first.dx + 44, y: first.dy + 40, exit: [{ x: first.dx + 44, y: room.laneY }] });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
Object.assign(COUNTER, { x: lobby.x + 14, y: lobby.y + FACE + 22 });
|
|
321
|
+
Object.assign(BOSS_HOME, { x: COUNTER.x + COUNTER.w + 10, y: COUNTER.y + 8, exit: [{ x: COUNTER.x + COUNTER.w + 10, y: lobby.laneY }] });
|
|
322
|
+
Object.assign(PHONE, { x: COUNTER.x + 72, y: COUNTER.y - 11 });
|
|
323
|
+
Object.assign(OWNER_HOME, { x: PHONE.x + 5, y: PHONE.y + 14 });
|
|
324
|
+
Object.assign(ENTRANCE, { x: lobby.x + 150, y: FLOOR_H - 2, exit: [{ x: lobby.x + 150, y: lobby.laneY }] });
|
|
325
|
+
Object.assign(RECEPTION, { x: COUNTER.x + COUNTER.w / 2, y: COUNTER.y + 14 });
|
|
326
|
+
drawBackground();
|
|
327
|
+
world.width = LW;
|
|
328
|
+
world.height = LH;
|
|
329
|
+
// The view stays over the same part of the office.
|
|
330
|
+
cam.x = wasW ? (cam.x / wasW) * LW : LW / 2;
|
|
331
|
+
cam.y = wasH ? (cam.y / wasH) * LH : LH / 2;
|
|
332
|
+
// Whoever is somewhere is drawn there again; whoever is on their way sets out again from where they were. A place
|
|
333
|
+
// beside a stage's full desks is a copy of its spare spot, held as where someone stands, sits, is going, or left
|
|
334
|
+
// from: each is moved with the spot it copies.
|
|
335
|
+
for (const p of [...people.values(), boss, owner]) {
|
|
336
|
+
for (const spot of [p.slot, p.at, p.current?.to, ...p.queue.map((q) => q.to)]) {
|
|
337
|
+
if (!spot?.extra) continue;
|
|
338
|
+
const { x, y, exit } = stages.get(spot.role).spare;
|
|
339
|
+
Object.assign(spot, { x, y, exit });
|
|
340
|
+
}
|
|
341
|
+
const from = p.at ?? ENTRANCE;
|
|
342
|
+
p.x = from.x;
|
|
343
|
+
p.y = from.y;
|
|
344
|
+
if (p.current?.kind === 'walk') p.path = route(from, p.current.to);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
237
347
|
|
|
238
|
-
/** The way from where someone stands to a spot: out to their room's lane, along the corridor when it is another room. */
|
|
348
|
+
/** The way from where someone stands to a spot: out to their room's lane and door, along the corridor when it is another room. */
|
|
239
349
|
function route(from, to) {
|
|
240
350
|
const out = from.exit ?? [{ x: from.x, y: from.room.laneY }];
|
|
241
351
|
const into = [...(to.exit ?? [{ x: to.x, y: to.room.laneY }])].reverse();
|
|
242
352
|
const pts = [...out];
|
|
243
353
|
if (from.room !== to.room) {
|
|
244
|
-
pts.push({ x: from.room.doorX, y: from.room.laneY }, { x:
|
|
354
|
+
pts.push({ x: from.room.doorX, y: from.room.laneY }, { x: from.room.doorX, y: HALL_Y }, { x: to.room.doorX, y: HALL_Y }, { x: to.room.doorX, y: to.room.laneY });
|
|
245
355
|
}
|
|
246
356
|
pts.push(...into, { x: to.x, y: to.y });
|
|
247
357
|
return pts.filter((p, i) => i === 0 || p.x !== pts[i - 1].x || p.y !== pts[i - 1].y);
|
|
@@ -321,38 +431,35 @@ function wallItem(g, room, kind, x) {
|
|
|
321
431
|
function sign(g, x, y, w) {
|
|
322
432
|
box(g, x, y, w, 9, C.sign, C.ink);
|
|
323
433
|
}
|
|
324
|
-
/** How wide a room's name plate is, so what hangs beside it starts after it. */
|
|
325
|
-
const signWidth = (room) => Math.max(40, room.name.length * 4 + 8);
|
|
326
434
|
/** Where a room's clock, board or poster hangs: towards the far end of its wall. */
|
|
327
435
|
const wallSpot = (room) => room.x + room.w - 70;
|
|
436
|
+
/** Whether a room's wall has space for its clock, board or poster past its name plate; and for a window between them. */
|
|
437
|
+
const hangs = (room) => wallSpot(room) >= room.x + 8 + signWidth(room) + 6;
|
|
438
|
+
const windowed = (room) => room.x + 8 + signWidth(room) + 16 + 30 <= (hangs(room) ? wallSpot(room) : room.x + room.w - (room.band === 'bottom' ? STRIP : 0)) - 6;
|
|
328
439
|
|
|
329
440
|
const background = document.createElement('canvas');
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
441
|
+
/** The building, drawn again whenever the floor is laid out anew. */
|
|
442
|
+
function drawBackground() {
|
|
443
|
+
background.width = LW;
|
|
444
|
+
background.height = LH;
|
|
333
445
|
const g = background.getContext('2d');
|
|
334
446
|
// The garden, and the path to the door.
|
|
335
447
|
rect(g, 0, FLOOR_H, LW, GARDEN, C.grass);
|
|
336
|
-
for (let i = 0; i <
|
|
448
|
+
for (let i = 0; i < Math.round(LW * 0.55); i += 1) {
|
|
337
449
|
const hx = hash(`tuft${i}`);
|
|
338
450
|
rect(g, hx % LW, FLOOR_H + 4 + ((hx >> 9) % (GARDEN - 6)), 1, 2, i % 3 ? C.grassDark : C.grassLight);
|
|
339
451
|
}
|
|
340
452
|
rect(g, ENTRANCE.x - 10, FLOOR_H, 20, GARDEN, C.path);
|
|
341
453
|
for (let y = FLOOR_H + 4; y < LH; y += 8) rect(g, ENTRANCE.x - 10, y, 20, 1, C.pathDark);
|
|
342
|
-
for (
|
|
343
|
-
for (
|
|
454
|
+
for (let tx = 6; tx < LW - 18; tx += 56 + (hash(`tree${tx}`) % 12)) if (Math.abs(tx + 9 - ENTRANCE.x) > 24) tree(g, tx, FLOOR_H + 14);
|
|
455
|
+
for (let fx = 34; fx < LW - 8; fx += 62) if (Math.abs(fx - ENTRANCE.x) > 20) {
|
|
344
456
|
rect(g, fx, FLOOR_H + 6, 2, 2, C.flower);
|
|
345
457
|
rect(g, fx + 5, FLOOR_H + 9, 2, 2, C.flowerY);
|
|
346
458
|
}
|
|
347
|
-
// The corridor,
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
rect(g, CORRIDOR_X, FACE - 2, CORRIDOR_W, 2, C.base);
|
|
352
|
-
box(g, CORRIDOR_X + 9, 4, 14, 9, '#3ec74d');
|
|
353
|
-
rect(g, CORRIDOR_X + 11, 7, 10, 3, C.white);
|
|
354
|
-
plant(g, CORRIDOR_X + 9, FACE + 2, true);
|
|
355
|
-
plant(g, CORRIDOR_X + 9, FLOOR_H - 26, true);
|
|
459
|
+
// The corridor, across the building between the two rows of rooms.
|
|
460
|
+
const hallTop = HALL_Y - CORRIDOR_H / 2;
|
|
461
|
+
tiles(g, 0, hallTop, LW, CORRIDOR_H, C.hall, C.hallLine);
|
|
462
|
+
plant(g, 6, hallTop + 6, true);
|
|
356
463
|
// Each room: its floor, the wall it faces, its furniture.
|
|
357
464
|
for (const room of [...rooms.values(), lobby]) {
|
|
358
465
|
tiles(g, room.x, room.y, room.w, room.h, C.floor, C.floorLine);
|
|
@@ -362,11 +469,16 @@ background.height = LH;
|
|
|
362
469
|
rect(g, room.x, room.y + FACE - 10, room.w, 1, C.bandDark);
|
|
363
470
|
rect(g, room.x, room.y + FACE - 2, room.w, 2, C.base);
|
|
364
471
|
if (room !== lobby) sign(g, room.x + 8, room.y + 4, signWidth(room));
|
|
472
|
+
if (room.band === 'bottom') {
|
|
473
|
+
// The doorway in the wall it faces, onto the corridor.
|
|
474
|
+
tiles(g, room.doorX - 10, room.y, 20, FACE, C.floor, C.floorLine);
|
|
475
|
+
rect(g, room.doorX - 11, room.y, 1, FACE, C.ink);
|
|
476
|
+
rect(g, room.doorX + 10, room.y, 1, FACE, C.ink);
|
|
477
|
+
}
|
|
365
478
|
}
|
|
366
479
|
for (const room of rooms.values()) {
|
|
367
|
-
|
|
368
|
-
wallItem(g, room, '
|
|
369
|
-
wallItem(g, room, room.key === 'design' ? 'board' : room.key === 'lab' ? 'poster' : 'clock', wallSpot(room));
|
|
480
|
+
if (windowed(room)) wallItem(g, room, 'window', room.x + 8 + signWidth(room) + 16);
|
|
481
|
+
if (hangs(room)) wallItem(g, room, room.key === 'design' ? 'board' : room.key === 'lab' ? 'poster' : 'clock', wallSpot(room));
|
|
370
482
|
for (const st of room.stages) for (const d of stages.get(st.role).desks) deskAt(g, d.dx, d.dy);
|
|
371
483
|
if (room.stages.length === 0) {
|
|
372
484
|
// A room with no stage of its own is somewhere to sit.
|
|
@@ -374,14 +486,14 @@ background.height = LH;
|
|
|
374
486
|
box(g, room.x + 70, room.y + FACE + 20, room.w - 140, 14, C.wood);
|
|
375
487
|
for (let i = 0; i < 4; i += 1) box(g, room.x + 58 + i * 30, room.y + FACE + 8, 10, 9, C.seatRed);
|
|
376
488
|
}
|
|
377
|
-
plant(g,
|
|
378
|
-
// The shelf and the rack stand in a
|
|
379
|
-
//
|
|
380
|
-
const corner = room
|
|
381
|
-
if (room.key === 'release'
|
|
382
|
-
if (room.key === 'lab'
|
|
383
|
-
box(g,
|
|
384
|
-
for (let i = 0; i < 6; i += 1) rect(g,
|
|
489
|
+
plant(g, room.x + 4, room.laneY - 18, true);
|
|
490
|
+
// The shelf and the rack stand in a column of their own past the last desk: in the room's far corner, the fourth
|
|
491
|
+
// desk of a room stood under them.
|
|
492
|
+
const corner = cornerX(room);
|
|
493
|
+
if (room.key === 'release') shelf(g, corner, room.y + FACE + 2);
|
|
494
|
+
if (room.key === 'lab') {
|
|
495
|
+
box(g, corner + 3, room.y + FACE + 2, 16, 30, C.rack);
|
|
496
|
+
for (let i = 0; i < 6; i += 1) rect(g, corner + 6, room.y + FACE + 5 + i * 4, 2, 1, i % 3 ? C.ledG : C.ledR);
|
|
385
497
|
}
|
|
386
498
|
}
|
|
387
499
|
// The reception: the counter's back, the waiting chairs, a vending machine, plants; the sign on its wall.
|
|
@@ -405,7 +517,7 @@ background.height = LH;
|
|
|
405
517
|
rect(g, lobby.x + 140, lobby.y + FACE + 22, 40, 16, C.rug);
|
|
406
518
|
box(g, lobby.x + 150, lobby.y + FACE + 26, 20, 8, C.wood);
|
|
407
519
|
plant(g, COUNTER.x - 12, COUNTER.y - 4, false);
|
|
408
|
-
plant(g, lobby.x +
|
|
520
|
+
plant(g, lobby.x + 206, lobby.laneY - 20, true);
|
|
409
521
|
rect(g, ENTRANCE.x - 12, FLOOR_H - 8, 24, 6, C.rugEdge);
|
|
410
522
|
}
|
|
411
523
|
// The walls themselves: their white tops, outlined, with doors onto the corridor and out to the garden.
|
|
@@ -418,15 +530,17 @@ background.height = LH;
|
|
|
418
530
|
rect(g, x0, y - 1, x1 - x0, 2, C.wallTop);
|
|
419
531
|
};
|
|
420
532
|
for (const room of [...rooms.values(), lobby]) {
|
|
421
|
-
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
533
|
+
// A room above the corridor has its door in the wall along its bottom; one below, in the wall along its top.
|
|
534
|
+
const doorWall = room.band === 'top' ? room.y + room.h - 1 : room.y + 1;
|
|
535
|
+
wallH(room.x, room.doorX - 10, doorWall);
|
|
536
|
+
wallH(room.doorX + 10, room.x + room.w, doorWall);
|
|
537
|
+
rect(g, room.doorX - 12, doorWall - 2, 2, 4, C.rail);
|
|
538
|
+
rect(g, room.doorX + 10, doorWall - 2, 2, 4, C.rail);
|
|
539
|
+
if (room.band === 'top') wallH(room.x, room.x + room.w, room.y + 1);
|
|
540
|
+
if (room.x > 0) wallV(room.x, room.y, room.y + room.h);
|
|
429
541
|
}
|
|
542
|
+
wallV(1, 0, FLOOR_H);
|
|
543
|
+
wallV(LW - 1, 0, FLOOR_H);
|
|
430
544
|
wallH(0, ENTRANCE.x - 12, FLOOR_H - 1);
|
|
431
545
|
wallH(ENTRANCE.x + 12, LW, FLOOR_H - 1);
|
|
432
546
|
}
|
|
@@ -475,6 +589,8 @@ function seatAt(stage, p, instant = false) {
|
|
|
475
589
|
}
|
|
476
590
|
}
|
|
477
591
|
if (!slot) {
|
|
592
|
+
// Already standing beside this stage's full desks, they stay where they stand.
|
|
593
|
+
if (p.slot?.extra && p.slot.role === stage.role) return p.slot;
|
|
478
594
|
const extra = { ...stage.spare, who: p, extra: true };
|
|
479
595
|
if (p.slot && p.slot.who === p) p.slot.who = null;
|
|
480
596
|
p.slot = extra;
|
|
@@ -546,7 +662,6 @@ let banner = null;
|
|
|
546
662
|
/** What the view follows when it is closer than the whole office: a person as they walk, or a spot. */
|
|
547
663
|
let focus = null;
|
|
548
664
|
const follow = (target) => (focus = target);
|
|
549
|
-
const RECEPTION = { x: COUNTER.x + COUNTER.w / 2, y: COUNTER.y + 14 };
|
|
550
665
|
/** The stage a dispatch past its cap was for, while the gate's call waits on the owner. */
|
|
551
666
|
let capRole = null;
|
|
552
667
|
function settleCap() {
|
|
@@ -805,8 +920,6 @@ function step(p, dt) {
|
|
|
805
920
|
}
|
|
806
921
|
|
|
807
922
|
const world = document.createElement('canvas');
|
|
808
|
-
world.width = LW;
|
|
809
|
-
world.height = LH;
|
|
810
923
|
const w = world.getContext('2d');
|
|
811
924
|
const screen = document.getElementById('screen');
|
|
812
925
|
const s = screen.getContext('2d');
|
|
@@ -834,7 +947,7 @@ let scale = 1;
|
|
|
834
947
|
let band = 0;
|
|
835
948
|
let ox = 0;
|
|
836
949
|
let oy = 0;
|
|
837
|
-
const cam = { x:
|
|
950
|
+
const cam = { x: 0, y: 0 };
|
|
838
951
|
let handsOffUntil = 0;
|
|
839
952
|
/** 'fit', a zoom the viewer chose in points an office pixel, or null when they never chose. */
|
|
840
953
|
let chosen = null;
|
|
@@ -967,6 +1080,9 @@ function resize() {
|
|
|
967
1080
|
screen.style.width = `${window.innerWidth - side}px`;
|
|
968
1081
|
screen.style.height = `${window.innerHeight}px`;
|
|
969
1082
|
band = Math.round(BAND * dpr);
|
|
1083
|
+
// The floor is laid out for the space the office is drawn in, and again when that space takes another shape.
|
|
1084
|
+
const next = arrange(window.innerWidth - side, window.innerHeight - BAND);
|
|
1085
|
+
if (!arranged || next.top !== arranged.top || next.bottom !== arranged.bottom) layout(next);
|
|
970
1086
|
fit = Math.min(screen.width / LW, (screen.height - band) / LH);
|
|
971
1087
|
scale = level() * dpr;
|
|
972
1088
|
syncButtons();
|
|
@@ -1101,7 +1217,7 @@ function drawWorld(now) {
|
|
|
1101
1217
|
// The clock in each room says the time it is here.
|
|
1102
1218
|
const t = new Date();
|
|
1103
1219
|
for (const room of rooms.values()) {
|
|
1104
|
-
if (room.key === 'design' || room.key === 'lab') continue;
|
|
1220
|
+
if (room.key === 'design' || room.key === 'lab' || !hangs(room)) continue;
|
|
1105
1221
|
const cx = wallSpot(room) + 5;
|
|
1106
1222
|
const cy = room.y + 10;
|
|
1107
1223
|
for (const [len, turn] of [[2, (t.getHours() % 12) / 12 + t.getMinutes() / 720], [3, t.getMinutes() / 60]]) {
|
|
@@ -1175,7 +1291,7 @@ function drawScreen(now) {
|
|
|
1175
1291
|
if (Number.isInteger(scale) || scale > 4) s.drawImage(world, ox, oy, LW * scale, LH * scale);
|
|
1176
1292
|
else {
|
|
1177
1293
|
const k = Math.max(1, Math.ceil(scale));
|
|
1178
|
-
if (crisp.width !== LW * k) {
|
|
1294
|
+
if (crisp.width !== LW * k || crisp.height !== LH * k) {
|
|
1179
1295
|
crisp.width = LW * k;
|
|
1180
1296
|
crisp.height = LH * k;
|
|
1181
1297
|
}
|
package/src/office.mjs
CHANGED
|
@@ -100,7 +100,8 @@ const REPLAY_MIN_GAP_MS = 500;
|
|
|
100
100
|
* @param {object[]} ledger - The ledger, oldest first.
|
|
101
101
|
*/
|
|
102
102
|
function readStarts(ledger) {
|
|
103
|
-
|
|
103
|
+
// What a session carried over from the one before it is that session's work, drawn there.
|
|
104
|
+
const entries = ledger.filter((e) => Number.isFinite(Date.parse(e?.at)) && !e.inherited);
|
|
104
105
|
const time = (e) => Date.parse(e.at);
|
|
105
106
|
const dispatches = new Map();
|
|
106
107
|
for (const e of entries) if (e.k === 'dispatch' && e.id && !dispatches.has(e.id)) dispatches.set(e.id, e);
|