agents-city 0.3.0-beta.21
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/.claude-plugin/marketplace.json +16 -0
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.es.md +2021 -0
- package/README.md +1999 -0
- package/benchmarks/committee/README.md +39 -0
- package/benchmarks/committee/metrics.py +51 -0
- package/benchmarks/committee/run.py +64 -0
- package/benchmarks/committee/traces/01-single.json +8 -0
- package/benchmarks/committee/traces/02-mesh.json +16 -0
- package/benchmarks/committee/traces/03-chair.json +15 -0
- package/benchmarks/latency/README.md +35 -0
- package/benchmarks/latency/fake-claude-cli.mjs +119 -0
- package/benchmarks/latency/fake-native-server.mjs +340 -0
- package/benchmarks/latency/fake-tui.py +91 -0
- package/benchmarks/latency/live.py +380 -0
- package/benchmarks/stress/README.md +20 -0
- package/benchmarks/stress/run.py +487 -0
- package/bin/agents +4 -0
- package/bin/agents-city.js +116 -0
- package/bin/benchmark +17 -0
- package/bin/bus +6 -0
- package/bin/cities +3 -0
- package/bin/city +86 -0
- package/bin/committee +6 -0
- package/bin/demo +200 -0
- package/bin/exit +5 -0
- package/bin/hall +73 -0
- package/bin/hall.html +426 -0
- package/bin/logs +3 -0
- package/bin/report.py +14 -0
- package/bin/reset +3 -0
- package/bin/road +3 -0
- package/bin/seat +10 -0
- package/bin/serve.py +1428 -0
- package/bin/setup.py +753 -0
- package/bin/skills +3 -0
- package/bin/test +131 -0
- package/bin/test-adapter.py +183 -0
- package/bin/test-admision.py +99 -0
- package/bin/test-avatar.py +58 -0
- package/bin/test-benchmark.py +40 -0
- package/bin/test-broker.py +334 -0
- package/bin/test-cage.py +206 -0
- package/bin/test-card.py +402 -0
- package/bin/test-channel.py +379 -0
- package/bin/test-cities.py +453 -0
- package/bin/test-claude-runtime.py +252 -0
- package/bin/test-committee.py +340 -0
- package/bin/test-contracts.py +544 -0
- package/bin/test-crecimiento.py +164 -0
- package/bin/test-demo.py +308 -0
- package/bin/test-doctor.py +106 -0
- package/bin/test-domains.py +151 -0
- package/bin/test-evidencia.py +50 -0
- package/bin/test-exit.py +128 -0
- package/bin/test-hall-protocol.py +93 -0
- package/bin/test-launch.py +169 -0
- package/bin/test-live-feed.py +508 -0
- package/bin/test-pairing.py +99 -0
- package/bin/test-parcels.py +283 -0
- package/bin/test-runtime-failures.py +252 -0
- package/bin/test-runtime-ui.py +488 -0
- package/bin/test-runtime.py +268 -0
- package/bin/test-rutas.py +80 -0
- package/bin/test-seat.py +1386 -0
- package/bin/test-security.py +150 -0
- package/bin/test-serve.py +1057 -0
- package/bin/test-stress.py +64 -0
- package/bin/test-widgets.py +143 -0
- package/bin/test-workspace.py +188 -0
- package/bin/testlib.py +95 -0
- package/bin/tokens.py +14 -0
- package/bus/scripts/deploy.sh +60 -0
- package/bus/scripts/mint-token.sh +68 -0
- package/bus/scripts/setup-dev.sh +79 -0
- package/bus/scripts/test-channel.ts +8 -0
- package/bus/scripts/test-hub.ts +266 -0
- package/bus/scripts/test-local.sh +40 -0
- package/bus/scripts/test-queue.ts +132 -0
- package/bus/worker/package-lock.json +1971 -0
- package/bus/worker/package.json +17 -0
- package/bus/worker/src/index.ts +485 -0
- package/bus/worker/tsconfig.json +13 -0
- package/bus/worker/wrangler.toml +32 -0
- package/city/oven/README.md +59 -0
- package/city/oven/collect.py +43 -0
- package/city/oven/oven.html +4 -0
- package/city/scripts/history.py +120 -0
- package/city/scripts/seed.py +442 -0
- package/city/web/assets/modelos/License.txt +28 -0
- package/city/web/assets/modelos/PROCEDENCIA.txt +3 -0
- package/city/web/assets/modelos/building-a.glb +0 -0
- package/city/web/assets/modelos/building-b.glb +0 -0
- package/city/web/assets/modelos/building-c.glb +0 -0
- package/city/web/assets/modelos/building-d.glb +0 -0
- package/city/web/assets/modelos/building-e.glb +0 -0
- package/city/web/assets/modelos/building-f.glb +0 -0
- package/city/web/assets/modelos/building-g.glb +0 -0
- package/city/web/assets/modelos/building-h.glb +0 -0
- package/city/web/assets/sprites/building-a.png +0 -0
- package/city/web/assets/sprites/building-b.png +0 -0
- package/city/web/assets/sprites/building-c.png +0 -0
- package/city/web/assets/sprites/building-d.png +0 -0
- package/city/web/assets/sprites/building-e.png +0 -0
- package/city/web/assets/sprites/building-f.png +0 -0
- package/city/web/assets/sprites/building-g.png +0 -0
- package/city/web/assets/sprites/building-h.png +0 -0
- package/city/web/assets/sprites/building-i.png +0 -0
- package/city/web/assets/sprites/building-j.png +0 -0
- package/city/web/assets/sprites/building-k.png +0 -0
- package/city/web/assets/sprites/building-l.png +0 -0
- package/city/web/assets/sprites/building-m.png +0 -0
- package/city/web/assets/sprites/building-n.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-a.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-b.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-c.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-d.png +0 -0
- package/city/web/assets/sprites/building-skyscraper-e.png +0 -0
- package/city/web/assets/sprites/catalogo.json +47 -0
- package/city/web/assets/sprites/detail-awning-wide.png +0 -0
- package/city/web/assets/sprites/detail-awning.png +0 -0
- package/city/web/assets/sprites/detail-overhang-wide.png +0 -0
- package/city/web/assets/sprites/detail-overhang.png +0 -0
- package/city/web/assets/sprites/detail-parasol-a.png +0 -0
- package/city/web/assets/sprites/detail-parasol-b.png +0 -0
- package/city/web/assets/sprites/low-detail-building-a.png +0 -0
- package/city/web/assets/sprites/low-detail-building-b.png +0 -0
- package/city/web/assets/sprites/low-detail-building-c.png +0 -0
- package/city/web/assets/sprites/low-detail-building-d.png +0 -0
- package/city/web/assets/sprites/low-detail-building-e.png +0 -0
- package/city/web/assets/sprites/low-detail-building-f.png +0 -0
- package/city/web/assets/sprites/low-detail-building-g.png +0 -0
- package/city/web/assets/sprites/low-detail-building-h.png +0 -0
- package/city/web/assets/sprites/low-detail-building-i.png +0 -0
- package/city/web/assets/sprites/low-detail-building-j.png +0 -0
- package/city/web/assets/sprites/low-detail-building-k.png +0 -0
- package/city/web/assets/sprites/low-detail-building-l.png +0 -0
- package/city/web/assets/sprites/low-detail-building-m.png +0 -0
- package/city/web/assets/sprites/low-detail-building-n.png +0 -0
- package/city/web/assets/sprites/low-detail-building-wide-a.png +0 -0
- package/city/web/assets/sprites/low-detail-building-wide-b.png +0 -0
- package/city/web/assets/sprites/medidas.json +248 -0
- package/city/web/dist/city.js +939 -0
- package/city/web/dist/index.html +294 -0
- package/city/web/dist/modelos/License.txt +28 -0
- package/city/web/dist/modelos/PROCEDENCIA.txt +3 -0
- package/city/web/dist/modelos/building-a.glb +0 -0
- package/city/web/dist/modelos/building-b.glb +0 -0
- package/city/web/dist/modelos/building-c.glb +0 -0
- package/city/web/dist/modelos/building-d.glb +0 -0
- package/city/web/dist/modelos/building-e.glb +0 -0
- package/city/web/dist/modelos/building-f.glb +0 -0
- package/city/web/dist/modelos/building-g.glb +0 -0
- package/city/web/dist/modelos/building-h.glb +0 -0
- package/city/web/dist/sprites/building-a.png +0 -0
- package/city/web/dist/sprites/building-b.png +0 -0
- package/city/web/dist/sprites/building-c.png +0 -0
- package/city/web/dist/sprites/building-d.png +0 -0
- package/city/web/dist/sprites/building-e.png +0 -0
- package/city/web/dist/sprites/building-f.png +0 -0
- package/city/web/dist/sprites/building-g.png +0 -0
- package/city/web/dist/sprites/building-h.png +0 -0
- package/city/web/dist/sprites/building-i.png +0 -0
- package/city/web/dist/sprites/building-j.png +0 -0
- package/city/web/dist/sprites/building-k.png +0 -0
- package/city/web/dist/sprites/building-l.png +0 -0
- package/city/web/dist/sprites/building-m.png +0 -0
- package/city/web/dist/sprites/building-n.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-a.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-b.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-c.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-d.png +0 -0
- package/city/web/dist/sprites/building-skyscraper-e.png +0 -0
- package/city/web/dist/sprites/catalogo.json +47 -0
- package/city/web/dist/sprites/detail-awning-wide.png +0 -0
- package/city/web/dist/sprites/detail-awning.png +0 -0
- package/city/web/dist/sprites/detail-overhang-wide.png +0 -0
- package/city/web/dist/sprites/detail-overhang.png +0 -0
- package/city/web/dist/sprites/detail-parasol-a.png +0 -0
- package/city/web/dist/sprites/detail-parasol-b.png +0 -0
- package/city/web/dist/sprites/low-detail-building-a.png +0 -0
- package/city/web/dist/sprites/low-detail-building-b.png +0 -0
- package/city/web/dist/sprites/low-detail-building-c.png +0 -0
- package/city/web/dist/sprites/low-detail-building-d.png +0 -0
- package/city/web/dist/sprites/low-detail-building-e.png +0 -0
- package/city/web/dist/sprites/low-detail-building-f.png +0 -0
- package/city/web/dist/sprites/low-detail-building-g.png +0 -0
- package/city/web/dist/sprites/low-detail-building-h.png +0 -0
- package/city/web/dist/sprites/low-detail-building-i.png +0 -0
- package/city/web/dist/sprites/low-detail-building-j.png +0 -0
- package/city/web/dist/sprites/low-detail-building-k.png +0 -0
- package/city/web/dist/sprites/low-detail-building-l.png +0 -0
- package/city/web/dist/sprites/low-detail-building-m.png +0 -0
- package/city/web/dist/sprites/low-detail-building-n.png +0 -0
- package/city/web/dist/sprites/low-detail-building-wide-a.png +0 -0
- package/city/web/dist/sprites/low-detail-building-wide-b.png +0 -0
- package/city/web/dist/sprites/medidas.json +248 -0
- package/city/web/dist-hall/hall.js +264 -0
- package/city/web/index.html +294 -0
- package/city/web/package.json +18 -0
- package/city/web/sella.py +21 -0
- package/city/web/src/activity-actors.ts +47 -0
- package/city/web/src/activity.ts +172 -0
- package/city/web/src/ayuntamiento.ts +580 -0
- package/city/web/src/draw.ts +640 -0
- package/city/web/src/game-speech.ts +79 -0
- package/city/web/src/hall.ts +1867 -0
- package/city/web/src/main.ts +2225 -0
- package/city/web/src/oven.ts +124 -0
- package/city/web/src/people.ts +244 -0
- package/city/web/src/presencia.ts +193 -0
- package/city/web/src/puertas.ts +180 -0
- package/city/web/src/repo-roles.ts +59 -0
- package/city/worker/package.json +16 -0
- package/city/worker/schema.sql +117 -0
- package/city/worker/src/index.ts +702 -0
- package/city/worker/src/square.ts +218 -0
- package/city/worker/wrangler.toml +58 -0
- package/demo/ada.md +50 -0
- package/demo/bruno.md +62 -0
- package/demo/camila.md +56 -0
- package/demo/city/ada.md +40 -0
- package/demo/city/city.yml +8 -0
- package/demo/city/parcels.yml +15 -0
- package/demo/city/roads.json +4 -0
- package/demo/city/units.yml +10 -0
- package/demo/clinica/city.yml +8 -0
- package/demo/clinica/parcels.yml +15 -0
- package/demo/clinica/roads.json +4 -0
- package/demo/clinica/units.yml +9 -0
- package/demo/clinica/vera.md +46 -0
- package/demo/dante.md +54 -0
- package/demo/despacho/city.yml +8 -0
- package/demo/despacho/marta.md +46 -0
- package/demo/despacho/parcels.yml +15 -0
- package/demo/despacho/roads.json +4 -0
- package/demo/despacho/units.yml +9 -0
- package/demo/elsa.md +50 -0
- package/demo/farid.md +52 -0
- package/demo/greta.md +50 -0
- package/demo/hugo.md +49 -0
- package/demo/iris.md +49 -0
- package/demo/jonas.md +51 -0
- package/demo/kira.md +51 -0
- package/demo/luca.md +49 -0
- package/demo/parcels.yml +92 -0
- package/demo/seed.py +20 -0
- package/demo/show.py +161 -0
- package/demo/stories.py +824 -0
- package/demo/units.yml +33 -0
- package/docs/agents-first.md +99 -0
- package/docs/glossary.md +55 -0
- package/docs/map-live-layers.md +73 -0
- package/docs/security.md +231 -0
- package/docs/self-host.md +151 -0
- package/docs/testing.md +205 -0
- package/package.json +73 -0
- package/plugin/.claude-plugin/plugin.json +62 -0
- package/plugin/.mcp.json +15 -0
- package/plugin/channel/activity-cli.ts +16 -0
- package/plugin/channel/adapter-prompts.ts +113 -0
- package/plugin/channel/adapter.js +4292 -0
- package/plugin/channel/adapter.ts +133 -0
- package/plugin/channel/bus.js +20188 -0
- package/plugin/channel/bus.ts +131 -0
- package/plugin/channel/city-config.ts +125 -0
- package/plugin/channel/claude-channel.ts +58 -0
- package/plugin/channel/cli-args.ts +75 -0
- package/plugin/channel/client.js +4200 -0
- package/plugin/channel/client.ts +38 -0
- package/plugin/channel/committee/activity.ts +256 -0
- package/plugin/channel/committee/collection.ts +154 -0
- package/plugin/channel/committee/decision.ts +175 -0
- package/plugin/channel/committee/floor.ts +135 -0
- package/plugin/channel/committee/guards.ts +30 -0
- package/plugin/channel/committee/history.ts +38 -0
- package/plugin/channel/committee/render.ts +102 -0
- package/plugin/channel/committee/service.ts +72 -0
- package/plugin/channel/committee/storage.ts +92 -0
- package/plugin/channel/committee/types.ts +163 -0
- package/plugin/channel/committee/view.ts +63 -0
- package/plugin/channel/committee-cli.ts +109 -0
- package/plugin/channel/delivery-metrics.ts +61 -0
- package/plugin/channel/delivery-queue.ts +118 -0
- package/plugin/channel/hub/activity-controller.ts +72 -0
- package/plugin/channel/hub/activity-feed.ts +169 -0
- package/plugin/channel/hub/committee-controller.ts +60 -0
- package/plugin/channel/hub/connections.ts +48 -0
- package/plugin/channel/hub/diagnostics.ts +67 -0
- package/plugin/channel/hub/envelope-validity.ts +109 -0
- package/plugin/channel/hub/envelopes.ts +66 -0
- package/plugin/channel/hub/lifecycle.ts +91 -0
- package/plugin/channel/hub/local-roads.ts +89 -0
- package/plugin/channel/hub/remote-roads.ts +165 -0
- package/plugin/channel/hub/road-controller.ts +99 -0
- package/plugin/channel/hub-client.ts +149 -0
- package/plugin/channel/local-hub.js +5995 -0
- package/plugin/channel/local-hub.ts +349 -0
- package/plugin/channel/map-reporter.ts +48 -0
- package/plugin/channel/package-lock.json +1731 -0
- package/plugin/channel/package.json +19 -0
- package/plugin/channel/protocol.ts +98 -0
- package/plugin/channel/road-cli.ts +18 -0
- package/plugin/channel/run.sh +15 -0
- package/plugin/channel/runtime/claude.ts +458 -0
- package/plugin/channel/runtime/codex-config.ts +77 -0
- package/plugin/channel/runtime/codex.ts +669 -0
- package/plugin/channel/runtime/command.ts +62 -0
- package/plugin/channel/runtime/factory.ts +15 -0
- package/plugin/channel/runtime/json-rpc.ts +154 -0
- package/plugin/channel/runtime/kimi.ts +277 -0
- package/plugin/channel/runtime/opencode.ts +248 -0
- package/plugin/channel/runtime/process.ts +84 -0
- package/plugin/channel/runtime/types.ts +45 -0
- package/plugin/channel/runtime-files.ts +73 -0
- package/plugin/channel/runtime-gateway.js +6396 -0
- package/plugin/channel/runtime-gateway.ts +358 -0
- package/plugin/channel/runtime-metrics.ts +52 -0
- package/plugin/channel/runtime-subscription.ts +180 -0
- package/plugin/channel/terminal-delivery.ts +131 -0
- package/plugin/channel/untrusted.ts +60 -0
- package/plugin/commands/committee.md +31 -0
- package/plugin/commands/exit.md +32 -0
- package/plugin/commands/goals.md +20 -0
- package/plugin/commands/join.md +18 -0
- package/plugin/commands/notice.md +20 -0
- package/plugin/commands/propose.md +19 -0
- package/plugin/commands/round.md +17 -0
- package/plugin/commands/session.md +22 -0
- package/plugin/commands/settings.md +25 -0
- package/plugin/commands/setup.md +21 -0
- package/plugin/commands/team.md +23 -0
- package/plugin/domains/custom.md +27 -0
- package/plugin/domains/finance.md +31 -0
- package/plugin/domains/healthcare.md +34 -0
- package/plugin/domains/legal.md +31 -0
- package/plugin/domains/marketing.md +33 -0
- package/plugin/domains/operations.md +31 -0
- package/plugin/domains/research.md +32 -0
- package/plugin/domains/sales.md +30 -0
- package/plugin/domains/software.md +37 -0
- package/plugin/hooks/activity.sh +6 -0
- package/plugin/hooks/digging.sh +68 -0
- package/plugin/hooks/growth.sh +42 -0
- package/plugin/hooks/hooks.json +106 -0
- package/plugin/hooks/notice-on-pr.sh +35 -0
- package/plugin/hooks/notice-on-stop.sh +80 -0
- package/plugin/hooks/notice-pending.sh +58 -0
- package/plugin/hooks/solo-en-ciudad.sh +23 -0
- package/plugin/hooks/tokens.sh +47 -0
- package/plugin/roles/examples/account-executive.md +25 -0
- package/plugin/roles/examples/ai-manager.md +34 -0
- package/plugin/roles/examples/associate.md +24 -0
- package/plugin/roles/examples/brand-lead.md +20 -0
- package/plugin/roles/examples/cfo.md +20 -0
- package/plugin/roles/examples/city-lead.md +25 -0
- package/plugin/roles/examples/clinical-director.md +26 -0
- package/plugin/roles/examples/clinical-ops.md +25 -0
- package/plugin/roles/examples/clinician.md +25 -0
- package/plugin/roles/examples/compliance.md +27 -0
- package/plugin/roles/examples/content.md +24 -0
- package/plugin/roles/examples/controller.md +27 -0
- package/plugin/roles/examples/cpto.md +41 -0
- package/plugin/roles/examples/customer-success.md +25 -0
- package/plugin/roles/examples/data-engineer.md +37 -0
- package/plugin/roles/examples/data.md +60 -0
- package/plugin/roles/examples/dev.md +37 -0
- package/plugin/roles/examples/devops.md +39 -0
- package/plugin/roles/examples/enablement.md +24 -0
- package/plugin/roles/examples/ethics.md +24 -0
- package/plugin/roles/examples/fin-analytics.md +27 -0
- package/plugin/roles/examples/health-compliance.md +25 -0
- package/plugin/roles/examples/health-data.md +26 -0
- package/plugin/roles/examples/knowledge.md +25 -0
- package/plugin/roles/examples/lifecycle.md +26 -0
- package/plugin/roles/examples/llm-engineer.md +34 -0
- package/plugin/roles/examples/managing-partner.md +20 -0
- package/plugin/roles/examples/methods.md +23 -0
- package/plugin/roles/examples/operations-lead.md +23 -0
- package/plugin/roles/examples/ops.md +24 -0
- package/plugin/roles/examples/patient-safety.md +26 -0
- package/plugin/roles/examples/performance.md +27 -0
- package/plugin/roles/examples/po.md +36 -0
- package/plugin/roles/examples/process-owner.md +23 -0
- package/plugin/roles/examples/product-design.md +39 -0
- package/plugin/roles/examples/program-manager.md +24 -0
- package/plugin/roles/examples/quality.md +25 -0
- package/plugin/roles/examples/research-director.md +24 -0
- package/plugin/roles/examples/research-ops.md +25 -0
- package/plugin/roles/examples/researcher.md +25 -0
- package/plugin/roles/examples/revenue-lead.md +25 -0
- package/plugin/roles/examples/revops.md +26 -0
- package/plugin/roles/examples/seo.md +27 -0
- package/plugin/roles/examples/specialist.md +24 -0
- package/plugin/scripts/admision.py +165 -0
- package/plugin/scripts/apaga.py +232 -0
- package/plugin/scripts/avatar.py +211 -0
- package/plugin/scripts/broker.py +531 -0
- package/plugin/scripts/cage.py +252 -0
- package/plugin/scripts/capabilities.py +197 -0
- package/plugin/scripts/card.py +312 -0
- package/plugin/scripts/cities.py +520 -0
- package/plugin/scripts/city-env.sh +90 -0
- package/plugin/scripts/city-runtime.sh +87 -0
- package/plugin/scripts/city-session.sh +526 -0
- package/plugin/scripts/city_env.py +67 -0
- package/plugin/scripts/crecimiento.py +140 -0
- package/plugin/scripts/deliberations.py +48 -0
- package/plugin/scripts/doctor.py +172 -0
- package/plugin/scripts/domains.py +201 -0
- package/plugin/scripts/evidencia.py +64 -0
- package/plugin/scripts/find-repos.sh +111 -0
- package/plugin/scripts/gh.py +159 -0
- package/plugin/scripts/hall_protocol.py +147 -0
- package/plugin/scripts/hook_activity.py +139 -0
- package/plugin/scripts/launch.py +94 -0
- package/plugin/scripts/logs.py +98 -0
- package/plugin/scripts/pairing.py +185 -0
- package/plugin/scripts/parcels.py +132 -0
- package/plugin/scripts/read-card.py +51 -0
- package/plugin/scripts/report.py +201 -0
- package/plugin/scripts/reset.py +180 -0
- package/plugin/scripts/roads.py +230 -0
- package/plugin/scripts/roles.py +274 -0
- package/plugin/scripts/runtime_log.py +69 -0
- package/plugin/scripts/runtime_processes.py +132 -0
- package/plugin/scripts/rutas.py +83 -0
- package/plugin/scripts/seat.py +1349 -0
- package/plugin/scripts/tokens.py +194 -0
- package/plugin/scripts/trust-repos.py +59 -0
- package/plugin/scripts/ui.py +280 -0
- package/plugin/scripts/units.py +80 -0
- package/plugin/scripts/workspace.py +364 -0
- package/plugin/skills/city/SKILL.md +191 -0
- package/templates/blank.md +39 -0
- package/templates/finance.md +44 -0
- package/templates/legal.md +45 -0
- package/templates/marketing.md +48 -0
- package/templates/product.md +45 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The city gates: one per road, at the entrance, past the square.
|
|
3
|
+
*
|
|
4
|
+
* A road is an allowlist entry — reachability, not a channel — and this is its
|
|
5
|
+
* honest drawing: not a highway to somewhere, but a gate with a name over it.
|
|
6
|
+
* Everything beyond the gate is another city this map will never draw; the
|
|
7
|
+
* other cities exist here exactly as much as they exist to the seat, as an
|
|
8
|
+
* address you may send to. A letter for one of them flies out through its gate
|
|
9
|
+
* and fades at the edge, because that is all this city ever sees of it.
|
|
10
|
+
*
|
|
11
|
+
* The gates come from the Hall's config message. The standalone team map never
|
|
12
|
+
* receives one and draws no gates: a map must not invent connections.
|
|
13
|
+
*/
|
|
14
|
+
import { Container, Graphics, Text, TextStyle } from 'pixi.js';
|
|
15
|
+
import { TH, tono } from './draw';
|
|
16
|
+
import type { RoadInfo } from './activity';
|
|
17
|
+
|
|
18
|
+
const PIEDRA = 0xb9a67c;
|
|
19
|
+
|
|
20
|
+
export interface Ancla {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class Puertas {
|
|
26
|
+
/** The arches, in world coordinates, under the people layer. */
|
|
27
|
+
readonly capa = new Container();
|
|
28
|
+
/** The name plates, in the banner layer, zoom-stable like every label. */
|
|
29
|
+
readonly carteles = new Container();
|
|
30
|
+
|
|
31
|
+
private readonly sitios = new Map<string, Ancla>();
|
|
32
|
+
|
|
33
|
+
constructor(
|
|
34
|
+
private readonly origen: Ancla,
|
|
35
|
+
private readonly anima: (f: (dt: number) => boolean) => void,
|
|
36
|
+
private readonly alTocar?: (road: RoadInfo) => void,
|
|
37
|
+
) {}
|
|
38
|
+
|
|
39
|
+
/** Draw the gates the Hall says exist. Called again when the roads change:
|
|
40
|
+
* it redraws from scratch — there are never more than a handful. */
|
|
41
|
+
configura(roads: RoadInfo[]): void {
|
|
42
|
+
this.capa.removeChildren().forEach((child) => child.destroy({ children: true }));
|
|
43
|
+
this.carteles.removeChildren().forEach((child) => child.destroy({ children: true }));
|
|
44
|
+
this.sitios.clear();
|
|
45
|
+
|
|
46
|
+
roads.forEach((road, i) => {
|
|
47
|
+
// Gates line up along the near edge, to the right of the square, each a
|
|
48
|
+
// step further out: the first road is the nearest gate.
|
|
49
|
+
const pos = { x: this.origen.x + 340 + i * 150, y: this.origen.y - 40 - i * 26 };
|
|
50
|
+
this.sitios.set(this.clave(road.address), pos);
|
|
51
|
+
this.sitios.set(this.clave(road.name), pos);
|
|
52
|
+
|
|
53
|
+
const g = new Container();
|
|
54
|
+
g.position.set(pos.x, pos.y);
|
|
55
|
+
// A gate is a question waiting to be clicked: where does this one go?
|
|
56
|
+
g.eventMode = 'static';
|
|
57
|
+
g.cursor = 'pointer';
|
|
58
|
+
g.on('pointertap', () => this.alTocar?.(road));
|
|
59
|
+
|
|
60
|
+
// The stub of road the gate stands on: it starts here and leaves the map.
|
|
61
|
+
const camino = new Graphics()
|
|
62
|
+
.poly([-46, 16, 96, -14, 96, 2, -46, 32])
|
|
63
|
+
.fill({ color: 0x1b2532, alpha: 0.9 });
|
|
64
|
+
camino.moveTo(-38, 22).lineTo(88, -4).stroke({ color: 0xc8b48a, width: 0.9, alpha: 0.3 });
|
|
65
|
+
g.addChild(camino);
|
|
66
|
+
|
|
67
|
+
// Two pillars flanking the road, a lintel across: the arch of the mock-up.
|
|
68
|
+
for (const [px, py] of [
|
|
69
|
+
[-12, 6],
|
|
70
|
+
[16, 22],
|
|
71
|
+
] as const) {
|
|
72
|
+
g.addChild(
|
|
73
|
+
new Graphics()
|
|
74
|
+
.ellipse(px, py + 3, 6, 2.6)
|
|
75
|
+
.fill({ color: 0x000000, alpha: 0.3 })
|
|
76
|
+
.poly([px, py, px - 5, py - 2.5, px - 5, py - 34, px, py - 31.5])
|
|
77
|
+
.fill({ color: tono(PIEDRA, -0.28) })
|
|
78
|
+
.poly([px, py, px + 5, py - 2.5, px + 5, py - 34, px, py - 31.5])
|
|
79
|
+
.fill({ color: tono(PIEDRA, -0.5) })
|
|
80
|
+
.poly([px, py - 36.5, px + 5, py - 34, px, py - 31.5, px - 5, py - 34])
|
|
81
|
+
.fill({ color: tono(PIEDRA, 0.24) }),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
g.addChild(
|
|
85
|
+
new Graphics()
|
|
86
|
+
.moveTo(-12, -30)
|
|
87
|
+
.lineTo(16, -14)
|
|
88
|
+
.stroke({ color: tono(PIEDRA, 0.25), width: 3.5, alpha: 0.95 }),
|
|
89
|
+
);
|
|
90
|
+
this.capa.addChild(g);
|
|
91
|
+
|
|
92
|
+
// The plate: the address is the point of the gate. `owner/city` is how the
|
|
93
|
+
// roads file names the far end, and how the seat addresses it.
|
|
94
|
+
const cartel = new Container();
|
|
95
|
+
const nombre = new Text({
|
|
96
|
+
text: road.name,
|
|
97
|
+
style: new TextStyle({
|
|
98
|
+
fontFamily: 'Chakra Petch, sans-serif',
|
|
99
|
+
fontSize: 10,
|
|
100
|
+
fontWeight: '700',
|
|
101
|
+
letterSpacing: 0.8,
|
|
102
|
+
fill: 0x131a24,
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
const dir = new Text({
|
|
106
|
+
text: road.address,
|
|
107
|
+
style: new TextStyle({
|
|
108
|
+
fontFamily: 'IBM Plex Mono, monospace',
|
|
109
|
+
fontSize: 8.5,
|
|
110
|
+
fill: 0x8d99a8,
|
|
111
|
+
}),
|
|
112
|
+
});
|
|
113
|
+
const ancho = Math.max(nombre.width, dir.width) + 14;
|
|
114
|
+
cartel.addChild(
|
|
115
|
+
new Graphics()
|
|
116
|
+
.roundRect(-ancho / 2, -12, ancho, 18, 3)
|
|
117
|
+
.fill({ color: PIEDRA, alpha: 0.94 }),
|
|
118
|
+
);
|
|
119
|
+
nombre.position.set(-nombre.width / 2, -10);
|
|
120
|
+
dir.position.set(-dir.width / 2, 8);
|
|
121
|
+
cartel.addChild(nombre, dir);
|
|
122
|
+
cartel.position.set(pos.x + 2, pos.y - 52);
|
|
123
|
+
this.carteles.addChild(cartel);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
hay(): boolean {
|
|
128
|
+
return this.sitios.size > 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** The gate a recipient leaves through — matched by address or name, and the
|
|
132
|
+
* first gate when the address is external but unknown: a letter that must
|
|
133
|
+
* leave the city leaves by A gate, not by teleport. */
|
|
134
|
+
puerta(destino: string): Ancla | null {
|
|
135
|
+
if (!this.sitios.size) return null;
|
|
136
|
+
const clave = this.clave(destino);
|
|
137
|
+
const exacta = this.sitios.get(clave);
|
|
138
|
+
if (exacta) return exacta;
|
|
139
|
+
for (const [k, v] of this.sitios) {
|
|
140
|
+
if (clave.includes(k) || k.includes(clave)) return v;
|
|
141
|
+
}
|
|
142
|
+
return this.sitios.values().next().value ?? null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** A letter crossing the arch, outward or inward, fading at the map's edge. */
|
|
146
|
+
vuela(puerta: Ancla, color: number, sale: boolean): void {
|
|
147
|
+
const carta = new Graphics()
|
|
148
|
+
.rect(-4, -3, 8, 6)
|
|
149
|
+
.fill({ color: 0xf2ecdd })
|
|
150
|
+
.rect(-4, -3, 8, 2)
|
|
151
|
+
.fill({ color });
|
|
152
|
+
const g = new Container();
|
|
153
|
+
g.addChild(new Graphics().circle(0, 0, 5).fill({ color, alpha: 0.16 }), carta);
|
|
154
|
+
this.capa.parent?.addChild(g);
|
|
155
|
+
const dentro = { x: puerta.x - 4, y: puerta.y - 18 };
|
|
156
|
+
const fuera = { x: puerta.x + 120, y: puerta.y - 44 };
|
|
157
|
+
const p0 = sale ? dentro : fuera;
|
|
158
|
+
const p1 = sale ? fuera : dentro;
|
|
159
|
+
let t = 0;
|
|
160
|
+
this.anima((dt) => {
|
|
161
|
+
t += 0.03 * dt;
|
|
162
|
+
const s = Math.min(1, t);
|
|
163
|
+
g.x = p0.x + (p1.x - p0.x) * s;
|
|
164
|
+
g.y = p0.y + (p1.y - p0.y) * s - Math.sin(s * Math.PI) * 10;
|
|
165
|
+
// Outward it fades leaving; inward it arrives already faint and firms up.
|
|
166
|
+
g.alpha = sale ? (s > 0.6 ? (1 - s) / 0.4 : 1) : s < 0.4 ? s / 0.4 : 1;
|
|
167
|
+
carta.rotation = Math.sin(t * 6) * 0.25;
|
|
168
|
+
if (t >= 1) {
|
|
169
|
+
g.parent?.removeChild(g);
|
|
170
|
+
g.destroy({ children: true });
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private clave(valor: string): string {
|
|
178
|
+
return valor.trim().toLowerCase();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** Pure rendering/data helpers for one operating role per repo support agent. */
|
|
2
|
+
export interface RepoRoleOption {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
summary: string;
|
|
6
|
+
trade: string;
|
|
7
|
+
domains: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type RepoRoleAssignments = Record<string, string>;
|
|
11
|
+
|
|
12
|
+
export function selectedRepoRoles(
|
|
13
|
+
repos: Iterable<string>,
|
|
14
|
+
assignments: RepoRoleAssignments,
|
|
15
|
+
): RepoRoleAssignments {
|
|
16
|
+
return Object.fromEntries([...repos].sort().map((repo) => [repo, assignments[repo] || 'blank']));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function renderRepoRoleEditor(
|
|
20
|
+
repos: Iterable<string>,
|
|
21
|
+
assignments: RepoRoleAssignments,
|
|
22
|
+
roles: RepoRoleOption[],
|
|
23
|
+
escape: (value: unknown) => string,
|
|
24
|
+
): string {
|
|
25
|
+
const selected = [...repos].sort();
|
|
26
|
+
if (!selected.length) {
|
|
27
|
+
return '<p class="prosa">No repo agents in this city.</p>';
|
|
28
|
+
}
|
|
29
|
+
return `<div class="agenteRoles">${selected
|
|
30
|
+
.map((repo) => {
|
|
31
|
+
const current = assignments[repo] || 'blank';
|
|
32
|
+
const choices = roles.some((role) => role.id === current)
|
|
33
|
+
? roles
|
|
34
|
+
: [
|
|
35
|
+
{
|
|
36
|
+
id: current,
|
|
37
|
+
name: `${current} (city-defined)`,
|
|
38
|
+
summary: 'Role defined in this city rather than the built-in catalogue.',
|
|
39
|
+
trade: current,
|
|
40
|
+
domains: [],
|
|
41
|
+
},
|
|
42
|
+
...roles,
|
|
43
|
+
];
|
|
44
|
+
return `<div class="agenteRol">
|
|
45
|
+
<div><code>${escape(repo)}</code><span>support agent · member</span></div>
|
|
46
|
+
<select data-repo-role="${escape(repo)}" aria-label="Operating role for ${escape(repo)}">
|
|
47
|
+
${choices
|
|
48
|
+
.map((role) => {
|
|
49
|
+
const family = role.domains.filter((domain) => domain !== 'custom').join(', ');
|
|
50
|
+
const suffix = family ? ` · ${family}` : '';
|
|
51
|
+
return `<option value="${escape(role.id)}"${role.id === current ? ' selected' : ''}
|
|
52
|
+
title="${escape(role.summary)}">${escape(role.name)}${escape(suffix)}</option>`;
|
|
53
|
+
})
|
|
54
|
+
.join('')}
|
|
55
|
+
</select>
|
|
56
|
+
</div>`;
|
|
57
|
+
})
|
|
58
|
+
.join('')}</div>`;
|
|
59
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "city-worker",
|
|
3
|
+
"private": true,
|
|
4
|
+
"scripts": {
|
|
5
|
+
"dev": "bun x wrangler@4 dev --local",
|
|
6
|
+
"deploy": "bun x wrangler@4 deploy",
|
|
7
|
+
"d1:crear": "bun x wrangler@4 d1 create city",
|
|
8
|
+
"d1:schema": "bun x wrangler@4 d1 execute city --remote --file schema.sql",
|
|
9
|
+
"d1:schema:local": "bun x wrangler@4 d1 execute city --local --file schema.sql",
|
|
10
|
+
"typecheck": "tsc"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@cloudflare/workers-types": "^5.20260826.1",
|
|
14
|
+
"typescript": "^7.0.2"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
-- Agents City — the record of what has been built.
|
|
2
|
+
-- The Durable Object holds the now; this holds the before.
|
|
3
|
+
|
|
4
|
+
-- A parcel is one business unit inside one repo: a repo can hold several, and
|
|
5
|
+
-- that is what the whole model is about. Seeded from your data repo's parcels.yml.
|
|
6
|
+
CREATE TABLE IF NOT EXISTS parcela (
|
|
7
|
+
id TEXT PRIMARY KEY, -- "org/repo:apps/checkout"
|
|
8
|
+
repo TEXT NOT NULL,
|
|
9
|
+
ruta TEXT NOT NULL, -- glob relative to the repo, "" = the whole repo
|
|
10
|
+
unidad TEXT NOT NULL, -- one of your units, or "none"
|
|
11
|
+
nombre TEXT NOT NULL, -- what the house is called on the map
|
|
12
|
+
dueno TEXT, -- the bus user who answers for it
|
|
13
|
+
UNIQUE(repo, ruta)
|
|
14
|
+
);
|
|
15
|
+
CREATE INDEX IF NOT EXISTS ix_parcela_unidad ON parcela(unidad);
|
|
16
|
+
|
|
17
|
+
-- What has been built: one row per parcel, recomputed by the cron.
|
|
18
|
+
CREATE TABLE IF NOT EXISTS casa (
|
|
19
|
+
parcela_id TEXT PRIMARY KEY REFERENCES parcela(id),
|
|
20
|
+
pisos INTEGER NOT NULL DEFAULT 0, -- merged PRs (a floor per landing)
|
|
21
|
+
ladrillos INTEGER NOT NULL DEFAULT 0, -- commits with no PR
|
|
22
|
+
andamios INTEGER NOT NULL DEFAULT 0, -- open PRs
|
|
23
|
+
andamio_viejo INTEGER NOT NULL DEFAULT 0, -- open PRs older than 14 days
|
|
24
|
+
grieta INTEGER NOT NULL DEFAULT 0, -- 1 = CI is red
|
|
25
|
+
actividad30 INTEGER NOT NULL DEFAULT 0, -- commits in the last 30 days
|
|
26
|
+
actualizado TEXT NOT NULL
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
-- Everything that happens, so the map can be rewound and the ticker has a feed.
|
|
30
|
+
CREATE TABLE IF NOT EXISTS evento (
|
|
31
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
32
|
+
ts TEXT NOT NULL,
|
|
33
|
+
tipo TEXT NOT NULL, -- notice | floor | scaffold | crack | light
|
|
34
|
+
origen TEXT, -- a bus agent, or a parcel
|
|
35
|
+
destino TEXT,
|
|
36
|
+
etiqueta TEXT, -- data | ux | security | cost | product | llm
|
|
37
|
+
texto TEXT,
|
|
38
|
+
leido INTEGER NOT NULL DEFAULT 0 -- an unopened notice is the one thing worth measuring
|
|
39
|
+
);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS ix_evento_ts ON evento(ts DESC);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS ix_evento_sin_leer ON evento(leido, ts DESC);
|
|
42
|
+
|
|
43
|
+
-- The syncer's own state: how far the last pass got.
|
|
44
|
+
CREATE TABLE IF NOT EXISTS meta (
|
|
45
|
+
clave TEXT PRIMARY KEY,
|
|
46
|
+
valor TEXT NOT NULL
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
-- Who is who on the site: the architect, the specialists, and their trade.
|
|
50
|
+
CREATE TABLE IF NOT EXISTS persona (
|
|
51
|
+
usuario TEXT PRIMARY KEY,
|
|
52
|
+
nombre TEXT NOT NULL,
|
|
53
|
+
rol TEXT NOT NULL,
|
|
54
|
+
oficio TEXT NOT NULL,
|
|
55
|
+
agente TEXT
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
-- The history of what was built, day by day: this is what the replay plays.
|
|
59
|
+
-- Rebuilt backwards from each PR's merge date, so you do not have to wait for
|
|
60
|
+
-- time to pass before you have a past.
|
|
61
|
+
CREATE TABLE IF NOT EXISTS hito (
|
|
62
|
+
parcela_id TEXT NOT NULL,
|
|
63
|
+
dia TEXT NOT NULL, -- "2026-08-25"
|
|
64
|
+
n INTEGER NOT NULL, -- PRs landed THAT day
|
|
65
|
+
PRIMARY KEY (parcela_id, dia)
|
|
66
|
+
);
|
|
67
|
+
-- Per day, not per month: a month is too coarse to watch anything grow.
|
|
68
|
+
CREATE INDEX IF NOT EXISTS ix_hito_dia ON hito(dia);
|
|
69
|
+
|
|
70
|
+
-- The districts of the city: your business units. Data, not code — so the map
|
|
71
|
+
-- redraws itself when the org changes shape, without a deploy.
|
|
72
|
+
CREATE TABLE IF NOT EXISTS unidad (
|
|
73
|
+
id TEXT PRIMARY KEY,
|
|
74
|
+
nombre TEXT NOT NULL,
|
|
75
|
+
color TEXT NOT NULL, -- hex, no #
|
|
76
|
+
orden INTEGER NOT NULL DEFAULT 50,
|
|
77
|
+
nota TEXT,
|
|
78
|
+
cols INTEGER NOT NULL DEFAULT 3 -- how wide its grid is on the map
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
-- Token spend, aggregated by day and person. Counts only: never content, never
|
|
82
|
+
-- prompts.
|
|
83
|
+
--
|
|
84
|
+
-- Stored per person because that is the only way to deduplicate reports and to
|
|
85
|
+
-- attribute spend to a unit. Shown as a GLOBAL total, and never as a ranking —
|
|
86
|
+
-- the moment there is a leaderboard, people optimise for the leaderboard. Same
|
|
87
|
+
-- rule as everywhere else in this map.
|
|
88
|
+
CREATE TABLE IF NOT EXISTS gasto (
|
|
89
|
+
dia TEXT NOT NULL,
|
|
90
|
+
usuario TEXT NOT NULL,
|
|
91
|
+
modelo TEXT NOT NULL DEFAULT '',
|
|
92
|
+
entrada INTEGER NOT NULL DEFAULT 0,
|
|
93
|
+
salida INTEGER NOT NULL DEFAULT 0,
|
|
94
|
+
cache_r INTEGER NOT NULL DEFAULT 0,
|
|
95
|
+
cache_w INTEGER NOT NULL DEFAULT 0,
|
|
96
|
+
PRIMARY KEY (dia, usuario, modelo)
|
|
97
|
+
);
|
|
98
|
+
CREATE INDEX IF NOT EXISTS ix_gasto_dia ON gasto(dia DESC);
|
|
99
|
+
|
|
100
|
+
-- Goals: one per person, with the command that measures them.
|
|
101
|
+
--
|
|
102
|
+
-- The one thing that does not change whatever kind of city this is, so it lives
|
|
103
|
+
-- in the database and not only in a card nobody opens. Seeded from the cards,
|
|
104
|
+
-- which stay the place they are written and reviewed — this is a copy for the
|
|
105
|
+
-- map, never the source.
|
|
106
|
+
CREATE TABLE IF NOT EXISTS objetivo (
|
|
107
|
+
usuario TEXT NOT NULL,
|
|
108
|
+
n INTEGER NOT NULL, -- O1, O2…
|
|
109
|
+
titulo TEXT NOT NULL,
|
|
110
|
+
como TEXT, -- what signal says it is going well
|
|
111
|
+
medida TEXT, -- the command or query, runnable as written
|
|
112
|
+
partida TEXT, -- what it returned the day it was agreed
|
|
113
|
+
meta TEXT, -- the value to reach
|
|
114
|
+
cuando TEXT, -- a date or a quarter
|
|
115
|
+
estado TEXT, -- not started | in progress | at risk | done
|
|
116
|
+
PRIMARY KEY (usuario, n)
|
|
117
|
+
);
|