@bongos/core 1.19.804 → 1.19.806
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 +267 -242
- package/.claude/skills/ask-for-help/SKILL.md +6 -6
- package/.claude/skills/backlog-review/SKILL.md +1 -1
- package/.claude/skills/blocker-review/SKILL.md +7 -7
- package/.claude/skills/blocker-solve/SKILL.md +5 -5
- package/.claude/skills/bug-triage/SKILL.md +7 -7
- package/.claude/skills/builder-claim/SKILL.md +3 -3
- package/.claude/skills/builder-cost/SKILL.md +2 -2
- package/.claude/skills/builder-end/SKILL.md +2 -2
- package/.claude/skills/builder-exit/SKILL.md +7 -7
- package/.claude/skills/builder-key/SKILL.md +2 -2
- package/.claude/skills/builder-reauth/SKILL.md +2 -2
- package/.claude/skills/builder-redteam/SKILL.md +7 -7
- package/.claude/skills/builder-release/SKILL.md +2 -2
- package/.claude/skills/builder-sequence/SKILL.md +1 -1
- package/.claude/skills/builder-setup/SKILL.md +3 -3
- package/.claude/skills/builder-ship/SKILL.md +1 -1
- package/.claude/skills/builder-stage/SKILL.md +1 -1
- package/.claude/skills/builder-start/SKILL.md +1 -1
- package/.claude/skills/fix-task/SKILL.md +4 -4
- package/.claude/skills/goal-create/SKILL.md +18 -18
- package/.claude/skills/goal-review/SKILL.md +7 -7
- package/.claude/skills/grade-audit/SKILL.md +5 -5
- package/.claude/skills/grade-recover/SKILL.md +4 -4
- package/.claude/skills/grader-health/SKILL.md +6 -6
- package/.claude/skills/idea-triage/SKILL.md +14 -14
- package/.claude/skills/merge-mode/SKILL.md +3 -3
- package/.claude/skills/planning-session/SKILL.md +20 -20
- package/.claude/skills/priority-session/SKILL.md +10 -10
- package/.claude/skills/recall/SKILL.md +1 -1
- package/.claude/skills/scan-before-install/SKILL.md +3 -3
- package/.claude/skills/status/SKILL.md +2 -2
- package/.claude/skills/strand-fix/SKILL.md +2 -2
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +2 -0
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +45 -11
- package/docs/api-reference.md +11 -10
- package/docs/copy-inventory.md +47 -34
- package/docs/copy-registry.json +200 -72
- package/docs/module-api-changelog.md +4 -0
- package/modules/builder-settings/profile-nudge-prefs.js +1 -1
- package/modules/builder-settings/render-prefs.js +1 -1
- package/modules/dev-box/app/README.md +1 -1
- package/modules/dev-box/app/src/gds-client.js +11 -9
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +2 -0
- package/modules/dev-box/app/test/unit.mjs +13 -13
- package/modules/dev-box/box-access.js +3 -3
- package/modules/dev-box/box-onboard.js +7 -7
- package/modules/discord/bug-attachments.js +1 -1
- package/modules/economy/cost-classify.js +6 -6
- package/modules/grading/grader-rubric.json +1 -1
- package/modules/grading/grader-score.js +1 -1
- package/modules/hall-ui/module.json +1 -1
- package/modules/hall-ui/public/drachmae.js +3 -3
- package/modules/hall-ui/public/goals-page.js +1 -1
- package/modules/hall-ui/public/goals-render.js +144 -22
- package/modules/hall-ui/public/goals.css +16 -1
- package/modules/hall-ui/public/idea.js +1 -1
- package/modules/hall-ui/public/md-reader.js +1 -1
- package/modules/hall-ui/public/people.html +1 -1
- package/modules/hall-ui/public/people.js +2 -2
- package/modules/hall-ui/public/primer.js +4 -4
- package/modules/hall-ui/public/roster.js +1 -1
- package/modules/hall-ui/public/shell.js +1 -1
- package/modules/hall-ui/public/task.js +1 -1
- package/modules/ideas/inbox.js +2 -2
- package/modules/lifecycle/db-analytics.js +1 -1
- package/modules/lifecycle/done-when.js +4 -4
- package/modules/lifecycle/version-close.js +1 -1
- package/modules/memory/learnings.js +2 -2
- package/modules/memory/memory.js +1 -1
- package/modules/onboarding/onboarding.js +1 -1
- package/modules/platform-identity/routes/my-projects.js +1 -1
- package/modules/platform-identity/routes/sso.js +2 -2
- package/modules/public-landing/public/index.html +2 -2
- package/modules/public-landing/public/projects-floor.states.json +1 -1
- package/modules/public-landing/public/projects.html +1 -1
- package/modules/public-landing/public/projects.states.json +1 -1
- package/modules/sessions/db.js +120 -0
- package/modules/sessions/module.json +2 -2
- package/modules/sessions/pollers/session-upload-health.js +111 -0
- package/modules/sessions/pulse.js +2 -2
- package/modules/sessions/routes/sessions.js +46 -0
- package/modules/sessions/upload-health.js +197 -0
- package/modules/status-ui/module.json +1 -1
- package/modules/status-ui/public/explore.js +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/agent-invoke.js +3 -3
- package/scripts/gds/api.js +4 -4
- package/scripts/gds/api.sh +1 -1
- package/scripts/gds/architect-audit.js +1 -1
- package/scripts/gds/artifact-audit.js +2 -2
- package/scripts/gds/audit-ships.js +2 -2
- package/scripts/gds/backfill-cost.js +1 -1
- package/scripts/gds/backfill-sessions.js +1 -1
- package/scripts/gds/backfill-subagent-rewards.js +1 -1
- package/scripts/gds/backfill-task-rewards.js +2 -2
- package/scripts/gds/box-auth-check.js +1 -1
- package/scripts/gds/box-sync.js +3 -3
- package/scripts/gds/box.js +10 -10
- package/scripts/gds/build-cli-package.js +3 -3
- package/scripts/gds/capture.js +2 -2
- package/scripts/gds/ci-grade.js +1 -1
- package/scripts/gds/claim-recall.js +2 -2
- package/scripts/gds/cli-lib.js +3 -3
- package/scripts/gds/context-pack.js +1 -1
- package/scripts/gds/copy-apply.js +2 -2
- package/scripts/gds/dev-lib.js +2 -2
- package/scripts/gds/fetch-art-key.js +2 -2
- package/scripts/gds/fetch-sound-prefs.js +3 -3
- package/scripts/gds/grade-smoke.js +1 -1
- package/scripts/gds/hooks/pre-push.js +1 -1
- package/scripts/gds/init.js +9 -9
- package/scripts/gds/key-card.js +1 -1
- package/scripts/gds/learning-capture.js +2 -2
- package/scripts/gds/linkify-refs.js +2 -2
- package/scripts/gds/local-preview-lib.js +1 -1
- package/scripts/gds/login.js +11 -10
- package/scripts/gds/main-audit.js +1 -1
- package/scripts/gds/newcomer-floor.config.json +1 -1
- package/scripts/gds/newcomer-floor.js +2 -2
- package/scripts/gds/newcomer-floor.templates.json +2 -2
- package/scripts/gds/onboarding-ship.js +1 -1
- package/scripts/gds/paste-token.js +3 -3
- package/scripts/gds/portability-smoke-memory.sh +5 -5
- package/scripts/gds/prove-strict-versioning.js +2 -2
- package/scripts/gds/provision-net.js +2 -2
- package/scripts/gds/provision-units.js +3 -3
- package/scripts/gds/pulse.js +2 -2
- package/scripts/gds/push-path-brief.js +2 -2
- package/scripts/gds/reauth.js +1 -1
- package/scripts/gds/recall.js +1 -1
- package/scripts/gds/redteam-patrol.js +3 -3
- package/scripts/gds/render-ideas.js +5 -5
- package/scripts/gds/repo-metrics.js +1 -1
- package/scripts/gds/sandbox-stage.js +3 -3
- package/scripts/gds/seed-adopt-tasks.js +3 -3
- package/scripts/gds/seed-board-room-tasks.js +1 -1
- package/scripts/gds/seed-bongos-app-tasks.js +2 -2
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +3 -3
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +4 -4
- package/scripts/gds/seed-bongos-tasks.js +5 -5
- package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +1 -1
- package/scripts/gds/seed-bongos-v1-seo-tasks.js +1 -1
- package/scripts/gds/seed-bv1-community-tasks.js +1 -1
- package/scripts/gds/seed-bv1-privacy-invites-tasks.js +1 -1
- package/scripts/gds/seed-bv1-profile-page-tasks.js +1 -1
- package/scripts/gds/seed-bv1-profiles-tasks.js +1 -1
- package/scripts/gds/seed-bv1-r01-delta-tasks.js +1 -1
- package/scripts/gds/seed-gds-v4-tasks.js +3 -3
- package/scripts/gds/seed-medusa-tasks.js +1 -1
- package/scripts/gds/seed-productization-tasks.js +1 -1
- package/scripts/gds/seed-project-admin-console-tasks.js +1 -1
- package/scripts/gds/seed-provisioning-tasks.js +2 -2
- package/scripts/gds/seed-strict-versioning-tasks.js +3 -3
- package/scripts/gds/seed-v2-world-tasks.js +2 -2
- package/scripts/gds/seed-verify-criteria.js +1 -1
- package/scripts/gds/session-digest.js +1 -1
- package/scripts/gds/session.js +2 -2
- package/scripts/gds/setup.js +7 -7
- package/scripts/gds/ship-flow.js +3 -3
- package/scripts/gds/ship-grade-steps.js +3 -3
- package/scripts/gds/ship-memory-sync.js +1 -1
- package/scripts/gds/ship-session-upload.js +3 -3
- package/scripts/gds/smoke-batch-claim.sh +10 -10
- package/scripts/gds/smoke-batch-release.sh +14 -14
- package/scripts/gds/smoke-claim-consistency.sh +19 -19
- package/scripts/gds/smoke-dependencies.sh +9 -9
- package/scripts/gds/smoke-write.sh +11 -11
- package/scripts/gds/start.js +1 -1
- package/scripts/gds/status.js +2 -2
- package/scripts/gds/strand-watch.js +1 -1
- package/scripts/gds/triage.js +4 -4
- package/scripts/gds/version-close.js +2 -2
- package/scripts/hall-preview/README.md +1 -1
- package/scripts/hall-preview/server.js +1 -1
- package/src/bongos/auth-admission.js +3 -3
- package/src/bongos/auth-idp.js +2 -2
- package/src/bongos/auth.js +3 -3
- package/src/bongos/db.js +2 -2
- package/src/bongos/llm-cache.js +2 -2
- package/src/bongos/metrics.js +1 -1
- package/src/bongos/middleware/audit.js +3 -3
- package/src/bongos/middleware/rate-limit.js +1 -1
- package/src/bongos/platform-visibility-gate.js +2 -2
- package/src/bongos/routes/_helpers.js +1 -1
- package/src/bongos/routes/audit-log.js +1 -1
- package/src/bongos/routes/auth.js +5 -5
- package/src/bongos/routes/backup.js +1 -1
- package/src/bongos/routes/builders.js +1 -1
- package/src/bongos/routes/instance.js +1 -1
- package/src/bongos/routes/live.js +1 -1
- package/src/bongos/routes/me.js +2 -2
- package/src/bongos/routes/modules.js +2 -2
- package/src/bongos/routes/public.js +1 -1
- package/src/bongos/routes/security.js +4 -4
- package/src/bongos/routes.js +1 -1
- package/src/bongos/serve-internal.js +6 -6
- package/src/branding.js +1 -1
- package/src/module-api.js +1 -1
- package/src/module-seams.js +2 -2
- package/src/platform-server.js +2 -2
- package/tests/api_alias_exceptions.mjs +67 -0
- package/tests/application_echo.mjs +12 -12
- package/tests/artifact_audit.mjs +1 -1
- package/tests/auth_page_gate.mjs +4 -4
- package/tests/auth_web_recovery.mjs +11 -11
- package/tests/bongos_login.mjs +7 -4
- package/tests/box_env.mjs +6 -6
- package/tests/bug_attachments.mjs +1 -1
- package/tests/cli_sessions.mjs +1 -1
- package/tests/dev_lib.mjs +1 -1
- package/tests/discord_bugs.mjs +2 -2
- package/tests/discord_inbound.mjs +2 -2
- package/tests/explore_visible_states.mjs +1 -1
- package/tests/goal_invite_consent.mjs +307 -0
- package/tests/government_page_gates.mjs +1 -1
- package/tests/hall_reference_world.mjs +1 -1
- package/tests/idea_ideate_full.mjs +1 -1
- package/tests/idp_federation.mjs +2 -2
- package/tests/llm-cache.mjs +1 -1
- package/tests/manage_manifest_shared_read.mjs +3 -3
- package/tests/people_directory_clip.mjs +1 -1
- package/tests/planning_session_skill.mjs +1 -1
- package/tests/platform_visibility_gate.mjs +15 -15
- package/tests/profile_route.mjs +25 -25
- package/tests/projects_hub.mjs +2 -2
- package/tests/provision.mjs +2 -2
- package/tests/provision_settings_apply.mjs +4 -4
- package/tests/sandbox_stage.mjs +8 -8
- package/tests/scouting_owner_access_and_reach.mjs +3 -3
- package/tests/session_upload_health.mjs +329 -0
- package/tests/setup_device_flow_fallback.mjs +1 -1
- package/tests/skill_ask_for_help.mjs +3 -3
- package/tests/skill_grade_audit.mjs +2 -2
- package/tests/skill_grader_health.mjs +3 -3
- package/tests/smoke_write_contract.mjs +1 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// modules/sessions/upload-health.js — the PURE verdict over session-upload
|
|
4
|
+
// coverage (task 1003865, goal 1000118).
|
|
5
|
+
//
|
|
6
|
+
// THE OUTAGE THIS EXISTS FOR. A Windows path-encoding bug made every transcript
|
|
7
|
+
// lookup miss, so each ship skipped its session upload with `transcript_not_found`.
|
|
8
|
+
// No session_records row was written, so no `session.token_reward` credit booked —
|
|
9
|
+
// and since ADR 0146 made cost-plus the SOLE reward stream, the affected builder
|
|
10
|
+
// earned nothing for real shipped work. It ran for weeks before a human noticed.
|
|
11
|
+
//
|
|
12
|
+
// WHY NOTHING NOTICED. The only trace was `session-upload-skips.jsonl`, written by
|
|
13
|
+
// recordUploadSkip on the BUILDER'S OWN MACHINE. It never reaches the server, so
|
|
14
|
+
// from the server's side a skipped upload and a builder who simply did not work
|
|
15
|
+
// look identical: the absence of a row, in both cases.
|
|
16
|
+
//
|
|
17
|
+
// So the signal is built from two things the server already knows INDEPENDENTLY:
|
|
18
|
+
// a task reached `shipped`, and whether that task's builder uploaded any session
|
|
19
|
+
// around then. A ship with no session record for its builder inside a window is
|
|
20
|
+
// the unit of evidence.
|
|
21
|
+
//
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// PER BUILDER, AND THAT IS THE WHOLE DESIGN — measured, not assumed.
|
|
24
|
+
//
|
|
25
|
+
// The obvious version of this check — the uncovered share across the CORPUS —
|
|
26
|
+
// cannot see the outage at all. Measured against the real corpora on 2026-09-16
|
|
27
|
+
// (4,495 session records and 2,640 ships carrying shipped_at + shipped_by, paged
|
|
28
|
+
// out of /sessions/search and /tasks):
|
|
29
|
+
//
|
|
30
|
+
// corpus-wide uncovered share, ±24h: 2026-06 1.7% · 2026-07 3.4% ·
|
|
31
|
+
// 2026-08 2.0% · 2026-09 0.2%
|
|
32
|
+
//
|
|
33
|
+
// July and August — the outage months — are indistinguishable from the rest. Of
|
|
34
|
+
// course they are: the failure was one builder on one machine, about 19 ships out
|
|
35
|
+
// of the ~1,164 that landed across those two months. A corpus-wide ratio puts the
|
|
36
|
+
// signal two orders of magnitude beneath its own noise floor.
|
|
37
|
+
//
|
|
38
|
+
// Keyed on the BUILDER, the same data separates cleanly. Re-running the check as
|
|
39
|
+
// it would have run — a rolling 14-day lookback stepped one day at a time over
|
|
40
|
+
// the ~92 evaluable days — at ±24h, min 8 ships, firing above 25%:
|
|
41
|
+
//
|
|
42
|
+
// fires on 13 days, ALL of them 2026-07-24 … 2026-08-05, ALL one builder
|
|
43
|
+
// peak 2026-07-25: 19 of 19 ships with no session record — a total outage
|
|
44
|
+
// silent on the other ~79 days and on every other builder
|
|
45
|
+
//
|
|
46
|
+
// That is the stated outage window (2026-07 into 2026-08) and about the stated
|
|
47
|
+
// ship count ("at least 16 ships"), found without being told where to look.
|
|
48
|
+
//
|
|
49
|
+
// The window width is measured too, not chosen: at ±12h the same sweep fires on
|
|
50
|
+
// 27 days across THREE builders — long sessions that upload once at the end drift
|
|
51
|
+
// past a narrow window and read as outages. ±24h keeps them in.
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
//
|
|
54
|
+
// KEYED ON BUILDER + TIME, NEVER ON task_ids. `session_records.task_ids` is EMPTY
|
|
55
|
+
// on 54% of rows (1,771 of 3,873 when task 1002448 measured it in 2026-09), so
|
|
56
|
+
// "no session record NAMES this task" is not a usable predicate — it reports the
|
|
57
|
+
// linkage gap as an outage. This file never sees task_ids at all, and the SQL in
|
|
58
|
+
// db.js does not mention it; a test asserts that about the SQL actually emitted.
|
|
59
|
+
//
|
|
60
|
+
// PURE so the firing condition is provable without a database, and so the route
|
|
61
|
+
// (on demand) and the poller (periodically) cannot answer the question two
|
|
62
|
+
// different ways.
|
|
63
|
+
|
|
64
|
+
// ---- the knobs, every one of them measured above ---------------------------
|
|
65
|
+
|
|
66
|
+
// The window around a ship in which its builder must have uploaded SOMETHING.
|
|
67
|
+
// The digest uploads at ship time (uploadSessionOnShip, inside finishShip), so a
|
|
68
|
+
// healthy ship's nearest upload is minutes away — p50 is 0.21h across the whole
|
|
69
|
+
// corpus. The width is for what is awkward but not an outage: a long session that
|
|
70
|
+
// uploads once after several ships, a land that polled for hours, a clock that
|
|
71
|
+
// disagrees. ±12h costs three false builders; ±24h costs nothing measurable.
|
|
72
|
+
const DEFAULT_WINDOW_HOURS = 24;
|
|
73
|
+
|
|
74
|
+
// How far back the check looks. Long enough that one quiet week cannot empty it,
|
|
75
|
+
// short enough that a resolved outage stops firing instead of haunting the number
|
|
76
|
+
// for a quarter. 14 days is what the sweep above was tuned on.
|
|
77
|
+
const DEFAULT_LOOKBACK_DAYS = 14;
|
|
78
|
+
|
|
79
|
+
// Below this many ships IN THE LOOKBACK, a builder is not judged at all. Three
|
|
80
|
+
// uncovered out of four is 75% and means nothing; the same share over twenty
|
|
81
|
+
// ships is the outage. A check that fires on someone's quiet fortnight teaches
|
|
82
|
+
// people to mute it, which is the state this task exists to fix.
|
|
83
|
+
const DEFAULT_MIN_SHIPS = 8;
|
|
84
|
+
|
|
85
|
+
// The uncovered share that counts as broken, per builder. The real outage ran at
|
|
86
|
+
// 86-100%; every healthy builder-fortnight in the same sweep stayed under this.
|
|
87
|
+
// Set here rather than at 50% so a PARTIAL outage — some ships uploading, some
|
|
88
|
+
// not — still fires, which is the shape a flaky path bug actually has.
|
|
89
|
+
const DEFAULT_MAX_UNCOVERED_SHARE = 0.25;
|
|
90
|
+
|
|
91
|
+
// ---- the clamps ------------------------------------------------------------
|
|
92
|
+
//
|
|
93
|
+
// Both reach an SQL interval, and both are reachable from a URL. They are clamped
|
|
94
|
+
// HERE rather than at the route because the route is not the only caller — the
|
|
95
|
+
// poller is the other — and a bound that lives at one of two call sites is not a
|
|
96
|
+
// bound.
|
|
97
|
+
function clampLookbackDays(n) {
|
|
98
|
+
const x = Number(n);
|
|
99
|
+
if (!Number.isFinite(x)) return DEFAULT_LOOKBACK_DAYS;
|
|
100
|
+
return Math.max(1, Math.min(365, Math.trunc(x)));
|
|
101
|
+
}
|
|
102
|
+
function clampWindowHours(n) {
|
|
103
|
+
const x = Number(n);
|
|
104
|
+
if (!Number.isFinite(x)) return DEFAULT_WINDOW_HOURS;
|
|
105
|
+
return Math.max(1, Math.min(720, Math.trunc(x)));
|
|
106
|
+
}
|
|
107
|
+
// The offender sample is evidence, not a report: enough rows to recognise the
|
|
108
|
+
// shape (one machine? one week? everyone?), never the whole corpus.
|
|
109
|
+
function clampSampleLimit(n) {
|
|
110
|
+
if (n == null) return 20;
|
|
111
|
+
const x = Number(n);
|
|
112
|
+
if (!Number.isFinite(x)) return 20;
|
|
113
|
+
return Math.max(1, Math.min(100, Math.trunc(x)));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---- the verdict -----------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
function toCount(v) {
|
|
119
|
+
const n = Number(v);
|
|
120
|
+
return Number.isFinite(n) && n > 0 ? Math.trunc(n) : 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// normalizeBuilderRows — take what the SQL returns (per-builder counts, with
|
|
124
|
+
// Postgres' bigint-as-string) and hand back clean numbers. A row without a
|
|
125
|
+
// builder is dropped rather than trusted, and an uncovered count above the ship
|
|
126
|
+
// count is a query bug, not an outage several times over: clamp, don't propagate.
|
|
127
|
+
function normalizeBuilderRows(rows) {
|
|
128
|
+
const list = Array.isArray(rows) ? rows : [];
|
|
129
|
+
return list
|
|
130
|
+
.filter((r) => r && r.builder_id != null)
|
|
131
|
+
.map((r) => {
|
|
132
|
+
const ships = toCount(r.ships);
|
|
133
|
+
const uncovered = Math.min(ships, toCount(r.uncovered));
|
|
134
|
+
return {
|
|
135
|
+
builder_id: String(r.builder_id),
|
|
136
|
+
github_login: r.github_login == null ? null : String(r.github_login),
|
|
137
|
+
ships,
|
|
138
|
+
uncovered,
|
|
139
|
+
uncovered_share: ships > 0 ? Number((uncovered / ships).toFixed(4)) : 0,
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// uploadHealthVerdict — is any builder's session upload silently failing?
|
|
145
|
+
//
|
|
146
|
+
// The verdict always carries its own arithmetic and names the builder, because
|
|
147
|
+
// the first question a firing check has to answer is "on what evidence", and the
|
|
148
|
+
// answer to "whose machine" is what makes it actionable. An alert that cannot
|
|
149
|
+
// answer either is one more thing to mute.
|
|
150
|
+
function uploadHealthVerdict(rows, opts = {}) {
|
|
151
|
+
const minShips = Number.isFinite(opts.minShips) ? opts.minShips : DEFAULT_MIN_SHIPS;
|
|
152
|
+
const maxShare = Number.isFinite(opts.maxUncoveredShare) ? opts.maxUncoveredShare : DEFAULT_MAX_UNCOVERED_SHARE;
|
|
153
|
+
const builders = normalizeBuilderRows(rows).sort((a, b) => b.uncovered_share - a.uncovered_share);
|
|
154
|
+
const judged = builders.filter((b) => b.ships >= minShips);
|
|
155
|
+
const offenders = judged.filter((b) => b.uncovered_share > maxShare);
|
|
156
|
+
const ships = builders.reduce((a, b) => a + b.ships, 0);
|
|
157
|
+
const uncovered = builders.reduce((a, b) => a + b.uncovered, 0);
|
|
158
|
+
const base = { ships, uncovered, builders, judged: judged.length, offenders, minShips, maxUncoveredShare: maxShare };
|
|
159
|
+
|
|
160
|
+
if (judged.length === 0) {
|
|
161
|
+
return {
|
|
162
|
+
...base,
|
|
163
|
+
firing: false,
|
|
164
|
+
status: 'insufficient-data',
|
|
165
|
+
reason: `no builder shipped ${minShips}+ tasks in the window (${builders.length} builder(s), ${ships} ship(s) total) — not enough to judge`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (offenders.length > 0) {
|
|
169
|
+
const worst = offenders[0];
|
|
170
|
+
const who = worst.github_login || `builder #${worst.builder_id}`;
|
|
171
|
+
const rest = offenders.length > 1 ? ` (and ${offenders.length - 1} other builder(s) over the line)` : '';
|
|
172
|
+
return {
|
|
173
|
+
...base,
|
|
174
|
+
firing: true,
|
|
175
|
+
status: 'uploads-missing',
|
|
176
|
+
reason: `${who} has ${worst.uncovered} of ${worst.ships} ships (${(worst.uncovered_share * 100).toFixed(1)}%) with no session record in the window${rest}. Their session uploads are probably failing, which means the cost-plus reward is not booking for work that shipped.`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
...base,
|
|
181
|
+
firing: false,
|
|
182
|
+
status: 'healthy',
|
|
183
|
+
reason: `${judged.length} builder(s) judged, worst ${(judged[0].uncovered_share * 100).toFixed(1)}% uncovered — under the ${(maxShare * 100).toFixed(0)}% threshold`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = {
|
|
188
|
+
DEFAULT_WINDOW_HOURS,
|
|
189
|
+
DEFAULT_LOOKBACK_DAYS,
|
|
190
|
+
DEFAULT_MIN_SHIPS,
|
|
191
|
+
DEFAULT_MAX_UNCOVERED_SHARE,
|
|
192
|
+
clampLookbackDays,
|
|
193
|
+
clampWindowHours,
|
|
194
|
+
clampSampleLimit,
|
|
195
|
+
normalizeBuilderRows,
|
|
196
|
+
uploadHealthVerdict,
|
|
197
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"key": "status-ui",
|
|
3
3
|
"title": "Status dashboard (\"The Watch\")",
|
|
4
|
-
"description": "The public build-status dashboard served at status.<apex> (status.example.com) — the live up/down banner, version-progress rollups, cost summary, recent ships, leaderboard, and the ecosystem fingerprint, all polling the read-only /api/
|
|
4
|
+
"description": "The public build-status dashboard served at status.<apex> (status.example.com) — the live up/down banner, version-progress rollups, cost summary, recent ships, leaderboard, and the ecosystem fingerprint, all polling the read-only /api/bongos/public/* surface every 60s. A WEB-SURFACE core-domain module carved out of the GDS core in BV1.R84 (ADR 0093 §1; 02-module-map §6 — a web surface is first-class). default-on: a Cloud Bongos instance ships its status page like it ships its hall. Registers no port and contributes no routes — it declares a webSurface (host prefix + static dir) the loader hands serve-internal, which serves the module's public/ dir on the matching host exactly as it served public-status/ before. The public read endpoints it renders stay SHARED core in routes/public.js (the hall + the off-box mirror read them too).",
|
|
5
5
|
"coreVersion": "^1.11.0",
|
|
6
6
|
"default": true,
|
|
7
7
|
"maintenance": { "status": "core-maintained" },
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
return el;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
fetch('/api/
|
|
116
|
+
fetch('/api/bongos/projects/featured', { headers: { Accept: 'application/json' } })
|
|
117
117
|
.then(function (r) { if (!r.ok) throw new Error('http ' + r.status); return r.json(); })
|
|
118
118
|
.then(function (data) {
|
|
119
119
|
var projects = (data && Array.isArray(data.projects)) ? data.projects : [];
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.806",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.806",
|
|
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.19.
|
|
3
|
+
"version": "1.19.806",
|
|
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",
|
|
@@ -610,7 +610,7 @@ module.exports = {
|
|
|
610
610
|
|
|
611
611
|
function usage() {
|
|
612
612
|
console.error('Usage: node scripts/gds/agent-invoke.js <agent> "<question>" [--out <path>] [--json]');
|
|
613
|
-
console.error(' <agent> the agent name as it appears in the registry (GET /api/
|
|
613
|
+
console.error(' <agent> the agent name as it appears in the registry (GET /api/bongos/agents)');
|
|
614
614
|
console.error(' --out <path> write the answer to a file and record it as the run\'s output_ref');
|
|
615
615
|
console.error(' --json print the whole result as JSON instead of prose');
|
|
616
616
|
}
|
|
@@ -624,7 +624,7 @@ async function main() {
|
|
|
624
624
|
// Rule 5. requireSession exits with its own guidance when there is no session.
|
|
625
625
|
const cli = require('./cli-lib');
|
|
626
626
|
await cli.requireSession();
|
|
627
|
-
const me = await cli.apiCall('GET', '/api/
|
|
627
|
+
const me = await cli.apiCall('GET', '/api/bongos/me');
|
|
628
628
|
const builder = (me && me.data && me.data.builder) || null;
|
|
629
629
|
if (!builder || !builder.id) {
|
|
630
630
|
console.error('agent-invoke: could not resolve who you are from /me — a fire has to be attributable.');
|
|
@@ -659,7 +659,7 @@ async function main() {
|
|
|
659
659
|
console.error(`\n ${name}: ${result.code}`);
|
|
660
660
|
if (result.reason) console.error(` ${result.reason}`);
|
|
661
661
|
if (result.code === 'agent_not_found') {
|
|
662
|
-
console.error(' Nothing by that name is in the registry. `node scripts/gds/api.js GET /api/
|
|
662
|
+
console.error(' Nothing by that name is in the registry. `node scripts/gds/api.js GET /api/bongos/agents` lists it.');
|
|
663
663
|
}
|
|
664
664
|
if (result.code === 'agent_refused' && /not enabled/.test(result.reason || '')) {
|
|
665
665
|
console.error(' Definitions land in the registry DISABLED by design: agents-sync reconciles');
|
package/scripts/gds/api.js
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
// session token + API base, so there is no manual token extraction here.
|
|
9
9
|
//
|
|
10
10
|
// Usage:
|
|
11
|
-
// node scripts/gds/api.js GET /api/
|
|
12
|
-
// node scripts/gds/api.js POST /api/
|
|
13
|
-
// node scripts/gds/api.js POST /api/
|
|
14
|
-
// echo '{"verdict":"promote"}' | node scripts/gds/api.js PATCH /api/
|
|
11
|
+
// node scripts/gds/api.js GET /api/bongos/inbox
|
|
12
|
+
// node scripts/gds/api.js POST /api/bongos/blockers/5/resolve --body '{"resolution_note":"fixed in #690"}'
|
|
13
|
+
// node scripts/gds/api.js POST /api/bongos/security/reports --body-file report.json
|
|
14
|
+
// echo '{"verdict":"promote"}' | node scripts/gds/api.js PATCH /api/bongos/inbox/12 --body-file -
|
|
15
15
|
//
|
|
16
16
|
// The HTTP status goes to STDERR ("POST /path → 201"); the pretty-printed JSON
|
|
17
17
|
// body goes to STDOUT, so `... | node -e ...` style piping stays clean. Exit 0
|
package/scripts/gds/api.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# scripts/gds/api.sh — Git Bash/Linux passthrough wrapper around api.js.
|
|
3
|
-
# MSYS_NO_PATHCONV avoids Git Bash mangling API paths (e.g. /api/
|
|
3
|
+
# MSYS_NO_PATHCONV avoids Git Bash mangling API paths (e.g. /api/bongos/inbox) into
|
|
4
4
|
# Windows paths before node ever sees them.
|
|
5
5
|
export MSYS_NO_PATHCONV=1
|
|
6
6
|
exec node "$(dirname "$0")/api.js" "$@"
|
|
@@ -268,7 +268,7 @@ async function main() {
|
|
|
268
268
|
console.log(`\n📜 wrote ${relDoc}`);
|
|
269
269
|
|
|
270
270
|
// File the seed ideas to the planning inbox. Payload mirrors capture.js
|
|
271
|
-
// (POST /api/
|
|
271
|
+
// (POST /api/bongos/inbox): { title, body_md, kind, suggested_version }.
|
|
272
272
|
// Provenance (which audit produced it) is folded into body_md.
|
|
273
273
|
let filed = 0;
|
|
274
274
|
const api = await cliClient();
|
|
@@ -157,7 +157,7 @@ async function fetchAuditedTasks({ call = apiCall } = {}) {
|
|
|
157
157
|
for (let page = 0; page < 100; page++) {
|
|
158
158
|
const q = buildTaskPageQuery({ status, limit: TASK_LIST_MAX_LIMIT, offset });
|
|
159
159
|
const qs = new URLSearchParams(q).toString();
|
|
160
|
-
const r = await call('GET', `/api/
|
|
160
|
+
const r = await call('GET', `/api/bongos/tasks?${qs}`);
|
|
161
161
|
if (!r || !r.ok) throw new Error(`GET /tasks?status=${status} → ${r && r.status}`);
|
|
162
162
|
const page_rows = (r.data && r.data.tasks) || [];
|
|
163
163
|
rows.push(...page_rows);
|
|
@@ -208,7 +208,7 @@ function blockerBody(stranded) {
|
|
|
208
208
|
|
|
209
209
|
async function fileBlocker(stranded, { call = apiCall } = {}) {
|
|
210
210
|
if (!stranded.length) return { filed: false, reason: 'nothing to report' };
|
|
211
|
-
const r = await call('POST', '/api/
|
|
211
|
+
const r = await call('POST', '/api/bongos/blockers', {
|
|
212
212
|
title: `${stranded.length} shipped task(s) claim an artifact nothing on main names`,
|
|
213
213
|
body_md: blockerBody(stranded),
|
|
214
214
|
source: 'artifact-audit',
|
|
@@ -160,7 +160,7 @@ async function fetchShipped(days) {
|
|
|
160
160
|
const d = b.domains || {};
|
|
161
161
|
const statusBase = String(d.statusOrigin || d.publicOrigin || '').replace(/\/+$/, '');
|
|
162
162
|
const r = await fetch(
|
|
163
|
-
`${statusBase}/api/
|
|
163
|
+
`${statusBase}/api/bongos/public/recent-shipped?days=${days}&limit=500`
|
|
164
164
|
);
|
|
165
165
|
const data = await r.json();
|
|
166
166
|
return data.tasks || [];
|
|
@@ -174,7 +174,7 @@ async function fetchFullTask(id) {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
async function fetchLearning(taskId) {
|
|
177
|
-
// /api/
|
|
177
|
+
// /api/bongos/learnings?task=<id> — we just need body_md.
|
|
178
178
|
const api = await cliClient();
|
|
179
179
|
const r = await api.learnings.getLearnings({ query: { task: taskId } });
|
|
180
180
|
if (!r.ok) return null;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Backfill cost_log from the art-pipeline cost ledger.
|
|
3
3
|
//
|
|
4
4
|
// Reads art/iterations/cost_ledger.jsonl (gitignored, lives in whichever
|
|
5
|
-
// worktree ran the pipeline) and POSTs each row to /api/
|
|
5
|
+
// worktree ran the pipeline) and POSTs each row to /api/bongos/cost.
|
|
6
6
|
//
|
|
7
7
|
// Idempotent thanks to migration 004_pms_cost_idempotency.sql:
|
|
8
8
|
// re-running this script is a no-op (skipped rows print as 'dup').
|
|
@@ -56,7 +56,7 @@ const argVal = (name) => {
|
|
|
56
56
|
};
|
|
57
57
|
const EXISTING_FILE = argVal('existing') || '/tmp/otb-existing-session-ids.txt';
|
|
58
58
|
const LIMIT = argVal('limit') ? parseInt(argVal('limit'), 10) : Infinity;
|
|
59
|
-
// The /api/
|
|
59
|
+
// The /api/bongos write limiter is per-IP 30 writes / 60s (the binding constraint;
|
|
60
60
|
// per-session is 60/60s). 2100ms spacing keeps us safely under 30/min so the
|
|
61
61
|
// limiter never trips during a long backfill. Override with --pace=<ms>.
|
|
62
62
|
const PACE_MS = argVal('pace') ? parseInt(argVal('pace'), 10) : 2100;
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
// SAFETY MODEL (mirrors scripts/gds/backfill-task-rewards.js, ADR 0097):
|
|
38
38
|
// * DRY-RUN BY DEFAULT. With no flags it prints the full plan + grand total and
|
|
39
39
|
// writes NOTHING. A live mint requires ALL of: --apply, Archon rank verified
|
|
40
|
-
// server-side via GET /api/
|
|
40
|
+
// server-side via GET /api/bongos/me, and a typed y/N confirmation (--yes skips
|
|
41
41
|
// only the typing).
|
|
42
42
|
// * IDEMPOTENT BY CONSTRUCTION, not by a new bookkeeping key. Every mint goes
|
|
43
43
|
// through the REAL reward writer (modules/economy/credits.js
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// * DRY-RUN BY DEFAULT. With no flags it prints the full plan + grand total
|
|
18
18
|
// and writes NOTHING. A live mint requires ALL of:
|
|
19
19
|
// --apply explicit opt-in to write
|
|
20
|
-
// Archon rank verified server-side via GET /api/
|
|
20
|
+
// Archon rank verified server-side via GET /api/bongos/me; the
|
|
21
21
|
// script refuses for any other rank
|
|
22
22
|
// interactive y/N a typed confirmation at the terminal (skip only
|
|
23
23
|
// with --yes, which an Archon must pass deliberately)
|
|
@@ -372,7 +372,7 @@ async function main() {
|
|
|
372
372
|
const api = await cliClient();
|
|
373
373
|
me = await api.me.getMe();
|
|
374
374
|
} catch (err) {
|
|
375
|
-
console.error('--apply requires a verified Archon session; could not reach /api/
|
|
375
|
+
console.error('--apply requires a verified Archon session; could not reach /api/bongos/me:', err.message);
|
|
376
376
|
await pool.end().catch(() => {});
|
|
377
377
|
process.exit(3);
|
|
378
378
|
}
|
|
@@ -70,7 +70,7 @@ async function probeMe(tokenInfo) {
|
|
|
70
70
|
const ctl = new AbortController();
|
|
71
71
|
const timer = setTimeout(() => ctl.abort(), ME_TIMEOUT_MS);
|
|
72
72
|
try {
|
|
73
|
-
const res = await fetch(`${tokenInfo.apiBase}/api/
|
|
73
|
+
const res = await fetch(`${tokenInfo.apiBase}/api/bongos/me`, {
|
|
74
74
|
method: 'GET',
|
|
75
75
|
headers: { Authorization: `Bearer ${tokenInfo.token}`, 'User-Agent': 'box-auth-check/1.0' },
|
|
76
76
|
signal: ctl.signal,
|
package/scripts/gds/box-sync.js
CHANGED
|
@@ -89,8 +89,8 @@ async function runWiden(argv) {
|
|
|
89
89
|
const listOnly = !add && !remove && !clear;
|
|
90
90
|
|
|
91
91
|
const r = listOnly
|
|
92
|
-
? await apiCall('GET', '/api/
|
|
93
|
-
: await apiCall('POST', '/api/
|
|
92
|
+
? await apiCall('GET', '/api/bongos/box/widen')
|
|
93
|
+
: await apiCall('POST', '/api/bongos/box/widen', {
|
|
94
94
|
...(add ? { add: [add] } : {}),
|
|
95
95
|
...(remove ? { remove: [remove] } : {}),
|
|
96
96
|
...(clear ? { clear: true } : {}),
|
|
@@ -200,7 +200,7 @@ function formatScopeReport(scope) {
|
|
|
200
200
|
async function reportScope() {
|
|
201
201
|
try {
|
|
202
202
|
const { apiCall } = require('./cli-lib');
|
|
203
|
-
const r = await apiCall('GET', '/api/
|
|
203
|
+
const r = await apiCall('GET', '/api/bongos/box/scope');
|
|
204
204
|
if (!r || r.status !== 200) {
|
|
205
205
|
console.log('scope: could not read your box scope right now (that does not affect the sync above).');
|
|
206
206
|
return;
|
package/scripts/gds/box.js
CHANGED
|
@@ -197,14 +197,14 @@ async function resolveBuilder(pool, ref) {
|
|
|
197
197
|
// 1002466). Split out of cmdProvision so GDS_BASE — and the named-tunnel block
|
|
198
198
|
// baked in beside it — can be unit-tested without DB/DO/Cloudflare.
|
|
199
199
|
//
|
|
200
|
-
// GDS_BASE is the FULL api base (origin + /api/
|
|
200
|
+
// GDS_BASE is the FULL api base (origin + /api/bongos), matching what
|
|
201
201
|
// infra/box-report-*.sh already derive from the session file when the env var is
|
|
202
202
|
// absent (`"$GDS_BASE/box/host-keys"` with no further path inserted) — every box
|
|
203
203
|
// used to get this only as a fallback derived on-box; baking it explicitly closes
|
|
204
204
|
// the one on-box script (box-source-fetch.sh, out-of-repo) that skips that
|
|
205
205
|
// derivation entirely and hardcodes a different instance's origin instead.
|
|
206
206
|
function buildBoxEnv({ apiOrigin, namedTunnel }) {
|
|
207
|
-
let env = `# /etc/otb/box.env — baked by box.js provision\nGDS_BASE=${String(apiOrigin).replace(/\/+$/, '')}/api/
|
|
207
|
+
let env = `# /etc/otb/box.env — baked by box.js provision\nGDS_BASE=${String(apiOrigin).replace(/\/+$/, '')}/api/bongos\n`;
|
|
208
208
|
if (namedTunnel) {
|
|
209
209
|
const { token, hostname, credential, previewHostname } = namedTunnel;
|
|
210
210
|
env += `# named tunnel (#771/#774, ADR 0038)\nBOX_TUNNEL_TOKEN=${token}\nBOX_TERMINAL_HOSTNAME=${hostname}\nBOX_TERMINAL_CREDENTIAL=${credential}\nBOX_PREVIEW_HOSTNAME=${previewHostname}\n`;
|
|
@@ -506,16 +506,16 @@ function printWelcomePacket(login, scope) {
|
|
|
506
506
|
console.log('own Mac/Windows (it signs you in, makes + registers your SSH key, and');
|
|
507
507
|
console.log('installs the Claude Desktop connection file):');
|
|
508
508
|
console.log('');
|
|
509
|
-
console.log(` macOS/Linux: curl -fsSL ${base}/api/
|
|
510
|
-
console.log(` Windows: irm ${base}/api/
|
|
511
|
-
console.log(` (guide: ${base}/api/
|
|
509
|
+
console.log(` macOS/Linux: curl -fsSL ${base}/api/bongos/box/connect.sh | bash`);
|
|
510
|
+
console.log(` Windows: irm ${base}/api/bongos/box/connect.ps1 | iex`);
|
|
511
|
+
console.log(` (guide: ${base}/api/bongos/box/connect )`);
|
|
512
512
|
console.log('');
|
|
513
513
|
console.log(`Then: restart Claude Desktop → Code → Environment → "${boxEnvLabel()} Dev Box".`);
|
|
514
514
|
console.log('');
|
|
515
515
|
console.log('On a Chromebook / browser-only device (no Claude Desktop)? Skip the above —');
|
|
516
516
|
console.log('your box serves its own terminal in a browser tab (ADR 0038). Once it is');
|
|
517
517
|
console.log('active, get the URL + password and open it:');
|
|
518
|
-
console.log(` GET ${base}/api/
|
|
518
|
+
console.log(` GET ${base}/api/bongos/box/terminal (or run /builder-box)`);
|
|
519
519
|
console.log('In that terminal, type `claude` to start working.');
|
|
520
520
|
console.log('');
|
|
521
521
|
console.log(`Your box: ${host} (scope=${scope})`);
|
|
@@ -532,8 +532,8 @@ async function cmdOnboard(pool, boxes, boxOnboard, ref, { apply, allowNoKeys })
|
|
|
532
532
|
console.error(`✖ @${builder.github_login} has no registered SSH key yet — the box would have no way in.`);
|
|
533
533
|
console.error('');
|
|
534
534
|
console.error(' Ask the builder to connect FIRST (this registers their key), then re-run onboard:');
|
|
535
|
-
console.error(` macOS/Linux: curl -fsSL ${gdsBase()}/api/
|
|
536
|
-
console.error(` Windows: irm ${gdsBase()}/api/
|
|
535
|
+
console.error(` macOS/Linux: curl -fsSL ${gdsBase()}/api/bongos/box/connect.sh | bash`);
|
|
536
|
+
console.error(` Windows: irm ${gdsBase()}/api/bongos/box/connect.ps1 | iex`);
|
|
537
537
|
console.error('');
|
|
538
538
|
console.error(' (Override with --allow-no-keys to provision a keyless box anyway — you will');
|
|
539
539
|
console.error(' then have to re-provision once they register a key.)');
|
|
@@ -890,7 +890,7 @@ async function cmdSweepDormant(pool, boxes, { apply }) {
|
|
|
890
890
|
|
|
891
891
|
const sendWarning = async (box, days) => {
|
|
892
892
|
const left = Math.max(CONFIG.dormantDays - days, 0);
|
|
893
|
-
const ping = postReclaimPing(`@${box.github_login} — your dev box has been parked ${days} days. Its saved disk image will be reclaimed in ${left} day(s) to save cost, and anything on it you haven't pushed will be gone with it. Wake it any time with POST /api/
|
|
893
|
+
const ping = postReclaimPing(`@${box.github_login} — your dev box has been parked ${days} days. Its saved disk image will be reclaimed in ${left} day(s) to save cost, and anything on it you haven't pushed will be gone with it. Wake it any time with POST /api/bongos/box/ensure to keep it.`);
|
|
894
894
|
if (!ping.ok) { pingFailed++; return false; }
|
|
895
895
|
await boxes.recordEvent(pool, {
|
|
896
896
|
boxId: box.id, builderId: box.builder_id, event: 'dormant_warning',
|
|
@@ -921,7 +921,7 @@ async function cmdSweepDormant(pool, boxes, { apply }) {
|
|
|
921
921
|
try {
|
|
922
922
|
await deprovisionOne(pool, boxes, needDo(), box, { actor: 'sweep:dormant' });
|
|
923
923
|
reclaimed++;
|
|
924
|
-
const ping = postReclaimPing(`@${box.github_login} — your dev box was parked for ${days} days and has now been reclaimed to save cost, as warned. Queue a fresh one anytime with POST /api/
|
|
924
|
+
const ping = postReclaimPing(`@${box.github_login} — your dev box was parked for ${days} days and has now been reclaimed to save cost, as warned. Queue a fresh one anytime with POST /api/bongos/box/ensure (no operator needed); your memory is server-side and unaffected.`);
|
|
925
925
|
if (!ping.ok) pingFailed++;
|
|
926
926
|
console.log(` ✓ reclaimed @${box.github_login} (parked ${days}d)${ping.ok ? '' : ' [chat ping failed]'}`);
|
|
927
927
|
} catch (e) { errors++; await markErrorUnlessDestroyed(pool, boxes, box.builder_id, e.message); console.log(` ✖ @${box.github_login}: ${e.message}`); }
|
|
@@ -131,7 +131,7 @@ const VERBS = {
|
|
|
131
131
|
login: { script: 'login.js', group: 'account', summary: 'Sign in to an instance (bongos login <url> — browser click, no paste)' },
|
|
132
132
|
reauth: { script: 'reauth.js', group: 'account', summary: 'Refresh your session' },
|
|
133
133
|
setup: { script: 'setup.js', group: 'account', summary: 'Finish builder setup on this instance (disciplines, consent)' },
|
|
134
|
-
box: { script: 'api.js', prefixArgs: ['POST', '/api/
|
|
134
|
+
box: { script: 'api.js', prefixArgs: ['POST', '/api/bongos/box/ensure'], group: 'account', summary: 'Turn on / wake your cloud dev box' },
|
|
135
135
|
shell: { script: 'shell.js', group: 'account', summary: 'Open a terminal on your dev box' },
|
|
136
136
|
code: { script: 'code.js', group: 'account', summary: 'Open VS Code on your dev box over Remote-SSH' },
|
|
137
137
|
|
|
@@ -142,7 +142,7 @@ const VERBS = {
|
|
|
142
142
|
cost: { script: 'cost.js', group: 'work', summary: 'Log a cost entry' },
|
|
143
143
|
release: { script: 'release.js', group: 'work', summary: 'Cancel a claim — task returns to ready' },
|
|
144
144
|
|
|
145
|
-
api: { script: 'api.js', group: 'work', summary: 'Call any instance endpoint (bongos api GET /api/
|
|
145
|
+
api: { script: 'api.js', group: 'work', summary: 'Call any instance endpoint (bongos api GET /api/bongos/me)' },
|
|
146
146
|
};
|
|
147
147
|
|
|
148
148
|
// Verbs that exist in the full core CLI and are deliberately absent here. The dispatcher prints
|
|
@@ -419,7 +419,7 @@ Run \`bongos help\` for the current list. In short: \`login\`, \`reauth\`, \`set
|
|
|
419
419
|
the web hall can do is reachable from the terminal:
|
|
420
420
|
|
|
421
421
|
\`\`\`sh
|
|
422
|
-
bongos api GET /api/
|
|
422
|
+
bongos api GET /api/bongos/me
|
|
423
423
|
\`\`\`
|
|
424
424
|
|
|
425
425
|
## Writing code
|
package/scripts/gds/capture.js
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
// --kind → server auto-classifies from title+body (keyword heuristics
|
|
38
38
|
// today; replaced by the real classifier when task B1 ships)
|
|
39
39
|
// --version → most recent version with status='building' (queried from
|
|
40
|
-
// /api/
|
|
40
|
+
// /api/bongos/versions); leave null if there isn't one
|
|
41
41
|
// --priority → null (set later at triage time)
|
|
42
42
|
// --goal → capture-time ROUTING (task 1003070, R09 of goal 1000071,
|
|
43
43
|
// interview decision 4). Naming a goal turns this filing into a
|
|
@@ -396,7 +396,7 @@ async function main() {
|
|
|
396
396
|
await offerToDevelop(idea.id);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
-
// Migration detection lives only on the server now (POST /api/
|
|
399
|
+
// Migration detection lives only on the server now (POST /api/bongos/tasks sets
|
|
400
400
|
// tasks.needs_migration from the title/description on create — migration 081,
|
|
401
401
|
// task 876). Ideas carry no touches[] and aren't tasks, so the old CLI-side
|
|
402
402
|
// "keep 'migrations/' in touches[]" hint was removed with the sentinel it
|
package/scripts/gds/ci-grade.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// gate (#855, ADR 0042). This is the security KEYSTONE for the ci deploy mode.
|
|
4
4
|
//
|
|
5
5
|
// WHY it must run in CI (not "read the recorded grade"):
|
|
6
|
-
// POST /api/
|
|
6
|
+
// POST /api/bongos/tasks/:id/grade records the grader scores FROM THE REQUEST
|
|
7
7
|
// BODY — the server does not independently recompute them. In laptop mode the
|
|
8
8
|
// grader runs on the OPERATOR's trusted machine, so that's fine. In ci mode the
|
|
9
9
|
// merge trigger moves to an UNTRUSTED builder machine; a tampered local ship.js
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
// Claim-time recall hits (#956 / V4.R18 — criterion sessions-start-knowing).
|
|
3
3
|
//
|
|
4
4
|
// When a builder claims a task, surface the top project-knowledge sources for it
|
|
5
|
-
// (POST /api/
|
|
5
|
+
// (POST /api/bongos/search — the rank/owner-scoped lexical recall layer, ADR 0060) so
|
|
6
6
|
// the work starts already pointed at the relevant ADRs / recipes / session-logs /
|
|
7
7
|
// learnings instead of re-discovering them. This is the claim-time half of the
|
|
8
8
|
// recall surface the V4.R04 context pack (#942) promised; #963 added the
|
|
9
|
-
// resumed-session (SessionStart) half. The two share the same /api/
|
|
9
|
+
// resumed-session (SessionStart) half. The two share the same /api/bongos/search call
|
|
10
10
|
// and the same title-cleaning, so a session sees the same knowledge whether it
|
|
11
11
|
// claims fresh or resumes.
|
|
12
12
|
//
|
package/scripts/gds/cli-lib.js
CHANGED
|
@@ -810,7 +810,7 @@ async function cliClient(opts = {}) {
|
|
|
810
810
|
// ---- does this instance even HAVE dev boxes? (task 1003730) -----------------
|
|
811
811
|
// The dev-box module is a CONTROL-PLANE capability: it provisions DigitalOcean droplets, so a
|
|
812
812
|
// hosted co-tenant instance runs without it. The instance manifest has always said so —
|
|
813
|
-
// GET /api/
|
|
813
|
+
// GET /api/bongos/instance carries modules.enabled — but no CLI script read it, so `bongos shell`
|
|
814
814
|
// on such an instance died with a bare `POST /box/ensure failed (HTTP 404: not_found)`.
|
|
815
815
|
//
|
|
816
816
|
// That mattered far more than a bad error string: the public CLI (ADR 0258) answers
|
|
@@ -956,7 +956,7 @@ function tableTask(t) {
|
|
|
956
956
|
|
|
957
957
|
// V3.R13 (#237): one-line "next: <stage>" nudge for newcomers.
|
|
958
958
|
//
|
|
959
|
-
// Given the /api/
|
|
959
|
+
// Given the /api/bongos/me response, print a banner pointing at the next
|
|
960
960
|
// uncleared onboarding stage. Silent when the builder has graduated or has
|
|
961
961
|
// already cleared first_ship (the post-newcomer threshold) — gates lift
|
|
962
962
|
// after the first ship, so the nudge is too. Also silent when the
|
|
@@ -1038,7 +1038,7 @@ function printCostWarning(meBody) {
|
|
|
1038
1038
|
}
|
|
1039
1039
|
|
|
1040
1040
|
// task 1013 / ADR 0073: the CLI half of the consistent "the system needs an input
|
|
1041
|
-
// from you" signal. Given the /api/
|
|
1041
|
+
// from you" signal. Given the /api/bongos/me response, print a short line for each
|
|
1042
1042
|
// `needs` item in the action_needed state — the builder's private surface is the
|
|
1043
1043
|
// right place to tell them an input is missing (mirrors printCostWarning). Silent
|
|
1044
1044
|
// when nothing needs action (covered / satisfied items don't nag) or when the
|
|
@@ -184,7 +184,7 @@ function osFacts({ platform, runWhich }) {
|
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// Normalize active claims (from /api/
|
|
187
|
+
// Normalize active claims (from /api/bongos/me) into {id, title, current} rows.
|
|
188
188
|
// currentTaskId marks the one just claimed so the print can say "(this one)".
|
|
189
189
|
function normalizeClaims(activeClaims, currentTaskId) {
|
|
190
190
|
const rows = Array.isArray(activeClaims) ? activeClaims : [];
|
|
@@ -219,7 +219,7 @@ function refuse(result) {
|
|
|
219
219
|
// answered from the same source of truth — the shape of bug where a rule is
|
|
220
220
|
// enforced on one path and merely stated on the other (task 1003493).
|
|
221
221
|
async function activeClaims() {
|
|
222
|
-
const me = await apiCall('GET', '/api/
|
|
222
|
+
const me = await apiCall('GET', '/api/bongos/me');
|
|
223
223
|
if (!me.ok) return { ok: false, code: 'no_session', detail: { status: me.status, run: 'node scripts/gds/setup.js' } };
|
|
224
224
|
return { ok: true, claims: me.data.active_claims || (me.data.active_claim ? [me.data.active_claim] : []) };
|
|
225
225
|
}
|
|
@@ -295,7 +295,7 @@ async function loadPatch({ taskId, patchFile }) {
|
|
|
295
295
|
? ['```' + proposals.FENCE, raw.trim(), '```'].join('\n')
|
|
296
296
|
: raw);
|
|
297
297
|
}
|
|
298
|
-
const res = await apiCall('GET', `/api/
|
|
298
|
+
const res = await apiCall('GET', `/api/bongos/tasks/${taskId}`);
|
|
299
299
|
if (!res.ok) {
|
|
300
300
|
return { ok: false, code: 'task_unreadable', detail: { task: taskId, status: res.status } };
|
|
301
301
|
}
|