@bongos/core 1.19.321 → 1.19.323

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 CHANGED
@@ -2,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.321",
6
- "core_contract": "1.19.321",
7
- "source_commit": "242735e2b39608c5500b8c5bd231832a90c5fae7",
5
+ "core_version": "1.19.323",
6
+ "core_contract": "1.19.323",
7
+ "source_commit": "6b1fb52bfb9b8d899ffc44c0b8a22fd08cab9379",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-24T01:17:55.486Z",
9
+ "built_at": "2026-08-24T01:33:26.263Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 323,
12
+ "docs_redacted": 324,
13
13
  "agent_docs_stubbed": 22,
14
- "functional_verbatim": 1455,
14
+ "functional_verbatim": 1457,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1800,
20
- "tree_sha256": "5d80f6db5c26850188eb0c3f5ace7c42ff85561d277dc525e24f46cdcf52dee8",
19
+ "file_count": 1803,
20
+ "tree_sha256": "6534c0e9c341ea8d670e2f26984693052bc41041c70f99e671d5abd7ca3448dc",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -367,7 +367,7 @@
367
367
  {
368
368
  "path": "clients/bongos-client/index.d.ts",
369
369
  "mode": "0000644",
370
- "sha256": "85041b30fb2113ca5b3684ae961e67dc2bd5dfdb152064b151af3f0a93a29f31"
370
+ "sha256": "356ef6ee04671774868423f5312cedd2ae194f1f4abcdcaaac01828b044c1c14"
371
371
  },
372
372
  {
373
373
  "path": "clients/bongos-client/index.mjs",
@@ -1409,20 +1409,25 @@
1409
1409
  "mode": "0000644",
1410
1410
  "sha256": "51931fe5ae89b14b6c8955e6d6cd43d88a7a6ed05f8c862cdfe56a14302cc990"
1411
1411
  },
1412
+ {
1413
+ "path": "docs/adr/0186-per-project-idea-templates.md",
1414
+ "mode": "0000644",
1415
+ "sha256": "749040f16b59cc1cd1c49ca40453fed838f31b36af8c8eed2b5de7db00ddb0d0"
1416
+ },
1412
1417
  {
1413
1418
  "path": "docs/adr/README.md",
1414
1419
  "mode": "0000644",
1415
- "sha256": "96f12718ea595a8fff3d3aeafc27013b4ef251724e80d077607addc167533639"
1420
+ "sha256": "c5af7723dbcc0e4a62a897153b1fa1cf34962a1f8ed72fc7bf9681ba074dab6a"
1416
1421
  },
1417
1422
  {
1418
1423
  "path": "docs/api-reference.md",
1419
1424
  "mode": "0000644",
1420
- "sha256": "a654d9def4780d3210c66031193198f58fd0d7d84f5088c4ce7e6d0a58682193"
1425
+ "sha256": "25a1978be80e817a5a9b54609aaa52dc0e172c941110183b9cfc93d193430f0b"
1421
1426
  },
1422
1427
  {
1423
1428
  "path": "docs/api/openapi.json",
1424
1429
  "mode": "0000644",
1425
- "sha256": "e0b531f19187a3c00a54917bff4e2827a75b250f1aaa761229660a974a4f6217"
1430
+ "sha256": "1cbc9af7fe828c5c81e6348a1a219b53ab484f9df67ec9ccb41e6f6cdef1693e"
1426
1431
  },
