@bongos/core 1.19.381 → 1.19.382
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 +43 -28
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +4 -0
- package/clients/bongos-client/index.cjs +4 -0
- package/clients/bongos-client/index.d.ts +6 -0
- package/clients/bongos-client/index.mjs +4 -0
- package/docs/api/openapi.json +141 -3
- package/docs/api-reference.md +5 -3
- package/docs/copy-inventory.md +14 -9
- package/docs/copy-registry.json +87 -42
- package/migrations/core_228_idea_inbox_captured_by_idx.sql +61 -0
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +4 -0
- package/modules/hall-ui/public/hall-kit.js +67 -6
- package/modules/hall-ui/public/profile.html +34 -2
- package/modules/hall-ui/public/profile.js +279 -0
- package/modules/ideas/inbox.js +98 -0
- package/modules/ideas/routes/inbox.js +39 -0
- package/modules/lifecycle/activity.js +205 -0
- package/modules/lifecycle/lifecycle.js +7 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/hall-preview/server.js +13 -3
- package/src/bongos/routes/builders.js +67 -0
- package/src/module-api.js +3 -1
- package/tests/profile_activity.mjs +625 -0
|
@@ -20,6 +20,7 @@ const db = require('./db');
|
|
|
20
20
|
const classifier = require('./task-classifier');
|
|
21
21
|
const helpRequests = require('./help-requests');
|
|
22
22
|
const taskRecommendations = require('./task-recommendations');
|
|
23
|
+
const activity = require('./activity');
|
|
23
24
|
|
|
24
25
|
module.exports = {
|
|
25
26
|
// --- retired doorway leaks (ADR 0093 §3) ---------------------------------
|
|
@@ -58,6 +59,12 @@ module.exports = {
|
|
|
58
59
|
recentGradesForBuilder: (...a) => db.recentGradesForBuilder(...a),
|
|
59
60
|
countShippedTasksForBuilder: (...a) => db.countShippedTasksForBuilder(...a),
|
|
60
61
|
recentShippedTasksByBuilder: (...a) => db.recentShippedTasksByBuilder(...a),
|
|
62
|
+
// builders.js (the profile's per-craft activity log, task 1003281): the paged
|
|
63
|
+
// "what did I do as an engineer / an artist" reads. Separate from the two
|
|
64
|
+
// above because those answer "how much, in total" and these answer "what,
|
|
65
|
+
// by craft" — the axis criterion legibility-activity-by-role asks for.
|
|
66
|
+
activityTasksByBuilder: (...a) => activity.activityTasksByBuilder(...a),
|
|
67
|
+
activityGoalsByBuilder: (...a) => activity.activityGoalsByBuilder(...a),
|
|
61
68
|
// ADR 0120 part 5: the confirmed tasks a builder owes a rebase on — the same
|
|
62
69
|
// read the part-3 claim gate uses, surfaced to me.js so the CLI + hall can
|
|
63
70
|
// show the owed-rebase warning that gates new claims (reward lands on ship).
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.382",
|
|
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.382",
|
|
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.382",
|
|
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",
|
|
@@ -82,6 +82,11 @@ const FIXTURE_FALLBACKS = [
|
|
|
82
82
|
[/^analytics\/builder\/\d+$/, 'analytics__builder'],
|
|
83
83
|
[/^builders\/\d+\/active-claims$/, 'builders__active-claims'],
|
|
84
84
|
[/^builders\/\d+\/profile$/, 'builders__profile'],
|
|
85
|
+
// the profile's per-craft activity log (task 1003281). One fixture per SECTION
|
|
86
|
+
// rather than per id, because the section is what changes the row shape; the
|
|
87
|
+
// craft and the page window are query string, which fixture matching ignores.
|
|
88
|
+
[/^builders\/\d+\/activity$/, (q) => (q.section === 'goals' ? 'builders__activity-goals' : 'builders__activity-tasks')],
|
|
89
|
+
[/^inbox\/by-builder\/\d+$/, 'inbox__by-builder'],
|
|
85
90
|
];
|
|
86
91
|
|
|
87
92
|
function loadFixture(name) {
|
|
@@ -102,12 +107,17 @@ function emptied(v) {
|
|
|
102
107
|
return v;
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
function
|
|
110
|
+
// A fallback name may be a plain string or a function of the query — the one
|
|
111
|
+
// case that needs it (task 1003281) is the profile activity log, where the ROW
|
|
112
|
+
// SHAPE is chosen by ?section=, not by the path, so one fixture per path would
|
|
113
|
+
// render goal rows into the tasks ledger.
|
|
114
|
+
function fixtureFor(apiPath, query = {}) {
|
|
106
115
|
const exact = loadFixture(apiPath.replace(/\//g, '__'));
|
|
107
116
|
if (exact !== undefined) return exact;
|
|
108
117
|
for (const [re, name] of FIXTURE_FALLBACKS) {
|
|
109
118
|
if (re.test(apiPath)) {
|
|
110
|
-
const
|
|
119
|
+
const resolved = typeof name === 'function' ? name(query) : name;
|
|
120
|
+
const hit = resolved && loadFixture(resolved);
|
|
111
121
|
if (hit !== undefined) return hit;
|
|
112
122
|
}
|
|
113
123
|
}
|
|
@@ -141,7 +151,7 @@ app.use((req, res, next) => {
|
|
|
141
151
|
if (req.method !== 'GET') {
|
|
142
152
|
return res.status(501).json({ error: { code: 'preview_readonly', message: 'the preview harness serves fixtures; writes are not wired' } });
|
|
143
153
|
}
|
|
144
|
-
const fix = fixtureFor(apiPath);
|
|
154
|
+
const fix = fixtureFor(apiPath, req.query || {});
|
|
145
155
|
if (fix === undefined) {
|
|
146
156
|
console.log(` no fixture: ${apiPath} (add scripts/hall-preview/fixtures/${apiPath.replace(/\//g, '__')}.json)`);
|
|
147
157
|
return res.status(404).json({ error: { code: 'no_fixture', message: apiPath } });
|
|
@@ -545,6 +545,73 @@ module.exports = function buildBuildersRouter() {
|
|
|
545
545
|
}
|
|
546
546
|
});
|
|
547
547
|
|
|
548
|
+
// GET /builders/:id/activity — the profile's PER-CRAFT activity log (task
|
|
549
|
+
// 1003281, goal 1000072, criterion legibility-activity-by-role).
|
|
550
|
+
//
|
|
551
|
+
// WHAT IT ADDS OVER /profile. The profile answers "how much has this person
|
|
552
|
+
// shipped" — one count and the last five works, craft-blind. A person's artist
|
|
553
|
+
// track record is a different question from their engineer one, so this route
|
|
554
|
+
// serves ONE section (`tasks` or `goals`) for ONE craft, paged. It EXTENDS the
|
|
555
|
+
// profile surface rather than forking it: the page is the same page, the
|
|
556
|
+
// identity band and the achievement shelf are unchanged, and this fills the
|
|
557
|
+
// ledger below them. The third section of that log — the IDEA TRAIL — is
|
|
558
|
+
// served by the ideas module's GET /inbox/by-builder/:id, because an idea is
|
|
559
|
+
// its domain's row, not a lifecycle one.
|
|
560
|
+
//
|
|
561
|
+
// ONE SECTION PER CALL, not all three in one payload: each ledger pages
|
|
562
|
+
// independently, and a single response carrying three page windows would need
|
|
563
|
+
// three limit/offset pairs on one query string to say anything at all.
|
|
564
|
+
//
|
|
565
|
+
// rank: any-builder, NOT owner-only — a track record is a thing other people
|
|
566
|
+
// read; that is what makes the profile a portfolio rather than a dashboard, and
|
|
567
|
+
// it is the same posture /profile, /builders/roster and the leaderboard already
|
|
568
|
+
// take toward the same rows. The per-viewer filtering that DOES matter is the
|
|
569
|
+
// private-goal wall below, and it is applied to the DATA, not to the caller.
|
|
570
|
+
//
|
|
571
|
+
// But, unlike /profile directly above, this read IS gated to a sign-in.
|
|
572
|
+
// The goals half is viewer-dependent: a private goal's title is exactly what
|
|
573
|
+
// ADR 0112 says a non-member must not learn, so the read needs to know who is
|
|
574
|
+
// asking. Serving it publicly would mean either leaking private goals or
|
|
575
|
+
// silently omitting the viewer's own — both worse than a sign-in. The tasks
|
|
576
|
+
// half is the same already-public shipped-work data /profile returns.
|
|
577
|
+
router.get('/builders/:id/activity', auth.requireBuilder, async (req, res) => {
|
|
578
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
579
|
+
if (targetId === null) return;
|
|
580
|
+
const section = req.query.section === 'goals' ? 'goals' : 'tasks';
|
|
581
|
+
// An unknown craft is normalized to "no filter" inside the module read
|
|
582
|
+
// rather than 400ing here — a stale bookmark should show the whole record,
|
|
583
|
+
// not an error card in the middle of a profile.
|
|
584
|
+
const role = typeof req.query.role === 'string' && req.query.role ? req.query.role : null;
|
|
585
|
+
const limit = Number(req.query.limit);
|
|
586
|
+
const offset = Number(req.query.offset);
|
|
587
|
+
try {
|
|
588
|
+
const b = await db.getBuilderById(targetId);
|
|
589
|
+
if (!b) return res.fail('builder_not_found', 404);
|
|
590
|
+
const viewer = req.builder || {};
|
|
591
|
+
const out = section === 'goals'
|
|
592
|
+
? await lc().activityGoalsByBuilder(targetId, {
|
|
593
|
+
role,
|
|
594
|
+
viewerId: viewer.id ?? null,
|
|
595
|
+
viewerIsArchon: viewer.rank === 'archon',
|
|
596
|
+
limit,
|
|
597
|
+
offset,
|
|
598
|
+
})
|
|
599
|
+
: await lc().activityTasksByBuilder(targetId, { role, limit, offset });
|
|
600
|
+
// Viewer-dependent (the goals half) and cheap to recompute — never cached.
|
|
601
|
+
res.set('Cache-Control', 'no-store');
|
|
602
|
+
res.json({
|
|
603
|
+
builder_id: targetId,
|
|
604
|
+
section,
|
|
605
|
+
role: role || null,
|
|
606
|
+
rows: out.rows,
|
|
607
|
+
total: out.total,
|
|
608
|
+
});
|
|
609
|
+
} catch (err) {
|
|
610
|
+
log.error('[gds] GET /builders/:id/activity', err);
|
|
611
|
+
res.fail('activity_read_failed', { status: 500, message: 'internal error' });
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
|
|
548
615
|
// GET /builders/me/pending-rank-change — V3.R28 / #249 ceremony signal #3.
|
|
549
616
|
//
|
|
550
617
|
// Returns the calling builder's most recent rank-change credit_log row, or
|
package/src/module-api.js
CHANGED
|
@@ -1202,8 +1202,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
1202
1202
|
// landed since 1.19.379 with no explicit bump. run 33085516721. (task 1002620)
|
|
1203
1203
|
// 1.19.381 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1204
1204
|
// landed since 1.19.380 with no explicit bump. run 33088290961. (task 1002620)
|
|
1205
|
+
// 1.19.382 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1206
|
+
// landed since 1.19.381 with no explicit bump. run 33094545251. (task 1002620)
|
|
1205
1207
|
// ---------------------------------------------------------------------------
|
|
1206
|
-
const CORE_VERSION = '1.19.
|
|
1208
|
+
const CORE_VERSION = '1.19.382'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
1207
1209
|
|
|
1208
1210
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
1209
1211
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|