@bongos/core 1.21.176 → 1.21.177
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 +61 -361
- package/.claude/skills/planning-session/SKILL.md +2 -2
- package/config/scheduled-routines.json +3 -8
- package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +1 -1
- package/docs/adr/0093-tranche-2-core-carve-sequence.md +1 -1
- package/docs/canonical-permissions.md +1 -1
- package/docs/file-map.md +3 -8
- package/docs/handoff-template.md +1 -1
- package/docs/module-api-changelog.md +2 -0
- package/docs/onboarding/diagrams/README.md +3 -7
- package/docs/onboarding/diagrams/assertions.json +3 -3
- package/docs/recipes/ops-gotchas.md +3 -1
- package/modules/autonomy/db.js +9 -0
- package/modules/autonomy/module.json +2 -2
- package/modules/autonomy/pollers/daily-checks.js +262 -0
- package/modules/autonomy/pollers/routine-timers.js +7 -5
- package/modules/autonomy/rank-roles.js +64 -0
- package/modules/autonomy/server-schedule.js +37 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +14 -0
- package/scripts/bongos/api-alias-caller-scan.js +2 -2
- package/scripts/bongos/audit-authorship.sh +0 -5
- package/scripts/bongos/audit-rank-roles.js +15 -56
- package/scripts/bongos/codemod-rename-scripts-gds.js +0 -1
- package/scripts/bongos/diagram-facts.js +1 -1
- package/scripts/bongos/do-api.js +1 -1
- package/scripts/bongos/fitness-checks-identity.js +4 -15
- package/scripts/bongos/gen-diagrams.js +3 -3
- package/scripts/bongos/pulse.js +5 -3
- package/scripts/bongos/routine-schedule.js +38 -3
- package/scripts/bongos/ship-regen.js +2 -3
- package/scripts/security/dep-audit.js +50 -124
- package/src/module-api.js +1 -1
- package/tests/autonomy_daily_checks.mjs +201 -0
- package/tests/claude_materialize.mjs +12 -12
- package/tests/effective_visibility_predicate.mjs +0 -18
- package/tests/routine_capture_kind.mjs +18 -7
- package/tests/routine_schedule.mjs +42 -0
- package/scripts/bongos/artifact-staleness.js +0 -267
- package/scripts/bongos/classify-discipline.js +0 -153
- package/scripts/bongos/codemod-rename-src-gds.js +0 -145
- package/scripts/bongos/coreB-carve-proof.sh +0 -725
- package/scripts/bongos/goal-names.js +0 -102
- package/scripts/bongos/rename-goals.js +0 -109
- package/scripts/bongos/seed-adopt-tasks.js +0 -75
- package/scripts/bongos/seed-api-contract-goal-tasks.js +0 -141
- package/scripts/bongos/seed-board-room-tasks.js +0 -196
- package/scripts/bongos/seed-bongos-app-tasks.js +0 -294
- package/scripts/bongos/seed-bongos-coreB-tranche1-tasks.js +0 -81
- package/scripts/bongos/seed-bongos-coreB-tranche2-tasks.js +0 -100
- package/scripts/bongos/seed-bongos-goal-hierarchy-tasks.js +0 -307
- package/scripts/bongos/seed-bongos-module-system-tasks.js +0 -346
- package/scripts/bongos/seed-bongos-tasks.js +0 -214
- package/scripts/bongos/seed-bongos-v1-seo-tasks.js +0 -104
- package/scripts/bongos/seed-bv1-community-tasks.js +0 -131
- package/scripts/bongos/seed-bv1-privacy-invites-tasks.js +0 -133
- package/scripts/bongos/seed-bv1-profile-page-tasks.js +0 -161
- package/scripts/bongos/seed-bv1-r01-delta-tasks.js +0 -154
- package/scripts/bongos/seed-bv2-tweak-mode-tasks.js +0 -277
- package/scripts/bongos/seed-gds-v4-tasks.js +0 -624
- package/scripts/bongos/seed-governance-tasks.js +0 -340
- package/scripts/bongos/seed-medusa-tasks.js +0 -440
- package/scripts/bongos/seed-module-upstreaming.js +0 -219
- package/scripts/bongos/seed-productization-tasks.js +0 -235
- package/scripts/bongos/seed-project-admin-console-tasks.js +0 -88
- package/scripts/bongos/seed-provisioning-tasks.js +0 -83
- package/scripts/bongos/seed-strict-versioning-tasks.js +0 -275
- package/scripts/bongos/seed-v2-world-tasks.js +0 -283
- package/scripts/gds/artifact-staleness.js +0 -7
- package/scripts/gds/classify-discipline.js +0 -7
- package/scripts/gds/codemod-rename-src-gds.js +0 -7
- package/scripts/gds/coreB-carve-proof.sh +0 -8
- package/scripts/gds/goal-names.js +0 -7
- package/scripts/gds/rename-goals.js +0 -7
- package/scripts/gds/seed-adopt-tasks.js +0 -7
- package/scripts/gds/seed-api-contract-goal-tasks.js +0 -7
- package/scripts/gds/seed-board-room-tasks.js +0 -6
- package/scripts/gds/seed-bongos-app-tasks.js +0 -7
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +0 -7
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +0 -7
- package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +0 -7
- package/scripts/gds/seed-bongos-module-system-tasks.js +0 -7
- package/scripts/gds/seed-bongos-tasks.js +0 -7
- package/scripts/gds/seed-bongos-v1-seo-tasks.js +0 -6
- package/scripts/gds/seed-bv1-community-tasks.js +0 -6
- package/scripts/gds/seed-bv1-privacy-invites-tasks.js +0 -6
- package/scripts/gds/seed-bv1-profile-page-tasks.js +0 -6
- package/scripts/gds/seed-bv1-r01-delta-tasks.js +0 -6
- package/scripts/gds/seed-bv2-tweak-mode-tasks.js +0 -6
- package/scripts/gds/seed-gds-v4-tasks.js +0 -7
- package/scripts/gds/seed-governance-tasks.js +0 -7
- package/scripts/gds/seed-medusa-tasks.js +0 -7
- package/scripts/gds/seed-module-upstreaming.js +0 -7
- package/scripts/gds/seed-productization-tasks.js +0 -7
- package/scripts/gds/seed-project-admin-console-tasks.js +0 -6
- package/scripts/gds/seed-provisioning-tasks.js +0 -7
- package/scripts/gds/seed-strict-versioning-tasks.js +0 -7
- package/scripts/gds/seed-v2-world-tasks.js +0 -7
- package/scripts/migrate_cost_ledger.sh +0 -178
- package/tests/artifact_staleness.mjs +0 -207
- package/tests/goal_names.mjs +0 -120
- package/tests/newcomer_generator.mjs +0 -48
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// scripts/bongos/goal-names.js — give every open goal a NAME, and move its
|
|
3
|
-
// explanation into `subtitle` (task 1003225, goal 1000072, criterion
|
|
4
|
-
// legibility-goal-names-and-claude-text).
|
|
5
|
-
//
|
|
6
|
-
// Owner directive: a goal's subtitle should not sit on its title. 28 open goals
|
|
7
|
-
// carried theirs after a dash and 3 more after a colon — the punctuation is not
|
|
8
|
-
// the point, the jamming is. Task 1003224 gave `goals` a `subtitle` column and
|
|
9
|
-
// taught the hall to render name / subtitle / Claude's prose at three weights;
|
|
10
|
-
// this moves the existing text into that shape.
|
|
11
|
-
//
|
|
12
|
-
// WHY A MAPPING FILE AND NOT 31 AD-HOC PATCHES. A rename is a judgment call, and
|
|
13
|
-
// judgment that lives only in a shell history cannot be reviewed, re-run, or
|
|
14
|
-
// argued with. The table below IS the decision: it can be read in a diff, its
|
|
15
|
-
// invariants are unit-tested (no duplicate names, no name still carrying its own
|
|
16
|
-
// explanation, nothing dropped), and re-running is a no-op.
|
|
17
|
-
//
|
|
18
|
-
// IT IS NOT A MECHANICAL SPLIT, which is the whole reason this is its own task.
|
|
19
|
-
// Splitting on the separator works where the head already names the thing
|
|
20
|
-
// ("Findability — the grep path"). It FAILS where the head is not distinctive:
|
|
21
|
-
// goals 1000038/1000039/1000040 all head "Agents module" and differ ONLY in the
|
|
22
|
-
// tail, so a split would leave three identically-named goals — strictly worse
|
|
23
|
-
// than today. Those three, the version catch-all, and three wordy heads get
|
|
24
|
-
// written names; the rest keep theirs verbatim.
|
|
25
|
-
//
|
|
26
|
-
// SAFETY. Dry-run by DEFAULT (`--apply` to write). Every write goes through
|
|
27
|
-
// PATCH /goals/:id, which is authorized (owner|manager|Archon) and records
|
|
28
|
-
// prose-edit deltas — so the rename is audit-trailed, unlike the prod SQL UPDATE
|
|
29
|
-
// that would otherwise be the only channel. It REFUSES to run at all if the
|
|
30
|
-
// server does not yet return `subtitle`, because renaming titles against a
|
|
31
|
-
// server that cannot store the subtitle would DELETE the explanations.
|
|
32
|
-
|
|
33
|
-
'use strict';
|
|
34
|
-
|
|
35
|
-
// id → { title, subtitle, why? }. `why` is recorded only where the name is
|
|
36
|
-
// NEW rather than the existing head — i.e. where judgment was applied.
|
|
37
|
-
const GOAL_NAMES = Object.freeze({
|
|
38
|
-
// ── names written, because the head was not usable ───────────────────────
|
|
39
|
-
1000003: { title: 'Work with no goal yet',
|
|
40
|
-
subtitle: 'The version catch-all. Tasks land here when nothing else fits — and nothing here can satisfy a criterion (ADR 0183), so it is a holding pen, not a home.',
|
|
41
|
-
why: 'was "BONGOS-V1 — general": a version id and the word general name nothing. Named for what it actually is.' },
|
|
42
|
-
1000038: { title: 'Agent framework & registry',
|
|
43
|
-
subtitle: 'The foundation — the plugin surface an agent is written against, and the registry that holds the roster.',
|
|
44
|
-
why: 'one of THREE goals heading "Agents module"; a mechanical split would have left three identically-named goals. Written without a colon on purpose: "Agents: framework" is the same name-plus-qualifier shape this task exists to remove, and the test flagged it.' },
|
|
45
|
-
1000039: { title: 'Agent authoring & first roster',
|
|
46
|
-
subtitle: 'Owner and builder authoring, plus the first real roster — event-driven and on-demand agents.',
|
|
47
|
-
why: 'second of the three "Agents module" goals. Named for what it adds — authoring and the first roster — rather than by a tail no list ever showed.' },
|
|
48
|
-
1000040: { title: 'Agent scheduling & spend limits',
|
|
49
|
-
subtitle: 'Scheduled agents, and the guardrails on what they are allowed to spend.',
|
|
50
|
-
why: 'third of the three "Agents module" goals. Scheduling and spend are what separate it from the framework and authoring goals.' },
|
|
51
|
-
1000053: { title: 'Sessions start knowing',
|
|
52
|
-
subtitle: 'Front-load auth, environment and instance facts so a session does not spend its first minutes rediscovering them.',
|
|
53
|
-
why: 'was "Session efficiency: sessions start knowing" — the head restated the tail. Kept the half that is a name.' },
|
|
54
|
-
1000064: { title: 'The hall as the room',
|
|
55
|
-
subtitle: 'Agora, Monitor & Contribute, and chat that does not care which channel it came from.',
|
|
56
|
-
why: 'colon-separated rather than dashed; same jamming, so treated identically.' },
|
|
57
|
-
1000075: { title: 'Collaboration & the social hall',
|
|
58
|
-
subtitle: 'Ask for help by craft, and let the hall become a mode rather than a page.',
|
|
59
|
-
why: 'was "Collab, then the social hall" — an ordering, not a name.' },
|
|
60
|
-
1000077: { title: 'Guards, not notes',
|
|
61
|
-
subtitle: 'The four failure modes that prose already documented and nothing refused.',
|
|
62
|
-
why: 'colon-separated; the head is already a good name, the tail is the explanation.' },
|
|
63
|
-
1000078: { title: 'Project money out',
|
|
64
|
-
subtitle: 'A funded balance, real builder payouts, visible outflows, and work that cannot outrun the money.',
|
|
65
|
-
why: 'colon-separated rather than dashed. The head is already the name; the tail is a four-part explanation that belongs underneath it.' },
|
|
66
|
-
|
|
67
|
-
// ── heads kept verbatim; only the tail moves ─────────────────────────────
|
|
68
|
-
1000025: { title: 'Builder experience', subtitle: 'Hall, dev box, and skills.' },
|
|
69
|
-
1000027: { title: 'Findability', subtitle: 'The grep path (ADR 0095).' },
|
|
70
|
-
1000029: { title: 'Module upstreaming & catalog', subtitle: 'Instances contribute modules back into core.' },
|
|
71
|
-
1000032: { title: 'Instance hosting + domains', subtitle: 'The `provisioning` module.' },
|
|
72
|
-
1000044: { title: 'Living project sky', subtitle: 'A shared, persistent, data-driven orb gate.' },
|
|
73
|
-
1000045: { title: 'Public builder profiles', subtitle: 'Track record, apply-to-project, and owner recruiting.' },
|
|
74
|
-
1000046: { title: 'Project creation', subtitle: 'Visibility and customization.' },
|
|
75
|
-
1000048: { title: 'SEO & public discoverability', subtitle: 'Rankable per-project profiles.' },
|
|
76
|
-
1000049: { title: 'Orb Physics', subtitle: 'Orb motion and space-whale flight.' },
|
|
77
|
-
1000052: { title: 'First-run onboarding', subtitle: 'From a bare machine to a first ship.' },
|
|
78
|
-
1000054: { title: 'Public distribution', subtitle: 'CLI installer and Claude plugin.' },
|
|
79
|
-
1000057: { title: 'Rank blocker matrix', subtitle: 'Empirically verify intended vs unintended blockers across xenos, thetes and metic.' },
|
|
80
|
-
1000058: { title: 'Non-cloudbongos project lifecycle', subtitle: 'Creation, governance, planning, building — the whole flow works and feels right.' },
|
|
81
|
-
1000063: { title: 'The front door', subtitle: 'Enter the Future: hero-only landing, wormhole transit, About on the map.' },
|
|
82
|
-
1000065: { title: 'Community surface', subtitle: 'Builder discovery on the hub.' },
|
|
83
|
-
1000067: { title: 'Ideator compensation', subtitle: 'The idea credit stream, separate from cost-plus.' },
|
|
84
|
-
1000068: { title: 'Government, not governance', subtitle: 'Ranks are ranks, and "role" belongs to the crafts.' },
|
|
85
|
-
1000070: { title: 'Scan-before-install', subtitle: 'First-real-run hardening.' },
|
|
86
|
-
1000071: { title: 'Idea routing', subtitle: 'Work that has a home lands in it.' },
|
|
87
|
-
1000072: { title: 'Human legibility', subtitle: 'Seeing, sorting and steering an AI-run project.' },
|
|
88
|
-
1000073: { title: 'Finish the GDS→Bongos rename', subtitle: 'Retire a legacy Primea term without rewriting history.' },
|
|
89
|
-
1000074: { title: "The artist's loop", subtitle: 'Review authority, copy an artist can change, and a place to do it.' },
|
|
90
|
-
// 1000080 already carried a subtitle, so the tail is PREPENDED to it rather than
|
|
91
|
-
// replacing it — overwriting would delete text, the exact loss this task guards.
|
|
92
|
-
1000080: { title: 'Apex UI pass 2', subtitle: 'One top bar, two dropdowns, and a project card worth opening — the chrome and the card on cloudbongos.com and /projects.' },
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// A name must not carry its own explanation — that is the whole point.
|
|
96
|
-
const SEPARATOR = / [—-] |: /;
|
|
97
|
-
|
|
98
|
-
// Goals deliberately untouched: their titles are already names. Listed so the
|
|
99
|
-
// coverage test can tell "already fine" from "forgotten".
|
|
100
|
-
const ALREADY_NAMES = Object.freeze([1000009, 1000024, 1000028, 1000037, 1000047, 1000050]);
|
|
101
|
-
|
|
102
|
-
module.exports = { GOAL_NAMES, ALREADY_NAMES, SEPARATOR };
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// scripts/bongos/rename-goals.js — apply the goal-names.js mapping (task 1003225).
|
|
3
|
-
//
|
|
4
|
-
// Usage:
|
|
5
|
-
// node scripts/bongos/rename-goals.js # DRY RUN — prints the diff, writes nothing
|
|
6
|
-
// node scripts/bongos/rename-goals.js --apply # writes, via PATCH /goals/:id
|
|
7
|
-
//
|
|
8
|
-
// Writes go through PATCH /goals/:id, never SQL: that route is authorized
|
|
9
|
-
// (owner|manager|Archon) and records prose-edit deltas, so a rename of somebody's
|
|
10
|
-
// goal is audit-trailed. A prod UPDATE would be invisible.
|
|
11
|
-
//
|
|
12
|
-
// THE GUARD THAT MATTERS: it refuses to run when the server does not return
|
|
13
|
-
// `subtitle`. Renaming a title against a server that cannot store the subtitle
|
|
14
|
-
// would DELETE the explanation — the exact data loss this task exists to avoid.
|
|
15
|
-
// core_224 ships the column; a live instance one release behind does not have it.
|
|
16
|
-
|
|
17
|
-
'use strict';
|
|
18
|
-
|
|
19
|
-
const { cliClient, requireSession, hasFlag } = require('./cli-lib');
|
|
20
|
-
const { GOAL_NAMES, SEPARATOR } = require('./goal-names.js');
|
|
21
|
-
|
|
22
|
-
// Nothing to do when the goal already reads the way the mapping wants.
|
|
23
|
-
function planFor(goal, want) {
|
|
24
|
-
const patch = {};
|
|
25
|
-
if ((goal.title || '') !== want.title) patch.title = want.title;
|
|
26
|
-
if ((goal.subtitle || '') !== want.subtitle) patch.subtitle = want.subtitle;
|
|
27
|
-
return patch;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function main() {
|
|
31
|
-
await requireSession();
|
|
32
|
-
const apply = hasFlag('--apply');
|
|
33
|
-
const api = await cliClient();
|
|
34
|
-
|
|
35
|
-
const res = await api.goals.getGoals({ query: { version: 'BONGOS-V1' } });
|
|
36
|
-
if (!res.ok) {
|
|
37
|
-
console.error(`could not list goals: ${res.status}`);
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
const goals = (res.data.goals || []).filter((g) => g.status === 'open');
|
|
41
|
-
if (!goals.length) {
|
|
42
|
-
console.error('no open goals returned — refusing to act on an empty read.');
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// The refusal above all others.
|
|
47
|
-
if (!Object.prototype.hasOwnProperty.call(goals[0], 'subtitle')) {
|
|
48
|
-
console.error('REFUSING: this server does not return `subtitle`, so it cannot store one.');
|
|
49
|
-
console.error('Renaming titles now would drop every explanation on the floor.');
|
|
50
|
-
console.error('core_224 adds the column — wait for the release carrying it to DEPLOY, then re-run.');
|
|
51
|
-
process.exit(2);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
let changed = 0; let already = 0; let missing = 0; let failed = 0;
|
|
55
|
-
for (const g of goals.sort((a, b) => Number(a.id) - Number(b.id))) {
|
|
56
|
-
const want = GOAL_NAMES[Number(g.id)];
|
|
57
|
-
if (!want) {
|
|
58
|
-
// Not an error: goals whose titles were already names are deliberately absent.
|
|
59
|
-
if (SEPARATOR.test(g.title || '')) {
|
|
60
|
-
console.error(`! ${g.id} has a jammed title but no mapping entry: ${g.title}`);
|
|
61
|
-
missing += 1;
|
|
62
|
-
}
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const patch = planFor(g, want);
|
|
66
|
-
if (!Object.keys(patch).length) { already += 1; continue; }
|
|
67
|
-
console.log(`${apply ? '→' : '·'} ${g.id}`);
|
|
68
|
-
if (patch.title) console.log(` title ${JSON.stringify(g.title)} -> ${JSON.stringify(patch.title)}`);
|
|
69
|
-
if (patch.subtitle !== undefined) console.log(` subtitle ${JSON.stringify(g.subtitle || '')} -> ${JSON.stringify(patch.subtitle)}`);
|
|
70
|
-
if (!apply) { changed += 1; continue; }
|
|
71
|
-
const r = await api.goals.patchGoalsId({ id: g.id, body: patch });
|
|
72
|
-
if (!r.ok) {
|
|
73
|
-
console.error(` FAILED ${r.status} ${JSON.stringify(r.data)}`);
|
|
74
|
-
failed += 1;
|
|
75
|
-
} else {
|
|
76
|
-
changed += 1;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
console.log('');
|
|
81
|
-
console.log(`${apply ? 'applied' : 'would change'}: ${changed} · already correct: ${already}`
|
|
82
|
-
+ `${missing ? ` · UNMAPPED jammed titles: ${missing}` : ''}${failed ? ` · FAILED: ${failed}` : ''}`);
|
|
83
|
-
if (!apply) console.log('dry run — re-run with --apply to write.');
|
|
84
|
-
|
|
85
|
-
// THE POST-CONDITION, CHECKED AGAINST REAL DATA — not against the mapping.
|
|
86
|
-
// The task's deliverable is a STATE of the live goal set ("no open goal's title
|
|
87
|
-
// contains a dash-appended subtitle"), and unit tests over the mapping's internal
|
|
88
|
-
// consistency cannot witness that: they would pass just as happily if --apply had
|
|
89
|
-
// never been run. This re-reads what the server actually holds now and reports it,
|
|
90
|
-
// so the claim is falsifiable by anyone re-running the command.
|
|
91
|
-
//
|
|
92
|
-
// SCOPED TO THIS VERSION, deliberately. The read above is `version: BONGOS-V1`;
|
|
93
|
-
// CB-V1 carries jammed titles of its own (id 4, 1000043, 1000066, 1000079) which
|
|
94
|
-
// are ANOTHER version's work, and sweeping them in here would rename goals this
|
|
95
|
-
// task never reviewed.
|
|
96
|
-
const stillJammed = goals.filter((g) => SEPARATOR.test(g.title || ''));
|
|
97
|
-
console.log('');
|
|
98
|
-
console.log(`post-condition (BONGOS-V1 open goals): ${goals.length} checked · `
|
|
99
|
-
+ `${stillJammed.length} still carrying an explanation in the title`);
|
|
100
|
-
for (const g of stillJammed) console.log(` ! ${g.id} ${JSON.stringify(g.title)}`);
|
|
101
|
-
|
|
102
|
-
process.exit(failed || missing ? 1 : 0);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (require.main === module) {
|
|
106
|
-
main().catch((err) => { console.error('fatal:', err); process.exit(1); });
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
module.exports = { planFor };
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// seed-adopt-tasks.js
|
|
3
|
-
// Seeds the brownfield adopt-mode task breakdown for BONGOS-V1 goal 35
|
|
4
|
-
// ("Project creation flow"), criterion `adopt-existing-repo`, per ADR 0121
|
|
5
|
-
// (task 1986). Scope-only deliverable: these are the BUILD tasks for
|
|
6
|
-
// `bongos init --adopt`; they are seeded as `backlog` (NOT promoted) so the
|
|
7
|
-
// owner schedules the adopt build deliberately. See ADR 0121 §Consequences.
|
|
8
|
-
//
|
|
9
|
-
// Idempotent: task create on source_ref (`BONGOS-V1-adopt-A0N`), criterion
|
|
10
|
-
// links on (task_id, criterion_id), dependency edges on (task_id,
|
|
11
|
-
// depends_on_task_id). Safe to re-run. Run: node scripts/bongos/seed-adopt-tasks.js
|
|
12
|
-
const { apiCall } = require('./cli-lib.js');
|
|
13
|
-
|
|
14
|
-
const GOAL_ID = 35;
|
|
15
|
-
const CRIT = 'adopt-existing-repo';
|
|
16
|
-
const RUNBOOK_TASK = 1981; // goal-35 canonical runbook; A05 depends on it (external edge)
|
|
17
|
-
|
|
18
|
-
// ref → task spec. `deps` are local A0N refs; `extDeps` are literal task ids.
|
|
19
|
-
const TASKS = [
|
|
20
|
-
{ ref: 'A01', kind: 'feature', priority: 4, est: 180, crit: [CRIT], deps: [], extDeps: [],
|
|
21
|
-
title: 'bongos init --adopt: mode skeleton + additive config layering (no clobber)',
|
|
22
|
-
description: 'Add an `--adopt` mode to `scripts/bongos/init.js` (ADR 0121 §Decision 1-2). Instead of the greenfield "stand up a NEW instance" path (which refuses where config/branding.json exists and whose --force OVERWRITES), --adopt LAYERS onto the existing tree: add the pinned @bongos/core dependency + the lean config/ overrides + .claude/ ADDITIVELY. For any pre-existing file (package.json, an existing .claude/, a CI workflow) it MERGES or LEAVES-AND-REPORTS — it never overwrites, and it must NOT reuse the --force code path. Writes only the lean branding.json overrides (rest resolves from *.neutral.json). Serves criterion adopt-existing-repo. deps: none (the ADR-0108 configurable-root substrate is shipped).' },
|
|
23
|
-
{ ref: 'A02', kind: 'feature', priority: 4, est: 150, crit: [CRIT], deps: [], extDeps: [],
|
|
24
|
-
title: 'bongos init --adopt: detect the existing stack + layout',
|
|
25
|
-
description: 'Before writing anything, --adopt inspects the existing tree — language/runtime, package manager, test + CI setup, directory layout — so the enabled modules, the generated repo-map, and the core<->host fitness boundary (ADR 0062 §1) fit what is already there instead of assuming the reference layout (ADR 0121 §Decision 4). Output: a detected-stack summary consumed by A03 (real-state capture) and A04 (pre-flight). Serves criterion adopt-existing-repo. deps: none.' },
|
|
26
|
-
{ ref: 'A03', kind: 'feature', priority: 3, est: 180, crit: [CRIT], deps: ['A01'], extDeps: [],
|
|
27
|
-
title: 'bongos init --adopt: reflect REAL state — capture version/goal + import backlog',
|
|
28
|
-
description: 'Replace the synthetic "V1 — Prove the loop" seed with the repo\'s ACTUAL current version/milestone + open goal (by interview + detection), and IMPORT the existing backlog into GDS tasks — GitHub issues (via the auth the flow already establishes), a TODO/ROADMAP/BACKLOG.md, or an interview fallback — so the ledger starts truthful rather than empty (ADR 0121 §Decision 3). Serves criterion adopt-existing-repo. deps: A01.' },
|
|
29
|
-
{ ref: 'A04', kind: 'feature', priority: 3, est: 150, crit: [CRIT], deps: ['A01', 'A02'], extDeps: [],
|
|
30
|
-
title: 'bongos init --adopt: conflict pre-flight report (--dry-run default, accept-gated)',
|
|
31
|
-
description: 'Produce the pre-flight report the owner must ACCEPT before anything is written (ADR 0121 §Decision 5): migration-namespace collisions (ADR 0108 §5), core<->host fitness-boundary violations in existing imports (ADR 0062 §1), incoming files that land on protected paths (ADR 0043), and CI collisions between core\'s expected unit/gate check and the repo\'s own workflows. --dry-run is the default first pass; nothing is written until accepted. Serves criterion adopt-existing-repo. deps: A01, A02.' },
|
|
32
|
-
{ ref: 'A05', kind: 'feature', priority: 3, est: 120, crit: [CRIT], deps: ['A01', 'A03', 'A04'], extDeps: [RUNBOOK_TASK],
|
|
33
|
-
title: 'bongos init --adopt: wire greenfield-vs-adopt into the runbook + both forms',
|
|
34
|
-
description: 'Offer the greenfield-vs-adopt choice at the SCAFFOLD leg of goal 35\'s canonical step sequence, across all three forms: the /new-project skill (task 1981), the `bongos onboard` CLI (task 1982), and the hall "start a project" wizard (task 1983). Since --adopt is a branch of the same init, the forms inherit it (ADR 0121 §Decision 1). Serves criterion adopt-existing-repo. deps: A01, A03, A04, and the runbook task 1981.' },
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
(async () => {
|
|
38
|
-
const idByRef = {};
|
|
39
|
-
// Phase 1: create tasks (idempotent on source_ref) + link the criterion.
|
|
40
|
-
for (const t of TASKS) {
|
|
41
|
-
const create = await apiCall('POST', '/api/bongos/tasks', {
|
|
42
|
-
version_id: 'BONGOS-V1',
|
|
43
|
-
goal_id: GOAL_ID,
|
|
44
|
-
title: t.title,
|
|
45
|
-
description: t.description,
|
|
46
|
-
kind: t.kind,
|
|
47
|
-
discipline: 'engineer',
|
|
48
|
-
priority: t.priority,
|
|
49
|
-
est_minutes: t.est,
|
|
50
|
-
source: 'planning',
|
|
51
|
-
source_ref: `BONGOS-V1-adopt-${t.ref}`,
|
|
52
|
-
});
|
|
53
|
-
const task = create.data && (create.data.task || create.data);
|
|
54
|
-
const id = task && task.id;
|
|
55
|
-
if (!id) { console.log(` ${t.ref}: CREATE FAILED — ${create.status} ${JSON.stringify(create.data).slice(0, 160)}`); continue; }
|
|
56
|
-
idByRef[t.ref] = id;
|
|
57
|
-
const link = await apiCall('POST', `/api/bongos/tasks/${id}/criteria`, { criterion_ids: t.crit });
|
|
58
|
-
console.log(` ${t.ref} -> task ${id} (${t.kind}, P${t.priority}, goal ${task.goal_id}) · criterion ${link.status === 200 ? 'ok' : (JSON.stringify(link.data).slice(0, 120))}`);
|
|
59
|
-
}
|
|
60
|
-
// Phase 2: dependency edges (idempotent on (task_id, depends_on_task_id)).
|
|
61
|
-
console.log('--- dependencies ---');
|
|
62
|
-
for (const t of TASKS) {
|
|
63
|
-
const id = idByRef[t.ref];
|
|
64
|
-
if (!id) continue;
|
|
65
|
-
const localDepIds = t.deps.map((d) => idByRef[d]).filter(Boolean);
|
|
66
|
-
const allDeps = [...localDepIds, ...t.extDeps];
|
|
67
|
-
for (const depId of allDeps) {
|
|
68
|
-
const r = await apiCall('POST', `/api/bongos/tasks/${id}/dependencies`, { depends_on_task_id: depId });
|
|
69
|
-
console.log(` ${t.ref}(${id}) -> ${depId} ${r.status === 200 || r.status === 201 ? 'ok' : (JSON.stringify(r.data).slice(0, 120))}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
// NOTE: intentionally NO promote step — these are backlog until the owner
|
|
73
|
-
// schedules the adopt build (ADR 0121; task 1986 is scope-only).
|
|
74
|
-
console.log('refs:', JSON.stringify(idByRef));
|
|
75
|
-
})().catch((e) => console.log('ERR ' + (e && e.message)));
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// seed-api-contract-goal-tasks.js
|
|
3
|
-
// Seeds BONGOS-V1 goal 36 — "Robust, versioned, easy-to-call public API" — from
|
|
4
|
-
// the 2026-07-04 Archon planning session (task 1987). Five done-when criteria
|
|
5
|
-
// (slugs api-error-envelope · api-versioning · api-client-sdk · api-validation ·
|
|
6
|
-
// api-pagination) were created via POST /versions/BONGOS-V1/done-when before this
|
|
7
|
-
// runs; this seeds the 14 tasks (refs R01-R14) + their criterion links + the
|
|
8
|
-
// dependency edges. Entry point is CONTRACT-FIRST, so only the zero-dep,
|
|
9
|
-
// non-spike Phase-A tasks (R01 envelope contract, R05 versioning policy) plus the
|
|
10
|
-
// independent R13 pagination decision are promoted to `ready`; R07 (the
|
|
11
|
-
// source-of-truth spike) stays backlog by convention and is opened manually when
|
|
12
|
-
// Phase B starts; everything else auto-promotes as its predecessor ships.
|
|
13
|
-
//
|
|
14
|
-
// Idempotent: task create on source_ref, criterion links on (task_id,
|
|
15
|
-
// criterion_id), dependency edges on (task_id, depends_on_task_id). Safe to re-run.
|
|
16
|
-
// Run: node scripts/bongos/seed-api-contract-goal-tasks.js
|
|
17
|
-
const { cliClient } = require('./cli-lib.js');
|
|
18
|
-
|
|
19
|
-
const GOAL_ID = 36;
|
|
20
|
-
const C = {
|
|
21
|
-
envelope: 'api-error-envelope',
|
|
22
|
-
versioning: 'api-versioning',
|
|
23
|
-
sdk: 'api-client-sdk',
|
|
24
|
-
validation: 'api-validation',
|
|
25
|
-
pagination: 'api-pagination',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// ref → task spec. `deps` are local R## refs, resolved to ids after create.
|
|
29
|
-
const TASKS = [
|
|
30
|
-
// ---- Criterion 1: error envelope (Phase A) ----
|
|
31
|
-
{ ref: 'R01', kind: 'decision', priority: 5, est: 90, crit: [C.envelope],
|
|
32
|
-
title: 'API error envelope + code taxonomy (contract + ADR)',
|
|
33
|
-
description: 'Define the single error response envelope `{error:{code,message,details}}` and the taxonomy that collapses today\'s ~339 ad-hoc error strings into a documented registry. Deliverable: an ADR + a shared registry module of canonical codes. No behaviour change — this is the contract R02 implements. Serves C1 (api-error-envelope). deps: none.',
|
|
34
|
-
deps: [] },
|
|
35
|
-
{ ref: 'R02', kind: 'infra', priority: 5, est: 120, crit: [C.envelope],
|
|
36
|
-
title: 'Central error-handling middleware + envelope helper',
|
|
37
|
-
description: 'Add a central Express error-handling middleware + an `ApiError`/`res.fail(code,status,details)` helper (kernel route layer) emitting the R01 envelope; wire the handler last so any thrown/unhandled error returns the envelope. Backward-compatible — existing ad-hoc responses keep working until the R04 sweep. Serves C1. deps: R01.',
|
|
38
|
-
deps: ['R01'] },
|
|
39
|
-
{ ref: 'R03', kind: 'infra', priority: 4, est: 90, crit: [C.envelope],
|
|
40
|
-
title: 'Build check: fail on a route emitting a non-envelope error',
|
|
41
|
-
description: 'Add a fitness/lint check (into fitness.js / the unit gate) that fails the build when a route hand-rolls a flat `res.status(NNN).json({error:\'...\'})` instead of the R02 helper. Holds the line as the sweep progresses. Serves C1. deps: R02.',
|
|
42
|
-
deps: ['R02'] },
|
|
43
|
-
{ ref: 'R04', kind: 'refactor', priority: 4, est: 240, crit: [C.envelope],
|
|
44
|
-
title: 'Sweep existing routes onto the error envelope',
|
|
45
|
-
description: 'Convert the ~219 handlers across core + modules from ad-hoc flat errors to the R02 envelope (the audit found 168 open-coded 500s + 615 flat-error sites). Mechanical but wide — touches every module\'s routes. Serves C1. deps: R02.',
|
|
46
|
-
deps: ['R02'] },
|
|
47
|
-
// ---- Criterion 2: versioning (Phase A) ----
|
|
48
|
-
{ ref: 'R05', kind: 'decision', priority: 5, est: 90, crit: [C.versioning],
|
|
49
|
-
title: 'API versioning + deprecation policy (ADR)',
|
|
50
|
-
description: 'ADR defining the versioning scheme (a `/v1/` path marker), what counts as a breaking change, the deprecation window, and how the currently-un-updatable consumers (shipped Dev Box binaries, live boxes, status dashboard) are handled. Serves C2 (api-versioning). deps: none.',
|
|
51
|
-
deps: [] },
|
|
52
|
-
{ ref: 'R06', kind: 'infra', priority: 5, est: 150, crit: [C.versioning],
|
|
53
|
-
title: 'Serve the API under /v1/ with legacy aliasing',
|
|
54
|
-
description: 'Mount the current surface under `/v1/` and alias today\'s unversioned paths (`/api/bongos`, `/api/gds`) into it so no consumer breaks on day one. Stamp the version into the OpenAPI spec + `/docs`. Serves C2. deps: R05.',
|
|
55
|
-
deps: ['R05'] },
|
|
56
|
-
// ---- Criterion 3: client SDK (Phase B) ----
|
|
57
|
-
{ ref: 'R07', kind: 'spike', priority: 4, est: 120, crit: [C.sdk],
|
|
58
|
-
title: 'Spike: pick the API contract source-of-truth (schema-first vs code-first)',
|
|
59
|
-
description: 'Decide whether the OpenAPI spec becomes the SOURCE (schema-first: define request/response schemas -> generate spec + validation + client) or stays GENERATED from code with codegen layered on. This one decision shapes the SDK (C3) and validation (C4). Output: an ADR + a sub-task list refining R08-R12. kind=spike (stays backlog; opened manually when Phase B starts). Serves C3, informs C4. deps: none (do after Phase A).',
|
|
60
|
-
deps: [] },
|
|
61
|
-
{ ref: 'R08', kind: 'feature', priority: 3, est: 180, crit: [C.sdk],
|
|
62
|
-
title: 'Generate + publish the typed API client',
|
|
63
|
-
description: 'Per the R07 decision, generate a typed client from the OpenAPI spec and publish it for install (internal package first). Serves C3. deps: R07.',
|
|
64
|
-
deps: ['R07'] },
|
|
65
|
-
{ ref: 'R09', kind: 'refactor', priority: 3, est: 240, crit: [C.sdk],
|
|
66
|
-
title: 'Migrate internal callers onto the client; delete duplicates',
|
|
67
|
-
description: 'Move the CLI (cli-lib apiCall), the devbox Electron app (its own gds-client), and the web UIs (per-page fetch helpers) onto the generated client; delete the 3 duplicate implementations. Cuts per-call boilerplate from ~15 lines to 1. Touches hall-ui/status-ui/dev-box. Serves C3. deps: R08.',
|
|
68
|
-
deps: ['R08'] },
|
|
69
|
-
{ ref: 'R10', kind: 'feature', priority: 3, est: 120, crit: [C.sdk],
|
|
70
|
-
title: 'External-consumer on-ramp + hello-world (proof)',
|
|
71
|
-
description: 'Document how an outside program authenticates (token acquisition beyond the interactive Device Flow) and makes its first call, with a runnable hello-world using the published client. The PROOF an external self-hoster can actually use the API. Serves C3. deps: R08.',
|
|
72
|
-
deps: ['R08'] },
|
|
73
|
-
// ---- Criterion 4: validation (Phase C) ----
|
|
74
|
-
{ ref: 'R11', kind: 'feature', priority: 3, est: 240, crit: [C.validation],
|
|
75
|
-
title: 'Spec-driven request validation: 100% writes + query params',
|
|
76
|
-
description: 'Per the R07 decision, drive validation from the spec so every write route AND its query parameters are validated, and unknown/typo\'d fields are rejected with the R02 envelope (today ~55% coverage, extras silently dropped). Serves C4 (api-validation). deps: R07.',
|
|
77
|
-
deps: ['R07'] },
|
|
78
|
-
{ ref: 'R12', kind: 'infra', priority: 3, est: 90, crit: [C.validation],
|
|
79
|
-
title: 'Build check: fail on an unvalidated write route',
|
|
80
|
-
description: 'Add a fitness check that fails the build when a write route (POST/PUT/PATCH/DELETE) has no spec-bound validation. Locks in C4\'s 100% coverage. Serves C4. deps: R11.',
|
|
81
|
-
deps: ['R11'] },
|
|
82
|
-
// ---- Criterion 5: pagination (Phase C) ----
|
|
83
|
-
{ ref: 'R13', kind: 'decision', priority: 2, est: 90, crit: [C.pagination],
|
|
84
|
-
title: 'Pagination contract + shared helper (decision)',
|
|
85
|
-
description: 'Decide one pagination convention (cursor vs limit/offset) and build the shared helper. Today three styles coexist (limit-only, limit+offset, none) with per-endpoint clamps. Serves C5 (api-pagination). deps: none (independent).',
|
|
86
|
-
deps: [] },
|
|
87
|
-
{ ref: 'R14', kind: 'refactor', priority: 2, est: 180, crit: [C.pagination],
|
|
88
|
-
title: 'Adopt the pagination contract across list endpoints; cap unbounded lists',
|
|
89
|
-
description: 'Apply the R13 helper across all list endpoints and cap the currently-unbounded public lists (leaderboard, blockers, versions). Serves C5. deps: R13.',
|
|
90
|
-
deps: ['R13'] },
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
(async () => {
|
|
94
|
-
const api = await cliClient();
|
|
95
|
-
const idByRef = {};
|
|
96
|
-
// Phase 1: create tasks (idempotent on source_ref) + link criteria explicitly
|
|
97
|
-
// (criterion_ids at create is not honored on this build; /criteria is idempotent).
|
|
98
|
-
for (const t of TASKS) {
|
|
99
|
-
const create = await api.tasks.postTasks({ body: {
|
|
100
|
-
version_id: 'BONGOS-V1',
|
|
101
|
-
goal_id: GOAL_ID,
|
|
102
|
-
title: t.title,
|
|
103
|
-
description: t.description,
|
|
104
|
-
kind: t.kind,
|
|
105
|
-
discipline: 'engineer',
|
|
106
|
-
priority: t.priority,
|
|
107
|
-
est_minutes: t.est,
|
|
108
|
-
source: 'planning',
|
|
109
|
-
source_ref: `BONGOS-V1-api-contract-${t.ref}`,
|
|
110
|
-
} });
|
|
111
|
-
const task = create.data && (create.data.task || create.data);
|
|
112
|
-
const id = task && task.id;
|
|
113
|
-
if (!id) { console.log(` ${t.ref}: CREATE FAILED — ${create.status} ${JSON.stringify(create.data).slice(0, 160)}`); continue; }
|
|
114
|
-
idByRef[t.ref] = id;
|
|
115
|
-
const link = await api.tasks.postTasksIdCriteria({ id, body: { criterion_ids: t.crit } });
|
|
116
|
-
console.log(` ${t.ref} -> task ${id} (${t.kind}, P${t.priority}, goal ${task.goal_id}) · criteria ${link.status === 200 ? 'ok' : (JSON.stringify(link.data).slice(0, 120))}`);
|
|
117
|
-
}
|
|
118
|
-
// Phase 2: dependency edges (idempotent on (task_id, depends_on_task_id)).
|
|
119
|
-
console.log('--- dependencies ---');
|
|
120
|
-
for (const t of TASKS) {
|
|
121
|
-
const id = idByRef[t.ref];
|
|
122
|
-
if (!id || !t.deps.length) continue;
|
|
123
|
-
for (const dep of t.deps) {
|
|
124
|
-
const depId = idByRef[dep];
|
|
125
|
-
if (!depId) { console.log(` ${t.ref}: dep ${dep} not created — skip`); continue; }
|
|
126
|
-
const r = await api.tasks.postTasksIdDependencies({ id, body: { depends_on_task_id: depId } });
|
|
127
|
-
console.log(` ${t.ref}(${id}) -> ${dep}(${depId}) ${r.status === 200 || r.status === 201 ? 'ok' : (JSON.stringify(r.data).slice(0, 120))}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
// Phase 3: promote the zero-dep, non-spike tasks to `ready` (contract-first:
|
|
131
|
-
// R01 + R05 open Phase A now; R13 is independent). R07 (spike) stays backlog.
|
|
132
|
-
console.log('--- promote (zero-dep, non-spike) ---');
|
|
133
|
-
for (const t of TASKS) {
|
|
134
|
-
if (t.deps.length || t.kind === 'spike') continue;
|
|
135
|
-
const id = idByRef[t.ref];
|
|
136
|
-
if (!id) continue;
|
|
137
|
-
const p = await api.tasks.postTasksIdPromote({ id, body: {} });
|
|
138
|
-
console.log(` ${t.ref}(${id}) promote -> ${p.status} ${p.ok ? 'ready' : JSON.stringify(p.data).slice(0, 120)}`);
|
|
139
|
-
}
|
|
140
|
-
console.log('refs:', JSON.stringify(idByRef));
|
|
141
|
-
})().catch((e) => console.log('ERR ' + (e && e.message)));
|