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,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: research
|
|
3
|
+
order: 70
|
|
4
|
+
name: Research & education
|
|
5
|
+
summary: Coordinate questions, evidence, methods, ethics and reusable knowledge.
|
|
6
|
+
parcel: a study, course, corpus or research repository
|
|
7
|
+
source: github|disk
|
|
8
|
+
grows_with: reviewed findings or learning outcomes
|
|
9
|
+
grow_command:
|
|
10
|
+
roles:
|
|
11
|
+
- research-director # on by default
|
|
12
|
+
- researcher # on by default
|
|
13
|
+
- methods # on by default
|
|
14
|
+
- research-ops
|
|
15
|
+
- ethics
|
|
16
|
+
- knowledge
|
|
17
|
+
- blank
|
|
18
|
+
units:
|
|
19
|
+
- Studies ; 3fb8a0
|
|
20
|
+
- Methods ; 4a9ede
|
|
21
|
+
- Teaching ; e08a3c
|
|
22
|
+
- Knowledge ; 8f7ae6
|
|
23
|
+
---
|
|
24
|
+
# Research & education
|
|
25
|
+
|
|
26
|
+
State the question, population, method, evidence quality and limits before the
|
|
27
|
+
conclusion. Preserve null results, competing explanations and provenance. Do not
|
|
28
|
+
upgrade correlation to causation or a preliminary result to settled knowledge.
|
|
29
|
+
|
|
30
|
+
The chair synthesises; methods and ethics roles remain independent checks. Reuse
|
|
31
|
+
existing evidence when it fits, but do not carry a result into a new context
|
|
32
|
+
without testing whether its assumptions still hold.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sales
|
|
3
|
+
order: 60
|
|
4
|
+
name: Sales & customer success
|
|
5
|
+
summary: Coordinate pipeline, accounts, revenue operations and customer outcomes.
|
|
6
|
+
parcel: an account segment, playbook or revenue repository
|
|
7
|
+
source: github|disk
|
|
8
|
+
grows_with: verified customer outcomes and correctly closed opportunities
|
|
9
|
+
grow_command:
|
|
10
|
+
roles:
|
|
11
|
+
- revenue-lead # on by default
|
|
12
|
+
- account-executive # on by default
|
|
13
|
+
- revops # on by default
|
|
14
|
+
- customer-success
|
|
15
|
+
- enablement
|
|
16
|
+
- blank
|
|
17
|
+
units:
|
|
18
|
+
- New business ; 3fb8a0
|
|
19
|
+
- Expansion ; 8f7ae6
|
|
20
|
+
- Customer success ; 4a9ede
|
|
21
|
+
- Revenue operations ; e08a3c
|
|
22
|
+
---
|
|
23
|
+
# Sales & customer success
|
|
24
|
+
|
|
25
|
+
Keep account facts, buyer intent, commitments and forecast judgement separate.
|
|
26
|
+
Never invent a customer statement or turn missing CRM data into a confident
|
|
27
|
+
pipeline claim. A promised feature, price or date must have an accountable owner.
|
|
28
|
+
|
|
29
|
+
Optimise for durable customer outcomes, not activity counts alone. Surface churn
|
|
30
|
+
risk, handoff gaps, stale stages and conflicting commitments across accounts.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: software
|
|
3
|
+
order: 10
|
|
4
|
+
name: Software development
|
|
5
|
+
summary: Build, operate and evolve software products and their repositories.
|
|
6
|
+
parcel: a repository or working folder
|
|
7
|
+
source: github|disk
|
|
8
|
+
grows_with: verified changes shipped
|
|
9
|
+
grow_command: git log --since=30.days --oneline | wc -l
|
|
10
|
+
roles:
|
|
11
|
+
- cpto # on by default
|
|
12
|
+
- dev # on by default
|
|
13
|
+
- data-engineer # on by default
|
|
14
|
+
- devops # on by default
|
|
15
|
+
- data # on by default
|
|
16
|
+
- product-design
|
|
17
|
+
- po
|
|
18
|
+
- llm-engineer
|
|
19
|
+
- ai-manager
|
|
20
|
+
- blank
|
|
21
|
+
units:
|
|
22
|
+
- Platform ; 3fb8a0
|
|
23
|
+
- Product ; e08a3c
|
|
24
|
+
- Mobile ; 8f7ae6
|
|
25
|
+
- Data ; 4a9ede
|
|
26
|
+
---
|
|
27
|
+
# Software development
|
|
28
|
+
|
|
29
|
+
The city coordinates evidence and decisions across repositories. A support
|
|
30
|
+
agent owns the context of its repo; the seat owns direction and the final call.
|
|
31
|
+
|
|
32
|
+
Ask for reproducible code, tests, logs and diffs. Treat a green build as evidence
|
|
33
|
+
for the checks it ran, not proof that the product behaves correctly. Changes to
|
|
34
|
+
public interfaces, schemas, security, costs, analytics or shared UI should reach
|
|
35
|
+
the relevant role even when the code itself still compiles.
|
|
36
|
+
|
|
37
|
+
Repo skills stay in their repos and are invoked by their own runtime.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PreToolUse / Edit|Write|MultiEdit — leave a note saying where the digging is.
|
|
3
|
+
#
|
|
4
|
+
# This hook does not publish on the bus. It writes a note on disk and the seat
|
|
5
|
+
# reports it. Repo runtimes receive chaired assignments through their adapter,
|
|
6
|
+
# but never get road credentials or authority to address peers directly.
|
|
7
|
+
#
|
|
8
|
+
# It runs before every edit, so the fast path has to be cheap: one check of the
|
|
9
|
+
# remote and a one-line file.
|
|
10
|
+
set -uo pipefail
|
|
11
|
+
# Outside a city runtime the whole plugin stays silent (see the guard).
|
|
12
|
+
. "$(dirname "$0")/solo-en-ciudad.sh"
|
|
13
|
+
nada() { printf '{}\n'; exit 0; }
|
|
14
|
+
|
|
15
|
+
# One resolver for settings and for "does this repo belong to the city".
|
|
16
|
+
# It used to be a hardcoded organisation name, which meant this hook did nothing
|
|
17
|
+
# at all for anybody who was not that one company.
|
|
18
|
+
. "${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}/scripts/city-env.sh"
|
|
19
|
+
REPO="$(repo_de_la_ciudad)" || nada
|
|
20
|
+
|
|
21
|
+
CITY_SCOPE="$(printf '%s' "${CITY_ADDRESS:-city}" | tr -c 'A-Za-z0-9_.@-' '-')"
|
|
22
|
+
DIR="$CITY_DIR/digging/$CITY_SCOPE"
|
|
23
|
+
mkdir -p "$DIR" 2>/dev/null || nada
|
|
24
|
+
|
|
25
|
+
# The parcel comes from the file being touched, matched against parcels.yml in
|
|
26
|
+
# the data repo. Without that, the house is the whole repo.
|
|
27
|
+
ENTRADA="$(cat)"
|
|
28
|
+
FICHERO="$(sed -n 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' <<<"$ENTRADA" | head -1)"
|
|
29
|
+
RAIZ="$(git rev-parse --show-toplevel 2>/dev/null || echo '')"
|
|
30
|
+
REL="${FICHERO#$RAIZ/}"
|
|
31
|
+
|
|
32
|
+
PARCELA="$REPO"
|
|
33
|
+
EQUIPO="${AGENTS_CITY_DATA:-$HOME/agents-city-data}"
|
|
34
|
+
if [ -n "$REL" ] && [ -f "$EQUIPO/parcelas.yml" ]; then
|
|
35
|
+
EN_REPO=0
|
|
36
|
+
while IFS= read -r linea; do
|
|
37
|
+
case "$linea" in
|
|
38
|
+
" $REPO:") EN_REPO=1; continue ;;
|
|
39
|
+
" "[a-zA-Z0-9_.-]*":") EN_REPO=0; continue ;;
|
|
40
|
+
esac
|
|
41
|
+
[ "$EN_REPO" -eq 1 ] || continue
|
|
42
|
+
case "$linea" in *"- ruta:"*) ;; *) continue ;; esac
|
|
43
|
+
RUTA="$(sed -n 's/.*- ruta:[[:space:]]*"\([^"]*\)".*/\1/p' <<<"$linea")"
|
|
44
|
+
[ -z "$RUTA" ] && { PARCELA="$REPO"; break; } # empty path = the whole repo
|
|
45
|
+
# shellcheck disable=SC2254
|
|
46
|
+
case "$REL" in $RUTA) PARCELA="$REPO:$RUTA"; break ;; esac
|
|
47
|
+
done < "$EQUIPO/parcelas.yml"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# El agente no es la persona, y tampoco es el repo: es ESTA ventana. Una persona
|
|
51
|
+
# tiene la del puesto y una por repo, y si trabaja con worktrees, una por
|
|
52
|
+
# worktree — mismo repo, ramas distintas, agentes distintos. Se distinguen por
|
|
53
|
+
# el directorio del worktree y la rama, que es lo que de verdad los separa.
|
|
54
|
+
DIRTRAB="$(basename "$RAIZ")"
|
|
55
|
+
RAMA="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo '')"
|
|
56
|
+
PRINCIPAL="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's|^origin/||')"
|
|
57
|
+
[ -z "$PRINCIPAL" ] && PRINCIPAL=main
|
|
58
|
+
|
|
59
|
+
AGENTE="$DIRTRAB"
|
|
60
|
+
if [ -n "$RAMA" ] && [ "$RAMA" != "$PRINCIPAL" ] && [ "$RAMA" != "HEAD" ]; then
|
|
61
|
+
AGENTE="$DIRTRAB@$RAMA"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# Un fichero por agente, no por repo: dos worktrees del mismo repo son dos.
|
|
65
|
+
SEGURO="$(printf '%s' "$AGENTE" | tr -c 'A-Za-z0-9_.@-' '-')"
|
|
66
|
+
printf '{"repo":"%s","parcela":"%s","agente":"%s","rama":"%s","ts":%s}\n' \
|
|
67
|
+
"$REPO" "$PARCELA" "$AGENTE" "$RAMA" "$(date +%s)" > "$DIR/$SEGURO.json"
|
|
68
|
+
nada
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop — report how much each parcel has grown, once a day.
|
|
3
|
+
#
|
|
4
|
+
# The city's cron can count merged pull requests on its own. It cannot run a
|
|
5
|
+
# command inside somebody's folders, and in a marketing, legal or finance city
|
|
6
|
+
# that is exactly what growth is: pieces published, matters filed, periods
|
|
7
|
+
# closed. So it has to be reported from where the folders are, and if that means
|
|
8
|
+
# somebody remembering to run a script, the map stops growing in week two.
|
|
9
|
+
#
|
|
10
|
+
# Once every twenty hours, not on every turn: these are real commands in real
|
|
11
|
+
# folders — a find, a wc, sometimes a query — and the number they return does not
|
|
12
|
+
# change by the minute. Detached and silent, like the spend report.
|
|
13
|
+
set -uo pipefail
|
|
14
|
+
# Outside a city runtime the whole plugin stays silent (see the guard).
|
|
15
|
+
. "$(dirname "$0")/solo-en-ciudad.sh"
|
|
16
|
+
nada() { printf '{}\n'; exit 0; }
|
|
17
|
+
|
|
18
|
+
RAIZ="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
|
|
19
|
+
. "$RAIZ/scripts/city-env.sh"
|
|
20
|
+
|
|
21
|
+
[ -n "${AGENTS_CITY_URL:-}" ] || nada
|
|
22
|
+
[ -n "${CITY_BUS_TOKEN:-}" ] || nada
|
|
23
|
+
[ -n "${AGENTS_CITY_DATA:-}" ] || nada
|
|
24
|
+
[ -d "${AGENTS_CITY_DATA:-}" ] || nada
|
|
25
|
+
command -v python3 >/dev/null 2>&1 || nada
|
|
26
|
+
|
|
27
|
+
MARCA="$CITY_DIR/growth-last"
|
|
28
|
+
mkdir -p "$CITY_DIR" 2>/dev/null || nada
|
|
29
|
+
AHORA="$(date +%s)"
|
|
30
|
+
if [ -f "$MARCA" ]; then
|
|
31
|
+
ANTES="$(cat "$MARCA" 2>/dev/null || echo 0)"
|
|
32
|
+
case "$ANTES" in ''|*[!0-9]*) ANTES=0 ;; esac
|
|
33
|
+
[ $((AHORA - ANTES)) -lt 72000 ] && nada
|
|
34
|
+
fi
|
|
35
|
+
printf '%s' "$AHORA" > "$MARCA"
|
|
36
|
+
|
|
37
|
+
( AGENTS_CITY_URL="$AGENTS_CITY_URL" CITY_BUS_TOKEN="$CITY_BUS_TOKEN" \
|
|
38
|
+
AGENTS_CITY_DATA="$AGENTS_CITY_DATA" \
|
|
39
|
+
python3 "$RAIZ/scripts/report.py" --push --quiet \
|
|
40
|
+
>/dev/null 2>&1 & ) >/dev/null 2>&1
|
|
41
|
+
|
|
42
|
+
nada
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PreToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "Bash",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/notice-on-pr.sh\"",
|
|
10
|
+
"timeout": 10
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"matcher": "Edit|Write|MultiEdit|NotebookEdit",
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/digging.sh\"",
|
|
20
|
+
"timeout": 5
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"SessionStart": [
|
|
26
|
+
{
|
|
27
|
+
"hooks": [
|
|
28
|
+
{
|
|
29
|
+
"type": "command",
|
|
30
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/activity.sh\" SessionStart",
|
|
31
|
+
"timeout": 10
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"hooks": [
|
|
37
|
+
{
|
|
38
|
+
"type": "command",
|
|
39
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/notice-pending.sh\"",
|
|
40
|
+
"timeout": 15
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"UserPromptSubmit": [
|
|
46
|
+
{
|
|
47
|
+
"hooks": [
|
|
48
|
+
{
|
|
49
|
+
"type": "command",
|
|
50
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/activity.sh\" UserPromptSubmit",
|
|
51
|
+
"timeout": 10
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"Stop": [
|
|
57
|
+
{
|
|
58
|
+
"hooks": [
|
|
59
|
+
{
|
|
60
|
+
"type": "command",
|
|
61
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/activity.sh\" Stop",
|
|
62
|
+
"timeout": 10
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"hooks": [
|
|
68
|
+
{
|
|
69
|
+
"type": "command",
|
|
70
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/notice-on-stop.sh\"",
|
|
71
|
+
"timeout": 10
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"hooks": [
|
|
77
|
+
{
|
|
78
|
+
"type": "command",
|
|
79
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/tokens.sh\"",
|
|
80
|
+
"timeout": 10
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"hooks": [
|
|
86
|
+
{
|
|
87
|
+
"type": "command",
|
|
88
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/growth.sh\"",
|
|
89
|
+
"timeout": 10
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
"SessionEnd": [
|
|
95
|
+
{
|
|
96
|
+
"hooks": [
|
|
97
|
+
{
|
|
98
|
+
"type": "command",
|
|
99
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/activity.sh\" SessionEnd",
|
|
100
|
+
"timeout": 10
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PreToolUse / Bash — when a PR is opened, hand the question to the agent.
|
|
3
|
+
#
|
|
4
|
+
# The hook matcher cannot filter Bash by the content of the command, so the filter
|
|
5
|
+
# is here and it comes first: if the command does not open a PR, leave. This runs
|
|
6
|
+
# before EVERY shell command, so the fast path has to be cheap.
|
|
7
|
+
#
|
|
8
|
+
# Like the rest of the notice hooks, this judges nothing: it only spots the
|
|
9
|
+
# moment. Which property the change touches, and who it hurts, is the agent's
|
|
10
|
+
# call.
|
|
11
|
+
set -uo pipefail
|
|
12
|
+
# Outside a city runtime the whole plugin stays silent (see the guard).
|
|
13
|
+
. "$(dirname "$0")/solo-en-ciudad.sh"
|
|
14
|
+
|
|
15
|
+
nada() { printf '{}\n'; exit 0; }
|
|
16
|
+
|
|
17
|
+
ENTRADA="$(cat)"
|
|
18
|
+
grep -qE 'gh[[:space:]]+pr[[:space:]]+create' <<<"$ENTRADA" || nada
|
|
19
|
+
|
|
20
|
+
# One resolver for settings and for "does this repo belong to the city".
|
|
21
|
+
# It used to be a hardcoded organisation name, which meant this hook did nothing
|
|
22
|
+
# at all for anybody who was not that one company.
|
|
23
|
+
. "${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}/scripts/city-env.sh"
|
|
24
|
+
REPO="$(repo_de_la_ciudad)" || nada
|
|
25
|
+
|
|
26
|
+
python3 - "$REPO" "${CITY_SEAT_NAME:-seat}" <<'PY'
|
|
27
|
+
import json, sys
|
|
28
|
+
repo, seat = sys.argv[1:3]
|
|
29
|
+
msg = f"""You are opening a PR in {repo}. As soon as it exists, judge whether what it carries touches a domain owned by a connected city, before moving on to anything else: this is the best moment there is, because after the merge it is decided and the destination seat can only ask for a rewrite.
|
|
30
|
+
|
|
31
|
+
Follow /city:notice: compare the PR's diff against the "What reaches you" section of each roles/<role>.md, and work out who owns each property from the cards and the unit map.
|
|
32
|
+
|
|
33
|
+
Two things about this window: it has no roads — repo windows deliberately do not get them — so hand the written notice to the city seat named "{seat}" and let it send. And if there is nothing to send, do not send anything and do not comment on it: silence is the right answer most of the time."""
|
|
34
|
+
print(json.dumps({"hookSpecificOutput": {"hookEventName": "PreToolUse", "additionalContext": msg}}))
|
|
35
|
+
PY
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop — at the end of a turn where something changed, hand the question to the
|
|
3
|
+
# agent.
|
|
4
|
+
#
|
|
5
|
+
# This hook does NOT decide whether to send a notice. It cannot: whether a change
|
|
6
|
+
# breaks somebody else's property is a judgement, and no pattern is going to get
|
|
7
|
+
# it right. All the code decides is whether there is new material nobody has
|
|
8
|
+
# judged yet — that part is deterministic and cheap. The judgement belongs to the
|
|
9
|
+
# agent, which has the diff and the roles in front of it.
|
|
10
|
+
set -uo pipefail
|
|
11
|
+
# Outside a city runtime the whole plugin stays silent (see the guard).
|
|
12
|
+
. "$(dirname "$0")/solo-en-ciudad.sh"
|
|
13
|
+
|
|
14
|
+
# Silent exit. It returns {} rather than nothing: with empty output, Claude Code
|
|
15
|
+
# logs a "Hook output does not start with {" and a spurious error.
|
|
16
|
+
nada() { printf '{}\n'; exit 0; }
|
|
17
|
+
|
|
18
|
+
ENTRADA="$(cat)"
|
|
19
|
+
|
|
20
|
+
# stop_hook_active arrives true when this hook already forced a continuation.
|
|
21
|
+
# Without this exit, infinite loop.
|
|
22
|
+
if grep -q '"stop_hook_active"[[:space:]]*:[[:space:]]*true' <<<"$ENTRADA"; then
|
|
23
|
+
nada
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# One resolver for settings and for "does this repo belong to the city".
|
|
27
|
+
# It used to be a hardcoded organisation name, which meant this hook did nothing
|
|
28
|
+
# at all for anybody who was not that one company.
|
|
29
|
+
. "${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}/scripts/city-env.sh"
|
|
30
|
+
REPO="$(repo_de_la_ciudad)" || nada
|
|
31
|
+
|
|
32
|
+
HEAD_SHA="$(git rev-parse HEAD 2>/dev/null || true)"
|
|
33
|
+
[ -z "$HEAD_SHA" ] && nada
|
|
34
|
+
|
|
35
|
+
# The fingerprint includes the CONTENT of the change, not just which files are
|
|
36
|
+
# touched: `git status --porcelain` returns the same thing the first time you edit
|
|
37
|
+
# a file and the fifth, so the second change — which may be the dangerous one —
|
|
38
|
+
# would never be judged.
|
|
39
|
+
SUCIO="$( { git status --porcelain 2>/dev/null
|
|
40
|
+
git diff HEAD 2>/dev/null
|
|
41
|
+
# Y el contenido de los ficheros nuevos, que no salen en el diff.
|
|
42
|
+
# Acotado a 200: esto corre al final de cada turno y no puede costar.
|
|
43
|
+
git ls-files --others --exclude-standard 2>/dev/null | head -200 \
|
|
44
|
+
| tr '\n' '\0' | xargs -0 shasum -a 256 2>/dev/null
|
|
45
|
+
} | shasum -a 256 | cut -d' ' -f1)"
|
|
46
|
+
HUELLA="$HEAD_SHA:$SUCIO"
|
|
47
|
+
|
|
48
|
+
CITY_SCOPE="$(printf '%s' "${CITY_ADDRESS:-city}" | tr -c 'A-Za-z0-9_.@-' '-')"
|
|
49
|
+
DIR="$CITY_DIR/notices-judged/$CITY_SCOPE"
|
|
50
|
+
mkdir -p "$DIR" 2>/dev/null || nada
|
|
51
|
+
MARCA="$DIR/$REPO"
|
|
52
|
+
|
|
53
|
+
# This exact state has already been asked about.
|
|
54
|
+
if [ -f "$MARCA" ] && [ "$(cat "$MARCA")" = "$HUELLA" ]; then
|
|
55
|
+
nada
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# First time in this repo: take note and do not interrupt. Otherwise the first
|
|
59
|
+
# session in any repo would open with a question nobody asked for.
|
|
60
|
+
if [ ! -f "$MARCA" ]; then
|
|
61
|
+
printf '%s\n' "$HUELLA" > "$MARCA"
|
|
62
|
+
nada
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
printf '%s\n' "$HUELLA" > "$MARCA"
|
|
66
|
+
|
|
67
|
+
python3 - "$REPO" "${CITY_SEAT_NAME:-seat}" <<'PY'
|
|
68
|
+
import json, sys
|
|
69
|
+
repo, seat = sys.argv[1:3]
|
|
70
|
+
razon = f"""Before you finish: you changed things in {repo}, and nobody has judged yet whether they touch another role's property.
|
|
71
|
+
|
|
72
|
+
Judge it yourself — you have the diff in front of you, and no pattern can decide this. Compare what you changed against the "What reaches you" section of each roles/<role>.md, and against the unit map to work out whose it is when a property has more than one owner.
|
|
73
|
+
|
|
74
|
+
Almost always the right answer is that there is nothing to send. If so, say it in one line and finish.
|
|
75
|
+
|
|
76
|
+
If there is something: write it the way /city:notice says — [property] first, evidence with file and line, why it reaches them, what to look at, and that it does not block — and hand it to the city seat named "{seat}", which is the one with the roads. This window does not have them, on purpose.
|
|
77
|
+
|
|
78
|
+
When in doubt, do not send one — except for anything about measurement (analytics, tags, pixels, consent, URLs, schemas, events): there, when in doubt, send it. It is the one property where arriving late cannot be fixed afterwards."""
|
|
79
|
+
print(json.dumps({"decision": "block", "reason": razon}))
|
|
80
|
+
PY
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SessionStart — catches what the other two triggers could not see.
|
|
3
|
+
#
|
|
4
|
+
# A PR opened from GitHub's web UI, or commits that arrived through a pull, never
|
|
5
|
+
# pass through a command in this session. So when the repo window opens, look for
|
|
6
|
+
# commits nobody has reviewed since the last pass.
|
|
7
|
+
#
|
|
8
|
+
# The FIRST time in a repo it says nothing and only leaves the mark. Otherwise
|
|
9
|
+
# the first session in a repo with two years of history sets off an avalanche.
|
|
10
|
+
set -uo pipefail
|
|
11
|
+
# Outside a city runtime the whole plugin stays silent (see the guard).
|
|
12
|
+
. "$(dirname "$0")/solo-en-ciudad.sh"
|
|
13
|
+
|
|
14
|
+
nada() { printf '{}\n'; exit 0; }
|
|
15
|
+
|
|
16
|
+
# One resolver for settings and for "does this repo belong to the city".
|
|
17
|
+
# It used to be a hardcoded organisation name, which meant this hook did nothing
|
|
18
|
+
# at all for anybody who was not that one company.
|
|
19
|
+
. "${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}/scripts/city-env.sh"
|
|
20
|
+
REPO="$(repo_de_la_ciudad)" || nada
|
|
21
|
+
|
|
22
|
+
CITY_SCOPE="$(printf '%s' "${CITY_ADDRESS:-city}" | tr -c 'A-Za-z0-9_.@-' '-')"
|
|
23
|
+
DIR="$CITY_DIR/notices-seen/$CITY_SCOPE"
|
|
24
|
+
mkdir -p "$DIR" 2>/dev/null || nada
|
|
25
|
+
MARCA="$DIR/$REPO"
|
|
26
|
+
HEAD_SHA="$(git rev-parse HEAD 2>/dev/null || true)"
|
|
27
|
+
[ -z "$HEAD_SHA" ] && nada
|
|
28
|
+
|
|
29
|
+
if [ ! -f "$MARCA" ]; then
|
|
30
|
+
printf '%s\n' "$HEAD_SHA" > "$MARCA"
|
|
31
|
+
nada
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
VISTO="$(cat "$MARCA")"
|
|
35
|
+
[ "$VISTO" = "$HEAD_SHA" ] && nada
|
|
36
|
+
if ! git cat-file -e "$VISTO" 2>/dev/null; then
|
|
37
|
+
printf '%s\n' "$HEAD_SHA" > "$MARCA"
|
|
38
|
+
nada
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# First-parent and no merges: in a repo with many merges, counting everything
|
|
42
|
+
# gives absurd figures — 85 commits for five real ones.
|
|
43
|
+
N="$(git rev-list --count --first-parent --no-merges "$VISTO..HEAD" 2>/dev/null || echo 0)"
|
|
44
|
+
[ "$N" -eq 0 ] && nada
|
|
45
|
+
|
|
46
|
+
python3 - "$REPO" "$VISTO" "$N" "$MARCA" "$HEAD_SHA" "${CITY_SEAT_NAME:-seat}" <<'PY'
|
|
47
|
+
import json, sys
|
|
48
|
+
repo, visto, n, marca, head, seat = sys.argv[1:7]
|
|
49
|
+
msg = f"""In {repo} there are {n} commit(s) nobody has reviewed since {visto[:8]}.
|
|
50
|
+
|
|
51
|
+
Before starting on whatever this session brings, judge whether any of them touch another role's property: look at {visto[:8]}..HEAD and follow /city:notice. No pattern can decide this; it has to be read.
|
|
52
|
+
|
|
53
|
+
If something does, write the notice and hand it to the city seat named "{seat}", which is the one with the roads. If nothing does, do not send anything and do not comment on it.
|
|
54
|
+
|
|
55
|
+
When you are done, bring the mark up to date so the pass is not repeated:
|
|
56
|
+
echo {head} > {marca}"""
|
|
57
|
+
print(json.dumps({"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": msg}}))
|
|
58
|
+
PY
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# shellcheck shell=bash
|
|
2
|
+
# Sourced first by every hook: the plugin's conscience runs only inside a city.
|
|
3
|
+
#
|
|
4
|
+
# Installing the plugin must not enrol every Claude conversation on the machine.
|
|
5
|
+
# A city runtime always carries its actor identity in the environment —
|
|
6
|
+
# CITY_BUS_ACTOR, set by city-session.sh for the seat and every repo window — and
|
|
7
|
+
# a plain session carries none, so that is the gate. Outside a city every hook
|
|
8
|
+
# answers `{}` and leaves: no passes, no digging notes, no judgements, no counters.
|
|
9
|
+
#
|
|
10
|
+
# Somebody who WANTS the old machine-wide conscience sets CITY_HOOKS=everywhere,
|
|
11
|
+
# in the environment or in $CITY_DIR/.env. It is an explicit choice, never the
|
|
12
|
+
# default: second-order effects should be opted into, not discovered.
|
|
13
|
+
_CITY_DIR="${CITY_DIR:-$HOME/.claude/channels/city-bus}"
|
|
14
|
+
_ambito="${CITY_HOOKS:-}"
|
|
15
|
+
if [ -z "$_ambito" ] && [ -f "$_CITY_DIR/.env" ]; then
|
|
16
|
+
_ambito="$(sed -n 's/^CITY_HOOKS=//p' "$_CITY_DIR/.env" | head -1)"
|
|
17
|
+
_ambito="${_ambito%\"}"; _ambito="${_ambito#\"}"
|
|
18
|
+
fi
|
|
19
|
+
if [ "$_ambito" != "everywhere" ] && [ -z "${CITY_BUS_ACTOR:-}" ]; then
|
|
20
|
+
# `{}` rather than nothing: empty hook output logs a spurious error upstream.
|
|
21
|
+
printf '{}\n'
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop — report what this machine has spent on tokens, at most twice an hour.
|
|
3
|
+
#
|
|
4
|
+
# The counter on the map is global: everybody's spend, one number, no ranking.
|
|
5
|
+
# For that number to mean anything it has to arrive on its own — a reporter you
|
|
6
|
+
# have to remember to run is a reporter that runs once, the day it is written,
|
|
7
|
+
# and then the map quietly starts lying about the cost of the whole thing.
|
|
8
|
+
#
|
|
9
|
+
# What leaves the machine: a day, a model name, and four counts. Never a prompt,
|
|
10
|
+
# never a file name, never a project path. The reporter reads the transcripts
|
|
11
|
+
# Claude Code already writes; nothing new is recorded to make this work.
|
|
12
|
+
#
|
|
13
|
+
# Three rules, because this runs at the end of every turn:
|
|
14
|
+
# - Throttled. Twice an hour is plenty for a number shown per day.
|
|
15
|
+
# - Detached. The turn does not wait for a network call.
|
|
16
|
+
# - Silent. A spend report is not worth a word in somebody's terminal, and it
|
|
17
|
+
# is certainly not worth an error there.
|
|
18
|
+
set -uo pipefail
|
|
19
|
+
# Outside a city runtime the whole plugin stays silent (see the guard).
|
|
20
|
+
. "$(dirname "$0")/solo-en-ciudad.sh"
|
|
21
|
+
nada() { printf '{}\n'; exit 0; }
|
|
22
|
+
|
|
23
|
+
RAIZ="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
|
|
24
|
+
. "$RAIZ/scripts/city-env.sh"
|
|
25
|
+
|
|
26
|
+
# Nothing to report to, or nothing to report with: this seat is not on a map.
|
|
27
|
+
[ -n "${AGENTS_CITY_URL:-}" ] || nada
|
|
28
|
+
[ -n "${CITY_BUS_TOKEN:-}" ] || nada
|
|
29
|
+
command -v python3 >/dev/null 2>&1 || nada
|
|
30
|
+
|
|
31
|
+
MARCA="$CITY_DIR/tokens-last"
|
|
32
|
+
mkdir -p "$CITY_DIR" 2>/dev/null || nada
|
|
33
|
+
AHORA="$(date +%s)"
|
|
34
|
+
if [ -f "$MARCA" ]; then
|
|
35
|
+
ANTES="$(cat "$MARCA" 2>/dev/null || echo 0)"
|
|
36
|
+
case "$ANTES" in ''|*[!0-9]*) ANTES=0 ;; esac
|
|
37
|
+
[ $((AHORA - ANTES)) -lt 1800 ] && nada
|
|
38
|
+
fi
|
|
39
|
+
printf '%s' "$AHORA" > "$MARCA"
|
|
40
|
+
|
|
41
|
+
# Detached, output discarded. Whatever happens out there is not this turn's
|
|
42
|
+
# problem; the next run picks up whatever this one failed to send.
|
|
43
|
+
( AGENTS_CITY_URL="$AGENTS_CITY_URL" CITY_BUS_TOKEN="$CITY_BUS_TOKEN" \
|
|
44
|
+
python3 "$RAIZ/scripts/tokens.py" --push --quiet --days 30 \
|
|
45
|
+
>/dev/null 2>&1 & ) >/dev/null 2>&1
|
|
46
|
+
|
|
47
|
+
nada
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: account-executive
|
|
3
|
+
trade: Master builder
|
|
4
|
+
cross_cutting: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
The opportunities and accounts you carry: buyer context, objections, decisions
|
|
10
|
+
and commitments made.
|
|
11
|
+
|
|
12
|
+
## What you ask others
|
|
13
|
+
|
|
14
|
+
- Whether a proposed promise is approved and deliverable.
|
|
15
|
+
- Which customer evidence is current and directly observed.
|
|
16
|
+
- Who owns the next dependency outside the account.
|
|
17
|
+
|
|
18
|
+
## What reaches you
|
|
19
|
+
|
|
20
|
+
A product, price, delivery or policy change affecting one of your opportunities.
|
|
21
|
+
|
|
22
|
+
## What you can answer
|
|
23
|
+
|
|
24
|
+
What the customer actually said, what remains inferred and why the opportunity is
|
|
25
|
+
in its current state.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: ai-manager
|
|
3
|
+
trade: Works inspector
|
|
4
|
+
cross_cutting: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
The portfolio of AI initiatives: what is being built, where it overlaps, what
|
|
10
|
+
actually gets adopted, and what the whole thing costs.
|
|
11
|
+
|
|
12
|
+
In the city you are the **works inspector**. You walk every site: what is being
|
|
13
|
+
built twice, what got built and nobody uses, and what the total costs.
|
|
14
|
+
|
|
15
|
+
## What you ask others
|
|
16
|
+
|
|
17
|
+
- What is being automated with AI in each repo, and in what state.
|
|
18
|
+
- Overlaps: two teams solving the same thing separately.
|
|
19
|
+
- What was built and nobody uses.
|
|
20
|
+
- Aggregate cost, and which initiative it comes from.
|
|
21
|
+
- What it would take for something working in one place to serve another.
|
|
22
|
+
|
|
23
|
+
## What reaches you
|
|
24
|
+
|
|
25
|
+
- A new AI initiative in a repo.
|
|
26
|
+
- Something starting to be built that already exists solved elsewhere.
|
|
27
|
+
|
|
28
|
+
The rest of your domain — adoption, aggregate cost, overlaps — does not show up
|
|
29
|
+
in a commit: that comes out in rounds, not in notices.
|
|
30
|
+
|
|
31
|
+
## What you can answer
|
|
32
|
+
|
|
33
|
+
What already exists in the house before they build something new, and who they
|
|
34
|
+
should talk to.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: associate
|
|
3
|
+
trade: Master builder
|
|
4
|
+
cross_cutting: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Domain
|
|
8
|
+
|
|
9
|
+
The matters you carry. You know their history, what was argued, what was conceded, and what is deliberately not in writing.
|
|
10
|
+
|
|
11
|
+
## What you ask others
|
|
12
|
+
|
|
13
|
+
- Whether a change to a shared template affects your matters.
|
|
14
|
+
- Who else is acting for the same client.
|
|
15
|
+
- Whether a precedent for this already exists in the firm.
|
|
16
|
+
|
|
17
|
+
## What reaches you
|
|
18
|
+
|
|
19
|
+
- A shared template or clause library changing.
|
|
20
|
+
- A deadline moving on a matter you carry.
|
|
21
|
+
|
|
22
|
+
## What you can answer
|
|
23
|
+
|
|
24
|
+
The state of your matters, what is deliberate, and what risk you have taken on knowingly. With the file open, not from memory.
|