@bongos/core 1.21.113 → 1.21.114
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/.bongos-core.json +603 -183
- package/.claude/skills/ask-for-help/SKILL.md +1 -1
- package/.claude/skills/bongos-feedback/SKILL.md +1 -1
- package/.claude/skills/builder-sequence/SKILL.md +1 -1
- package/.claude/skills/builder-ship/SKILL.md +1 -0
- package/GOVERNMENT.md +128 -11
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +28 -0
- package/clients/bongos-client/index.cjs +28 -0
- package/clients/bongos-client/index.d.ts +45 -2
- package/clients/bongos-client/index.mjs +28 -0
- package/docs/adr/0372-an-ask-is-stored-per-docket-matter-and-the-server-refuses-slop.md +33 -0
- package/docs/adr/0373-an-ai-session-files-a-blocker-with-an-ask.md +31 -0
- package/docs/adr/0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md +30 -0
- package/docs/adr/0375-who-may-build-without-a-vote-comes-from-the-form-of-government.md +38 -0
- package/docs/adr/0376-every-ask-is-routed-to-a-real-seat-on-the-server.md +30 -0
- package/docs/adr/0377-governance-is-a-held-position-read-on-me.md +24 -0
- package/docs/adr/0378-a-leads-build-outs-are-rows-built-at-once-or-by-a-passed-vote.md +33 -0
- package/docs/adr/0379-the-treasury-is-pots-per-goal-a-reserve-and-borrowing-over-real-spend.md +32 -0
- package/docs/adr/0380-a-strictness-preset-is-a-bundle-of-laws-switched-by-one-laws-vote.md +26 -0
- package/docs/adr/README.md +10 -1
- package/docs/api/openapi.json +989 -87
- package/docs/api-reference.md +18 -4
- package/docs/copy-inventory.md +343 -262
- package/docs/copy-registry.json +1223 -426
- package/docs/file-map.md +2 -1
- package/docs/module-api-changelog.md +2 -0
- package/docs/packs/engineer.md +2 -1
- package/docs/page-inventory.json +91 -6
- package/docs/page-readings.json +5017 -4458
- package/modules/builder-settings/law-locks.js +202 -0
- package/modules/builder-settings/routes/settings.js +66 -6
- package/modules/builder-settings/settings.js +7 -0
- package/modules/discord/ship-broadcast.js +22 -13
- package/modules/government/asks-db.js +54 -0
- package/modules/government/asks.js +269 -0
- package/modules/government/board-idea-reads.js +68 -0
- package/modules/government/board.js +21 -57
- package/modules/government/build-rights.js +148 -0
- package/modules/government/buildouts.js +160 -0
- package/modules/government/counts.js +81 -0
- package/modules/government/db.js +242 -0
- package/modules/government/decision-board.js +234 -8
- package/modules/government/decision-rules.js +2 -0
- package/modules/government/docket.js +114 -6
- package/modules/government/law-board.js +131 -0
- package/modules/government/laws.js +241 -0
- package/modules/government/leads.js +170 -0
- package/modules/government/migrations/government_027_laws.sql +143 -0
- package/modules/government/migrations/government_028_asks.sql +57 -0
- package/modules/government/migrations/government_029_leads.sql +135 -0
- package/modules/government/migrations/government_030_buildouts.sql +111 -0
- package/modules/government/migrations/government_031_treasury.sql +107 -0
- package/modules/government/module.json +2 -1
- package/modules/government/pollers/treasury-borrow.js +62 -0
- package/modules/government/positions.js +107 -0
- package/modules/government/presets.js +149 -0
- package/modules/government/routes/government.js +425 -2
- package/modules/government/routing.js +154 -0
- package/modules/government/treasury-db.js +166 -0
- package/modules/government/treasury.js +241 -0
- package/modules/hall-ui/public/atlas.html +2 -2
- package/modules/hall-ui/public/blockers.html +2 -2
- package/modules/hall-ui/public/board-room.html +2 -2
- package/modules/hall-ui/public/board-room.js +2 -0
- package/modules/hall-ui/public/city-draw.js +604 -11
- package/modules/hall-ui/public/city.css +157 -1
- package/modules/hall-ui/public/city.html +37 -7
- package/modules/hall-ui/public/city.js +441 -21
- package/modules/hall-ui/public/city.states.json +110 -5
- package/modules/hall-ui/public/collab.html +2 -2
- package/modules/hall-ui/public/commands.html +2 -2
- package/modules/hall-ui/public/copy-desk.html +2 -2
- package/modules/hall-ui/public/craft-mode.js +112 -29
- package/modules/hall-ui/public/deploy.html +2 -2
- package/modules/hall-ui/public/diagram-viewer.css +12 -0
- package/modules/hall-ui/public/diagram-viewer.js +4 -0
- package/modules/hall-ui/public/diagrams.html +2 -2
- package/modules/hall-ui/public/drachmae.html +2 -2
- package/modules/hall-ui/public/fleet.html +2 -2
- package/modules/hall-ui/public/gate.html +2 -2
- package/modules/hall-ui/public/goal-map.html +2 -2
- package/modules/hall-ui/public/goals.html +2 -2
- package/modules/hall-ui/public/gov-feeds.js +141 -0
- package/modules/hall-ui/public/gov-living.js +1002 -0
- package/modules/hall-ui/public/gov-positions.js +97 -0
- package/modules/hall-ui/public/government.html +2 -2
- package/modules/hall-ui/public/hall-render.js +3 -0
- package/modules/hall-ui/public/idea.html +2 -2
- package/modules/hall-ui/public/ideas.html +2 -2
- package/modules/hall-ui/public/index.html +3 -3
- package/modules/hall-ui/public/modules.html +2 -2
- package/modules/hall-ui/public/my-agents.css +334 -0
- package/modules/hall-ui/public/my-agents.html +72 -0
- package/modules/hall-ui/public/my-agents.js +603 -0
- package/modules/hall-ui/public/my-agents.states.json +37 -0
- package/modules/hall-ui/public/primer.html +2 -2
- package/modules/hall-ui/public/profile-connections.js +40 -28
- package/modules/hall-ui/public/profile.html +2 -2
- package/modules/hall-ui/public/project-settings.html +2 -2
- package/modules/hall-ui/public/ranks.html +2 -2
- package/modules/hall-ui/public/roadmap.html +2 -2
- package/modules/hall-ui/public/room.css +8 -0
- package/modules/hall-ui/public/roster.html +2 -2
- package/modules/hall-ui/public/sessions.html +2 -2
- package/modules/hall-ui/public/settings.html +2 -2
- package/modules/hall-ui/public/shell.js +116 -16
- package/modules/hall-ui/public/street-card.js +18 -1
- package/modules/hall-ui/public/street-deck.css +299 -0
- package/modules/hall-ui/public/street-deck.js +1145 -0
- package/modules/hall-ui/public/street-depth.js +712 -0
- package/modules/hall-ui/public/street-desk.js +5 -2
- package/modules/hall-ui/public/street-draw.js +109 -16
- package/modules/hall-ui/public/street-inside.js +137 -22
- package/modules/hall-ui/public/street-office.js +705 -0
- package/modules/hall-ui/public/street.css +161 -11
- package/modules/hall-ui/public/street.html +41 -11
- package/modules/hall-ui/public/street.js +78 -66
- package/modules/hall-ui/public/street.states.json +129 -21
- package/modules/hall-ui/public/studio.html +2 -2
- package/modules/hall-ui/public/style.css +5 -1
- package/modules/hall-ui/public/task.html +2 -2
- package/modules/hall-ui/public/thinking.html +2 -2
- package/modules/hall-ui/public/tweak-editor.html +2 -2
- package/modules/hall-ui/public/watch.html +2 -2
- package/modules/hall-ui/public/watch.js +14 -1
- package/modules/hall-ui/public/work.html +2 -2
- package/modules/hall-ui/records/living-city.md +57 -0
- package/modules/hall-ui/records/my-agents.md +21 -0
- package/modules/hall-ui/records/oversight-family.md +1 -0
- package/modules/hall-ui/records/profile-connections.md +10 -0
- package/modules/hall-ui/records/reading-rooms.md +2 -0
- package/modules/ideas/routes/blockers.js +92 -3
- package/modules/lifecycle/module.json +2 -1
- package/modules/lifecycle/moving.js +17 -1
- package/modules/lifecycle/routes/moving.js +6 -0
- package/modules/lifecycle/routes/project-settings.js +23 -0
- package/modules/onboarding/approval-broadcast.js +8 -0
- package/modules/onboarding/routes/access-requests.js +16 -6
- package/modules/platform-identity/connections.js +13 -2
- package/modules/platform-identity/routes/connections.js +7 -1
- package/modules/public-landing/public/account-private.states.json +2 -2
- package/modules/public-landing/public/account.html +65 -5
- package/modules/public-landing/public/account.states.json +3 -3
- package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp +0 -0
- package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp.json +13 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp +0 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp.json +13 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp +0 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp.json +13 -0
- package/modules/public-landing/public/assets/world.css +4 -4
- package/modules/public-landing/public/connections-empty.states.json +14 -0
- package/modules/public-landing/public/connections-inactive.states.json +14 -0
- package/modules/public-landing/public/connections.html +450 -0
- package/modules/public-landing/public/connections.probes.json +414 -0
- package/modules/public-landing/public/connections.states.json +17 -0
- package/modules/public-landing/public/contact.html +2 -2
- package/modules/public-landing/public/guild.html +2 -2
- package/modules/public-landing/public/index.html +2 -2
- package/modules/public-landing/public/invitations.html +2 -2
- package/modules/public-landing/public/privacy.html +2 -2
- package/modules/public-landing/public/projects.html +2 -2
- package/modules/public-landing/public/projects.probes.json +6 -2
- package/modules/public-landing/public/terms.html +2 -2
- package/modules/ui-design/kit/fixtures/connections-empty.json +12 -0
- package/modules/ui-design/kit/fixtures/connections-inactive.json +7 -0
- package/modules/ui-design/kit/fixtures/connections.json +22 -0
- package/modules/ui-design/kit/serve.js +95 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +122 -0
- package/scripts/discord/README.md +8 -5
- package/scripts/discord/post.js +12 -1
- package/scripts/gds/artifact-audit.js +20 -3
- package/scripts/gds/ask.js +164 -0
- package/scripts/gds/autobongos-verify.js +21 -2
- package/scripts/gds/government-walk.js +638 -4
- package/scripts/gds/pulse.js +9 -6
- package/scripts/gds/ship-escalation.js +22 -3
- package/scripts/gds/ship-finish.js +5 -4
- package/scripts/gds/ship-merge-gate.js +18 -6
- package/scripts/hall-preview/README.md +41 -1
- package/scripts/hall-preview/pref-writes.js +140 -0
- package/scripts/hall-preview/refresh-fixtures.js +101 -7
- package/scripts/hall-preview/scrub-identity.js +366 -7
- package/scripts/hall-preview/server.js +27 -1
- package/scripts/render-diagrams.sh +4 -2
- package/src/bongos/auth-idp.js +6 -1
- package/src/bongos/project-settings.js +41 -0
- package/src/bongos/route-rank-check.js +27 -0
- package/src/bongos/routes/me.js +68 -7
- package/src/bongos/serve-internal.js +5 -1
- package/src/module-api.js +7 -1
- package/src/platform-server.js +10 -0
- package/tests/application_lifecycle.mjs +47 -5
- package/tests/conductor_main_e2e.mjs +21 -0
- package/tests/connections_api.mjs +18 -0
- package/tests/craft_mode_nav.mjs +5 -3
- package/tests/craft_mode_tallies.mjs +52 -16
- package/tests/discord_approvals.mjs +11 -0
- package/tests/discord_channels.mjs +20 -0
- package/tests/fixtures/gov-seated.mjs +64 -0
- package/tests/fixtures/government-ask-cards.json +1284 -0
- package/tests/government_act_alone_buildings.mjs +1 -0
- package/tests/government_agent_asks.mjs +322 -0
- package/tests/government_asks.mjs +408 -0
- package/tests/government_build_rights.mjs +253 -0
- package/tests/government_buildouts.mjs +382 -0
- package/tests/government_counts.mjs +143 -0
- package/tests/government_decision_rules.mjs +5 -1
- package/tests/government_laws.mjs +488 -0
- package/tests/government_laws_session.mjs +321 -0
- package/tests/government_leads.mjs +375 -0
- package/tests/government_positions.mjs +127 -0
- package/tests/government_presets.mjs +215 -0
- package/tests/government_routes.mjs +8 -1
- package/tests/government_routing.mjs +118 -0
- package/tests/government_seed.mjs +5 -0
- package/tests/government_treasury.mjs +394 -0
- package/tests/governor_docket.mjs +26 -2
- package/tests/hall_buildouts.mjs +208 -0
- package/tests/hall_city.mjs +14 -6
- package/tests/hall_city_living.mjs +617 -0
- package/tests/hall_gov_counts.mjs +336 -0
- package/tests/hall_gov_living.mjs +636 -0
- package/tests/hall_gov_real_site.mjs +655 -0
- package/tests/hall_matter_card.mjs +6 -1
- package/tests/hall_my_agents.mjs +481 -0
- package/tests/hall_nav.mjs +107 -4
- package/tests/hall_page_gate_map.mjs +4 -0
- package/tests/hall_preview_governor_fixtures.mjs +30 -3
- package/tests/hall_preview_scrub.mjs +59 -1
- package/tests/hall_preview_security.mjs +169 -0
- package/tests/hall_reading_world.mjs +44 -0
- package/tests/hall_roster_world.mjs +6 -2
- package/tests/hall_street.mjs +18 -2
- package/tests/hall_street_amend.mjs +1 -1
- package/tests/hall_street_deck.mjs +609 -0
- package/tests/hall_street_depth.mjs +559 -0
- package/tests/hall_street_desk.mjs +1 -1
- package/tests/hall_street_inside.mjs +29 -5
- package/tests/hall_tweak_editor.mjs +4 -1
- package/tests/hub_account_page.mjs +94 -3
- package/tests/hub_connections_page.mjs +507 -0
- package/tests/hub_invite_badge.mjs +1 -1
- package/tests/idp_device_exchange.mjs +18 -0
- package/tests/landing_legal_pages.mjs +8 -5
- package/tests/landing_page.mjs +23 -4
- package/tests/nav_permission_atoms.mjs +4 -1
- package/tests/profile_connections_ui.mjs +88 -25
- package/tests/projects_hub.mjs +15 -0
- package/tests/render_check.mjs +2 -2
- package/tests/ship_broadcast_routing.mjs +57 -16
- package/tests/ship_broadcast_server.mjs +40 -7
- package/tests/ship_merge_gate.mjs +19 -0
- package/tests/ui_design_kit.mjs +2 -2
- package/tests/watch_applications_queue.mjs +23 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# ADR 0372 — An ask is stored per docket matter, and the server refuses slop
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-09
|
|
5
|
+
- **Task:** [task 1004703](https://cloudbongos.com/builders#/task/1004703) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** the governor's docket (`modules/government/docket.js`, task 1004523), the living-city prototype's ask format (`modules/hall-ui/public/gov-living.js` `askFormat`, task 1004685)
|
|
7
|
+
- **Followed by:** task 1004704 (agents write asks in this shape), task 1004705 (each ask routed to a seat)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The owner's biggest worry is that agents "slop" people: a wall of text where a decision is needed, which suppresses the decision. The prototype drew every request as a short card (a question of at most twelve words, two or three tap answers each with a one-line result, a pick and why, who it waits on, what happens if nobody answers), but the cards were hand-written rewrites in a prototype overlay. Nothing stored the shape, and nothing stopped an agent from filing prose.
|
|
12
|
+
|
|
13
|
+
Requests to a person live in a dozen sources: blockers, board sittings, override requests, criteria awaiting sign-off, and more. The docket already gathers all of them under one id per matter (`<source>:<id>`).
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
**D1 — One table, keyed by the docket matter id.** `government_asks` (`government_028`) holds one ask per matter: `blockers:12`, `board:34`, `override_requests:5`. The government module owns it because it owns the docket. The docket attaches each matter's ask as `ask`, only to matters the viewer already sees, so every surface (street, deck, city) reads the same stored words, and no source module needs a column of its own.
|
|
18
|
+
|
|
19
|
+
**D2 — The server refuses slop and names every fix.** `modules/government/asks.js` `checkAsk` applies the prototype's rules number for number (`ASK_RULES`), and a write that breaks them answers 400 `ask_refused`. The message is one plain paragraph listing each fix; the details list every broken rule. The table's CHECKs are the floor under it, so a hand-written INSERT cannot store a twelve-plus-word question, a second line, fewer than two or more than three answers, or a pick that was not offered.
|
|
20
|
+
|
|
21
|
+
**D3 — Two copies of the rules, held to one verdict.** The hall runs in the browser and cannot require server code, so `gov-living.js` keeps its `askFormat`. `tests/government_asks.mjs` drives both over the same cases and requires the same rules and the same words for each. The server adds only what a stored ask needs: a routable seat (`owner`, `lead:<b>`, `committee:<b>.<k>`, `board:<b>`), answer keys and acts in a fixed grammar, and character caps.
|
|
22
|
+
|
|
23
|
+
**D4 — The long text rides along, never as the ask.** A matter keeps its own title and body as its raw form. An ask may carry `detail`, but the card a person answers is the short shape.
|
|
24
|
+
|
|
25
|
+
**D5 — Writers.** `POST /blockers` takes an optional `ask`, checked before anything is filed. `PUT /government/asks/:matter` writes an ask onto any docket matter, under the docket's atom plus the same per-source gate the docket applies, so an ask is never written onto a matter its writer cannot see. `POST /government/asks/check` is the dry run an agent uses before filing. An ask stays optional on `POST /blockers` for now: unattended pollers file blockers without one, and making agents write asks everywhere is task 1004704.
|
|
26
|
+
|
|
27
|
+
**D6 — The deck draws a stored ask as real.** A stored card carries no prototype mark, on a real site too. An answer's optional `act` is mapped onto the matter's own desk act, so tapping the pick takes the real route. The city card still draws only overlay rewrites, because its answer sends nothing; a stored ask is answered on the deck. Who a seat names stays the overlay's to resolve until task 1004705 routes it.
|
|
28
|
+
|
|
29
|
+
## Consequences
|
|
30
|
+
|
|
31
|
+
- A new docket source gets asks for free: the id is the docket's own.
|
|
32
|
+
- A matter that closes leaves its ask row behind. It is never read again (the docket reads asks only for open matters) and costs one small row.
|
|
33
|
+
- Changing a rule means changing both copies; the parity test fails until they agree.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# ADR 0373 — An AI session files a blocker with an ask, and checks the card first
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-09
|
|
5
|
+
- **Task:** [task 1004704](https://cloudbongos.com/builders#/task/1004704) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** [ADR 0372](0372-an-ask-is-stored-per-docket-matter-and-the-server-refuses-slop.md) (the ask's shape, stored per docket matter, slop refused)
|
|
7
|
+
- **Followed by:** task 1004705 (each ask routed to a seat)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
ADR 0372 gave every request from an agent to a person one shape and made the server refuse a card that breaks it. But the card was optional: an agent could still file a blocker as a title and a wall of prose, and most did (every open blocker on the hub was prose, the longest over 700 words). The owner's ruling is that agents ask like humans: short, decidable, no slop.
|
|
12
|
+
|
|
13
|
+
Asks reach people in four places: blockers, Bongos feedback, the "please confirm" lists at the end of a run, and review or help requests. Only a blocker is a stored docket matter today. Three scripts also file blockers unattended from a CLI session (`ship-escalation.js`, `artifact-audit.js`, `autobongos-verify.js`), and the hall's form files them for a person.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
**D1 — A blocker an AI session files by hand must carry an ask.** `POST /blockers` from a CLI session (`builder_sessions.source = 'cli'`, the token an agent's tools carry) without an `ask` answers 400 `ask_required`, whose message names the shape and the helper. A web session (a person on the hall's form) is unchanged.
|
|
18
|
+
|
|
19
|
+
**D2 — The exemption is an allow-list of templated sources.** The scripts that file a templated blocker unattended are named by the `source` each sends (`no-artifact-close`, `artifact-audit`, `autobongos`, `TEMPLATED_SOURCES` in the route). Everything else from a CLI session is held to the rule, because agents file with `task`, `manual`, or no source at all, and a source nobody thought of should be held rather than let through. So an unattended run, or a checkout older than this rule, never fails to file. A test reads each script's source off the script, so the list and the scripts cannot drift.
|
|
20
|
+
|
|
21
|
+
**D3 — The templated scripts send a card too, and never lose the blocker over it.** Each builds its card from what it knows (`escalationAsk`, `blockerAsk`). `scripts/gds/ask.js` `postWithAsk` checks the card with the server's own rules before sending, sends nothing broken, and re-sends the blocker without the card if the server refuses or cannot check it.
|
|
22
|
+
|
|
23
|
+
**D4 — The rewrite helper is the agent's loop.** `node scripts/gds/ask.js template` gives a blank card; `check <file>` asks the server's dry run (`POST /government/asks/check`) and prints every fix, or on a pass prints the card as a person reads it (`asks.cardText`). With no session or no answer, it checks locally with the same rules and says so. The printed card is what an agent pastes for an ask that is not a stored matter: the end-of-run confirm list, a help or review request, a Bongos feedback wish. The engineer pack and the ask-for-help, bongos-feedback, builder-ship and builder-sequence skills say so.
|
|
24
|
+
|
|
25
|
+
**D5 — The Conductor reminds, the server enforces.** The hook adds an `ask-shape` advisory when the prompt is about to put something to a person (a blocker, stuck, confirm, review, feedback, ship or wrap-up). It is advisory and its words are local; a test holds its numbers to `ASK_RULES`. The refusal is the server's.
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
|
|
29
|
+
- A legacy sourceless session (minted before migration 090) is not a CLI session, so it is not held to D1. Those tokens are old and rare.
|
|
30
|
+
- An agent could dodge D1 by sending a templated script's source. That is a deliberate evasion, visible in the row's `source`, not an accident the rule should prevent.
|
|
31
|
+
- Feedback and help requests are not stored matters, so their card is text at the top of the message, not a stored ask. Storing one would need those sources in the docket first.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# ADR 0374 — A building's Lead is a held position, appointed and removed by a People matter
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-09
|
|
5
|
+
- **Task:** [task 1004709](https://cloudbongos.com/builders#/task/1004709) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** [ADR 0363](0363-who-decides-what-is-a-table-changed-only-by-amendment.md) (the nine buildings, their decision rules, and matters)
|
|
7
|
+
- **Followed by:** task 1004705 (each ask routed to a seat), task 1004710 (who may build without a vote comes from the form of government), task 1004713 (positions on `/me`)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The living-city prototype gave five of the nine buildings a Lead (a person in charge, with a charter) and let the other four fall to the owner. Those Leads were invented: they lived only in the hall-preview overlay, so a real site showed no Lead and no owner at all. The owner's idea (2026-10-09) is that every civic building can have a Lead, appointed by the government through a People matter, carrying a short charter; an unseated building falls to the project owner; governance is a held position, not a picked craft.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
**D1 — One row per appointment, in `government_leads` (`government_029`).** A Lead is a builder, a building of the nine, and a one-line charter (3 to 140 characters; left out, the building's default line is filed). At most one Lead per building is in office (a partial unique index). The row records the board item that appointed them and when; leaving office records the item that ended it and when, and the row stays on the record.
|
|
16
|
+
|
|
17
|
+
**D2 — Appointed and removed only by a passed People matter.** Two People matter actions: `appoint_lead { building, builder_id, charter? }` and `remove_lead { building }`, filed through the existing `POST /government/board/matters`. A passed appointment ends the building's Lead in office (if any) and seats the new one; a passed removal ends it. There is no settings route. The table's trigger refuses any INSERT that does not name a passed `people_matter` item whose matter says exactly this building, builder and charter, any UPDATE except leaving office by a passed People matter for the same building, and every DELETE, so hand-written SQL is refused too.
|
|
18
|
+
|
|
19
|
+
**D3 — Where People decides as today, the government appoints.** Under the default rows every building, People included, is "decided as today" and refuses a matter ([ADR 0363](0363-who-decides-what-is-a-table-changed-only-by-amendment.md)). A Lead is the government's to appoint, so a Lead matter there sits under the board in force, like an amendment (on a Monarchy, the founder's one yes). Where People names a sitting, the matter sits under that row's members and rule. A vacant People appoints nobody. Rank assignments keep their old behaviour.
|
|
20
|
+
|
|
21
|
+
**D4 — Who answers for a building is one rule.** `leads.js` `answerFor`: the building's Lead in office, or the owner seat when it is unseated. The project has no owner field, so the owner seat is held by the founder's rank: every active Archon, the founding one (lowest id) first. Picking one Archon by a guess was rejected; the hub has five. `GET /government/leads` (pinned `perm:board.vote.cast`, where the Board Room reads) gives the nine buildings, each Lead with their charter, since when and the sitting that appointed them, and who answers for each.
|
|
22
|
+
|
|
23
|
+
**D5 — The hall draws the real Lead, and the overlay's invented Leads go.** When the read answers, the city's plates and cards, the street's doors and plates, and a Lead's capsule floor show the real Lead or the owner, with nothing marked prototype. The overlay keeps only the deputies and committees it hangs on a building whose real Lead is in office. Who an ask waits on is still routed by the overlay where it is read (task 1004705 makes routing real), so a real site keeps the docket's own count of what needs you.
|
|
24
|
+
|
|
25
|
+
## Consequences
|
|
26
|
+
|
|
27
|
+
- Holding the office confers no authority yet. Whether a Lead may build without a vote comes from the form of government (task 1004710), not a per-Lead flag, so the charter is one line of words and the prototype's `can_build_without_vote` and budget line are not stored.
|
|
28
|
+
- A Lead whose builder leaves stays in office until a People matter removes them. A passed appointment of someone who left before it passed seats nobody and says `builder_gone`.
|
|
29
|
+
- The hub has seated no Lead, so its city now shows the owner on every building, in the hall preview too. The prototype's five invented Leads only show where the read is missing.
|
|
30
|
+
- The government walk appoints and removes a Planning Lead under a council's consent; a real-database run of the walk is still later.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# ADR 0375 — Who may build without a vote comes from the form of government
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-09
|
|
5
|
+
- **Task:** [task 1004710](https://cloudbongos.com/builders#/task/1004710) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** [ADR 0374](0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md) (real Leads), [ADR 0363](0363-who-decides-what-is-a-table-changed-only-by-amendment.md) (each building's decision rule)
|
|
7
|
+
- **Followed by:** task 1004711 (build-outs actually go up), task 1004713 (positions on `/me`)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The living-city prototype let a building's Lead build it out (a committee room, a new floor, an annex, a district) either at once or by filing a vote, and decided which from a per-Lead flag on the Lead's charter (`can_build_without_vote`). ADR 0374 made Leads real but stored the charter as one line of words, so the flag had nowhere to live and the hall fell back to "by vote" everywhere. The owner ruled (2026-10-09): whether a Lead may change their building's structure without a vote is decided by the FORM OF GOVERNMENT, and later will often be shaped by goals. It is not a per-Lead flag.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
**D1 — One pure rule, `modules/government/build-rights.js`.** `buildRight({ building, capsule, form, decision, holder, goals })` answers `{ without_vote, why, ground }`; `buildRightsFor` answers all four capsules for a building. First match decides:
|
|
16
|
+
|
|
17
|
+
1. a district is always a vote (`ground: 'city'`);
|
|
18
|
+
2. a vacant building builds nothing (`ground: 'building'`);
|
|
19
|
+
3. a goal's limit is a vote (`ground: 'goal'`);
|
|
20
|
+
4. a building with its own sitting follows it: `decide` / `first` let a holder that sitting seats build at once, any other rule goes to the sitting (`ground: 'building'`);
|
|
21
|
+
5. a goal's grant is at once (`ground: 'goal'`);
|
|
22
|
+
6. otherwise the form (`ground: 'form'`): Monarchy at once; Timocratic Republic at once when the holder sits on the board, else a vote; Direct Democracy, Foundation and Custom a vote.
|
|
23
|
+
|
|
24
|
+
**D2 — The form is read from the constitution's settings, not a label.** `charter.readCharter(board)` names the form from what the board block seats and its pass rule, so the real constitution decides. Forms that cannot be in force (Presidential, Cooperative, Federation) have no answer; an unknown form reads as Custom.
|
|
25
|
+
|
|
26
|
+
**D3 — The holder, not the Lead.** The rule is about whoever holds the building: its Lead, or the owner seat when unseated (ADR 0374 `answerFor`). Under a Timocratic Republic the owner seat (Archons) sits on the board and builds at once; a newly appointed Lead who has not earned the trusted rank does not.
|
|
27
|
+
|
|
28
|
+
**D4 — Resolved on the server, per request, uncached, fail closed.** `decision-board.leadsView` reads the constitution in force, the decision table, who the board seats, and who each `decide`/`first` sitting seats, and `GET /government/leads` carries `build_rights` on every building. An unreadable part reads as "a vote", never "at once".
|
|
29
|
+
|
|
30
|
+
**D5 — The goals hook is a parameter, empty today.** A goal term is `{ goal_id, building | '*', capsules?, allow, why? }`. A limit beats the building's sitting and the form; a grant beats the form only. No goal stores terms yet, so the server passes `[]`; adding them later changes the caller, not the rule.
|
|
31
|
+
|
|
32
|
+
**D6 — The hall reads the answer and holds no rule.** `gov-living.js` carries `build_rights` per building (`real` when the read answers; the overlay's sample, made by the same rule, otherwise), and `street-office.js` `buildPlan` reads it per capsule. The overlay's `can_build_without_vote` flags are gone; a test fails if any module, src file or fixture names the flag again, and if anything but `leads.js` requires the rule.
|
|
33
|
+
|
|
34
|
+
## Consequences
|
|
35
|
+
|
|
36
|
+
- On a real site no build-out goes up yet (task 1004711); the answer is there for it to ask.
|
|
37
|
+
- The hub runs `rank:metic+` with a unanimous rule, which reads as Custom, so every building there reads "a vote" until the constitution is changed.
|
|
38
|
+
- Rejected: a per-Lead flag on the charter (the owner's ruling); a hall-side copy of the rule (two copies drift); letting a goal's grant override a sitting the project voted in.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# ADR 0376 — Every ask is routed to a real seat on the server
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-09
|
|
5
|
+
- **Task:** [task 1004705](https://cloudbongos.com/builders#/task/1004705) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** [ADR 0372](0372-an-ask-is-stored-per-docket-matter-and-the-server-refuses-slop.md) (the stored ask and its seat), [ADR 0374](0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md) (Leads, and the owner seat an unseated building falls to)
|
|
7
|
+
- **Followed by:** task 1004713 (positions on `/me`), task 1004716 (one count endpoint)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
Every open matter on the docket said "needs" for anyone who could act on it, and the hall decided whose it was from the prototype overlay's invented seats. On a real site, with no overlay, everything a viewer could act on was "to do", so the count never said what was really theirs. Asks now carry a seat (`owner`, `lead:<building>`, `committee:<building>.<name>`, `board:<building>`), and Leads are real, so the server can route.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
**D1 — The server routes; the hall reads the answer.** `modules/government/routing.js` (pure) decides, per docket matter and per viewer, which seat it waits on and whether it is the viewer's. `GET /government/docket` reads the seats once per request, uncached (the Leads in office, every active Archon as the owner seat, each building's holders), and every matter carries `route { seat, label, asked, fell_to_owner, yours, nobody }`, with `routed: true` on the docket and `counts.yours`. The home line counts what is yours. A failed seats read routes nothing (`routed: false`), never a guess.
|
|
16
|
+
|
|
17
|
+
**D2 — The seat.** A stored ask's `waits_on` wins. Without one, a board sitting waits on `board:<building>` (its voters: the docket's own per-voter `needs`), anything else on `lead:<building>`. `lead:<b>` is its Lead in office, else the owner seat (owner ruling, through `leads.answerFor`, still the one rule). `board:<b>` is the members its decision-rules row seats now, else the owner. Committees are not held in any table yet, so `committee:<b>.<k>` goes to the building's Lead (or the owner).
|
|
18
|
+
|
|
19
|
+
**D3 — An ask nobody answers does what its line says.** A matter past its deadline, or on a seat nobody holds, is on nobody's "to do": its route carries `nobody { why: lapsed | empty_seat, outcome }`, the outcome being its own "if nobody answers" line. The hall settles it and prints that line.
|
|
20
|
+
|
|
21
|
+
**D4 — Passing an ask on is a real write.** `POST /government/asks/:matter/pass { seat }` (pinned `perm:board.vote.cast`): only whoever the ask waits on today may hand it on, only a stored ask, never a vote (a sitting is its voters'), and only to a different seat. The words stay; only `waits_on` changes. The deck offers it on a real, stored ask that is yours, with real seats only (the owner, the Leads in office).
|
|
22
|
+
|
|
23
|
+
**D5 — The hall's counts stay one definition.** `gov-living.js` takes `needs_you` from the route (`yours`, only for the docket's own viewer) and `waits_on` from the route's seat, both labelled real/derived; `countsOf` is still the one count every surface prints. The overlay's seats now route only its own prototype asks, and a docket that is not routed keeps the old rule.
|
|
24
|
+
|
|
25
|
+
## Consequences
|
|
26
|
+
|
|
27
|
+
- On a real site "to do" is what waits on you; everything else you can see "waits on others".
|
|
28
|
+
- An Archon sees every unseated building's asks; a seated Lead takes their building's off the owner's list.
|
|
29
|
+
- The deck's pass-it-on sends a request on a real ask, and is still a page-only prototype on the overlay's asks.
|
|
30
|
+
- Committees and deputies remain prototype; when a table holds them, `resolveSeat` is the one place to seat them.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# ADR 0377 — Governance is a held position, read on /me
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-09
|
|
5
|
+
- **Task:** [task 1004713](https://cloudbongos.com/builders#/task/1004713) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** [ADR 0374](0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md) (Leads and the owner seat), [ADR 0376](0376-every-ask-is-routed-to-a-real-seat-on-the-server.md) (`routing.resolveSeat`), [ADR 0175](0175-the-board-room-full-idea-ratification.md) (board membership)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
Owner ruling (2026-10-09): you either hold a government position or you don't; governance is not a craft you pick. The living-city prototype drew this (task 1004685) with `gov-positions.js`, but it named seats from the prototype overlay and re-derived board membership in the browser. On a real site, with no overlay, the seats were unknown, so nothing ever hid; in the preview the craft mode said "Planning Lead" while the real Leads read seated nobody.
|
|
11
|
+
|
|
12
|
+
## Decision
|
|
13
|
+
|
|
14
|
+
**D1 — The server resolves positions.** `modules/government/positions.js` folds, for one builder, the seats they hold: `owner` (every active Archon, `leads.ownerOf`), `lead` (a Lead in office), `seat` (a seat on a building's own sitting, its decision-rules predicate), `board` (a member under the constitution in force). Owner and Lead come from `routing.resolveSeat` (so `leads.answerFor`); the board and each sitting from `board-membership.isBoardMember`. No second rule. A Lead names the set first (`lead` → `owner` → `seat` → `board`).
|
|
15
|
+
|
|
16
|
+
**D2 — `/me` carries it.** The government port's `positionsFor(builderId)` is read per request, uncached; `GET /me` returns `positions: { held: [{ kind, seat, building, title }], title, has_position, from }`, or `null` when the module is off or a read failed. A craft never makes a seat; holding one grants no permission.
|
|
17
|
+
|
|
18
|
+
**D3 — The hall only reads it.** `gov-positions.js` maps `/me.positions` and nothing else (no overlay, constitution or rank). The shell hides the `position` nav items (City, Board Room, the Government group) from a builder the server says holds none, and craft-mode names Governing by `title`. A `null` block is unknown, which keeps today's nav. `gov-living.js` viewer seats and its governance tab follow the block too, marked real. Every page keeps its own server-side gate (ADR 0016).
|
|
19
|
+
|
|
20
|
+
## Consequences
|
|
21
|
+
|
|
22
|
+
- A builder with no seat sees no governance tab; a Lead sees one named by their seat ("Planning Lead").
|
|
23
|
+
- Every active Archon holds the owner seat, so the owner always sees governance.
|
|
24
|
+
- Deputies and committee seats are still not held in any table; when they are, they are new kinds in `positions.js` (and `resolveSeat`).
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# ADR 0378 — A Lead's build-outs are rows on the record, built at once or by a passed vote
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-10
|
|
5
|
+
- **Task:** [task 1004711](https://cloudbongos.com/builders#/task/1004711) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** [ADR 0375](0375-who-may-build-without-a-vote-comes-from-the-form-of-government.md) (who may build without a vote), [ADR 0374](0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md) (real Leads), [ADR 0363](0363-who-decides-what-is-a-table-changed-only-by-amendment.md) (building matters)
|
|
7
|
+
- **Followed by:** task 1004712 (treasury and pots — build-outs carry no money here)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The living-city prototype let a building's holder grow it — a committee room, a new floor, an annex, or a district — and drew the result: a live site with scaffold and crane where it may build at once, a dashed ghost annex with the board's tally arc where it must wait on a vote, and a vote card carrying a picture of the building with the change drawn in. All of it was overlay data, so a real site drew none of it. ADR 0375 put the rule (at once, or a vote) on the server; nothing yet carried a build-out out.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
**D1 — Structure is data: `government_buildouts` (government_030).** One row per build-out ever: building (the nine), capsule (`committee`, `floor`, `annex`, `district`), a 2–40 character name, a one-line line, who asked (`built_by`), and exactly one record of how it was allowed — `authorised_by_item_id` (a passed matter) or `ground` + `why` (the build-rights answer). `started_at` is the database clock. A row is never edited or deleted.
|
|
16
|
+
|
|
17
|
+
**D2 — Two paths, one rule.** `POST /government/buildouts { building, capsule, name?, line? }` (pinned `perm:board.vote.cast`; the wall is server-side): only the building's HOLDER may ask — its Lead, or the owner seat when unseated (`leads.answerFor`) — else 403 `not_the_holder`. The server reads `build_rights` off the same view `GET /government/leads` serves (build-rights.js; no second rule): `without_vote` → the row is written now with its ground (`path: 'at_once'`); otherwise the ask is filed as a `build_out` matter through `openMatter`, the code `POST /government/board/matters` runs (`path: 'vote'`). Rights that cannot be read are a vote. The matters route meets the same wall: a `build_out` filed straight at `POST /government/board/matters` by anyone but the holder is refused 403 `not_the_holder`, and every refusal says whom to ask instead.
|
|
18
|
+
|
|
19
|
+
**D3 — Where the vote sits.** A build-out is a matter at the building it adds to (the Charter, which takes no matters, files as a People matter). It sits under the board in force when the building has no sitting of its own, and always for a district or the Charter; otherwise at the building's own sitting — the same places build-rights.js says the vote goes. `build_out` is valid at every matter area and carried out by the government module, whichever modules are on.
|
|
20
|
+
|
|
21
|
+
**D4 — A passed vote builds once.** `actOnPassedMatter` writes the row naming the passed item; a returned matter builds nothing; a second run of the same item is `already_carried_out` (unique index). The trigger refuses a row whose vote did not say exactly that building, capsule, name and line, an at-once row without a ground, an at-once district, and every UPDATE and DELETE. One SQL writer (`db.insertBuildout`), called only from decision-board.js.
|
|
22
|
+
|
|
23
|
+
**D5 — The read.** `GET /government/leads` carries each building's `structure`: `standing` (each build-out with `state` `building` or `built`, `progress` 0..1 over 24 hours from `started_at`, `builder`, `allowed`) and `proposed` (each open `build_out` sitting with its `docket_id`, so the hall finds its tally on the docket). A failed read of either part leaves `structure` null.
|
|
24
|
+
|
|
25
|
+
**D6 — The hall draws the real thing.** `gov-living.js` turns `structure` into construction (a live site at the real progress; a ghost whose tally is its sitting's) and real committee rooms and built floors; at a building whose structure is read the overlay's build-outs and committees are not used. `city-draw.js` draws them unmarked. `street-office.js` stands the Lead's office on a real site once the Leads are read, posts a capsule tap to `POST /government/buildouts`, and draws a build-out's vote picture FROM THE REAL BUILDING: what stands solid (built floors, rooms, a built annex or district), the change dashed on top of it.
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
|
|
29
|
+
- A real project's city now shows its build-outs; the hub has none yet, so its harness fixture carries empty structures and the overlay's samples no longer draw where the read answers.
|
|
30
|
+
- Progress is a clock, not work: a build-out stands as a site for a day. If build-outs later carry real work (a task), progress can come from it without changing the table.
|
|
31
|
+
- Deputies are still the overlay's; a committee room seats nobody yet (routing still sends a committee's asks to the Lead).
|
|
32
|
+
- A build-out costs nothing here; pots and the treasury are task 1004712.
|
|
33
|
+
- Rejected: a hall-side copy of the rule; letting any builder with `board.item.open` build at once; a separate vote route (votes go through the existing matters path).
|
package/docs/adr/0379-the-treasury-is-pots-per-goal-a-reserve-and-borrowing-over-real-spend.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# ADR 0379 — The treasury is pots per goal, a reserve, and borrowing, over real spend
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-10
|
|
5
|
+
- **Task:** [task 1004712](https://cloudbongos.com/builders#/task/1004712) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** [ADR 0376](0376-every-ask-is-routed-to-a-real-seat-on-the-server.md) (routing), [ADR 0372](0372-an-ask-is-stored-per-docket-matter-and-the-server-refuses-slop.md) (the ask shape), [ADR 0374](0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md) (Leads)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
The project's AI spend is its treasury. The living-city prototype drew a pot per goal, a reserve, a dry pot's borrow and a spend conduit, all from overlay data, so a real site drew none of it. The owner ruled (2026-10-09): there is **no spend limit by default** (a cap is an optional project setting, off by default); a goal **may** have a pot; when a pot runs dry it **asks to borrow from the reserve**, and that borrow is a treasury matter the government decides. Nothing here may move money or touch a payment provider: this is the project's own accounting over the spend it already records (`cost_log`).
|
|
11
|
+
|
|
12
|
+
## Decision
|
|
13
|
+
|
|
14
|
+
**D1 — Spend is read, never copied.** A pot's spend is the `cost_log` rows whose task is in the goal, in this calendar month (`to_char(recorded_at, 'YYYY-MM')`, the month cost-summary's `by_month` uses), summed on every read. Only what the treasury decides is stored.
|
|
15
|
+
|
|
16
|
+
**D2 — A pot is a stored budget (government_031 `government_pots`).** One row per goal that has a pot: dollars a month. A goal with no row has no pot. Only whoever answers for the Treasury today — its Lead, or the owner seat while it is unseated (`routing.resolveSeat('lead:treasury')`) — sets, changes or removes one: `PUT /government/treasury/pots/:goalId { budget_usd | null }` (403 `not_the_holder`). Only an open goal.
|
|
17
|
+
|
|
18
|
+
**D3 — The reserve is derived.** Last month's real spend that no pot was given this month, less what the reserve lent this month. It may go negative (overdrawn): with no limit, work runs on and the overspend shows as debt. With no month of spend behind it, it is unknown (null), never invented.
|
|
19
|
+
|
|
20
|
+
**D4 — A dry pot files a borrow (government_031 `government_pot_borrows`).** A pot is dry at spend ≥ budget + this month's loans. The `treasury-borrow` poller (every 15 minutes) files one open borrow for each dry pot with nothing open and no "no" this month, asking for enough to finish the month at its pace (spend over the share of the month gone, rounded up to $50). Its ask is stored in the ask shape on the docket id `treasury_spending:<id>`, waiting on `lead:treasury`, so `routing.js` routes it to the Treasury's Lead or the owner. A goal title that would make the question slop falls back to "this goal"; the ask is checked by `asks.checkAsk` before it is stored. One open borrow per goal (a partial unique index).
|
|
21
|
+
|
|
22
|
+
**D5 — The borrow is answered once, by its seat.** `POST /government/treasury/borrows/:borrowId/answer { key: lend | half | no }`: only whoever the borrow's ask waits on today (`routing.routeMatter(...).yours`, 403 `not_yours`); a second answer is 409, and a trigger refuses any second answer, any edit of what was asked and every delete. Saying no stops nothing; a "no" holds until the month turns.
|
|
23
|
+
|
|
24
|
+
**D6 — The cap exists and is off.** `project_settings['treasury.spend_cap_usd']`: no row is off; `PATCH /project-settings/spend-cap { usd | null }` (project.settings.manage, and the Treasury's decision row: `requireActAlone('treasury')`). On, it is reported (the month against it) and a borrow that would carry the month past it is recommended against. It never stops work; enforcing it is not this decision.
|
|
25
|
+
|
|
26
|
+
**D7 — The docket and the hall.** The `treasury_spending` docket source is real (it was "coming"): each open borrow is a matter at the Treasury, with acts only for a viewer who sits in its seat. `GET /government/treasury` (board.vote.cast) serves the pots, reserve, cap and who answers. The hall reads it: a district's pot, the spend conduit's spurs and a dry pot's beacon, the Treasury's book (tiles, cap, pots) and the borrow's in-place card are real when it is read; the overlay's sample pots and loan are gone.
|
|
27
|
+
|
|
28
|
+
## Consequences
|
|
29
|
+
|
|
30
|
+
- A project with no pots files nothing: deploying this is silent on the hub until the Treasury's holder gives a goal a pot.
|
|
31
|
+
- Pots attach to goals only; build-outs (ADR 0378) still carry no money.
|
|
32
|
+
- Setting a pot's budget is the holder's alone even where the decision table puts Treasury to a sitting: a vote path (a `set_pot` matter action) and enforcing an "on" cap are later work.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# ADR 0380 — A strictness preset is a bundle of laws, switched by one laws vote and read from the laws in force
|
|
2
|
+
|
|
3
|
+
- **Status:** accepted
|
|
4
|
+
- **Date:** 2026-10-10
|
|
5
|
+
- **Task:** [task 1004715](https://cloudbongos.com/builders#/task/1004715) (goal 1000111, "government is how a project steers its AI")
|
|
6
|
+
- **Builds on:** the laws (task 1004706: a law is written only by a passed laws amendment, government_027's trigger) and their locks (task 1004707, `builder-settings/law-locks.js`)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
The living-city prototype offered three strictness presets — Open workshop, Guild, Factory — from overlay data, so a real site had none and My agents could only preview "N would lock". The task: a project picks how strict it is the way it picks a form of government; a preset is a bundle of laws and locks (Open few laws, Guild the standard set, Factory strict: caps on, the ask format enforced, no unattended runs); switching presets is a vote. Two walls stand: a law is written only by a passed vote, and no law may be seeded (the first laws are the owner's to ratify, task 1004708).
|
|
11
|
+
|
|
12
|
+
## Decision
|
|
13
|
+
|
|
14
|
+
**D1 — A preset is a catalogue of laws, in code (`modules/government/presets.js`).** Open workshop: "Land only. Ask before going live". Guild: that, "Stuck? Note it, skip it, keep going", and "Stay on the task; note side ideas" (caps wandering at `focused`). Factory: the first two, "Stay on the task; no side trips" (fixes wandering at `locked`), "Ask like a human", "No unattended runs", and "Models stay under their caps" (main ≤ opus, helpers ≤ sonnet, routine ≤ haiku). Every lock names a stored personal setting, so every lock is enforced; a law shared by two presets has the same words and locks in both.
|
|
15
|
+
|
|
16
|
+
**D2 — Switching is ONE laws amendment through the existing path.** `POST /government/board/presets { preset }` (pinned `perm:board.item.open`, the same atom as any laws proposal) builds the change — enact the preset's laws not in force, repeal the other presets' laws that are — and files it through `board.proposeLaws`. Nothing new writes a law: only the sitting passing does (`applyPassedLaws`, the trigger). A law that belongs to no preset is never touched; if it locks a setting the preset locks, the switch is refused by name (409 `setting_already_locked`).
|
|
17
|
+
|
|
18
|
+
**D3 — The preset in force is READ, never stored.** A preset is in force when every one of its laws is (same words, same locks) and no other preset's law is; otherwise none ("No preset yet"). No table, no migration, nothing to drift from the law book, and nothing seeded: a fresh project runs no preset.
|
|
19
|
+
|
|
20
|
+
**D4 — What each would lock is the server's.** `GET /government/presets` (pinned `perm:board.vote.cast`, like the law book) carries, per preset, its laws and the locks in force after a switch to it (its own plus those of the project's own laws it would keep). My agents' strip counts those against the viewer's rows and offers "put it to a vote"; the Charter inside the building shows the preset in force and files the same vote. Both are real, unmarked.
|
|
21
|
+
|
|
22
|
+
## Consequences
|
|
23
|
+
|
|
24
|
+
- "No unattended runs" reaches every session as a law's words; nothing yet refuses an unattended run. "Ask like a human" is already enforced for AI-filed blockers (ADR 0373).
|
|
25
|
+
- A project that passes a preset's law by hand, with the same words, has it counted toward that preset — intended: the book, not a label, is the truth.
|
|
26
|
+
- Rejected: a stored `strictness` setting (a second truth beside the laws, and a write path the trigger does not guard); one vote per law (a switch half-passed is no preset); the overlay's "Factory sets every setting" (a lock on a setting no table holds is not enforced).
|
package/docs/adr/README.md
CHANGED
|
@@ -451,7 +451,7 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
|
|
|
451
451
|
| 0330 | [**An ask is answered where it was asked** ([task 1004216](https://cloudbongos.com/builders#/task/1004216), goal 1000095 — BONGOS-V2), amending [ADR 0187](0187-collab-four-decisions.md) §4a. `lifecycle_004` let a builder ASK for help and let the **asker** mark their own row answered; the person being **asked** had no write at all, so the answer happened somewhere Bongos cannot see and the row sat open until its author remembered it — six asks addressed to the owner had been open between four and thirteen days on 2026-09-23, every one of them answerable. That was not an oversight: §4a deferred conversation to the Agora and a test named *"there is deliberately NO reply thread"* enforced it. **The deferral lost its addressee** — task 1002946 is ABANDONED and goal 1000064 ARCHIVED (verified against the live DB), so the rule had stopped meaning "wait for the Agora" and started meaning "an ask stays unanswerable forever to keep a promise to something that does not exist". **Decisions:** (1) an ask carries a thread of replies, APPEND-ONLY in the SCHEMA rather than by convention — no `updated_at`, `edited_by`, `deleted_at` or `parent_reply_id`, no reactions, no mentions, and a trigger that refuses UPDATE and DELETE outright, because a thing you can edit, nest, react to and address at people is a chat and that is what §4a declined; any builder may reply, since the board read is already project-wide and the good case is somebody you did not ask knowing the answer; (2) the **ADDRESSEE** may close an ask (`answered`), widening an asker-only UPDATE that was coherent only while nothing could be said on the row — but `withdrawn` does NOT widen, since "I no longer need this" is the asker's sentence alone and widening it would be a way to make an ask vanish unanswered; `settled_by` records which of the two closed it, and ADR 0187 §3's consent posture is untouched — closing ends a question, it does not accept work; (3) `/collab-review` posts the reply and **leaves the ask open** (owner decision), since an answer the reader has not read is exactly what an unattended run must halt on. **Consequences:** a reply cannot be taken back, by design; the FK **RESTRICTS rather than cascades** — the first draft cascaded, which reads right and was wrong, because a cascade is a plain DELETE the trigger refuses, so deleting an answered ask failed outright (caught by applying the migration to a real Postgres, not by reading it); the old test was REPLACED, not deleted, so the record that the restraint was deliberate survives; and replies inherit the pull-not-push posture, so nothing still tells an asker they were answered. Rejected: a single `answer` column (cheapest and unambiguously not a chat, but a follow-up would have nowhere to go except a second ask, splitting one conversation across two rows); waiting for the Agora (abandoned — waiting means forever); letting anyone close any ask (an open question is somebody's, and a stranger ending it should not be one click away).](0330-an-ask-is-answered-where-it-was-asked.md) | collab / lifecycle / schema |
|
|
452
452
|
| 0331 | [**The sky is the ideator's home, and the project sky takes the goal map's page** ([task 1004229](https://cloudbongos.com/builders#/task/1004229), goal 1000095 — BONGOS-V2), amending [ADR 0227](0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md) and decision 11 of `docs/specs/<redacted>.md`. The owner reviewed an interactive prototype of the ideator sky and the project sky over five rounds on 2026-09-24 and adopted it AS IS — copy, layout, colours, tour text, toggles, interactions — which contradicts two things already written down, so they are rewritten rather than leaving the build graded against a contract nobody means any more. **Decisions:** (1) the sky is the ideator's HOME surface — it replaces *Your thinking*, and the project sky replaces the goal map page — so "never load-bearing" and "arrives last" are DROPPED as a sequencing hedge from before there was a design to look at; the rule that survives at full force is the accessibility half, that the sky is never the ONLY path to anything it shows (the list drawer — the room — is one key away, and every drawn thing is a row in it); (2) ADR 0227 is AMENDED, not reversed — its measured refusal of a whole-corpus task map stands, and the project sky is §1's own prescription rather than its refusal: the goal graph is the entry point, tasks are drawn only INSIDE one goal past a zoom threshold (the per-goal drill-down §10.5 measured readable at 85.2px pitch worst case), below that they are dust density on the rings with NO identities, and the goal map's table survives as the sky's ledger drawer (§6's table equivalent kept); the nav slot the goal map was deliberately denied is GRANTED to the project sky, under Goals (owner, 2026-09-24), so part 4 changes the page and the test asserting no slot together; (3) the five states and the two channels are UNTOUCHED — criterion `ideator-sky-tells-the-truth` names a model, not a picture, and this amendment changes the picture's standing only; (4) the two HEURISTICS in the prototype — an idea's origin guessed from its text, and "born of a thought" found by scanning text for idea ids — must not ship as ledger facts: parts 3 and 4 hide both layers, part 5 replaces them with a `filed_via` column and a real born-of read. **Consequences:** `docs/design/mocks/sky/sky.template.html` is the PIXEL CONTRACT for parts 2–5, and every deviation a gate or the file ratchet forces is listed in that part's ship notes; no snapshot JSON or built page is ever committed (it carries real task and idea titles and this repo is public); ADR 0264's deleted goal "Living project sky" is superseded by this work under Working area 3. Rejected: shipping the sky as an extra and keeping "never load-bearing" (makes the adopted home surface unroutable); reversing ADR 0227 (its refusal is measured and still correct — the sky needs its drill-down shape, not its repeal); shipping the heuristics behind a disclaimer (a labelled guess is still a guess in a picture whose promise is that it cannot be faked).](0331-the-sky-is-the-ideators-home.md) | design / ideator / sky |
|
|
453
453
|
| 0332 | [**Offboarding scrubs stored secrets: an event, not a direct write, and reactivation restores neither** (spike [task 1003338](https://cloudbongos.com/builders#/task/1003338), goal 1000110 — BONGOS-V2). `deactivateBuilder` revokes sessions but never scrubs the two third-party credentials the platform holds on a departing builder's behalf: the `github_oauth_tokens` row and the per-builder Gemini BYOK key (`gemini_key_enc`/`last4`/`set_at`, module-owned by `art-pipeline` per [ADR 0102](0102-finish-bounding-the-kernel.md)). **Decisions:** (1) `deleteGithubToken` is called synchronously inside `deactivateBuilder`'s existing transaction — the table is core's own; (2) a new best-effort event, `builder.secrets-scrub-needed`, is emitted post-commit (mirroring the existing `builder.box-reconcile-needed` pattern) so `art-pipeline` — or any future module storing a builder-keyed secret — can clear its own store without core reaching across the module boundary ADR 0102 drew; (3) reactivation restores NEITHER secret, symmetric with rank ("not auto-restored… re-promotes deliberately") — a returning builder re-enters their own key and re-derives a fresh GitHub token. **Rejected:** a direct `UPDATE` nulling the Gemini-key columns from core (re-opens the ADR 0102 leak); deleting the `builders` row to get `ON DELETE CASCADE` for free (breaks the explicit lossless design of graceful exit); a cron sweep (a new mechanism where an event already fits); auto-restoring the key on reactivation (a stored credential is not earned state). The core-side change (GitHub-token delete, event emission, contract doc, tests) shipped with this task; follow-up [task 1004239](https://cloudbongos.com/builders#/task/1004239) is narrowed to the `art-pipeline` module-side listener plus a periodic reconcile backstop.](0332-offboarding-secret-scrub-semantics.md) | security / privacy / modules |
|
|
454
|
-
| 0333 | [**The application vouch is a third token kind, spent once, bound to the login it names, and carries a handle only past the consent floor** ([task 1002285](https://cloudbongos.com/builders#/task/1002285), goal 1000045 — criterion C4), resolving [ADR 0208](0208-application-lifecycle-the-handle-waits-and-the-vouch-has-no-minter.md) D1 + D2. The hub's join relay now carries a signed application vouch in `<redacted>`, so the ADR 0260 live-record path is no longer dormant. `mintHubApplicationVouch` / `<redacted>` share one envelope with the login and logout tokens, and each verifier demands what the other two lack; `verifyHubAssertion` now refuses any `purpose`, closing the device-login replay. The jti is a chosen, separate single-use store; a vouch must carry a jti and an audience, and must name the login the request names, or the row is written unvouched (never refused); a vouched re-application takes over an unvouched pending row for its login. The vouch carries its login as `applicant_login`, so even an un-upgraded core refuses it as a login. `applicant_handle` (`core_254`) is identity, not record, and rides only past the consent floor.](0333-the-application-vouch-is-a-third-token-spent-once-and-bound-to-its-login.md) |
|
|
454
|
+
| 0333 | [**The application vouch is a third token kind, spent once, bound to the login it names, and carries a handle only past the consent floor** ([task 1002285](https://cloudbongos.com/builders#/task/1002285), goal 1000045 — criterion C4), resolving [ADR 0208](0208-application-lifecycle-the-handle-waits-and-the-vouch-has-no-minter.md) D1 + D2. The hub's join relay now carries a signed application vouch in `<redacted>`, so the ADR 0260 live-record path is no longer dormant. `mintHubApplicationVouch` / `<redacted>` share one envelope with the login and logout tokens, and each verifier demands what the other two lack; `verifyHubAssertion` now refuses any `purpose`, closing the device-login replay. The jti is a chosen, separate single-use store; a vouch must carry a jti and an audience, and must name the login the request names, or the row is written unvouched (never refused); a vouched re-application takes over an unvouched pending row for its login. The vouch carries its login as `applicant_login`, so even an un-upgraded core refuses it as a login. `applicant_handle` (`core_254`) is identity, not record, and rides only past the consent floor.](0333-the-application-vouch-is-a-third-token-spent-once-and-bound-to-its-login.md) | security / onboarding / platform-identity |
|
|
455
455
|
| 0334 | [**The recruiting directory lists a hidden builder by name, and hide changes a row's shape, not whether it exists** ([task 1002291](https://cloudbongos.com/builders#/task/1002291), R15 — goal 1000110). Privacy spec D2 (owner-signed) lists an active, public, hidden account on the recruiter surface "name-only (if not opted out)"; the directory dropped it outright, making hide a second opt-out while Settings told that builder recruiters would see their name and picture. `GET /scouting` now answers two tiers: `builders` (ranked, `scoutingListableSql`, unchanged) and `name_only` (`scoutingNameOnlySql` = the same predicate with the hide term flipped, so the tiers partition the directory and only the opt-out removes anyone), projected to `github_login`, `display_name`, `avatar_url` by `scouting-name-only.js`. The existence floor stays (a private account is the archon-floor D3 sliver's, never the directory's); presence never depends on activity; the only order is the login; the predicate is pinned to that one reader and its three columns. The hall's `/people` renders the tier as its own panel, never ranked, found by name, never by a role filter. Rejected: fixing only the copy; trailing rows in the ranked ledger; listing private discoverable accounts by name.](0334-the-recruiting-directory-lists-a-hidden-builder-by-name.md) | privacy / recruiting / hall |
|
|
456
456
|
| 0335 | [**An invite is a pre-approved row on the project's own instance, and `project.recruit` says who may send one** ([task 1002813](https://cloudbongos.com/builders#/task/1002813), R1 of the project admin console wave, goal 1000110 — BONGOS-V2). Supersedes ADR 0141 §5's "Invitations (deferred slice)" paragraph only. Formalises spike task 1002786's three decisions and reconciles them with six weeks of shipping: the instance invite route (task 1003044), the PATCH rescind (ADR 0201 D4.2) and the composed join door (ADR 0247) already exist, and the hub invite's dead end is now reachable from the creation wizard. **Decisions:** (D1) authority lives on the project's own instance, and the instance IS the project; the hub is identity, relay, echo, notification and links, and never writes a project's admission row; (D2) a recruit invite is an `access_requests` row with `status='invited'`, so signing in is the acceptance act and the gate is untouched; the row gains `kind ∈ (application, invite)` and `created_by` (the inviter, which a rescind would otherwise overwrite), reuses `note`, backfills exactly (`created_at = resolved_at`), and neither column ever enters an admission read; (D3) one new grantable atom, `project.recruit` (`system:false`, floor archon, widened per instance through the existing governance tab), guards the invite, the outstanding list, the invite rescind and the queue read, while `access_request.review` keeps the verdict; because inviting is admitting, a recruiter without the review atom may not approve or re-admit an APPLICANT through the invite route (409 to the queue); the hub sliver moves onto the atom, and the hub directory and hub invite KEEP `project.curate`, revising ADR 0210/0215/0248, since swapping the directory would raise a gate on a viewing surface (ADR 0217). **Task map:** R2 (task 1002814) = the migration, the invite writes and the sender list, still on `access_request.review`; R3 (task 1002815) = mint the atom, move the gates, the 409 clause, the sliver swap and the pins, and it lands after R2; R5 (task 1002817) is already delivered, so close it into task 1002331; task 1003362 folds into R3. Rejected: a new invitations table; the hub pending row as the invite; widening `access_request.review` instead of minting an atom; a per-project settings row for the floor; letting a recruiter's invite approve applications; `system:true`; swapping `project.curate` on the hub directory.](0335-an-invite-is-a-pre-approved-row-on-the-projects-own-instance.md) | governance / onboarding / platform-identity |
|
|
457
457
|
| 0336 | [**A guild is a hub-side group whose members each consent twice, and its collective record is only ever the sum of what those members already show** ([task 1002299](https://cloudbongos.com/builders#/task/1002299), goal 1000110 — the R23 design spike for goal 1000045's C7/C8/C9). No platform guild existed (every "guild" in the tree is Discord's). Decisions: (1) three hub tables in `platform-identity`, in their own `guilds.js` (the 1,500-line ratchet), distinct from instance-local `goal_members`: guilds (slug, name, `visibility ∈ public|unlisted` with **no default**), members (`membership_kind ∈ owner|member`, never `role` per ADR 0174; a partial unique index holds exactly one owner; a per-member `shown_publicly`), and requests; (2) two consents to join, no self-join, through ADR 0202's connections lifecycle verbatim (silent decline, 90-day swallowed re-ask, 30-day read-time expiry); `accountActiveSql` floors the feature; an **unlisted guild 404s to everyone on the public read, members included**, and takes invites only, because a slug is guessable; (3) the public roster is `shown_publicly AND accountVisibleSql`, and widening a guild to public changes no member's flag but the flipping owner's, so consent given to a small audience is never reused for a large one; (4) **the privacy resolution — NOT ratified; superseded by [ADR 0337](0337-the-hub-account-is-the-person-a-hall-account-is-their-seat-in-one-project.md) D4.4:** it proposed that a member is counted iff shown AND `rollupVisibleSql`, read-time, `no-store`, never stored, and N and M are both lengths of lists the reader can see. The guild record is therefore always a sum of numbers already on members' own public profiles, so nothing can be subtracted out. All-or-nothing is rejected (one member blanks everyone and hiding becomes costly), as is per-member consent to count hidden numbers (it breaks "hide_stats beats everything"). The trade-off: guilds of privacy-minded builders look smaller and rank lower. A union count of all members' projects is refused because it reveals shared private projects; (5) the namespace is `/g/<slug>`, `g` is reserved in the SEO spec's project-slug list, the slug is fixed in V1, and `tests/guild_namespace_reserved.mjs` pins the two documents together; (6) a guild engages a project only through the individual door: a guild application is each member's own vouched application, labelled through ADR 0260's live applicant-profile read (no new instance field); inviting a guild fans out ordinary individual invites to its public roster at that moment, **never a guild-level pre-approval** (that would let a guild owner decide admission to someone else's project); (7) the map ranks public guilds by size and counted works shipped, read-time, with a slug tiebreak, and R29 narrows to the visual. Scope changes for R24–R37 are tabled in the ADR, including R28's dependency on the abandoned R11 and R29/R31's archived orb goals.](0336-a-guilds-record-is-the-sum-of-what-its-members-already-show.md) | platform identity / privacy / social graph |
|
|
@@ -490,3 +490,12 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
|
|
|
490
490
|
| 0369 | [**Ship mode decides who starts a ship, not how it lands** ([task 1004628](https://cloudbongos.com/builders#/task/1004628), goal 1000106). **D1:** a `ship.mode` project setting, `auto` (the AI ships and lands a finished task with no commands) or `manual` (a person approves each ship), in `project_settings` with no migration. **D2:** Auto is the default, and the resolver reports whether anyone has chosen. **D3:** it is separate from deploy mode (`config/deploy.json`), which decides how a land happens. **D4:** any builder can read it (the AI must know), and `project.settings.manage` writes it, from the settings page or `bongos ship-mode`.](0369-ship-mode-decides-who-starts-a-ship-not-how-it-lands.md) | lifecycle / shipping / project settings |
|
|
491
491
|
| 0370 | [**A repo we create for a new project is private** ([task 1004645](https://cloudbongos.com/builders#/task/1004645), goal 1000106). Supersedes ADR 0155 Decision 3: `createUserRepo` sends `private: true`, still not a parameter, and the wizard says the new repo is private. Safe because ADR 0176 already gives a private repo its own read-only deploy key before the first pull; the owner can make it public from the manage page.](0370-a-repo-we-create-is-private.md) | onboarding / security / github |
|
|
492
492
|
| 0371 | [**Auto-pickup applies a submitted tweak on the runner, and the artist still approves** ([task 1004330](https://cloudbongos.com/builders#/task/1004330), goal 1000095, BV2.TW19). **D1:** a tweak lane of the Autobongos runner (ADR 0307), not a write-capable agent: the agents spawn is read-only by construction. **D2:** the trigger is the runner's ledger poll of the oldest `submitted` round, no new event. **D3:** off until a `tweak.autopickup` project setting turns it on; it replaces only the fence's goal allowlist. **D4:** runs as the runner's Metic+ builder, no service principal. **D5:** model time is the runner owner's; grades are the project's, under a monthly round cap (default 20) counted from the ledger. **D6:** the held pass still waits for the artist; two automatic applies per round, then a person; a failed apply waits for the round to change. **D7:** protected-path and host checks run on the page's files. **D8:** `/tweak --unattended`. **D9:** "applied automatically" is shown. Build tasks 1004677–1004681.](0371-auto-pickup-applies-a-submitted-tweak-on-the-runner.md) | copy-desk / autonomy / tweak mode |
|
|
493
|
+
| 0372 | [**An ask is stored per docket matter, and the server refuses slop** ([task 1004703](https://cloudbongos.com/builders#/task/1004703), goal 1000111). **D1:** one `government_asks` row per docket matter id (`blockers:12`), attached by the docket to the matters a viewer sees. **D2:** `checkAsk` refuses a slop ask with 400 `ask_refused`, every fix named in plain words; the table's CHECKs are the floor. **D3:** the hall's `askFormat` and the server's rules are held to one verdict by a parity test. **D4:** the long text rides along as detail. **D5:** written by `POST /blockers` (optional `ask`) and `PUT /government/asks/:matter` under the docket's per-source gate; `POST /government/asks/check` is the dry run. **D6:** the deck draws a stored ask as real; routing its seat is task 1004705.](0372-an-ask-is-stored-per-docket-matter-and-the-server-refuses-slop.md) | government / asks / docket |
|
|
494
|
+
| 0373 | [**An AI session files a blocker with an ask, and checks the card first** ([task 1004704](https://cloudbongos.com/builders#/task/1004704), goal 1000111). **D1:** `POST /blockers` from a CLI session without an `ask` answers 400 `ask_required`; the hall's web form is unchanged. **D2:** the exemption is an allow-list of the templated scripts' sources (`no-artifact-close`, `artifact-audit`, `autobongos`), so `task`, `manual` and unknown sources are held. **D3:** those scripts send a card too, checked first, and re-file without it if it is refused. **D4:** `scripts/gds/ask.js` `template` / `check` is the rewrite loop and prints the card to paste for asks that are not stored matters. **D5:** the Conductor reminds; the server enforces.](0373-an-ai-session-files-a-blocker-with-an-ask.md) | government / asks / agents |
|
|
495
|
+
| 0374 | [**A building's Lead is a held position, appointed and removed by a People matter** ([task 1004709](https://cloudbongos.com/builders#/task/1004709), goal 1000111). **D1:** one `government_leads` row per appointment, at most one in office per building, a one-line charter. **D2:** only a passed People matter (`appoint_lead`, `remove_lead`) writes it; the trigger refuses everything else. **D3:** where People decides as today, a Lead matter sits under the board in force. **D4:** `answerFor`: a building's Lead, or the owner seat (every active Archon) when unseated; `GET /government/leads` reads it. **D5:** the hall draws the real Lead and drops the overlay's invented ones; routing stays task 1004705.](0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md) | government / leads / city |
|
|
496
|
+
| 0375 | [**Who may build without a vote comes from the form of government** ([task 1004710](https://cloudbongos.com/builders#/task/1004710), goal 1000111). Owner ruling: not a per-Lead flag. **D1:** one pure rule, `build-rights.js`: a district is always a vote; a vacant building builds nothing; a goal limit is a vote; a building's own sitting decides (`decide`/`first` let a seated holder build at once); a goal grant is at once; otherwise the form: Monarchy at once, Timocratic Republic at once if the holder sits on the board, Direct Democracy / Foundation / Custom a vote. **D2:** the form is read from the constitution's settings. **D3:** it is about the building's holder (Lead or owner seat). **D4:** resolved per request, uncached, fail closed; `GET /government/leads` carries `build_rights`. **D5:** a goals hook, empty today. **D6:** the hall reads the answer and holds no rule; the overlay's `can_build_without_vote` is gone.](0375-who-may-build-without-a-vote-comes-from-the-form-of-government.md) | government / leads / city |
|
|
497
|
+
| 0376 | [**Every ask is routed to a real seat on the server** ([task 1004705](https://cloudbongos.com/builders#/task/1004705), goal 1000111). **D1:** `routing.js` decides per matter and viewer; the docket carries `route` on every matter, `routed`, `counts.yours`, and a line that counts only what is yours. **D2:** the stored ask's seat, else the building's Lead (or a sitting's voters); unseated falls to the owner; a board seat to its holders; a committee to the Lead. **D3:** an ask past its deadline or on an empty seat is on nobody's to do and carries its own "if nobody answers" line. **D4:** `POST /government/asks/:matter/pass` hands a stored ask on, only by whoever it waits on, never a vote. **D5:** the hall reads `yours`; `countsOf` stays the one count.](0376-every-ask-is-routed-to-a-real-seat-on-the-server.md) | government / asks / docket |
|
|
498
|
+
| 0377 | [**Governance is a held position, read on /me** ([task 1004713](https://cloudbongos.com/builders#/task/1004713), goal 1000111). **D1:** `positions.js` folds a builder's seats (owner, Lead, a building's sitting, the board) from `routing.resolveSeat` and `isBoardMember`, no second rule. **D2:** `GET /me` carries `positions`, per request, uncached; null is unknown. **D3:** the hall only reads it: no seat, no governance tab; a Lead's Governing mode is named by the seat.](0377-governance-is-a-held-position-read-on-me.md) | government / hall |
|
|
499
|
+
| 0378 | [**A Lead's build-outs are rows on the record, built at once or by a passed vote** ([task 1004711](https://cloudbongos.com/builders#/task/1004711), goal 1000111). **D1:** `government_buildouts` (government_030): one row per committee room, floor, annex or district, never edited. **D2:** `POST /government/buildouts`: only the building's holder; build-rights says at once (written now, with its ground) or a vote (a `build_out` matter through `openMatter`). **D3:** the vote sits under the board unless the building has its own sitting; a district and the Charter always the board. **D4:** a passed vote builds once; the trigger refuses anything else. **D5:** `GET /government/leads` carries each building's `structure`. **D6:** the hall draws the real site, ghost and tally, and the vote picture from the real building.](0378-a-leads-build-outs-are-rows-built-at-once-or-by-a-passed-vote.md) | government / leads / city |
|
|
500
|
+
| 0379 | [**The treasury is pots per goal, a reserve, and borrowing, over real spend** ([task 1004712](https://cloudbongos.com/builders#/task/1004712), goal 1000111). **D1:** spend is cost_log through each task's goal, this month, read every time. **D2:** a pot is a budget the Treasury's holder gives a goal (`government_pots`, government_031). **D3:** the reserve is last month's spend no pot was given, less loans; it may be overdrawn. **D4:** a dry pot files a borrow (poller), its ask stored on `treasury_spending:<id>` and routed to the Treasury. **D5:** answered once (lend, half, no) by its seat. **D6:** the spend cap is a project setting, off by default. **D7:** the docket source and the hall's pots, reserve, beacon and book are real.](0379-the-treasury-is-pots-per-goal-a-reserve-and-borrowing-over-real-spend.md) | government / treasury / city |
|
|
501
|
+
| 0380 | [**A strictness preset is a bundle of laws, switched by one laws vote and read from the laws in force** ([task 1004715](https://cloudbongos.com/builders#/task/1004715), goal 1000111). **D1:** Open workshop, Guild, Factory are catalogues of laws in `presets.js`; every lock names a stored personal setting. **D2:** a switch is ONE laws amendment through `board.proposeLaws` (`POST /government/board/presets`); only its passing writes. **D3:** the preset in force is read from the laws in force, never stored; nothing is seeded. **D4:** `GET /government/presets` says what each would lock; My agents and the Charter are real.](0380-a-strictness-preset-is-a-bundle-of-laws-switched-by-one-laws-vote.md) | government / laws / my agents |
|