@bongos/core 1.19.316 → 1.19.318
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 +108 -33
- package/modules/economy/cost.js +84 -19
- package/modules/lifecycle/db-analytics.js +719 -0
- package/modules/lifecycle/db-claim-reads.js +165 -0
- package/modules/lifecycle/db-claims.js +934 -0
- package/modules/lifecycle/db-deps-criteria.js +441 -0
- package/modules/lifecycle/db-goals.js +763 -0
- package/modules/lifecycle/db-grade.js +233 -0
- package/modules/lifecycle/db-overrides.js +181 -0
- package/modules/lifecycle/db-rank-authz.js +446 -0
- package/modules/lifecycle/db-shared.js +115 -0
- package/modules/lifecycle/db-ship.js +994 -0
- package/modules/lifecycle/db-tasks.js +810 -0
- package/modules/lifecycle/db-versions.js +118 -0
- package/modules/lifecycle/db.js +167 -5564
- package/modules/lifecycle/publish-reconciler.js +7 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/coreB-carve-proof.sh +18 -9
- package/scripts/gds/fitness.js +34 -26
- package/scripts/gds/identity-strip.js +75 -0
- package/scripts/gds/provision.js +7 -3
- package/scripts/gds/run-unit-tests.js +8 -1
- package/scripts/gds/session-cost.js +16 -0
- package/scripts/gds/session-digest-build.js +261 -0
- package/scripts/gds/ship.js +7 -198
- package/src/module-api.js +5 -1
- package/tests/auto_satisfy_criteria.mjs +3 -2
- package/tests/dependencies_migration.mjs +3 -2
- package/tests/fitness.mjs +43 -0
- package/tests/goal_abuse_matrix.mjs +3 -2
- package/tests/goal_advisory.mjs +3 -2
- package/tests/government_claim_eligibility.mjs +3 -1
- package/tests/government_rank_sync.mjs +9 -2
- package/tests/helpers.mjs +19 -0
- package/tests/migration_allocation.mjs +3 -1
- package/tests/publish_reconciler.mjs +41 -1
- package/tests/rank_gate.mjs +3 -1
- package/tests/reward_gate.mjs +3 -1
- package/tests/session_cost.mjs +64 -0
- package/tests/session_cost_row_raise.mjs +139 -0
- package/tests/session_records.mjs +72 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// modules/lifecycle/db-claim-reads.js — read-only claim + grade lookups (no state transitions).
|
|
2
|
+
//
|
|
3
|
+
// Carved out of modules/lifecycle/db.js by task 1003204 (goal 1000079, the R03
|
|
4
|
+
// de-monolith plan) — a STRUCTURAL move, not a rewrite: the code below is the
|
|
5
|
+
// original db.js lines 4774-4915 unchanged. db.js remains the facade that
|
|
6
|
+
// re-exports every name, so every existing db call site is unchanged.
|
|
7
|
+
//
|
|
8
|
+
// THE BOUNDARY (ADR 0093 §1): this file reaches core ONLY through the published
|
|
9
|
+
// doorway ../../src/module-api.js — never a core internal, never a sibling module.
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const api = require('../../src/module-api');
|
|
14
|
+
const { pool } = api;
|
|
15
|
+
|
|
16
|
+
async function getActiveClaimsForBuilder(builderId) {
|
|
17
|
+
// release_requested_* (task 1736): a goal owner/manager's flag-for-release
|
|
18
|
+
// nudge rides on the holder's own claim read so /me (and the surfaces built
|
|
19
|
+
// on it) can show "someone asked you to wrap this up".
|
|
20
|
+
const { rows } = await pool.query(
|
|
21
|
+
`SELECT c.id AS claim_id, c.task_id, c.worktree_name, c.claimed_at,
|
|
22
|
+
c.head_sha, c.reserved_migration_number,
|
|
23
|
+
c.release_requested_by, c.release_requested_at, c.release_requested_note,
|
|
24
|
+
t.title, t.touches, t.priority, t.credits_reward, t.version_id, t.module_key
|
|
25
|
+
FROM claims c JOIN tasks t ON t.id = c.task_id
|
|
26
|
+
WHERE c.builder_id = $1 AND c.released_at IS NULL
|
|
27
|
+
ORDER BY c.claimed_at`,
|
|
28
|
+
[builderId]
|
|
29
|
+
);
|
|
30
|
+
return rows;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Task-scoped dev box (goal 1000051 / R92, ADR 0148 §2). The set-union of the
|
|
34
|
+
// module KEYS a builder's active claims put in scope: each active claim's task →
|
|
35
|
+
// its goal → goal.scope_modules (the ADR 0086 scope wall), unioned + deduped
|
|
36
|
+
// across all the builder's active claims. This is the "what code does this
|
|
37
|
+
// builder's current work need" signal the dev-box source-access resolver
|
|
38
|
+
// (modules/dev-box/box-access.js, wired in R93/R94) maps to git sparse-checkout
|
|
39
|
+
// globs via the doorway `moduleScopeMap`. Returns [] when the builder holds no
|
|
40
|
+
// active claim, or when every claimed task carries no goal / an empty
|
|
41
|
+
// scope_modules — the box then falls back to BASE-only (the pre-existing Bongos
|
|
42
|
+
// instance). KEYS only; glob resolution is the box module's job (it reaches
|
|
43
|
+
// moduleScopeMap through the doorway, never a core-internal require — the
|
|
44
|
+
// R90/ADR-0148 boundary). Honours the #538 deps.pool test seam
|
|
45
|
+
// (NODE_ENV==='test' only), like the goals reads above.
|
|
46
|
+
async function moduleScopeForActiveClaims(builderId, deps = {}) {
|
|
47
|
+
const activePool = (deps.pool && process.env.NODE_ENV === 'test') ? deps.pool : pool;
|
|
48
|
+
const id = Number(builderId);
|
|
49
|
+
if (!Number.isInteger(id)) {
|
|
50
|
+
throw new Error('moduleScopeForActiveClaims: builderId must be numeric');
|
|
51
|
+
}
|
|
52
|
+
const { rows } = await activePool.query(
|
|
53
|
+
`SELECT DISTINCT m AS module_key
|
|
54
|
+
FROM claims c
|
|
55
|
+
JOIN tasks t ON t.id = c.task_id
|
|
56
|
+
JOIN goals g ON g.id = t.goal_id
|
|
57
|
+
CROSS JOIN LATERAL unnest(g.scope_modules) AS m
|
|
58
|
+
WHERE c.builder_id = $1 AND c.released_at IS NULL
|
|
59
|
+
ORDER BY m`,
|
|
60
|
+
[id]
|
|
61
|
+
);
|
|
62
|
+
return rows.map((r) => r.module_key);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Task 1002729 — the companion signal moduleScopeForActiveClaims cannot carry.
|
|
66
|
+
// That query INNER JOINs goals and unnests scope_modules, so it returns [] for
|
|
67
|
+
// BOTH "this builder holds no claim" and "this builder holds claims whose goals
|
|
68
|
+
// declare no scope_modules". Those must not be treated alike: the first is a
|
|
69
|
+
// genuinely unscoped box (BASE-only is right), the second is a builder actively
|
|
70
|
+
// working who would be handed a box with no modules/ at all. Live evidence for
|
|
71
|
+
// why this matters: 247 of 248 source grants on the cloudbongos fleet resolved to
|
|
72
|
+
// BASE, including an Archon holding 7 active claims — every one of those claims
|
|
73
|
+
// sat on a goal with scope_modules = {}. Counts CLAIMS, deliberately not joining
|
|
74
|
+
// goals, so it stays true regardless of how the goal wall is (or isn't) declared.
|
|
75
|
+
async function activeClaimCountForBuilder(builderId, deps = {}) {
|
|
76
|
+
const activePool = (deps.pool && process.env.NODE_ENV === 'test') ? deps.pool : pool;
|
|
77
|
+
const id = Number(builderId);
|
|
78
|
+
if (!Number.isInteger(id)) {
|
|
79
|
+
throw new Error('activeClaimCountForBuilder: builderId must be numeric');
|
|
80
|
+
}
|
|
81
|
+
const { rows } = await activePool.query(
|
|
82
|
+
`SELECT count(*)::int AS n FROM claims WHERE builder_id = $1 AND released_at IS NULL`,
|
|
83
|
+
[id]
|
|
84
|
+
);
|
|
85
|
+
return rows.length ? Number(rows[0].n) : 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// task 1642 — every active claim bound to a given CLI session. "Active" is the
|
|
89
|
+
// claims-table convention (released_at IS NULL); there is NO `status` column on
|
|
90
|
+
// claims (a common misread — the task's status lives on `tasks`). Keyed on
|
|
91
|
+
// creator_session_id (the auth-token session shared across a builder's worktrees),
|
|
92
|
+
// NOT builder_id. This backs the one-active-claim guard (shouldRefuseSessionClaim),
|
|
93
|
+
// which further discriminates by `worktree_name` — the real commingle boundary —
|
|
94
|
+
// so two claims can coexist for one auth session as long as they land in different
|
|
95
|
+
// worktrees. NULL-session callers must never reach this — they are session-UNBOUND
|
|
96
|
+
// web claims (bind_session=false) that any CLI session may adopt; the route
|
|
97
|
+
// short-circuits before calling here.
|
|
98
|
+
async function getActiveClaimsForSession(creatorSessionId) {
|
|
99
|
+
if (!creatorSessionId) return [];
|
|
100
|
+
const { rows } = await pool.query(
|
|
101
|
+
// task 1002709: requested_worktree_name rides along because the guard keys on
|
|
102
|
+
// it — comparing the incoming REQUESTED name against a stored DISAMBIGUATED
|
|
103
|
+
// one is what let a second same-tree claim through. worktree_name stays
|
|
104
|
+
// selected: callers still render the on-disk name.
|
|
105
|
+
`SELECT c.id AS claim_id, c.task_id, c.creator_session_id, c.worktree_name,
|
|
106
|
+
c.requested_worktree_name, c.claimed_at,
|
|
107
|
+
t.title
|
|
108
|
+
FROM claims c JOIN tasks t ON t.id = c.task_id
|
|
109
|
+
WHERE c.creator_session_id = $1 AND c.released_at IS NULL
|
|
110
|
+
ORDER BY c.claimed_at`,
|
|
111
|
+
[creatorSessionId]
|
|
112
|
+
);
|
|
113
|
+
return rows;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// The builder who most recently held a claim on this task — active OR resolved.
|
|
117
|
+
// Used by the `--regrade` ownership guard (#678): when a ship lands at
|
|
118
|
+
// `completed` but the subagent grader fails, the claim is already consumed, so
|
|
119
|
+
// the only record of "whose work this is" lives in the claims ledger. Returns
|
|
120
|
+
// the latest claim row by claim time (id is the tiebreak, monotonic), joined to
|
|
121
|
+
// the builder for github_login, plus the claim's head_sha (the grader's
|
|
122
|
+
// last-resort baseline), or null if the task was never claimed. Deliberately
|
|
123
|
+
// does NOT return the holder's rank — the regrade gate keys off the CALLER's
|
|
124
|
+
// rank (from /me), and rank is sensitive metadata not previously on this read
|
|
125
|
+
// surface (grader hacker finding, #678). Pure read, builder-agnostic.
|
|
126
|
+
|
|
127
|
+
async function getLastClaimHolder(taskId) {
|
|
128
|
+
const { rows } = await pool.query(
|
|
129
|
+
`SELECT c.builder_id, c.head_sha, c.released_at, c.outcome, c.claimed_at,
|
|
130
|
+
b.github_login
|
|
131
|
+
FROM claims c
|
|
132
|
+
JOIN builders b ON b.id = c.builder_id
|
|
133
|
+
WHERE c.task_id = $1
|
|
134
|
+
ORDER BY c.claimed_at DESC, c.id DESC
|
|
135
|
+
LIMIT 1`,
|
|
136
|
+
[taskId]
|
|
137
|
+
);
|
|
138
|
+
return rows[0] ?? null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// getTaskGrade — fetch the current grade row for a task (V4.R08 diff-hash
|
|
142
|
+
// reuse). Returns { diff_hash, passed, score, threshold, grader_kind,
|
|
143
|
+
// grader_version, rubric_scores, signals, notes_md } or null when no grade
|
|
144
|
+
// exists yet. Used by ship.js before the grade step to detect "same diff →
|
|
145
|
+
// skip the panel".
|
|
146
|
+
async function getTaskGrade(taskId) {
|
|
147
|
+
const { rows } = await pool.query(
|
|
148
|
+
`SELECT diff_hash, passed, score, threshold, grader_kind, grader_version,
|
|
149
|
+
rubric_scores, signals, notes_md
|
|
150
|
+
FROM task_grades
|
|
151
|
+
WHERE task_id = $1
|
|
152
|
+
LIMIT 1`,
|
|
153
|
+
[taskId]
|
|
154
|
+
);
|
|
155
|
+
return rows[0] ?? null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = {
|
|
159
|
+
activeClaimCountForBuilder,
|
|
160
|
+
getActiveClaimsForBuilder,
|
|
161
|
+
getActiveClaimsForSession,
|
|
162
|
+
getLastClaimHolder,
|
|
163
|
+
getTaskGrade,
|
|
164
|
+
moduleScopeForActiveClaims,
|
|
165
|
+
};
|