@bongos/core 1.24.2 → 1.24.3

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,11 +2,11 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/bongos/package-core.js",
5
- "core_version": "1.24.2",
6
- "core_contract": "1.24.2",
7
- "source_commit": "ee62d8bbc8ba5881c14529f59c7c4977cdd3d369",
5
+ "core_version": "1.24.3",
6
+ "core_contract": "1.24.3",
7
+ "source_commit": "b57757a23ba80fcb66599c385508e0b57994bafe",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-10-30T04:03:46.558Z",
9
+ "built_at": "2026-10-30T04:14:41.527Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 628,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 4368,
20
- "tree_sha256": "fdbf473ba97bae610265a82edb99185a1d26c069f869004283746e7d404265dd",
20
+ "tree_sha256": "333a8c24a58c90c682ef438927dd00904322b616a1541e97f4cc7df448276e54",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2992,7 +2992,7 @@
2992
2992
  {
2993
2993
  "path": "docs/module-api-changelog.md",
2994
2994
  "mode": "0000644",
2995
- "sha256": "7d908c8a090025c583b91a08ea9130918cb3157f768fc0db60a6ae1930c8e88d"
2995
+ "sha256": "1ffe38d130de3c38240a4a03fd1357f70cd780f49576ee382bc49dd8f706a205"
2996
2996
  },
