@bongos/core 1.20.80 → 1.20.82
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 +98 -53
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +8 -0
- package/clients/bongos-client/index.cjs +8 -0
- package/clients/bongos-client/index.d.ts +12 -0
- package/clients/bongos-client/index.mjs +8 -0
- package/docs/api/openapi.json +245 -4
- package/docs/api-reference.md +7 -3
- package/docs/copy-inventory.md +84 -71
- package/docs/copy-registry.json +271 -145
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-inventory.json +2 -1
- package/docs/page-readings.json +139 -119
- package/modules/autonomy/cadence.js +3 -0
- package/modules/autonomy/db.js +136 -0
- package/modules/autonomy/fence.js +88 -3
- package/modules/autonomy/migrations/autonomy_005_builder_scope.sql +55 -0
- package/modules/autonomy/routes/autonomy.js +123 -3
- package/modules/economy/earnings.js +117 -0
- package/modules/economy/module.json +1 -1
- package/modules/economy/routes/earnings.js +47 -0
- package/modules/government/catalog.js +9 -1
- package/modules/government/migrations/government_022_autonomy_run.sql +38 -0
- package/modules/hall-ui/public/gate.css +49 -0
- package/modules/hall-ui/public/gate.html +8 -7
- package/modules/hall-ui/public/gate.js +272 -115
- package/modules/hall-ui/public/profile-charts.js +206 -104
- package/modules/hall-ui/public/profile.css +23 -0
- package/modules/hall-ui/public/profile.js +3 -3
- package/modules/hall-ui/public/profile.states.json +8 -4
- package/modules/hall-ui/public/settings-autobongos.js +156 -0
- package/modules/hall-ui/public/settings.html +19 -0
- package/modules/hall-ui/public/settings.js +1 -0
- package/modules/hall-ui/records/profile-roles.md +21 -0
- package/modules/lifecycle/db-goals.js +6 -0
- package/modules/lifecycle/db-versions.js +3 -0
- package/modules/lifecycle/done-when.js +4 -0
- package/modules/lifecycle/goal-close-sweep.js +34 -0
- package/modules/provisioning/app-status.js +17 -4
- package/modules/public-landing/public/projects.html +7 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +28 -0
- package/scripts/hall-preview/server.js +4 -0
- package/src/module-api.js +1 -1
- package/tests/auto_satisfy_criteria.mjs +8 -6
- package/tests/autonomy_builder_scope.mjs +474 -0
- package/tests/autonomy_fence_priority.mjs +7 -3
- package/tests/autonomy_runner_identity.mjs +1 -1
- package/tests/criterion_goal_attach.mjs +5 -1
- package/tests/goal_close_cancels_requests.mjs +82 -0
- package/tests/goal_closure_invariants.mjs +5 -2
- package/tests/hall_profile_world.mjs +57 -58
- package/tests/profile_earnings.mjs +237 -0
- package/tests/projects_hub_app_status.mjs +17 -0
- package/tests/provisioning_app_status.mjs +25 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// modules/economy/routes/earnings.js — GET /builders/:builderId/earnings: what a
|
|
2
|
+
// builder earned, per day and per kind of credit (task 1004436 / WA6.RP06).
|
|
3
|
+
//
|
|
4
|
+
// → { builder_id, days: [{ day, kind, credits }], totals: { <kind>: credits }, total }
|
|
5
|
+
//
|
|
6
|
+
// The profile's earnings chart reads it for EVERY builder, whatever their craft:
|
|
7
|
+
// an ideator or an artist who never shipped a task is paid all the same, and the
|
|
8
|
+
// chart used to draw only for someone who had. `../earnings.js` owns the read and
|
|
9
|
+
// the kinds; this file is only the doorway, and must never grow SQL.
|
|
10
|
+
//
|
|
11
|
+
// SIGNED IN. The owner's decision (a), 2026-09-30: "no one should be able to open
|
|
12
|
+
// up the hood of data without being signed in." Sums only — the itemised ledger
|
|
13
|
+
// (/builders/:builderId/credits) stays behind builder.roster.read.
|
|
14
|
+
//
|
|
15
|
+
// MODULE BOUNDARY: reaches core only through the published doorway
|
|
16
|
+
// `../../../src/module-api`; `../earnings` is an intra-module sibling.
|
|
17
|
+
|
|
18
|
+
'use strict';
|
|
19
|
+
|
|
20
|
+
const express = require('express');
|
|
21
|
+
const api = require('../../../src/module-api');
|
|
22
|
+
const { readEarnings } = require('../earnings');
|
|
23
|
+
|
|
24
|
+
module.exports = function buildEarningsRouter() {
|
|
25
|
+
const router = express.Router();
|
|
26
|
+
|
|
27
|
+
// rank: builder — any signed-in builder may read any builder's earnings by
|
|
28
|
+
// kind, as the profile's other signed-in sections are; a stranger gets the
|
|
29
|
+
// sign-in line. The param names the builder (`:builderId`), the credits
|
|
30
|
+
// route's convention, because this route deliberately reads someone else.
|
|
31
|
+
router.get('/builders/:builderId/earnings', api.requireBuilder, async (req, res) => {
|
|
32
|
+
const targetId = api.parseId(req, res, { param: 'builderId', code: 'bad_builder_id', positiveInt: true });
|
|
33
|
+
if (targetId === null) return;
|
|
34
|
+
try {
|
|
35
|
+
const b = await api.getBuilderById(targetId);
|
|
36
|
+
if (!b) return res.fail('builder_not_found', 404);
|
|
37
|
+
const out = await readEarnings(targetId);
|
|
38
|
+
res.set('Cache-Control', 'no-store');
|
|
39
|
+
res.json({ builder_id: targetId, ...out });
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.error('[gds] GET /builders/:builderId/earnings', err);
|
|
42
|
+
if (!res.headersSent) res.fail('earnings_read_failed', { status: 500, message: 'internal error' });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return router;
|
|
47
|
+
};
|
|
@@ -119,7 +119,15 @@ const PERMISSIONS = [
|
|
|
119
119
|
// suggestion. Deliberately NOT paired with a read permission: seeing whether the
|
|
120
120
|
// runner is on is harmless, and GET /autonomy/fence is any-builder so the runner
|
|
121
121
|
// itself does not need an elevated session merely to learn it must stop.
|
|
122
|
-
{ key: 'autonomy.fence.manage', system: true, floor: 'archon', guards: 'POST /autonomy/fence (the kill switch), POST|DELETE /autonomy/fence/goals (the allowlist) — the Autobongos fence (ADR 0307 §6)' },
|
|
122
|
+
{ key: 'autonomy.fence.manage', system: true, floor: 'archon', guards: 'POST /autonomy/fence (the kill switch), POST|DELETE /autonomy/fence/goals (the allowlist), POST /autonomy/builders/:id/pause (one builder\'s runner), GET /autonomy/runners/all — the Autobongos fence (ADR 0307 §6)' },
|
|
123
|
+
// autonomy.run (task 1004501) — WHO MAY RUN A RUNNER AT ALL. Held, a builder may
|
|
124
|
+
// pick which allowlisted goals their own runner works, and GET /autonomy/fence
|
|
125
|
+
// hands their runner those goals; not held, the fence they read is off. NOT
|
|
126
|
+
// system: it is operational, and an owner who wants a custom rank of
|
|
127
|
+
// "runner operators" should be able to compose one. It can never widen the fence
|
|
128
|
+
// — the project allowlist and the kill switch stay behind autonomy.fence.manage —
|
|
129
|
+
// so delegating it delegates only "whose machine may work the allowed goals".
|
|
130
|
+
{ key: 'autonomy.run', system: false, floor: 'metic', guards: 'PUT /autonomy/me/goals (a builder\'s own runner scope); also decides whether GET /autonomy/fence answers enabled for the caller' },
|
|
123
131
|
// BV1.R21 (task 1003608, goal 1000086). ADR 0250 §6 amends ADR 0157 for exactly
|
|
124
132
|
// this key: `version.create` returns to the Archon floor.
|
|
125
133
|
//
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- government_022_autonomy_run.sql — grant the new `autonomy.run` atom to Metic and
|
|
2
|
+
-- Archon (task 1004501).
|
|
3
|
+
--
|
|
4
|
+
-- WHAT IT IS. Whether a builder may run an Autobongos runner at all: pick the
|
|
5
|
+
-- allowlisted goals their own runner works, and be answered `enabled` when their
|
|
6
|
+
-- runner reads GET /autonomy/fence. Without it, a builder's runner reads a fence
|
|
7
|
+
-- that is off for them, whatever the project switch says.
|
|
8
|
+
--
|
|
9
|
+
-- METIC FLOOR. A runner spawns sessions with blanket bypassPermissions on the
|
|
10
|
+
-- builder's own machine, and sub-Metic builders stay out of the build pipeline
|
|
11
|
+
-- (ADR 0043). NOT system: an owner may add it to a custom rank. That delegates
|
|
12
|
+
-- only whose machine may work the allowed goals — the allowlist and the kill
|
|
13
|
+
-- switch stay behind the archon-only `autonomy.fence.manage`.
|
|
14
|
+
--
|
|
15
|
+
-- WHY THIS FILE EXISTS AT ALL. RANK_SEED is derived from the catalog's floors and
|
|
16
|
+
-- tests/government_seed.mjs compares it against the run-once seed plus every later
|
|
17
|
+
-- grant migration, per rank. A catalog row without this migration leaves the key
|
|
18
|
+
-- held on paper and not in the database.
|
|
19
|
+
--
|
|
20
|
+
-- Additive only; idempotent (ON CONFLICT DO NOTHING); forward-safe (INSERT only).
|
|
21
|
+
-- The `SELECT '<rank>', unnest(ARRAY[…])` shape is load-bearing: the drift guard
|
|
22
|
+
-- scans for it literally.
|
|
23
|
+
|
|
24
|
+
BEGIN;
|
|
25
|
+
|
|
26
|
+
INSERT INTO government_rank_permissions (rank_key, permission_key)
|
|
27
|
+
SELECT 'metic', unnest(ARRAY[
|
|
28
|
+
'autonomy.run'
|
|
29
|
+
])
|
|
30
|
+
ON CONFLICT (rank_key, permission_key) DO NOTHING;
|
|
31
|
+
|
|
32
|
+
INSERT INTO government_rank_permissions (rank_key, permission_key)
|
|
33
|
+
SELECT 'archon', unnest(ARRAY[
|
|
34
|
+
'autonomy.run'
|
|
35
|
+
])
|
|
36
|
+
ON CONFLICT (rank_key, permission_key) DO NOTHING;
|
|
37
|
+
|
|
38
|
+
COMMIT;
|
|
@@ -23,3 +23,52 @@
|
|
|
23
23
|
.gate-reason > span:nth-of-type(2) { flex: 1 1 100%; order: 3; }
|
|
24
24
|
.gate-reason__floor { margin-left: auto; }
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
/* The Autobongos runner panel (task 1004509): a status line with the switch,
|
|
28
|
+
a checklist only while something is missing, goals as chips, and the
|
|
29
|
+
machine facts folded under Details. */
|
|
30
|
+
.rn-head { display: flex; align-items: center; gap: 12px; }
|
|
31
|
+
.rn-head__text { flex: 1; min-width: 0; }
|
|
32
|
+
.rn-title { margin: 0; font-size: 17px; color: var(--ink); }
|
|
33
|
+
.rn-meta { margin: 2px 0 0; font-size: 12.5px; color: var(--ink-faint); }
|
|
34
|
+
.rn-dot { width: 12px; height: 12px; border-radius: 50%; flex: none; background: var(--info); }
|
|
35
|
+
.rn-dot--ok { background: var(--ok); }
|
|
36
|
+
.rn-dot--warn { background: var(--warn); }
|
|
37
|
+
.rn-dot--danger { background: var(--danger); }
|
|
38
|
+
|
|
39
|
+
.rn-switch { display: inline-flex; align-items: center; gap: 8px; background: none; border: 0; padding: 4px; cursor: pointer; color: var(--ink-soft); font: inherit; font-size: 13px; }
|
|
40
|
+
.rn-switch__track { position: relative; width: 40px; height: 22px; border-radius: var(--radius-pill); background: var(--rule); transition: background .15s; }
|
|
41
|
+
.rn-switch__track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: var(--bg-card); transition: transform .15s; }
|
|
42
|
+
.rn-switch[aria-checked="true"] .rn-switch__track { background: var(--ok); }
|
|
43
|
+
.rn-switch[aria-checked="true"] .rn-switch__track::after { transform: translateX(18px); }
|
|
44
|
+
.rn-switch:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--radius-sm); }
|
|
45
|
+
|
|
46
|
+
.rn-check { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 10px; }
|
|
47
|
+
.rn-check__item { display: flex; align-items: flex-start; gap: 10px; font-size: 14px; color: var(--ink); }
|
|
48
|
+
.rn-check__icon { width: 20px; height: 20px; border-radius: 50%; flex: none; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; }
|
|
49
|
+
.rn-check__item--ok .rn-check__icon { background: var(--ok-weak); color: var(--ok); }
|
|
50
|
+
.rn-check__item--todo .rn-check__icon { background: var(--warn-weak); color: var(--warn); }
|
|
51
|
+
.rn-check__item--wait { color: var(--ink-faint); }
|
|
52
|
+
.rn-check__item--wait .rn-check__icon { border: var(--line) solid var(--rule); color: var(--ink-faint); }
|
|
53
|
+
.rn-check__text { flex: 1; min-width: 0; }
|
|
54
|
+
.rn-check__hint { display: block; font-size: 12.5px; color: var(--ink-faint); }
|
|
55
|
+
.rn-check .rn-meta { display: inline; }
|
|
56
|
+
|
|
57
|
+
.rn-sub { margin: 20px 0 8px; font-size: 13px; font-weight: 500; color: var(--ink-soft); }
|
|
58
|
+
.rn-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
59
|
+
.rn-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 6px; border: var(--line) solid var(--rule); border-radius: var(--radius-pill); font-size: 13px; background: none; color: var(--ink); }
|
|
60
|
+
.rn-chip a { color: inherit; text-decoration: none; padding: 0 2px; }
|
|
61
|
+
.rn-chip a:hover { text-decoration: underline; }
|
|
62
|
+
.rn-chip--pri { border-color: var(--accent); }
|
|
63
|
+
.rn-chip__star, .rn-chip__x { background: none; border: 0; padding: 0 4px; cursor: pointer; color: var(--ink-faint); font: inherit; font-size: 14px; line-height: 1; }
|
|
64
|
+
.rn-chip--pri .rn-chip__star { color: var(--accent); }
|
|
65
|
+
.rn-chip__star:hover, .rn-chip__x:hover { color: var(--ink); }
|
|
66
|
+
.rn-chip--add { border-style: dashed; color: var(--ink-soft); padding: 3px 12px; cursor: pointer; font: inherit; font-size: 13px; }
|
|
67
|
+
.rn-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
68
|
+
.rn-add input[type="number"] { width: 140px; }
|
|
69
|
+
|
|
70
|
+
.rn-details { margin: 18px 0 0; font-size: 12.5px; color: var(--ink-faint); }
|
|
71
|
+
.rn-details summary { cursor: pointer; width: fit-content; }
|
|
72
|
+
.rn-details p, .rn-details ul { margin: 8px 0 0; max-width: var(--measure); }
|
|
73
|
+
.rn-details ul { padding-left: 18px; display: grid; gap: 4px; }
|
|
74
|
+
.rn-dot--sm { display: inline-block; width: 8px; height: 8px; vertical-align: 1px; }
|
|
@@ -51,12 +51,13 @@
|
|
|
51
51
|
behind it are system:true/archon server-side regardless. -->
|
|
52
52
|
<section class="scroll" id="fence-panel" aria-labelledby="fence-h" hidden>
|
|
53
53
|
<h2 class="scroll__h" id="fence-h">Autobongos runner</h2>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<div id="fence-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
<!-- One panel (task 1004509): a checklist while anything the runner
|
|
55
|
+
needs is missing, one status line with the switch once it is all
|
|
56
|
+
ticked. Drawn from /autonomy/runners + /autonomy/fence together. -->
|
|
57
|
+
<div id="fence-body"><span class="kit-skel"></span></div>
|
|
58
|
+
<!-- Every builder's runner (task 1004501): what each one picked to
|
|
59
|
+
work, whether you paused it, and whether it is checking in. -->
|
|
60
|
+
<div id="fence-builders"></div>
|
|
60
61
|
</section>
|
|
61
62
|
|
|
62
63
|
<section class="scroll" aria-labelledby="gate-list-h">
|
|
@@ -81,6 +82,6 @@
|
|
|
81
82
|
<script src="/builders/palette.js" defer></script>
|
|
82
83
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
83
84
|
<script src="/builders/hall-kit.js"></script>
|
|
84
|
-
<script src="/builders/gate.js?v=2026-
|
|
85
|
+
<script src="/builders/gate.js?v=2026-10-01-runner-checklist"></script>
|
|
85
86
|
</body>
|
|
86
87
|
</html>
|