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,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: llm-engineer
|
|
3
|
+
trade: Machinist
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Everything touching language models: cost per token, latency, answer quality,
|
|
10
|
+
evaluations, model versions, and what data leaves for a provider.
|
|
11
|
+
|
|
12
|
+
In the city you are the **machinist**. You run the machinery: which model moves
|
|
13
|
+
what, how much it burns, and whether yesterday's change improved anything.
|
|
14
|
+
|
|
15
|
+
## What you ask others
|
|
16
|
+
|
|
17
|
+
- New model calls: which model, which prompt, and with what cost ceiling.
|
|
18
|
+
- Whether any prompt carries personal or confidential data unmasked.
|
|
19
|
+
- Prompts changed with no evaluation behind the change.
|
|
20
|
+
- Models pinned to old versions worth migrating.
|
|
21
|
+
- Where an expensive model is doing a job a small one would do.
|
|
22
|
+
|
|
23
|
+
## What reaches you
|
|
24
|
+
|
|
25
|
+
- A new model call.
|
|
26
|
+
- A model or version change, in either direction.
|
|
27
|
+
- A prompt modified with no evaluation behind it.
|
|
28
|
+
- Personal or confidential data entering a prompt.
|
|
29
|
+
- Limit changes: temperature, max tokens, retries, timeouts.
|
|
30
|
+
|
|
31
|
+
## What you can answer
|
|
32
|
+
|
|
33
|
+
Which models fit which case, comparative cost, how to set up the evaluation for
|
|
34
|
+
a prompt change, and whether the idea they bring is already solved elsewhere.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: managing-partner
|
|
3
|
+
trade: Architect
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Where the practice is going: which matters get taken, how they are staffed, and whether the work matches what the firm agreed to be. In the city you are the **architect** — you do not draft.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- What moved on each matter since last time, and against which goal.
|
|
14
|
+
- What is blocked, and whether the block needs a partner.
|
|
15
|
+
- Matters with no activity for weeks: closed, or dropped?
|
|
16
|
+
- Heavy work on something nobody prioritised.
|
|
17
|
+
|
|
18
|
+
## What you can answer
|
|
19
|
+
|
|
20
|
+
Priority between two matters, whether the firm takes something on, and the commercial context behind a decision.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: methods
|
|
3
|
+
trade: Surveyor
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Study design, measurement validity, statistical uncertainty and reproducibility.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- Population, sampling, power, controls and analysis plan.
|
|
14
|
+
- Whether the measure represents the claimed construct.
|
|
15
|
+
- Which analytic choice was made after seeing the result.
|
|
16
|
+
|
|
17
|
+
## What reaches you
|
|
18
|
+
|
|
19
|
+
A protocol, instrument, outcome definition, exclusion rule or analysis changing.
|
|
20
|
+
|
|
21
|
+
## What you can answer
|
|
22
|
+
|
|
23
|
+
What the design permits the city to conclude and which uncertainty is structural.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: operations-lead
|
|
3
|
+
trade: Architect
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Operating direction, service outcomes, resource trade-offs and accountability.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- Which accepted outcome moved, not merely which activity happened.
|
|
14
|
+
- Dependencies and exceptions that need an accountable decision.
|
|
15
|
+
- What should stop so the priority can actually be delivered.
|
|
16
|
+
|
|
17
|
+
## What reaches you
|
|
18
|
+
|
|
19
|
+
A material service, priority, resource or accepted-risk decision changing.
|
|
20
|
+
|
|
21
|
+
## What you can answer
|
|
22
|
+
|
|
23
|
+
Priority, ownership and operating trade-offs across programmes and processes.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: ops
|
|
3
|
+
trade: Master builder
|
|
4
|
+
cross_cutting: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
The processes you run: payroll, billing, procurement, whatever is yours. You know why a step exists and which exception is deliberate.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- Whether a change upstream breaks your process.
|
|
14
|
+
- Who else depends on the output you produce.
|
|
15
|
+
- Whether a tool being introduced already exists somewhere.
|
|
16
|
+
|
|
17
|
+
## What reaches you
|
|
18
|
+
|
|
19
|
+
- An upstream change to a system your process depends on.
|
|
20
|
+
- A calendar or deadline change affecting your cycle.
|
|
21
|
+
|
|
22
|
+
## What you can answer
|
|
23
|
+
|
|
24
|
+
How the process actually runs — including the exception nobody wrote down — what is half done, and what you have decided not to fix yet.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: patient-safety
|
|
3
|
+
trade: Surveyor
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Preventable harm, incident learning, safeguards and quality signals across every
|
|
10
|
+
care pathway.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- What can fail, how it will be detected and who responds.
|
|
15
|
+
- Whether a near miss or incident has happened before.
|
|
16
|
+
- Which independent check protects the highest-consequence step.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A safeguard removed, an escalation threshold changed, an incident, near miss or
|
|
21
|
+
new failure mode.
|
|
22
|
+
|
|
23
|
+
## What you can answer
|
|
24
|
+
|
|
25
|
+
Known failure patterns, current controls and whether verification is independent
|
|
26
|
+
enough for the risk.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: performance
|
|
3
|
+
trade: Surveyor
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Paid acquisition standing up: spend, bids, creative fatigue, landing speed and tracking. In the city you are the **surveyor** — you own a property of every campaign, not any single one.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- New campaigns or budget changes, and what the cap is.
|
|
14
|
+
- New landing pages, and whether they load and convert.
|
|
15
|
+
- Creatives running long past their fatigue point.
|
|
16
|
+
- Anything that changes the conversion event.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
- A new campaign, or a budget change over your threshold.
|
|
21
|
+
- A new or changed landing page.
|
|
22
|
+
- A change to a conversion event or its value.
|
|
23
|
+
- A tracking parameter added, removed or renamed.
|
|
24
|
+
|
|
25
|
+
## What you can answer
|
|
26
|
+
|
|
27
|
+
What each channel is spending and returning, what is saturated, and whether the thing they are about to launch collides with something live.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: po
|
|
3
|
+
trade: Site manager
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Scope against delivery, roadmap coherence, and unblocking. You do not review
|
|
10
|
+
code: you review whether what is being built is what was agreed.
|
|
11
|
+
|
|
12
|
+
In the city you are the **site manager**. You keep the pace of the works: what
|
|
13
|
+
goes into this stretch and what stays out.
|
|
14
|
+
|
|
15
|
+
## What you ask others
|
|
16
|
+
|
|
17
|
+
- What is in flight right now, and against which goal.
|
|
18
|
+
- What is blocked, and by whom or by what.
|
|
19
|
+
- Work in progress matching nothing that was prioritised.
|
|
20
|
+
- Scope that grew along the way without a decision.
|
|
21
|
+
- What is ready for review, or ready to ship.
|
|
22
|
+
|
|
23
|
+
## What reaches you
|
|
24
|
+
|
|
25
|
+
- A behaviour the user sees, changing.
|
|
26
|
+
- Something that was there being removed.
|
|
27
|
+
- New scope that came from nothing prioritised.
|
|
28
|
+
|
|
29
|
+
Few on purpose: if you get notices every day, the trigger is mis-tuned — it is
|
|
30
|
+
not that the team is drifting.
|
|
31
|
+
|
|
32
|
+
## What you can answer
|
|
33
|
+
|
|
34
|
+
Relative priority between two things, whether something is inside the agreed
|
|
35
|
+
scope, and the business context of a requirement that makes no sense from the
|
|
36
|
+
code.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: process-owner
|
|
3
|
+
trade: Master builder
|
|
4
|
+
cross_cutting: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
The process you own, including its exceptions, controls, customers and outcomes.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- Whether an upstream or downstream change breaks a real handoff.
|
|
14
|
+
- Which exception path the proposed design ignores.
|
|
15
|
+
- What measure reflects the process outcome rather than activity.
|
|
16
|
+
|
|
17
|
+
## What reaches you
|
|
18
|
+
|
|
19
|
+
An input, handoff, control, calendar or service expectation changing.
|
|
20
|
+
|
|
21
|
+
## What you can answer
|
|
22
|
+
|
|
23
|
+
How the process actually works and why a step or exception exists.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: product-design
|
|
3
|
+
trade: Interior designer
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Design-system coherence, accessibility, and consistency of the experience across
|
|
10
|
+
products. It cuts across the front end of every repo.
|
|
11
|
+
|
|
12
|
+
In the city you are the **interior designer**. You answer for how the house is
|
|
13
|
+
lived in: that it can be understood, that it can be used, and that rooms look
|
|
14
|
+
alike across houses.
|
|
15
|
+
|
|
16
|
+
## What you ask others
|
|
17
|
+
|
|
18
|
+
- New screens or components, and whether they step outside the design system.
|
|
19
|
+
- Duplicated components: the same thing solved twice in two repos.
|
|
20
|
+
- Accessibility: contrast, focus, keyboard navigation, alt text.
|
|
21
|
+
- The states everyone forgets: empty, loading, error, no permission.
|
|
22
|
+
- Interface copy that does not follow the agreed tone.
|
|
23
|
+
|
|
24
|
+
## What reaches you
|
|
25
|
+
|
|
26
|
+
- A shared component changing — one used by two screens or more.
|
|
27
|
+
- A new screen or view.
|
|
28
|
+
- A flow with more than one step being modified: signup, onboarding, forms.
|
|
29
|
+
- New or changed visible copy.
|
|
30
|
+
- Global CSS, design tokens or typography.
|
|
31
|
+
|
|
32
|
+
What does **not** reach you, deliberately: refactors with no visible effect,
|
|
33
|
+
tests, and internal changes to a component that alter neither how it looks nor
|
|
34
|
+
how it is used.
|
|
35
|
+
|
|
36
|
+
## What you can answer
|
|
37
|
+
|
|
38
|
+
Whether a pattern already exists in the system, how a flow should behave, and
|
|
39
|
+
what the alternative is to the bespoke thing they are about to build.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: program-manager
|
|
3
|
+
trade: Site manager
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Programme scope, dependencies, milestones, risks and acceptance across workstreams.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- What is blocked, by which dependency and with what consequence.
|
|
14
|
+
- Whether a milestone represents accepted output or internal motion.
|
|
15
|
+
- Which scope change happened without a decision.
|
|
16
|
+
|
|
17
|
+
## What reaches you
|
|
18
|
+
|
|
19
|
+
A dependency, milestone, scope boundary, owner or delivery risk changing.
|
|
20
|
+
|
|
21
|
+
## What you can answer
|
|
22
|
+
|
|
23
|
+
The integrated delivery picture and where local progress does not produce the
|
|
24
|
+
programme outcome.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: quality
|
|
3
|
+
trade: Surveyor
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Acceptance standards, failure modes, controls, corrective action and independent
|
|
10
|
+
verification.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- The observable definition of done and evidence it was met.
|
|
15
|
+
- Known failure modes, controls and residual risk.
|
|
16
|
+
- Whether the verifier is independent from the executor.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
An acceptance criterion, control, verification method, incident or waiver
|
|
21
|
+
changing.
|
|
22
|
+
|
|
23
|
+
## What you can answer
|
|
24
|
+
|
|
25
|
+
Whether the evidence supports acceptance and what condition should reopen it.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: research-director
|
|
3
|
+
trade: Architect
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Research questions, portfolio direction, evidence standards and the decisions a
|
|
10
|
+
finding is meant to inform.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- What decision the study changes and what evidence would change the conclusion.
|
|
15
|
+
- Whether the question duplicates existing work.
|
|
16
|
+
- Which uncertainty matters enough to investigate next.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A research question, portfolio priority, conclusion or intended use changing.
|
|
21
|
+
|
|
22
|
+
## What you can answer
|
|
23
|
+
|
|
24
|
+
Priority and synthesis while preserving methodological dissent and uncertainty.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: research-ops
|
|
3
|
+
trade: Site manager
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Participants, recruitment, consent operations, tooling, data handling and study
|
|
10
|
+
delivery.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- Recruitment feasibility, participant burden and operational dependencies.
|
|
15
|
+
- Where consent, source data and study records live.
|
|
16
|
+
- Which handoff or tool change can break the protocol.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A recruitment, consent, schedule, tool, storage or participant-contact process
|
|
21
|
+
changing.
|
|
22
|
+
|
|
23
|
+
## What you can answer
|
|
24
|
+
|
|
25
|
+
Whether the study can be run as designed and what operational evidence exists.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: researcher
|
|
3
|
+
trade: Master builder
|
|
4
|
+
cross_cutting: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
The studies, sources or teaching materials you own and their full evidentiary
|
|
10
|
+
context.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- Whether a method, source or construct is already available.
|
|
15
|
+
- Which assumptions a shared change invalidates.
|
|
16
|
+
- What evidence contradicts the emerging interpretation.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A source, protocol, instrument or shared construct used by your work changing.
|
|
21
|
+
|
|
22
|
+
## What you can answer
|
|
23
|
+
|
|
24
|
+
What was observed, how it was obtained, what it does not establish and why a
|
|
25
|
+
choice in the study was deliberate.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: revenue-lead
|
|
3
|
+
trade: Architect
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Commercial direction, revenue quality, forecast judgement and commitments across
|
|
10
|
+
the customer lifecycle.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- Which customer evidence supports the forecast and which part is judgement.
|
|
15
|
+
- Commitments that product, delivery or finance has not accepted.
|
|
16
|
+
- Where pipeline movement does not correspond to buyer progress.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A material forecast change, non-standard commitment, pricing exception or risk
|
|
21
|
+
to a strategic account.
|
|
22
|
+
|
|
23
|
+
## What you can answer
|
|
24
|
+
|
|
25
|
+
Priority, commercial trade-offs and whether the evidence justifies the call.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: revops
|
|
3
|
+
trade: Surveyor
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Pipeline definitions, routing, territories, systems, attribution and forecast
|
|
10
|
+
hygiene.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- Stage-entry evidence and stale-opportunity rules.
|
|
15
|
+
- Changes to ownership, routing, fields or source attribution.
|
|
16
|
+
- Manual overrides that bypass the operating model.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A pipeline definition, routing rule, territory, CRM field or forecast calculation
|
|
21
|
+
changing.
|
|
22
|
+
|
|
23
|
+
## What you can answer
|
|
24
|
+
|
|
25
|
+
How the revenue system actually classifies work and whether reported movement is
|
|
26
|
+
comparable over time.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: seo
|
|
3
|
+
trade: Master builder
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
Organic surface: structure, indexing, internal linking, and the URLs that hold a decade of accumulated authority.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- URLs and slugs about to change, and what they will break.
|
|
14
|
+
- New pages and where they sit in the structure.
|
|
15
|
+
- Anything that changes rendering, redirects or canonical tags.
|
|
16
|
+
- Content merged, moved or deleted.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
- A URL, slug or route structure changing.
|
|
21
|
+
- A redirect added or removed.
|
|
22
|
+
- A page deleted, merged or moved.
|
|
23
|
+
- A change to how pages render or to canonical tags.
|
|
24
|
+
|
|
25
|
+
## What you can answer
|
|
26
|
+
|
|
27
|
+
Whether a URL carries traffic worth keeping, where a new page belongs, and what an apparently harmless move costs in organic terms.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: specialist
|
|
3
|
+
trade: Master builder
|
|
4
|
+
cross_cutting: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
The body of work assigned to you in a custom domain, including its evidence,
|
|
10
|
+
history and deliberate exceptions.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- Which shared change affects your work.
|
|
15
|
+
- What source or specialist contradicts the current assumption.
|
|
16
|
+
- Who owns a dependency outside your evidence boundary.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A shared rule, input, interface or deadline affecting work you own.
|
|
21
|
+
|
|
22
|
+
## What you can answer
|
|
23
|
+
|
|
24
|
+
What your evidence supports, what remains unknown and why a local choice was made.
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Admission as an ordered gate graph, not a boolean.
|
|
3
|
+
|
|
4
|
+
Whether a seat accepts an inbound road message is a decision with a *reason*,
|
|
5
|
+
and the reason must be inspectable without leaking who is on the allowlist. So
|
|
6
|
+
every admission returns the ordered list of gates it evaluated, which gate was
|
|
7
|
+
decisive, a stable machine-readable reason code, and — for each gate — a
|
|
8
|
+
redacted diagnostic: counts and opaque ids, never a raw sender or allowlist
|
|
9
|
+
entry.
|
|
10
|
+
|
|
11
|
+
The mechanism (an ordered reducer that stops at the first blocking gate) is
|
|
12
|
+
kept separate from the policy (`decide_entrada`), so new gates or new callers
|
|
13
|
+
compose without rewriting either. Pure and transport-free: the tests drive it
|
|
14
|
+
directly, and the same function can decide a local road, a remote road, or a
|
|
15
|
+
future chat channel.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import hashlib
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from enum import Enum
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Admision(str, Enum):
|
|
24
|
+
DESPACHA = 'dispatch' # deliver to the seat
|
|
25
|
+
OBSERVA = 'observe' # record as context, do not act
|
|
26
|
+
OMITE = 'skip' # not addressed to us; ignore quietly
|
|
27
|
+
DESCARTA = 'drop' # malformed or refused; drop
|
|
28
|
+
EMPAREJA = 'pairing-required' # unknown sender, a pairing code is owed
|
|
29
|
+
|
|
30
|
+
def __str__(self):
|
|
31
|
+
return self.value
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
#: Closed set of reason codes. A code outside this set is a bug, so the
|
|
35
|
+
#: constructor asserts membership rather than letting prose leak in.
|
|
36
|
+
RAZONES = frozenset({
|
|
37
|
+
'road_allowed',
|
|
38
|
+
'road_missing',
|
|
39
|
+
'road_incident',
|
|
40
|
+
'sender_not_paired',
|
|
41
|
+
'sender_paired',
|
|
42
|
+
'payload_malformed',
|
|
43
|
+
'payload_empty',
|
|
44
|
+
'not_addressed_here',
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
#: Which reason a gate emits maps to how the seat should treat the message.
|
|
48
|
+
_ADMISION_POR_RAZON = {
|
|
49
|
+
'road_allowed': Admision.DESPACHA,
|
|
50
|
+
'sender_paired': Admision.DESPACHA,
|
|
51
|
+
'road_missing': Admision.OMITE,
|
|
52
|
+
'not_addressed_here': Admision.OMITE,
|
|
53
|
+
'road_incident': Admision.DESCARTA,
|
|
54
|
+
'payload_malformed': Admision.DESCARTA,
|
|
55
|
+
'payload_empty': Admision.DESCARTA,
|
|
56
|
+
'sender_not_paired': Admision.EMPAREJA,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def id_opaco(valor):
|
|
61
|
+
"""A stable, non-reversible short id for one allowlist entry or sender."""
|
|
62
|
+
return 'x' + hashlib.sha256(str(valor).encode()).hexdigest()[:12]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def redacta(entradas):
|
|
66
|
+
"""A diagnostic for an allowlist that reveals shape, never content."""
|
|
67
|
+
entradas = list(entradas)
|
|
68
|
+
return {'n': len(entradas), 'ids': [id_opaco(e) for e in entradas]}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class Puerta:
|
|
73
|
+
id: str
|
|
74
|
+
fase: str
|
|
75
|
+
permitido: bool
|
|
76
|
+
razon: str
|
|
77
|
+
diagnostico: dict = field(default_factory=dict)
|
|
78
|
+
|
|
79
|
+
def __post_init__(self):
|
|
80
|
+
# A real raise, not assert: validation must survive `python -O`.
|
|
81
|
+
if self.razon not in RAZONES:
|
|
82
|
+
raise ValueError(f'unknown reason code: {self.razon}')
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dataclass(frozen=True)
|
|
86
|
+
class Decision:
|
|
87
|
+
admision: Admision
|
|
88
|
+
razon: str
|
|
89
|
+
puerta_decisiva: str
|
|
90
|
+
grafo: tuple
|
|
91
|
+
|
|
92
|
+
def permitido(self):
|
|
93
|
+
# Authorization lives here and ONLY here — never inferred from an
|
|
94
|
+
# evidence field, so a blocked decision can never read as authorised.
|
|
95
|
+
return self.admision is Admision.DESPACHA
|
|
96
|
+
|
|
97
|
+
def como_dict(self):
|
|
98
|
+
return {
|
|
99
|
+
'admission': str(self.admision),
|
|
100
|
+
'reasonCode': self.razon,
|
|
101
|
+
'decisiveGate': self.puerta_decisiva,
|
|
102
|
+
'gates': [
|
|
103
|
+
{'id': g.id, 'phase': g.fase, 'allowed': g.permitido,
|
|
104
|
+
'reasonCode': g.razon, 'diagnostic': g.diagnostico}
|
|
105
|
+
for g in self.grafo
|
|
106
|
+
],
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _resuelve(grafo):
|
|
111
|
+
"""Reduce an ordered gate list to a decision: first blocker wins, else last.
|
|
112
|
+
|
|
113
|
+
The decision carries no evidence state on purpose: allow/deny is `permitido()`
|
|
114
|
+
(derived from the admission), and an audit-provenance vocabulary belongs to
|
|
115
|
+
the layer that records the action, not to this pure routing decision. That
|
|
116
|
+
keeps authorization impossible to read off a decorative field.
|
|
117
|
+
"""
|
|
118
|
+
decisiva = next((g for g in grafo if not g.permitido), grafo[-1])
|
|
119
|
+
admision = _ADMISION_POR_RAZON[decisiva.razon]
|
|
120
|
+
return Decision(admision, decisiva.razon, decisiva.id, tuple(grafo))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def decide_entrada(*, road_existe, road_incidente, direccion_coincide,
|
|
124
|
+
emparejado, allowlist, payload_valido, texto_no_vacio,
|
|
125
|
+
dirigido_aqui=True):
|
|
126
|
+
"""Agents City's road-inbound policy, phase by phase.
|
|
127
|
+
|
|
128
|
+
Order matters and is the policy: address → road → sender → payload. A road
|
|
129
|
+
that resolves but has no matching sender is an explicit block, never a
|
|
130
|
+
fallthrough; an unknown sender under pairing yields EMPAREJA so the seat can
|
|
131
|
+
mint a code rather than silently dropping a first contact.
|
|
132
|
+
"""
|
|
133
|
+
grafo = []
|
|
134
|
+
diag = redacta(allowlist)
|
|
135
|
+
|
|
136
|
+
if not dirigido_aqui:
|
|
137
|
+
grafo.append(Puerta('address', 'route', False, 'not_addressed_here'))
|
|
138
|
+
return _resuelve(grafo)
|
|
139
|
+
grafo.append(Puerta('address', 'route', True, 'road_allowed'))
|
|
140
|
+
|
|
141
|
+
if not road_existe:
|
|
142
|
+
grafo.append(Puerta('road', 'route', False, 'road_missing', diag))
|
|
143
|
+
return _resuelve(grafo)
|
|
144
|
+
if road_incidente:
|
|
145
|
+
grafo.append(Puerta('road', 'route', False, 'road_incident', diag))
|
|
146
|
+
return _resuelve(grafo)
|
|
147
|
+
grafo.append(Puerta('road', 'route', True, 'road_allowed', diag))
|
|
148
|
+
|
|
149
|
+
if not direccion_coincide:
|
|
150
|
+
if emparejado:
|
|
151
|
+
grafo.append(Puerta('sender', 'sender', True, 'sender_paired', diag))
|
|
152
|
+
else:
|
|
153
|
+
grafo.append(Puerta('sender', 'sender', False, 'sender_not_paired', diag))
|
|
154
|
+
return _resuelve(grafo)
|
|
155
|
+
else:
|
|
156
|
+
grafo.append(Puerta('sender', 'sender', True, 'road_allowed', diag))
|
|
157
|
+
|
|
158
|
+
if not payload_valido:
|
|
159
|
+
grafo.append(Puerta('payload', 'event', False, 'payload_malformed'))
|
|
160
|
+
return _resuelve(grafo)
|
|
161
|
+
if not texto_no_vacio:
|
|
162
|
+
grafo.append(Puerta('payload', 'event', False, 'payload_empty'))
|
|
163
|
+
return _resuelve(grafo)
|
|
164
|
+
grafo.append(Puerta('payload', 'event', True, 'road_allowed'))
|
|
165
|
+
return _resuelve(grafo)
|