2997
2997
  {
2998
2998
  "path": "docs/modules-contract.md",
@@ -3082,7 +3082,7 @@
3082
3082
  {
3083
3083
  "path": "docs/page-readings.json",
3084
3084
  "mode": "0000644",
3085
- "sha256": "5f42ce17aec4f1cd6f50f4567657281a0427e3ad9c5ad3c05f938428b49bf1de"
3085
+ "sha256": "32b5769127bc8ec156e6a56635307c9dc3ce4952f10cda58e3b9b8a579054521"
3086
3086
  },
3087
3087
  {
3088
3088
  "path": "docs/project-context.template.md",
@@ -5172,7 +5172,7 @@
5172
5172
  {
5173
5173
  "path": "modules/economy/governor-docket.js",
5174
5174
  "mode": "0000644",
5175
- "sha256": "6afc037169fac7d8cb29bc6cdd95352183ec4709de8f197602c429c788d49ff3"
5175
+ "sha256": "8c0df9e00269a3df0a560d9a7421912e18c7827e8aebc2e5836107c0bb298bc0"
5176
5176
  },
5177
5177
  {
5178
5178
  "path": "modules/economy/idea-brightness.js",
@@ -6937,7 +6937,7 @@
6937
6937
  {
6938
6938
  "path": "modules/hall-ui/public/street-inside.js",
6939
6939
  "mode": "0000644",
6940
- "sha256": "9c644d975b2436e3f6716073bb00f83d19a304b6a57c664742fd9f348caa3ec8"
6940
+ "sha256": "c631a125f8ee5538d7fa8b0dcd40fe305a849335c8464cef5e59885a41e658e0"
6941
6941
  },
6942
6942
  {
6943
6943
  "path": "modules/hall-ui/public/street-office.js",
@@ -11392,12 +11392,12 @@
11392
11392
  {
11393
11393
  "path": "package-lock.json",
11394
11394
  "mode": "0000644",
11395
- "sha256": "d54e9e0c5bbf39452f84da6adfcbb70db3083f841949f1395a90a09bb75a9c51"
11395
+ "sha256": "538e75547b022a21993846718836005f1ce515b6cacbeacdaf2bd950fddb1cc8"
11396
11396
  },
11397
11397
  {
11398
11398
  "path": "package.json",
11399
11399
  "mode": "0000644",
11400
- "sha256": "3613bd5a007016140cadc02da91c0156995160ea2100b25d47b0453593320305"
11400
+ "sha256": "ea0a5b8f4bd3a23abb119e799db5de9505ac2bed3c7174806c4ac6c34b865d3d"
11401
11401
  },
11402
11402
  {
11403
11403
  "path": "public-docs/index.html",
@@ -11417,7 +11417,7 @@
11417
11417
  {
11418
11418
  "path": "release-notes.json",
11419
11419
  "mode": "0000644",
11420
- "sha256": "855871603a1664076bf302b341cd91e05c8ca2c51082cb66f3ba76f0ceb37ad4"
11420
+ "sha256": "76098fa523d64daa93da3923d0d5246ca2ec6770af4b8979336c7dc2862a8858"
11421
11421
  },
11422
11422
  {
11423
11423
  "path": "scripts/bongos/CLAUDE.md",
@@ -15252,7 +15252,7 @@
15252
15252
  {
15253
15253
  "path": "src/module-api.js",
15254
15254
  "mode": "0000644",
15255
- "sha256": "49d1cfec2aa19c29c98f5fc96c241bfb7f7815ea86e2fc42baccf715511e180b"
15255
+ "sha256": "8104d0ef07471964487deae59260b1acb032921d0094616a679d2f4c3ecf3b4e"
15256
15256
  },
15257
15257
  {
15258
15258
  "path": "src/module-loader/catalog.js",
@@ -17727,7 +17727,7 @@
17727
17727
  {
17728
17728
  "path": "tests/governor_docket.mjs",
17729
17729
  "mode": "0000644",
17730
- "sha256": "b58a2e5675158aabc2b74abc683a97269dd3c6c21f84ef6ee24006cc59c1a68b"
17730
+ "sha256": "49cf94b338640f0c7ea7f9ad3ec113ebc519983f46a0c996735140c6d99e4e23"
17731
17731
  },
17732
17732
  {
17733
17733
  "path": "tests/governor_matter_acts.mjs",
@@ -18187,7 +18187,7 @@
18187
18187
  {
18188
18188
  "path": "tests/hall_street_inside.mjs",
18189
18189
  "mode": "0000644",
18190
- "sha256": "5a5d0be53259416cedce40531a525ed2c170c2896a30bf2b8d2192e0518a16c9"
18190
+ "sha256": "9c0996085a92e67ba2a9d15452641cb11ccb4a92c067aa40431a6bf8c46e1074"
18191
18191
  },
18192
18192
  {
18193
18193
  "path": "tests/hall_studio_home.mjs",
@@ -3266,5 +3266,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
3266
3266
  landed since 1.24.0 with no explicit bump. run 40985289858. (task 1002620)
3267
3267
  1.24.2 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
3268
3268
  landed since 1.24.1 with no explicit bump. run 41000649913. (task 1002620)
3269
+ 1.24.3 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
3270
+ landed since 1.24.2 with no explicit bump. run 41001671514. (task 1002620)
3269
3271
  ---------------------------------------------------------------------------
3270
3272
  ```
@@ -5,7 +5,7 @@
5
5
  "adr": "0341 D3",
6
6
  "reread": "node scripts/bongos/page-reader.js --stale",
7
7
  "how": ["Generated by node scripts/bongos/page-reader.js (BV2.TW04, task 1004315; ADR 0341 D3). Do not hand-edit.","One entry per page of docs/page-inventory.json. Lines are in page order: the default state first, and a line only another state shows sits where that state shows it, with its state named.","placement: placed = a docs/copy-registry.json row renders it (file, line, string_id); shared = shell text every page of the surface carries (top bar, sidebar, footer), with its row when the registry has one; unplaced = the registry cannot place it (a rewrite becomes an engineer task, ADR 0341 D4).","text keeps {…} where the registry row has a hole, or where a value the page read from its API was filled in. A string that is only such data is counted under omitted.data, not listed.","reading_hash is over the non-shared lines (key, section, text); files_hash is over the page's inventory files. --check compares files_hash only and never opens a browser.","Rendered through the hall-preview harness (hall) and the ui-design kit stub (landing, status), at 1280x800 with the clock pinned, so a reading is the fixture world's page."],
8
- "counts": {"pages":48,"lines":5456,"placed":1683,"shared":427,"unplaced":3346,"omitted_data":3730},
8
+ "counts": {"pages":48,"lines":5456,"placed":1683,"shared":427,"unplaced":3346,"omitted_data":3731},
9
9
  "pages": [
10
10
  {
11
11
  "id": "builders:ai-studio",
@@ -271,7 +271,7 @@
271
271
  "surface": "builders",
272
272
  "title": "The city",
273
273
  "states_read": ["city","fullscreen","switched","focus","pins","living","card","card-ask"],
274
- "files_hash": "a3b905698a39c7bc",
274
+ "files_hash": "6a8a96e1f9f6084a",
275
275
  "reading_hash": "77470c4eb3047a05",
276
276
  "counts": {"lines":43,"placed":10,"shared":8,"unplaced":25},
277
277
  "omitted": {"data":17},
@@ -3370,10 +3370,10 @@
3370
3370
  "surface": "builders",
3371
3371
  "title": "The street",
3372
3372
  "states_read": ["street","fullscreen","card","switched","focus","here","inside-rules","inside-disputes","inside-people","inside-planning","inside-automation","inside-review","inside-release","inside-treasury","floor","amend","district","desk","desk-facts","desk-quiet","desk-people-builders","desk-people-tier","desk-disputes","desk-automation-goals","desk-release-core","desk-rules","desk-rules-category","desk-planning-priorities","desk-planning-ideas","desk-planning-blockers","pins","pins-pager","living","deck","deck-treasury","sitting","object","voted","admission","settled","blocker","blocker-more","report","report-more","core","core-more","recheck","recheck-more","idea","idea-more","queue","queue-more","automation","automation-more"],
3373
- "files_hash": "5c081c34c9e70e53",
3374
- "reading_hash": "f9a1c5189c877bb0",
3373
+ "files_hash": "6180e15ad9dcf4d6",
3374
+ "reading_hash": "b5cd1724efa21f28",
3375
3375
  "counts": {"lines":650,"placed":75,"shared":8,"unplaced":567},
3376
- "omitted": {"data":552},
3376
+ "omitted": {"data":553},
3377
3377
  "notes": ["sitting: an action failed (page.click: Timeout 6000ms exceeded.); read as it stood","object: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"board:47\"]); read as it stood","voted: an action failed (page.click: Timeout 6000ms exceeded.); read as it stood","admission: an action failed (page.click: Timeout 6000ms exceeded.); read as it stood","settled: an action failed (page.click: Timeout 6000ms exceeded.); read as it stood","blocker: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"blockers:11\"]); read as it stood","blocker-more: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"blockers:11\"]); read as it stood","report: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"redteam_reports:4\"]); read as it stood","report-more: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"redteam_reports:4\"]); read as it stood","core: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"core_update:1.21.20\"]); read as it stood","core-more: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"core_update:1.21.20\"]); read as it stood","recheck: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"module_rechecks:7\"]); read as it stood","recheck-more: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"module_rechecks:7\"]); read as it stood","idea: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"board:41\"]); read as it stood","idea-more: an action failed (page.evaluate: Error: dispatchClick: nothing matches .street-pin[data-matter=\"board:41\"]); read as it stood"],
3378
3378
  "lines": [
3379
3379
  {"key":"L0001","section":"skip link","text":"Skip to content","placement":"shared","file":"modules/hall-ui/public/shell.js","line":868,"string_id":"87cee78ca134"},
@@ -3597,7 +3597,7 @@
3597
3597
  {"key":"L0219","section":"Spending matters","text":"{…} of {…}","placement":"placed","file":"modules/hall-ui/public/sky-panel.js","line":120,"string_id":"73c1372b43d9","state":"inside-treasury"},
3598
3598
  {"key":"L0220","section":"Spending matters","text":"{…} from the reserve?","placement":"unplaced","state":"inside-treasury"},
3599
3599
  {"key":"L0221","section":"Spending matters","text":"{…} · today","placement":"unplaced","state":"inside-treasury"},
3600
- {"key":"L0222","section":"Spending matters","text":"Paid $5,549 to 7 buil… · today","placement":"unplaced","state":"inside-treasury"},
3600
+ {"key":"L0222","section":"Spending matters","text":"7 builders earned 5,5… · today","placement":"unplaced","state":"inside-treasury"},
3601
3601
  {"key":"L0223","section":"Spending matters","text":"{…} · 4w","placement":"unplaced","state":"inside-treasury","occurrences":2},
3602
3602
  {"key":"L0224","section":"Spending matters","text":"the record","placement":"placed","file":"modules/hall-ui/public/street.html","line":192,"string_id":"4bde7b562cf4","state":"inside-treasury"},
3603
3603
  {"key":"L0225","section":"Spending matters","text":"1 matter on the docket · 16 on the {…}","placement":"unplaced","state":"inside-treasury"},
@@ -3832,7 +3832,7 @@
3832
3832
  {"key":"L0454","section":"Priorities","text":"standing law","placement":"unplaced","state":"desk-planning-priorities"},
3833
3833
  {"key":"L0455","section":"Waiting on {…}","text":"Waiting on {…}","placement":"placed","file":"modules/hall-ui/public/goals-lib.js","line":91,"string_id":"b18832e219dc","state":"inside-planning"},
3834
3834
  {"key":"L0456","section":"Waiting on {…}","text":"9 waiting · oldest 3 weeks","placement":"unplaced","state":"inside-planning"},
3835
- {"key":"L0457","section":"Waiting on {…}","text":"waiting","placement":"placed","file":"modules/hall-ui/public/work.js","line":431,"string_id":"8186b562553a","state":"inside-planning"},
3835
+ {"key":"L0457","section":"Waiting on {…}","text":"waiting","placement":"placed","file":"modules/hall-ui/public/work.js","line":438,"string_id":"8186b562553a","state":"inside-planning"},
3836
3836
  {"key":"L0458","section":"Waiting on {…}","text":"on {…}","placement":"unplaced","state":"inside-planning"},
3837
3837
  {"key":"L0459","section":"Waiting on {…}","text":"WA","placement":"unplaced","state":"inside-planning"},
3838
3838
  {"key":"L0460","section":"Waiting on {…}","text":"Working area 2…","placement":"unplaced","state":"inside-planning"},
@@ -5,7 +5,7 @@
5
5
  // modules/government/docket.js).
6
6
  //
7
7
  // WHY. Inside the Treasury building three floors are the project's real
8
- // spending lines — rewards paid for shipped work, the AI grader, and hosting —
8
+ // lines — credits earned for shipped work, the AI grader, and hosting —
9
9
  // and its record drawers are those same lines month by month. They come from
10
10
  // the two ledgers this module owns (credit_log, cost_log) through ONE bounded
11
11
  // read, cost.treasuryMonths. The ledgers are already published unauthenticated
@@ -28,22 +28,28 @@ function usd(n) {
28
28
  const v = Math.round(Number(n) || 0);
29
29
  return `$${v.toLocaleString('en-US')}`;
30
30
  }
31
+ // Credits are a contribution meter, not money (ADR 0385, ADR 0387): the rewards
32
+ // line counts them and never wears a $ sign (task 1005006).
33
+ function credits(n) {
34
+ const v = Math.round(Number(n) || 0);
35
+ return `${v.toLocaleString('en-US')} ${v === 1 ? 'credit' : 'credits'}`;
36
+ }
31
37
  function monthKey(now) { const d = new Date(now); return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}`; }
32
38
  function monthWord(key) { const m = Number(String(key).slice(5, 7)); return MONTHS[m - 1] || String(key); }
33
39
 
34
40
  // One spending line's floor from the month rows. Pure.
35
- function lineFloor(months, now, field, { what, meta }) {
41
+ function lineFloor(months, now, field, { what, meta, fmt = usd }) {
36
42
  const rows = Array.isArray(months) ? months : [];
37
43
  const cur = rows.find((r) => r.month === monthKey(now));
38
44
  const prev = rows.find((r) => r.month < monthKey(now));
39
45
  const v = cur ? Number(cur[field]) || 0 : 0;
40
46
  const lines = [[what, meta]];
41
- if (prev) lines.push([`${usd(prev[field])} in ${monthWord(prev.month)}.`, 'last month']);
42
- return { count: usd(v), line: `${usd(v)} this month`, lines, hot: false };
47
+ if (prev) lines.push([`${fmt(prev[field])} in ${monthWord(prev.month)}.`, 'last month']);
48
+ return { count: fmt(v), line: `${fmt(v)} this month`, lines, hot: false };
43
49
  }
44
50
 
45
51
  function rewardsFloor(months, now) {
46
- const f = lineFloor(months, now, 'rewards_credits', { what: 'Paid to builders for shipped work, one credit to the dollar.', meta: 'each ship' });
52
+ const f = lineFloor(months, now, 'rewards_credits', { what: 'Credits earned for shipped work. They count contribution; they are not money.', meta: 'each ship', fmt: credits });
47
53
  const cur = (months || []).find((r) => r.month === monthKey(now));
48
54
  const n = cur ? cur.rewarded_builders : 0;
49
55
  return { ...f, line: `${f.count} this month · ${n} ${n === 1 ? 'builder' : 'builders'}` };
@@ -56,7 +62,7 @@ function treasuryHistory(months) {
56
62
  const out = [];
57
63
  for (const r of months || []) {
58
64
  const at = `${r.month}-01T00:00:00.000Z`;
59
- if (r.rewards_credits > 0) out.push({ id: `rewards:${r.month}`, title: `Paid ${usd(r.rewards_credits)} to ${r.rewarded_builders} ${r.rewarded_builders === 1 ? 'builder' : 'builders'}`, at, outcome: 'rewards' });
65
+ if (r.rewards_credits > 0) out.push({ id: `rewards:${r.month}`, title: `${r.rewarded_builders} ${r.rewarded_builders === 1 ? 'builder' : 'builders'} earned ${credits(r.rewards_credits)}`, at, outcome: 'rewards' });
60
66
  if (r.grading_usd > 0) out.push({ id: `grading:${r.month}`, title: `AI grading cost ${usd(r.grading_usd)}`, at, outcome: 'grading' });
61
67
  if (r.hosting_usd > 0) out.push({ id: `hosting:${r.month}`, title: `Hosting cost ${usd(r.hosting_usd)}`, at, outcome: 'hosting' });
62
68
  }
@@ -471,7 +471,7 @@
471
471
  treasury: {
472
472
  holds: 'The budget, and who gets paid for what.', rule: 'majority', cap: 7,
473
473
  growth: 'Each new spending line takes a floor.', annex: 'room for an annex of spending lines',
474
- floors: [['Builder rewards', 'paid for shipped work', { floor: 'treasury.rewards' }], ['AI grading', 'the reviewer that grades every ship', { floor: 'treasury.grading' }], ['Hosting', 'servers and storage', { floor: 'treasury.hosting', desk: 'treasury.backup' }], ['Reserve', 'what is left this month', { reading: 'money', desk: 'treasury.budgets' }], ['Spending matters', 'spending put to a vote', { source: 'treasury_spending' }]],
474
+ floors: [['Builder rewards', 'credits earned for shipped work', { floor: 'treasury.rewards' }], ['AI grading', 'the reviewer that grades every ship', { floor: 'treasury.grading' }], ['Hosting', 'servers and storage', { floor: 'treasury.hosting', desk: 'treasury.backup' }], ['Reserve', 'what is left this month', { reading: 'money', desk: 'treasury.budgets' }], ['Spending matters', 'spending put to a vote', { source: 'treasury_spending' }]],
475
475
  },
476
476
  });
477
477
  const MONTHS = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.24.2",
3
+ "version": "1.24.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.24.2",
9
+ "version": "1.24.3",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.24.2",
3
+ "version": "1.24.3",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
@@ -10811,5 +10811,11 @@
10811
10811
  "id": "1004970",
10812
10812
  "text": "The payments decision record now carries the owner's answers: credits can be tuned but not switched off, pay rules live on the settings page, and Verro is Verro Labs."
10813
10813
  }
10814
+ ],
10815
+ "1.24.3": [
10816
+ {
10817
+ "id": "1005006",
10818
+ "text": "The Treasury screen now counts builder rewards in credits instead of dollars, and no longer says one credit is a dollar."
10819
+ }
10814
10820
  ]
10815
10821
  }
package/src/module-api.js CHANGED
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
81
81
  // MAJOR (see allowBoxScope below): passes the request through untouched.
82
82
  function deprecatedNoopMiddleware(_req, _res, next) { next(); }
83
83
 
84
- const CORE_VERSION = '1.24.2'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
84
+ const CORE_VERSION = '1.24.3'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
85
85
 
86
86
  // A namespaced logger so a module's log lines are attributable + consistent.
87
87
  // Usage: const log = api.logger('discord'); log.info('mounted');
@@ -678,10 +678,14 @@ test('automation, treasury and disputes floors read their own ledgers, and say s
678
678
  const rep = autonomyDocket.reportsFloor([{ routine: 'builder', decision: 'go', created_at: '2026-09-30T00:00:00Z' }, { routine: 'idea-triage', decision: 'no-go', reason: 'nothing open', created_at: '2026-09-01T00:00:00Z' }], NOW);
679
679
  assert.deepEqual([rep.count, rep.lines.map((l) => l[0])], ['1', ['The builder went ahead.', 'Idea sorting held back: nothing open.']], 'said in words, not the gate\'s keys');
680
680
  const months = [{ month: '2026-10', rewards_credits: 1180, rewarded_builders: 6, grading_usd: 310.4, hosting_usd: 120 }, { month: '2026-09', rewards_credits: 4920, rewarded_builders: 8, grading_usd: 0, hosting_usd: 160 }];
681
- assert.deepEqual([economyDocket.rewardsFloor(months, NOW).count, economyDocket.rewardsFloor(months, NOW).line], ['$1,180', '$1,180 this month · 6 builders']);
681
+ assert.deepEqual([economyDocket.rewardsFloor(months, NOW).count, economyDocket.rewardsFloor(months, NOW).line], ['1,180 credits', '1,180 credits this month · 6 builders']);
682
682
  assert.deepEqual(economyDocket.hostingFloor(months, NOW).lines[1], ['$160 in sep.', 'last month']);
683
683
  assert.equal(economyDocket.gradingFloor([], NOW).count, '$0', 'a month with no rows is a real zero, read from the ledger');
684
- assert.deepEqual(economyDocket.treasuryHistory(months).map((h) => h.title), ['Paid $1,180 to 6 builders', 'AI grading cost $310', 'Hosting cost $120', 'Paid $4,920 to 8 builders', 'Hosting cost $160']);
684
+ assert.deepEqual(economyDocket.treasuryHistory(months).map((h) => h.title), ['6 builders earned 1,180 credits', 'AI grading cost $310', 'Hosting cost $120', '8 builders earned 4,920 credits', 'Hosting cost $160']);
685
+ // Credits are a contribution meter, not money (ADR 0385/0387, task 1005006): no $ sign, no dollar peg, no "paid".
686
+ const rewardWords = JSON.stringify([economyDocket.rewardsFloor(months, NOW), economyDocket.treasuryHistory(months).filter((h) => h.outcome === 'rewards')]);
687
+ assert.doesNotMatch(rewardWords, /\$|dollar|\bpaid\b/i, 'the rewards line counts credits, never money');
688
+ assert.equal(economyDocket.rewardsFloor([{ month: '2026-10', rewards_credits: 1, rewarded_builders: 1 }], NOW).count, '1 credit');
685
689
  assert.deepEqual(reportsRoute.rulingHistory([{ id: 1, title: 'sign-in limits', status: 'fixed', fixed_at: '2026-08-02T00:00:00Z' }, { id: 2, title: 'open one', status: 'open' }, { id: 3, title: 'undated', status: 'wontfix' }]).map((h) => [h.title, h.outcome]), [['Security report: sign-in limits', 'fixed']]);
686
690
  });
687
691
 
@@ -706,7 +710,7 @@ test('one ledger read per docket request: the treasury floors and record share i
706
710
  for (const f of ['modules/economy/routes/cost.js', 'modules/autonomy/routes/autonomy.js']) require(path.join(ROOT, f))();
707
711
  const d = await docket.buildDocket({ viewer: VIEWER, permissions: ['board.vote.cast', 'autonomy.precheck'], now: NOW + 1 });
708
712
  const by = Object.fromEntries(d.floors.map((f) => [f.key, f]));
709
- assert.deepEqual([by['treasury.rewards'].count, by['treasury.hosting'].count, by['automation.spending_limit'].status], ['$10', '$3', 'live']);
713
+ assert.deepEqual([by['treasury.rewards'].count, by['treasury.hosting'].count, by['automation.spending_limit'].status], ['10 credits', '$3', 'live']);
710
714
  assert.equal(reads, 1, 'one treasury read for three floors and the record');
711
715
  assert.equal(spends, 1, 'one spend read for the money reading and the spending limit');
712
716
  assert.equal(fences, 1, 'one fence read for the switch, allowed goals and the switch\'s record');
@@ -303,12 +303,12 @@ test('every floor of every building is bound to a docket feed: none is left unwi
303
303
 
304
304
  test('a live floor shows exactly what the docket says: its count, line and lines; hot is being decided', () => {
305
305
  const d = docket([], { floors: [
306
- floorRow('treasury.rewards', { count: '$2,400', line: '$2,400 this month · 6 builders', lines: [['Paid to builders for shipped work.', 'each ship']] }),
306
+ floorRow('treasury.rewards', { count: '2,400 credits', line: '2,400 credits this month · 6 builders', lines: [['Credits earned for shipped work.', 'each ship']] }),
307
307
  floorRow('automation.allowed_goals', { count: '2', line: '2 goals it may build', lines: [['goal 7', 'first in line'], ['goal 99', 'since sep 2']] }),
308
308
  floorRow('charter.founding', { count: '', line: '1 of 2 founding steps passed', lines: [['The charter.', 'passed']], hot: true }),
309
309
  ] });
310
310
  const t = I.civicInfo('treasury', { docket: d, now: NOW }).floors.find((f) => f.name === 'Builder rewards');
311
- assert.deepEqual([t.count, t.line, t.status, t.lines], ['$2,400', '$2,400 this month · 6 builders', 'ok', [['Paid to builders for shipped work.', 'each ship']]]);
311
+ assert.deepEqual([t.count, t.line, t.status, t.lines], ['2,400 credits', '2,400 credits this month · 6 builders', 'ok', [['Credits earned for shipped work.', 'each ship']]]);
312
312
  const a = I.civicInfo('automation', { docket: d, goals: [goal(7, 'open', 'Onboarding')], now: NOW }).floors.find((f) => f.name === 'Allowed goals');
313
313
  assert.deepEqual(a.lines, [['Onboarding', 'first in line'], ['goal 99', 'since sep 2']], 'a goal it knows is lettered by title; one it does not keeps its id');
314
314
  const c = I.buildingModel({ key: 'charter', docket: d, mode: 'dark', now: NOW });