1427
1432
  {
1428
1433
  "path": "docs/architecture.md",
@@ -1447,12 +1452,12 @@
1447
1452
  {
1448
1453
  "path": "docs/copy-inventory.md",
1449
1454
  "mode": "0000644",
1450
- "sha256": "265f46593fe663dc38aa7980b0eacde8e6ab001b75301c5d0e38f1c1887d0e11"
1455
+ "sha256": "9b667d64d98c00a5a0d5991f3f69a783d82f8368719f50610d7514fff4d8ebe7"
1451
1456
  },
1452
1457
  {
1453
1458
  "path": "docs/copy-registry.json",
1454
1459
  "mode": "0000644",
1455
- "sha256": "e2e2af87ad6c8023e6b7399caac2372f08a87f41239873e83dbff39ac2fe1855"
1460
+ "sha256": "039628f57cb1bbda153b4450053cb9ca10e9eb7bad9c950854250139ac810c4a"
1456
1461
  },
1457
1462
  {
1458
1463
  "path": "docs/design-contract.md",
@@ -2454,6 +2459,11 @@
2454
2459
  "mode": "0000644",
2455
2460
  "sha256": "8fc38c0353811699e19d861321d4fca8fe8fd5cca1f66ff96312d7f44fb0290e"
2456
2461
  },
2462
+ {
2463
+ "path": "migrations/core_224_goal_subtitle.sql",
2464
+ "mode": "0000644",
2465
+ "sha256": "a379e9f926274559d8c57c9127024463e38b99e3f73962022b9f5d0f4e156a57"
2466
+ },
2457
2467
  {
2458
2468
  "path": "modules/autonomy/CLAUDE.md",
2459
2469
  "mode": "0000644",
@@ -3412,22 +3422,22 @@
3412
3422
  {
3413
3423
  "path": "modules/hall-ui/public/goals-lib.js",
3414
3424
  "mode": "0000644",
3415
- "sha256": "b899d1245f1138bf0e82115b80664eaa68ed2601c940bb0848ce2b784866d3e3"
3425
+ "sha256": "a7a0385c3c8026e6b21ac5793bdf5b48fa31968f176ebe891c43ad5c867df1c8"
3416
3426
  },
3417
3427
  {
3418
3428
  "path": "modules/hall-ui/public/goals-page.js",
3419
3429
  "mode": "0000644",
3420
- "sha256": "472483a2a5c8d5a2d033e630de2c24025dcbc7d7fc40017f64ea0d18f830e3a0"
3430
+ "sha256": "969aee56c6ec869a04d6e01752b24109114bd10e061c4a16fb8c7fa050671f47"
3421
3431
  },
3422
3432
  {
3423
3433
  "path": "modules/hall-ui/public/goals.css",
3424
3434
  "mode": "0000644",
3425
- "sha256": "ef69c360f46f508b1e987d8e9e523ed8708b7c74f48b6069103fae14ccc710f9"
3435
+ "sha256": "4ebae2d1b12a4a6a196e510dc034e2534ca0429e516292babdcb04917188c004"
3426
3436
  },
3427
3437
  {
3428
3438
  "path": "modules/hall-ui/public/goals.html",
3429
3439
  "mode": "0000644",
3430
- "sha256": "a9a6a23f60abba6072114db729691714819fefd316d42441462653e44eeab27b"
3440
+ "sha256": "f3656a4952d581c902c91c267a576193a91e60617b45745c879157e9cc8e702e"
3431
3441
  },
3432
3442
  {
3433
3443
  "path": "modules/hall-ui/public/goals.js",
@@ -3847,7 +3857,7 @@
3847
3857
  {
3848
3858
  "path": "modules/lifecycle/db-goals.js",
3849
3859
  "mode": "0000644",
3850
- "sha256": "29b950000d31618de168c6128d9b78c03daad7e68b9a9b6d3e83aa40abd3d9fb"
3860
+ "sha256": "b9d1768f8e271ad5c3595728f2433c27f44c841ab1c6be7d24086d1f6c8c7691"
3851
3861
  },
3852
3862
  {
3853
3863
  "path": "modules/lifecycle/db-grade.js",
@@ -3927,7 +3937,7 @@
3927
3937
  {
3928
3938
  "path": "modules/lifecycle/goal-edits.js",
3929
3939
  "mode": "0000644",
3930
- "sha256": "0367f88aefa890d8d7f2472dd847467d632150a93db8a96b85717b5fb1cc8c9e"
3940
+ "sha256": "7115a27272fe2594b65e2e56a796f5bf97600cb94ba301bc21599c6bc4e60175"
3931
3941
  },
3932
3942
  {
3933
3943
  "path": "modules/lifecycle/goal-suggest.js",
@@ -4002,7 +4012,7 @@
4002
4012
  {
4003
4013
  "path": "modules/lifecycle/routes/goals.js",
4004
4014
  "mode": "0000644",
4005
- "sha256": "3fcc0339927bcc7f426e93c7a5762b45496ecf4e9b841f905fb5f1c468b5f8c0"
4015
+ "sha256": "a58f01647120ce0b1143314f5edab2501bc18b8a748073dac788c92aaa0484ca"
4006
4016
  },
4007
4017
  {
4008
4018
  "path": "modules/lifecycle/routes/lifecycle.js",
@@ -4642,12 +4652,12 @@
4642
4652
  {
4643
4653
  "path": "package-lock.json",
4644
4654
  "mode": "0000644",
4645
- "sha256": "6f62185348f89cc7ae1c8998a25d4bdccb2e204ad81581555686f37057db1511"
4655
+ "sha256": "670e665f41fbb4d1c4154b2e2a08dcb64383583a8162188101dd0807ae849caa"
4646
4656
  },
4647
4657
  {
4648
4658
  "path": "package.json",
4649
4659
  "mode": "0000644",
4650
- "sha256": "3ba87e851af1bf1ad2a08cb62d4c875be12d7ec6d86ffda9e5b26e24fee313ae"
4660
+ "sha256": "27ab832e2bac7f7baac4016571d5536ac884b4b0f125a4b6f6a2dbae9b73112f"
4651
4661
  },
4652
4662
  {
4653
4663
  "path": "public-docs/index.html",
@@ -6417,7 +6427,7 @@
6417
6427
  {
6418
6428
  "path": "src/module-api.js",
6419
6429
  "mode": "0000644",
6420
- "sha256": "31c5e453080859713ed00c327a6b1fb1a022d2509438523979bad2e0e8feb7bf"
6430
+ "sha256": "8624156a5587eaca3430325ef66420fb96b9567ed19af27dce361dc8af08611f"
6421
6431
  },
6422
6432
  {
6423
6433
  "path": "src/module-loader/catalog.js",
@@ -7399,6 +7409,11 @@
7399
7409
  "mode": "0000644",
7400
7410
  "sha256": "447e6376ae5f5e2bedf1a80b3355604544a5e349da87d110fc0135cc3cd98fac"
7401
7411
  },
7412
+ {
7413
+ "path": "tests/goal_subtitle.mjs",
7414
+ "mode": "0000644",
7415
+ "sha256": "4505dbeaafba7e7ca716d693864bea3246b4fe8767386bf0c7f3d48c41030db1"
7416
+ },
7402
7417
  {
7403
7418
  "path": "tests/goal_suggest.mjs",
7404
7419
  "mode": "0000644",
@@ -7407,7 +7422,7 @@
7407
7422
  {
7408
7423
  "path": "tests/goal_tier.mjs",
7409
7424
  "mode": "0000644",
7410
- "sha256": "00539cd1b188def53c67aab06301971132fbbe0bcd47818c19763ed760aaccda"
7425
+ "sha256": "e6a3114339989123d20f42f120f9fed52690fbc0230b10a99fa1fd0453acbfd2"
7411
7426
  },
7412
7427
  {
7413
7428
  "path": "tests/goal_wall_proof.mjs",
@@ -238,7 +238,7 @@ export interface PostGoalsIdTransferRequest { builder_id?: StringifiableId }
238
238
  export interface PostGoalsIdTransferResponse { ok: boolean; goal: unknown; changed: boolean }
239
239
  export interface PostGoalsReorderRequest { version_id: string; ordered_ids: number[] }
240
240
  export interface PostGoalsReorderResponse { ok: boolean; goals: unknown }
241
- export interface PostGoalsRequest { version_id: string; title: string; description?: string; scope_modules?: string[]; succeeds_goal_id?: number }
241
+ export interface PostGoalsRequest { version_id: string; title: string; subtitle?: string; description?: string; scope_modules?: string[]; succeeds_goal_id?: number }
242
242
  export interface PostGoalsResponse { ok: boolean; goal: unknown; succeeds_goal_id: unknown }
243
243
  export interface PostGovernmentAssignmentsRequest { builder_id: number; rank_key: string }
244
244
  export interface PostGovernmentBoardItemsItemIdVotesRequest { direction: string; reason_md?: string; section_key?: string }
@@ -0,0 +1,146 @@
1
+ # 0186 — Per-project idea templates: the seam is already built; the economics are the open problem
2
+
3
+ - **Status:** Accepted (spike outcome — decisions below; no implementation in this task)
4
+ - **Date:** 2026-08-23
5
+ - **Tasks:** [#1002932](https://cloudbongos.com/builders#/task/1002932) (BV1.R156, goal 1000062 — three grades of idea). Spike output: this ADR plus the downstream task list in §7. Gates criterion `abi-full-idea-base-template`.
6
+ - **Builds on:** [ADR 0172](<redacted>.md) (the ideator credit lane), [ADR 0185](<redacted>.md) (the 70/30 split), [ADR 0083](<redacted>.md) (module boundary + module-owned migrations)
7
+ - **Related:** R141 (`modules/ideas/templates.js` — the template declaration), R142 (`modules/ideas/completeness.js` — the deterministic scorer)
8
+
9
+ ## 1. Context
10
+
11
+ The owner's philosophy for this platform, recorded on goal 1000062: **the best
12
+ possible simple base, already designed to be altered.** R141 shipped `base-v1` —
13
+ five fields, declared as data — and R142 shipped a scorer that walks that
14
+ declaration rather than hard-coding five names. This spike asks the question those
15
+ two deliberately deferred: *how does a project founder define their own idea
16
+ shape — different fields, different weights — without a schema change and without
17
+ forking the scorer?*
18
+
19
+ ## 2. The finding that matters: the seam is already there
20
+
21
+ The answer to the literal question is short, because R141 built for it:
22
+
23
+ - **Every template function already takes an optional `registry`**
24
+ (`templateFor`, `validateFieldValues`, `fieldOrder`, `scoreFieldValues`),
25
+ defaulting to `BUILTIN_TEMPLATES`. Validation and scoring both read the
26
+ declaration as data. Swapping the registry changes what both accept with no
27
+ code change in either consumer, and `tests/idea_templates.mjs` already proves
28
+ it by injecting a different registry.
29
+ - **The store is already project-ready.** `ideas_grades.template_key` is per-row
30
+ with `CHECK (template_key ~ '^[a-z][a-z0-9-]*$' AND length <= 64)` — its own
31
+ migration comment says a project-defined key "stays addressable".
32
+ - **A per-project settings home already exists**: `provisioning_instances.settings
33
+ jsonb NOT NULL DEFAULT '{}'` (provisioning_009).
34
+
35
+ So: **no schema change is required, and the scorer does not need forking.** That
36
+ part of the task's question is answered by work already shipped. What the spike
37
+ actually found is a different problem, in §4.
38
+
39
+ ## 3. Decision A — where a project template comes from
40
+
41
+ A new **`project-settings` kernel port**, the sibling of the existing
42
+ `builder-settings` port, reading `provisioning_instances.settings` under a
43
+ namespaced key (`settings.ideas.templates`).
44
+
45
+ - The `ideas` module resolves it with `resolveOptional`, so a vanilla instance
46
+ with no `provisioning` module **degrades to the built-in registry** rather than
47
+ failing — the same graceful posture `lifecycle` takes toward `reward` and
48
+ `onboarding` (ADR 0093 §2).
49
+ - `base-v1` remains the default and the **fallback for any row whose
50
+ `template_key` does not resolve**. An unresolvable key already renders raw
51
+ rather than throwing (`templateFor` returns null by design, after the R143
52
+ prototype-pollution fix); that behaviour is kept.
53
+
54
+ **Rejected:** a new `ideas_templates` table (a second home for a thing that
55
+ already has one, and a module-owned table for data the project owner edits in
56
+ project settings); a config file (`config/idea-templates.json` is per-*instance*,
57
+ and one instance hosts many projects — wrong granularity).
58
+
59
+ **Boundary note, load-bearing for whoever implements it:** goal 1000062's
60
+ `scope_modules` is `['ideas','hall-ui']`. The port lives in `provisioning` +
61
+ kernel, which is **outside this goal's scope wall**. The port task therefore
62
+ cannot be claimed under goal 1000062 — see §7 T1.
63
+
64
+ ## 4. Decision B — the economic lever (the real finding)
65
+
66
+ Completeness is normalised **0–100 within its own template**: the scorer takes the
67
+ mean of per-field ratios and multiplies by 100. Karma reads that relative number
68
+ against an absolute bar — `IDEA_FULL_PASS_BAR = 60`, `IDEA_FULL_PASS_CREDIT = 5`.
69
+
70
+ Those two facts together mean **template choice becomes a credit-minting lever**:
71
+
72
+ | Template | Required text for a passing score | Credits |
73
+ |---|---|---|
74
+ | `base-v1` (5 fields × substanceMin 40) | ~200 characters of real content | 5 |
75
+ | a project template: 1 field, substanceMin 10 | ~10 characters | 5 |
76
+
77
+ A ~20× arbitrage, available to any project that can define its own shape — and
78
+ per-project templates are exactly what this ADR enables. Shipping Decision A
79
+ without addressing this would make the feature a way to print credits.
80
+
81
+ **Decision:** separate the two questions the single number is currently answering.
82
+
83
+ - **Completeness stays relative** and keeps its present meaning: *did you fill in
84
+ YOUR project's form.* That is the right signal for triage ordering (R148) and
85
+ the hall's live meter (R152), and it must stay comparable within a project.
86
+ - **Karma stops reading it.** Credit eligibility reads an **absolute substance
87
+ total** instead — which the scorer already computes per field (`fields[].substance`)
88
+ and currently discards after averaging. No new measurement is needed; the number
89
+ is there.
90
+
91
+ **Rejected:** making completeness itself absolute (it would break the meter and
92
+ the ordering, which want "how complete is this form"); leaving karma relative and
93
+ policing templates by review (unenforceable, and the platform should not depend on
94
+ someone noticing).
95
+
96
+ **Interim guard**, cheap and shippable before the karma change: a project template
97
+ is karma-eligible only if it declares **≥3 required fields and ≥120 total
98
+ `substanceMin`**. This does not fix the arbitrage, it bounds it — and it is worth
99
+ having on day one because it is a data check, not an economics change.
100
+
101
+ ## 5. Decision C — per-field weights
102
+
103
+ The task asks for "different fields, different weights". Today the scorer is an
104
+ **unweighted** mean (`fields.reduce((s,f) => s + f.ratio, 0) / fields.length`).
105
+
106
+ **Decision:** an optional `weight` on the field declaration, default `1`, and a
107
+ weighted mean in the scorer. Today's behaviour is the special case where every
108
+ weight is 1, so this is a pure data addition with one arithmetic line changed and
109
+ no migration. Weights are declared alongside `substanceMin`, which keeps the whole
110
+ shape of a template in one declaration.
111
+
112
+ ## 6. Decision D — do the five base fields stay mandatory?
113
+
114
+ **No.** A project may define any shape; forcing the five would make "define your
115
+ own" cosmetic, and the base fields are the owner's wording for *this* project's
116
+ concerns, not universal truths.
117
+
118
+ Two constraints stand in their place:
119
+
120
+ 1. **A template must declare at least one required field.** A template with none
121
+ makes completeness vacuous (an empty submission scores 100).
122
+ 2. **A stored template is validated at write time**, so a malformed registry is
123
+ refused when the project saves it — not discovered later inside the capture
124
+ path, which must never throw (R142's hard requirement).
125
+
126
+ ## 7. Downstream tasks (the spike's other output)
127
+
128
+ | # | Task | Scope / goal note |
129
+ |---|---|---|
130
+ | T1 | `project-settings` kernel port, sibling of `builder-settings`, reading `provisioning_instances.settings` | `provisioning` + kernel — **outside goal 1000062's wall**; needs a goal whose scope covers it |
131
+ | T2 | `ideas` resolves that port and merges the project registry over the built-in; `resolveOptional`, degrading to built-in | `ideas` — in this goal's wall |
132
+ | T3 | Optional per-field `weight` (default 1) + weighted mean in the scorer | `ideas` |
133
+ | T4 | Karma eligibility reads an absolute substance total, not the relative completeness score | `economy` — outside this goal's wall |
134
+ | T5 | Interim guard: a project template is karma-eligible only at ≥3 required fields and ≥120 total `substanceMin` | `ideas` |
135
+ | T6 | Write-time validation of a stored project template | `ideas` (+ wherever project settings are saved) |
136
+
137
+ T1 → T2 is the ordering dependency; T3, T5, T6 are independent. **T4 is the one
138
+ that must not be skipped** — T5 bounds the arbitrage, only T4 removes it.
139
+
140
+ ## 8. What this ADR deliberately does not do
141
+
142
+ No customization UI, per the task's own instruction ("Do not build the
143
+ customization UI from this task"). No implementation of any row above. The spike's
144
+ deliverable is this decision record plus §7, and the reason the platform builds
145
+ the seam before the surface is ADR 0062 §7's core↔host split: the core ships the
146
+ mechanism, the host supplies the content.
@@ -259,5 +259,6 @@ This keeps the decision history honest and traceable.
259
259
  | 0183 | [**A done-when criterion closes itself; the review queue becomes a place to look** ([task 1002069](https://cloudbongos.com/builders#/task/1002069), goal 1000072, owner request 2026-07-05). ADR 0086 §6 made `satisfied` reachable exactly one way — a Metic+ calling `POST /done-when/:id/satisfy` — even though the signal it gated on is unambiguous (**every** gating task shipped) and a human confirming it adds no information. When nobody runs `/goal-review` the result is not a careful pause but a **lying board**: this session measured goal 1000072 at `6/9 shipped, 0/5 criteria`. Now one helper, `doneWhen.autoSatisfyShippedCriteria(exec, {taskId})`, runs from **two** places for two different reasons — inside `shipTask`'s txn (scoped, **immediate**, on the txn client so a rolled-back ship cannot leave a goal achieved) and unscoped on every `publish-reconciler` tick (**backlog drain** for criteria whose tasks shipped before this existed, since nothing will ship against them again, plus **self-heal**). Idempotent by construction — it reads only `satisfied=false` rows — which is what makes an every-tick sweep safe. **The load-bearing subtlety is the delivery guard.** Auto-close needs BOTH "nothing still pending" AND **≥ 1 task actually `shipped`**; the second is not redundant, because since [task 1002651](https://cloudbongos.com/builders#/task/1002651) made `abandoned` terminal-not-pending, a criterion whose tasks were **all cut** satisfies the first clause *vacuously* and would auto-close on ZERO delivered work, cascading its goal to `achieved` (measured: `buildCriterionProgress` returns `pending_review:true` for exactly that shape). Yet `pending_review` **keeps** that wider meaning on purpose — it asks "should a human LOOK at this", and 1002651 chose that an all-abandoned criterion surfaces so someone decides whether it still means anything. So: everything that auto-closes was flagged; not everything flagged auto-closes. An earlier draft "aligned" the two predicates and broke that intent — `tests/criterion_progress.mjs` caught it; **do not re-align them**, the gap is the design. `/goal-review` is kept, demoted from gate to viewing surface; manual `POST /satisfy` stays for what automation cannot judge (a criterion with no linked tasks never auto-closes). Honest limits recorded: auto-satisfy cannot help a criterion nothing is LINKED to, and the in-txn close logs before commit (accepted — threading the summary out through `withTx` would cost ~5 lines in the over-threshold `db.js` under shrink-only ratchet policy). Rejected: sweep-only (up to 5 min to see your own goal close), hook-only (never drains the backlog), a stored `pending_review` column (second source of truth), deleting `/goal-review`.](<redacted>.md) | lifecycle / goal tier |
260
260
  | 0184 | [**A ship must account for itself: `shipTask` requires a land proof or a declared no-artifact** ([task 1002483](https://cloudbongos.com/builders#/task/1002483), goal 1000024). `db.shipTask` is the confirmed→shipped flip and, since [ADR 0120](<redacted>.md), where the CREDIT is booked — yet its only precondition was `WHERE status = 'confirmed'`, nothing about whether code reached main. The two AUTOMATED paths each proved the land first; the MANUAL route passed nothing, so a task confirmed with no pushed code could be shipped by its claim holder **or by any Metic+ sweeping `/merge-mode`**, booking its `task.shipped` credit. It stayed untracked for two months because its tracking task was closed in June asserting task 1001547 had delivered the gate — it had not, blocker 1000047's own final update says so, and the code agreed with the blocker rather than the closure note: **a hole hidden by a record nobody checked**, which is the same failure the gate is about. Decision: the gate lives at the WRITE, not the route (a route gate leaves the invariant unenforced at the layer that moves the ledger, so the next caller reopens it silently), and `shipTask` is FAIL-CLOSED on a required `landAssurance`. TWO kinds, and the second is why this does not make things worse: `proof` (this task's commit is on main) and **`no_artifact`** — a deliberate DB-only ship, an explicitly supported shape (CLAUDE.md "Direct DB writes are work too") that [task 1002478](https://cloudbongos.com/builders#/task/1002478) documents as a dead end below Archon. A naive proof-only gate would have made 1002478 strictly worse; naming no-artifact as a KIND turns it from an absence the gate must be talked out of into a recorded answer. Both carry a reason, audited post-commit and best-effort (an audit miss must never roll back a landed ship). `ship.js` now declares its own `--db-only`/`--allow-empty` lands, without which this fix would have regressed the very flow CLAUDE.md calls supported. Rejected: (b) gate only the route — leaves the write unguarded; (c) record the residual as tolerable — defensible on blast radius and genuinely close, but it would have been the FOURTH record asserting this was handled with nothing checkable behind it. Does NOT gate confirm: a codeless confirm is still accepted, it simply cannot reach `shipped` or pay.](<redacted>.md) | lifecycle / integrity |
261
261
  | 0185 | [**The spark-handoff credit split: 70% developer, 30% spark author** ([task 1002923](https://cloudbongos.com/builders#/task/1002923), BV1.R147, goal 1000062 — completing the chain [task 1002920](https://cloudbongos.com/builders#/task/1002920) mark → [task 1002921](https://cloudbongos.com/builders#/task/1002921) queue → [task 1002922](https://cloudbongos.com/builders#/task/1002922) pickup). [ADR 0172](<redacted>.md) built the ideator streams and paid `captured_by`, the only person an idea then had. The spark handoff created a second: R146 develops a spark IN PLACE, preserving the author while recording a `developed_by`. **R146 therefore shipped paying NOTHING on purpose** — not an oversight but a refusal to guess, because `awardIdeaFullPassCredit`'s idempotency predicate is `(builder_id, reason)`, so paying the DEVELOPER would not have blocked a later payment to the AUTHOR and one idea would have paid twice; the cost of that caution was that a developed Full Idea received stream 2 **never** unless its author resubmitted. Owner decision (2026-08-22): **70/30 favouring the developer**, on BOTH existing streams, one ratio so there is one rule to explain. The reasoning is behavioural, not sentimental — developing someone else's spark is the scarce act the queue depends on, and at an even split it pays HALF what authoring your own Full Idea pays for the same writing work, so the rational move is always to write your own and the R145 queue stays a list nobody reads. The author keeps 30% plus their share of stream 1 on every task shipped under the idea, forever. `IDEA_DEVELOPER_SHARE = 0.70` is a **policy constant in `credits.js`** beside the pass bar and quick factor (ADR 0172's own consequence, the ADR 0023 precedent): a share of someone's earnings deserves a review and a commit, not a runtime edit. **The structural half is what retires R146's caution:** the economy module now derives the payees itself (`ideaCreditParties` reads `captured_by` + `developed_by`), so the caller can no longer choose a recipient — the develop route hands over an idea and a score, never a payee, and books the split like any other path (fail-open; the development has already committed). Three arithmetic properties, each a real bug if missed: the total is **conserved** (developer rounded, author gets the REMAINDER — rounding both pays 6 out of a 5-credit payout); a **self-developed** idea collapses to ONE payee, because two rows for one builder would silently UNDER-pay under the per-builder idempotency predicate, not double-pay (the comparison normalises via `String()` since `bigint` arrives as a string, so a type mismatch cannot become a phantom payee); and **zero-value rows are dropped**. Ids otherwise pass through unconverted — `Number()`-ing a `bigint` risks precision. `builder_id` in the idempotency predicate, which entered as an index optimisation (the R143/IC2 grader finding), is now **load-bearing for correctness**: two payees share one `reason`, so a reason-only predicate would refuse the second, and a partially-booked split completes on the next call. **Not decided here:** stream 3's split (ships with the Board Room, task 1002999), and whether `origin='develop'` in `ideas_task_lineage` belongs to whoever promotes a DEVELOPED idea into a task — ADR 0172 §5 says the row is "set at promotion and at develop (R146)", but R146 creates no task, so that origin stays deliberately unwired rather than invented; it changes who stream 1 pays.](<redacted>.md) | economy / ideator lane |
262
+ | 0186 | [**Per-project idea templates: the seam is already built; the economics are the open problem** ([task 1002932](https://cloudbongos.com/builders#/task/1002932), BV1.R156, goal 1000062 — a SPIKE, output is this ADR plus a task list, no implementation). The literal question — how does a founder define their own idea shape without a schema change or forking the scorer — is **already answered by shipped work**: R141 gave every template function an optional `registry` defaulting to the built-in one, so validation and scoring both read the declaration as data; `ideas_grades.template_key` is per-row with a format CHECK whose own comment says a project key "stays addressable"; and `provisioning_instances.settings jsonb` is an existing per-project home. **No schema change, no fork.** Decision A: a **`project-settings` kernel port**, sibling of `builder-settings`, read via `resolveOptional` so a vanilla instance with no provisioning module degrades to the built-in registry; `base-v1` stays the default and the fallback for an unresolvable key. Rejected a new `ideas_templates` table (second home for data that has one) and a config file (per-instance, but one instance hosts many projects). **Decision B is the finding that matters.** Completeness is normalised 0–100 WITHIN its template (mean of per-field ratios), while karma reads it against an absolute bar (`IDEA_FULL_PASS_BAR = 60`, `IDEA_FULL_PASS_CREDIT = 5`) — so template choice becomes a credit-minting lever: `base-v1` needs ~200 characters for 5 credits, a 1-field template with `substanceMin` 10 needs ~10, a ~20× arbitrage handed to exactly the projects this ADR empowers. Shipping A without B would make the feature a way to print credits. The fix separates the two questions one number is answering: **completeness stays relative** (it is the right signal for triage ordering and the hall meter) and **karma stops reading it**, switching to an absolute substance total the scorer already computes per field and currently discards after averaging. An interim guard (≥3 required fields, ≥120 total `substanceMin`) bounds the arbitrage without fixing it. Decision C: an optional per-field `weight` (default 1) turning the unweighted mean into a weighted one — today's behaviour is the all-weights-1 case, so it is a data addition and one arithmetic line. Decision D: the five base fields are **not** mandatory (forcing them would make "define your own" cosmetic), replaced by two constraints — a template must declare ≥1 required field, and a stored template is validated at WRITE time so a malformed one is refused there rather than discovered inside the capture path, which must never throw. **Boundary note:** goal 1000062's wall is `[ideas, hall-ui]`, so the port task (provisioning + kernel) and the karma task (economy) cannot be claimed under it.](<redacted>.md) | ideas / templates |
262
263
 
263
264
  > ⚠️ **Numbering collision (known):** two ADRs share `0008`. The numbers were assigned in parallel sessions before the lock could be enforced. The files are kept under their existing filenames to preserve git history, but the table disambiguates them as `0008-a` / `0008-b`. New ADRs should resume at `0040` to avoid further collisions. (`0024` is also a real on-disk duplicate: the cloneable-repo/local-first-memory ADR and the multi-agent-system-architecture ADR were both numbered `0024` in parallel; both keep their filenames, disambiguated as `0024-a` / `0024-b` like `0008`. Likewise `0025` ended up with two on-disk files — the offsite-backup ADR and the structured-criterion↔task-link ADR — both kept under their existing filenames and disambiguated as `0025-a` / `0025-b`; separately, the BFG ADR had also claimed `0025` on 2026-05-30 and yielded to `0026`. A third happened 2026-06-06: `0036` was claimed in parallel by the builders-subdomain ADR ([#726](https://example.com/builders#/task/726)) and this Discord-channels ADR ([#727](https://example.com/builders#/task/727)); the Discord-channels ADR yielded to `0037`. A fourth landed 2026-06-10: `0044` was claimed in parallel by the palette-replacement ADR and the per-box game-preview ADR ([#897](https://example.com/builders#/task/897)); both keep their filenames, disambiguated as `0044-a` / `0044-b` like `0008`. A fifth was caught pre-land 2026-06-13: `0050` was claimed in parallel by the device-flow-admission ADR ([#1000](https://example.com/builders#/task/1000)) and the sandbox-for-everyone ADR ([#1001](https://example.com/builders#/task/1001)); the latter yielded to `0052` before merging, so there is no `0050` duplicate. A sixth was caught pre-land 2026-06-21: the tool-agnostic-design-layer ADR ([#1375](https://example.com/builders#/task/1375)) first collided at `0079` with the value-gated-autonomous-engagement ADR, then at `0080` with the llm-cache-api-transport ADR (both part of the 0075–0080 LLM-cost-reduction series, landed on `main` in parallel); it yielded to `0081` before merging, so there is no `0079`/`0080` design-layer duplicate. A seventh landed 2026-06-23: `0084` was claimed in parallel by the auto-derived-per-task-rank-floor ADR and the remove-default-spend-cap ADR (task 1499); the rank-floor ADR landed on `main` first, so the spend-cap ADR yielded to `0085`, leaving no `0084` duplicate. An eighth landed 2026-06-27: `0095` was claimed in parallel by the borrowed-memory-and-retrieval-concepts ADR (PR #459, landed first) and the cross-agent-context-management ADR ([#1651](https://example.com/builders#/task/1651), PR #460); both keep their filenames, disambiguated as `0095-a` / `0095-b` like `0008`. These two are companions — `0095-a` adopts the memory/retrieval concepts and explicitly defers the grep-vs-semantic question to `0095-b`.)
@@ -4316,7 +4316,7 @@
4316
4316
  "goals"
4317
4317
  ],
4318
4318
  "summary": "PATCH /goals/:id",
4319
- "description": "PATCH /goals/:id — correct a goal's own title/description (task 1003102). Handler + rationale + rank note: ../goal-edits.js. Pinned in route-rank-check.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
4319
+ "description": "PATCH /goals/:id — correct a goal's own title/subtitle/description (tasks 1003102, 1003224). Handler + rationale + rank note: ../goal-edits.js. Pinned in route-rank-check.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
4320
4320
  "x-rank": "any-builder",
4321
4321
  "x-source": "modules/lifecycle/routes/goals.js",
4322
4322
  "parameters": [
@@ -16983,6 +16983,10 @@
16983
16983
  "minLength": 1,
16984
16984
  "maxLength": 200
16985
16985
  },
16986
+ "subtitle": {
16987
+ "type": "string",
16988
+ "maxLength": 200
16989
+ },
16986
16990
  "description": {
16987
16991
  "type": "string",
16988
16992
  "maxLength": 50000
@@ -202,9 +202,9 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
202
202
  | Method | Path | Rank | Body | Description |
203
203
  |---|---|---|---|---|
204
204
  | GET | `/api/bongos/goals` | `any-builder` | — | GET /goals?version=&status= — list goals (read). |
205
- | POST | `/api/bongos/goals` | `metic+archon` | `version_id`, `title`, `description`, `scope_modules`, `succeeds_goal_id` | POST /goals — create a goal. |
205
+ | POST | `/api/bongos/goals` | `metic+archon` | `version_id`, `title`, `subtitle`, `description`, `scope_modules`, `succeeds_goal_id` | POST /goals — create a goal. |
206
206
  | GET | `/api/bongos/goals/:id` | `any-builder` | — | GET /goals/:id — one goal with its members + linked criteria (read). |
207
- | PATCH | `/api/bongos/goals/:id` | `any-builder` | — | PATCH /goals/:id — correct a goal's own title/description (task 1003102). |
207
+ | PATCH | `/api/bongos/goals/:id` | `any-builder` | — | PATCH /goals/:id — correct a goal's own title/subtitle/description (tasks 1003102, 1003224). |
208
208
  | POST | `/api/bongos/goals/:id/archive` | `metic+archon` | — | POST /goals/:id/archive — retire a goal (open\|achieved → archived). |
209
209
  | GET | `/api/bongos/goals/:id/conflicts` | `any-builder` | — | GET /goals/:id/conflicts — the server-side task-conflict view (task 1736). |
210
210
  | POST | `/api/bongos/goals/:id/conflicts/resolve` | `any-builder` | `action`, `note`, `touches`, `first_task_id`, `then_task_id`, `task_id` | POST /goals/:id/conflicts/resolve — the owner/manager resolution actions for a detected conflict (task 1736; authority model ADR 0106): s… |
@@ -4,13 +4,13 @@
4
4
  > Deterministic on a given tree — regenerate and commit rather than hand-editing.
5
5
  > Machine-readable twin: [`copy-registry.json`](copy-registry.json).
6
6
 
7
- **1379 strings** across 3 surfaces · 1224 distinct pieces of copy · 1379 certain, 0 heuristic · 125 shown in more than one place.
7
+ **1380 strings** across 3 surfaces · 1225 distinct pieces of copy · 1380 certain, 0 heuristic · 125 shown in more than one place.
8
8
 
9
9
  ## Surfaces
10
10
 
11
11
  | surface | lives at | files | strings |
12
12
  |---|---|---|---|
13
- | `builders-hall` | `modules/hall-ui/public` | 65 | 1095 |
13
+ | `builders-hall` | `modules/hall-ui/public` | 65 | 1096 |
14
14
  | `status-dashboard` | `modules/status-ui/public` | 4 | 98 |
15
15
  | `landing` | `public-landing` | 2 | 186 |
16
16
 
@@ -52,7 +52,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
52
52
  | `df38941b25a6` | 3x | Sign in with GitHub | public-landing/projects.html:525, public-landing/projects.html:583, public-landing/projects.html:692 |
53
53
  | `b2b399fdd6a4` | 3x | in progress | modules/hall-ui/public/goals-page.js:423, modules/hall-ui/public/roadmap.js:108, modules/hall-ui/public/roadmap.js:194 |
54
54
  | `cc5106af4b35` | 3x | {…} of {…} criteria satisfied | modules/hall-ui/public/goals-lib.js:30, modules/hall-ui/public/goals-page.js:1016, modules/hall-ui/public/goals.js:45 |
55
- | `7926e30955d2` | 3x | ← Back to goal | modules/hall-ui/public/goals.html:152, modules/hall-ui/public/goals.html:163, modules/hall-ui/public/goals.html:175 |
55
+ | `7926e30955d2` | 3x | ← Back to goal | modules/hall-ui/public/goals.html:160, modules/hall-ui/public/goals.html:171, modules/hall-ui/public/goals.html:183 |
56
56
  | `a8813c34d20d` | 2x | &ldquo;Host denied&rdquo; | modules/hall-ui/public/box-panel.js:160, modules/hall-ui/public/box-panel.js:340 |
57
57
  | `66cea7cefa4e` | 2x | '; for (const row of bodyRows) { html += ' | modules/hall-ui/public/md-reader.js:188, modules/hall-ui/public/primer.js:278 |
58
58
  | `87fa099f5068` | 2x | '; } html += ' | modules/hall-ui/public/md-reader.js:192, modules/hall-ui/public/primer.js:282 |
@@ -64,8 +64,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
64
64
  | `490b73a0c6e8` | 2x | Approve your Dev Box app — {{worldName}} | modules/hall-ui/public/pair.html:6, modules/hall-ui/public/pair.html:6 |
65
65
  | `b71a26e6fb37` | 2x | Archons only | modules/hall-ui/public/sessions.html:28, modules/hall-ui/public/watch.html:31 |
66
66
  | `08afb1257b71` | 2x | Back to home | modules/hall-ui/public/primer.html:68, modules/hall-ui/public/primer.js:516 |
67
- | `563d29ed86d8` | 2x | Bulk actions | modules/hall-ui/public/goals.html:140, modules/hall-ui/public/work.html:118 |
68
- | `46b33550d52b` | 2x | Bulk claim | modules/hall-ui/public/goals.html:143, modules/hall-ui/public/work.html:121 |
67
+ | `563d29ed86d8` | 2x | Bulk actions | modules/hall-ui/public/goals.html:148, modules/hall-ui/public/work.html:118 |
68
+ | `46b33550d52b` | 2x | Bulk claim | modules/hall-ui/public/goals.html:151, modules/hall-ui/public/work.html:121 |
69
69
  | `c10806b50c61` | 2x | Claim task {…} | modules/hall-ui/public/goals-page.js:551, modules/hall-ui/public/work.js:356 |
70
70
  | `a832f32b5597` | 2x | Claimed {…} tasks. Open a terminal to start work. | modules/hall-ui/public/goals-page.js:647, modules/hall-ui/public/work.js:754 |
71
71
  | `cfe0f4c4fcc2` | 2x | Closing your box… (a few seconds) | modules/hall-ui/public/box-panel.js:265, modules/hall-ui/public/box-panel.js:370 |
@@ -78,7 +78,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
78
78
  | `7775fec0fa85` | 2x | Could not load sessions. | modules/hall-ui/public/sessions.js:168, modules/hall-ui/public/sessions.js:207 |
79
79
  | … | | _85 more in the JSON registry_ | |
80
80
 
81
- ## `builders-hall` — 1095 strings
81
+ ## `builders-hall` — 1096 strings
82
82
 
83
83
  | id | conf | text | where |
84
84
  |---|---|---|---|
@@ -184,9 +184,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
184
184
  | `a78477a24a48` | certain | Builders' Hall | `modules/hall-ui/public/index.html:12` |
185
185
  | `a78477a24a48` | certain | Builders' Hall | `modules/hall-ui/public/index.html:38` |
186
186
  | `b51edc826cbe` | certain | Built by this project | `modules/hall-ui/public/modules.html:47` |
187
- | `563d29ed86d8` | certain | Bulk actions | `modules/hall-ui/public/goals.html:140` |
187
+ | `563d29ed86d8` | certain | Bulk actions | `modules/hall-ui/public/goals.html:148` |
188
188
  | `563d29ed86d8` | certain | Bulk actions | `modules/hall-ui/public/work.html:118` |
189
- | `46b33550d52b` | certain | Bulk claim | `modules/hall-ui/public/goals.html:143` |
189
+ | `46b33550d52b` | certain | Bulk claim | `modules/hall-ui/public/goals.html:151` |
190
190
  | `46b33550d52b` | certain | Bulk claim | `modules/hall-ui/public/work.html:121` |
191
191
  | `6d6d626fc518` | certain | Bulk release | `modules/hall-ui/public/work.html:122` |
192
192
  | `181cfa50b127` | certain | By the numbers | `modules/hall-ui/public/profile.html:37` |
@@ -215,6 +215,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
215
215
  | `b9c64fe023a9` | certain | Claude Desktop app | `modules/hall-ui/public/builders.js:984` |
216
216
  | `9edebf179aa3` | certain | Claude Online | `modules/hall-ui/public/builders.js:984` |
217
217
  | `f2c734539bb8` | certain | Claude starts automatically when you open the terminal. | `modules/hall-ui/public/builders.js:984` |
218
+ | `5b3b75ee0596` | certain | Claude's notes on this goal | `modules/hall-ui/public/goals.html:67` |
218
219
  | `593dda3178eb` | certain | Click to copy | `modules/hall-ui/public/copy-on-click.js:137` |
219
220
  | `87789c3dc97c` | certain | Click to copy {…} | `modules/hall-ui/public/box-panel.js:137` |
220
221
  | `e712dd69a5f6` | certain | Clone the project to your machine, or open your hosted dev box (where it is already cloned). The build command | `modules/hall-ui/public/builders.js:1154` |
@@ -381,7 +382,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
381
382
  | `c15d1f0ddfb6` | certain | Estimation accuracy | `modules/hall-ui/public/watch.html:133` |
382
383
  | `44f928d13699` | certain | Event sounds | `modules/hall-ui/public/settings.html:282` |
383
384
  | `8690c6424585` | certain | Every builder in {{worldName}} — rank, {{currency}}, karma, and active claims. | `modules/hall-ui/public/watch.html:61` |
384
- | `2ae1eb35611e` | certain | Every done-when criterion for this goal, with its full detail. | `modules/hall-ui/public/goals.html:178` |
385
+ | `2ae1eb35611e` | certain | Every done-when criterion for this goal, with its full detail. | `modules/hall-ui/public/goals.html:186` |
385
386
  | `1e05b7fe42c8` | certain | Every project you build on across the platform. | `modules/hall-ui/public/my-projects.html:24` |
386
387
  | `efafe5ce29ed` | certain | Every task linked to this criterion has shipped — a Metic can confirm it | `modules/hall-ui/public/goals-page.js:1042` |
387
388
  | `ddebbccd4b37` | certain | Everyone building across hosted projects, ranked by track record. Descriptive only — cross-project numbers nev | `modules/hall-ui/public/people.html:23` |
@@ -419,7 +420,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
419
420
  | `13acaeb4b0bf` | certain | Goal #{…} | `modules/hall-ui/public/task.js:202` |
420
421
  | `9e70797b7e97` | certain | Goal id | `modules/hall-ui/public/goals-page.js:1213` |
421
422
  | `529460e82058` | certain | Goal invitations to you | `modules/hall-ui/public/goal-inbox.js:113` |
422
- | `e2a9e33abe60` | certain | Goal tasks | `modules/hall-ui/public/goals.html:104` |
423
+ | `e2a9e33abe60` | certain | Goal tasks | `modules/hall-ui/public/goals.html:112` |
423
424
  | `e0bc28d10785` | certain | Goals could not be loaded. Refresh to try again. | `modules/hall-ui/public/goals-page.js:1799` |
424
425
  | `4517f2253d0f` | certain | Goals couldn’t be loaded just now. Refresh to try again. | `modules/hall-ui/public/goals.js:112` |
425
426
  | `2ed2cb8fbffd` | certain | Goals page | `modules/hall-ui/public/goals.js:94` |
@@ -616,8 +617,8 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
616
617
  | `855277dff074` | certain | Open task #{…} | `modules/hall-ui/public/work.js:963` |
617
618
  | `e0810149de64` | certain | Open task details | `modules/hall-ui/public/goals-page.js:559` |
618
619
  | `e0810149de64` | certain | Open task details | `modules/hall-ui/public/work.js:341` |
619
- | `99c630009152` | certain | Open tasks whose declared files overlap — sequence these before two builders collide. | `modules/hall-ui/public/goals.html:90` |
620
- | `99c630009152` | certain | Open tasks whose declared files overlap — sequence these before two builders collide. | `modules/hall-ui/public/goals.html:155` |
620
+ | `99c630009152` | certain | Open tasks whose declared files overlap — sequence these before two builders collide. | `modules/hall-ui/public/goals.html:98` |
621
+ | `99c630009152` | certain | Open tasks whose declared files overlap — sequence these before two builders collide. | `modules/hall-ui/public/goals.html:163` |
621
622
  | `29ff278e96a8` | certain | Open the Work Board | `modules/hall-ui/public/task.js:258` |
622
623
  | `e706a4836ce8` | certain | Open the pairing page | `modules/hall-ui/public/settings.html:201` |
623
624
  | `2cad724171e6` | certain | Open your online environment. | `modules/hall-ui/public/builders.js:984` |
@@ -907,7 +908,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
907
908
  | `d3a8b2b5b93f` | certain | Where {{currency}} and karma come from and where they go. | `modules/hall-ui/public/diagrams.html:76` |
908
909
  | `8f5954c06daa` | certain | Whether your session cards — what | `modules/hall-ui/public/settings.html:229` |
909
910
  | `f9ab9eb870a6` | certain | While you wait: install the Claude desktop app at | `modules/hall-ui/public/builders.js:640` |
910
- | `045c629729b7` | certain | Who’s on this goal, and what they’ve contributed to it. | `modules/hall-ui/public/goals.html:166` |
911
+ | `045c629729b7` | certain | Who’s on this goal, and what they’ve contributed to it. | `modules/hall-ui/public/goals.html:174` |
911
912
  | `6e8a3151ec76` | certain | Why \u2014 the reason the author will act on | `modules/hall-ui/public/government.js:741` |
912
913
  | `a3ac116b499a` | certain | Why? | `modules/hall-ui/public/copy-desk.html:99` |
913
914
  | `6108c16edece` | certain | Window: last {…} days. | `modules/hall-ui/public/watch.js:628` |
@@ -1160,9 +1161,9 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1160
1161
  | `7d29dc9e0391` | certain | ← Back to Home | `modules/hall-ui/public/not-ready.html:35` |
1161
1162
  | `9e7f83400f9a` | certain | ← Back to Ideas | `modules/hall-ui/public/idea.html:27` |
1162
1163
  | `a71cd6fa8d57` | certain | ← Back to Tasks | `modules/hall-ui/public/task.html:55` |
1163
- | `7926e30955d2` | certain | ← Back to goal | `modules/hall-ui/public/goals.html:152` |
1164
- | `7926e30955d2` | certain | ← Back to goal | `modules/hall-ui/public/goals.html:163` |
1165
- | `7926e30955d2` | certain | ← Back to goal | `modules/hall-ui/public/goals.html:175` |
1164
+ | `7926e30955d2` | certain | ← Back to goal | `modules/hall-ui/public/goals.html:160` |
1165
+ | `7926e30955d2` | certain | ← Back to goal | `modules/hall-ui/public/goals.html:171` |
1166
+ | `7926e30955d2` | certain | ← Back to goal | `modules/hall-ui/public/goals.html:183` |
1166
1167
  | `1e7cf7b1e64e` | certain | ← Newer | `modules/hall-ui/public/sessions.html:56` |
1167
1168
  | `2180e0ecf138` | certain | → no idea # | `modules/hall-ui/public/task-detail.js:479` |
1168
1169
  | `d5d76f1c0dfe` | certain | ○ reserved | `modules/hall-ui/public/diagrams.html:53` |