@bongos/core 1.21.76 → 1.21.78
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 +24 -19
- package/docs/copy-inventory.md +13 -10
- package/docs/copy-registry.json +42 -15
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-readings.json +308 -307
- package/modules/hall-ui/public/goals-page.js +13 -1
- package/modules/hall-ui/public/goals-render.js +1 -1
- package/modules/hall-ui/public/style.css +5 -1
- package/modules/hall-ui/public/task-lib.js +21 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/src/module-api.js +1 -1
- package/tests/goal_plan_with_claude.mjs +41 -0
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// below reads exactly as before; the single copy lives in task-lib.js.
|
|
32
32
|
const {
|
|
33
33
|
priorityRank, touchesConflict, rankTagHtml, deHashRefs,
|
|
34
|
-
creditsPerMinute, buildPromptForTask, friendlyBatchReason,
|
|
34
|
+
creditsPerMinute, buildPromptForTask, buildPlanPromptForGoal, friendlyBatchReason,
|
|
35
35
|
} = window.OTBTaskLib;
|
|
36
36
|
// Shared component kit (hall-kit.js, task 2166): pager, filter bar, tabs,
|
|
37
37
|
// empty/skeleton states — adopted here by task 2171.
|
|
@@ -404,6 +404,18 @@
|
|
|
404
404
|
} catch (_e) { return false; }
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
|
+
// task 1004587 (ADR 0366 D4) — the optional "Plan with Claude" hand-off; every planning form works without it.
|
|
408
|
+
async function planWithClaude() {
|
|
409
|
+
const d = state.details.get(String(state.current));
|
|
410
|
+
if (!d) return;
|
|
411
|
+
// The spec task is found in the goal's task list, so wait for it: copying early would hand back the fallback prompt for a goal that has a spec task.
|
|
412
|
+
if (!state.workLoaded) return toast("Still loading this goal's tasks. Try again in a moment.");
|
|
413
|
+
const g = d.goal;
|
|
414
|
+
const ok = await copyText(buildPlanPromptForGoal(g, state.work.todo));
|
|
415
|
+
toast(ok ? 'Prompt copied. Paste it into a Claude Code session to plan this goal.' : 'Could not copy to the clipboard. Try again.');
|
|
416
|
+
}
|
|
417
|
+
// The button is drawn by renderActions (which re-draws it), so the click is delegated.
|
|
418
|
+
document.addEventListener('click', (e) => { if (e.target.closest && e.target.closest('#goal-plan-btn')) planWithClaude(); });
|
|
407
419
|
async function copyPromptForTask(taskId, btn) {
|
|
408
420
|
const t = state.work.todo.find((x) => String(x.id) === String(taskId));
|
|
409
421
|
if (!t) return;
|
|
@@ -962,7 +962,7 @@
|
|
|
962
962
|
if (canManage && g.status === 'open') {
|
|
963
963
|
parts.push('<button class="btn-ghost" id="goal-archive-btn" type="button" title="Retire this goal — you will be asked what happens to any unfinished work">Archive goal</button>');
|
|
964
964
|
}
|
|
965
|
-
if (g.status === 'open') {
|
|
965
|
+
if (g.status === 'open') { parts.push('<button class="btn-ghost" id="goal-plan-btn" type="button" title="Copies a prompt to paste into a Claude Code session">Plan with Claude</button>'); // task 1004587
|
|
966
966
|
if (joined) {
|
|
967
967
|
parts.push('<button class="btn-ghost" id="goal-leave-btn" type="button">Leave goal</button>');
|
|
968
968
|
} else if ((g.visibility === 'private' || g.scope_protected) && !isArchon()) {
|
|
@@ -497,7 +497,11 @@ body::after {
|
|
|
497
497
|
z-index: var(--z-sidebar);
|
|
498
498
|
display: flex;
|
|
499
499
|
flex-direction: column;
|
|
500
|
-
|
|
500
|
+
/* Glass laid over a solid ground: the rail opens OVER the top bar and the
|
|
501
|
+
content, and --glass in light is a 5% tint with no blur, so bare glass let
|
|
502
|
+
the page title read straight through the brand ("Builders' Hall" on top of
|
|
503
|
+
"profile"). Same fix as the board's bar. */
|
|
504
|
+
background: linear-gradient(var(--glass), var(--glass)), var(--bg);
|
|
501
505
|
border-right: 1px solid var(--glass-edge);
|
|
502
506
|
backdrop-filter: blur(var(--glass-blur));
|
|
503
507
|
-webkit-backdrop-filter: blur(var(--glass-blur));
|
|
@@ -109,10 +109,15 @@
|
|
|
109
109
|
return c / m;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// Where the hall lives: the builders. subdomain's own origin, else the apex /builders tree.
|
|
113
|
+
function hallBaseUrl() {
|
|
114
|
+
return location.hostname.startsWith('builders.') ? location.origin : `${location.origin}/builders`;
|
|
115
|
+
}
|
|
116
|
+
|
|
112
117
|
// The paste-into-your-agent prompt for one task.
|
|
113
118
|
function buildPromptForTask(t) {
|
|
114
119
|
const desc = deHashRefs((t.description || '').trim());
|
|
115
|
-
const hallBase =
|
|
120
|
+
const hallBase = hallBaseUrl();
|
|
116
121
|
const hallUrl = `${hallBase}#/task/${t.id}`;
|
|
117
122
|
return [
|
|
118
123
|
`I am working on Bongos task ${t.id} (${t.title}) — ${hallUrl}`,
|
|
@@ -123,6 +128,20 @@
|
|
|
123
128
|
].join('\n');
|
|
124
129
|
}
|
|
125
130
|
|
|
131
|
+
// task 1004587 (ADR 0366 D4) — the "Plan with Claude" prompt for one goal. When the
|
|
132
|
+
// goal has an unshipped spec task (source_ref goal-<id>-spec, made by the hall form)
|
|
133
|
+
// the prompt is that task's; otherwise it asks a session to run /goal-create against
|
|
134
|
+
// the goal. `todoTasks` is the goal's unshipped tasks. An extra, never a requirement.
|
|
135
|
+
function buildPlanPromptForGoal(goal, todoTasks) {
|
|
136
|
+
const spec = (todoTasks || []).find((t) => t.source_ref === `goal-${goal.id}-spec`);
|
|
137
|
+
if (spec) return buildPromptForTask(spec);
|
|
138
|
+
const hallBase = hallBaseUrl();
|
|
139
|
+
return [
|
|
140
|
+
`I want to plan Bongos goal ${goal.id} (${deHashRefs(goal.title || '')}) — ${hallBase}#/goal/${goal.id}`,
|
|
141
|
+
`Run /goal-create against this existing goal to add its seed tasks. Do not create a new goal.`,
|
|
142
|
+
].join('\n');
|
|
143
|
+
}
|
|
144
|
+
|
|
126
145
|
// Turn a batch-claim refusal into a sentence. THE DEFAULT MATTERS: an unmapped
|
|
127
146
|
// code falls through to the raw string, which is how the missing MODULE_CONFLICT
|
|
128
147
|
// case leaked a machine code into the Goals page UI. Adding a server-side reason
|
|
@@ -195,7 +214,7 @@
|
|
|
195
214
|
focusVersionDefault,
|
|
196
215
|
msOf, taskActivityMs, STALE_CHOICES, isStale,
|
|
197
216
|
priorityRank, touchesConflict, conflictPeers, conflictChipHtml, rankTagHtml, deHashRefs,
|
|
198
|
-
creditsPerMinute, buildPromptForTask, friendlyBatchReason,
|
|
217
|
+
creditsPerMinute, buildPromptForTask, buildPlanPromptForGoal, friendlyBatchReason,
|
|
199
218
|
};
|
|
200
219
|
if (typeof window !== 'undefined') window.OTBTaskLib = api;
|
|
201
220
|
if (typeof module !== 'undefined' && module.exports) module.exports = api;
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.78",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.21.
|
|
9
|
+
"version": "1.21.78",
|
|
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.21.
|
|
3
|
+
"version": "1.21.78",
|
|
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",
|
package/release-notes.json
CHANGED
|
@@ -9266,5 +9266,17 @@
|
|
|
9266
9266
|
"id": "1004499",
|
|
9267
9267
|
"text": "Artists can now review the public website while looking at it. A signed-in builder on cloudbongos.com's public pages (home, projects, account, guilds, invitations, privacy, terms, contact) sees a Review button in the top bar,"
|
|
9268
9268
|
}
|
|
9269
|
+
],
|
|
9270
|
+
"1.21.77": [
|
|
9271
|
+
{
|
|
9272
|
+
"id": "1004638",
|
|
9273
|
+
"text": "The hall sidebar now has a solid background, so the page title no longer shows through the Builders' Hall name in light mode."
|
|
9274
|
+
}
|
|
9275
|
+
],
|
|
9276
|
+
"1.21.78": [
|
|
9277
|
+
{
|
|
9278
|
+
"id": "1004587",
|
|
9279
|
+
"text": "Goal pages now have a Plan with Claude button that copies a ready-made planning prompt."
|
|
9280
|
+
}
|
|
9269
9281
|
]
|
|
9270
9282
|
}
|
package/src/module-api.js
CHANGED
|
@@ -75,7 +75,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
75
75
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
76
76
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
77
77
|
|
|
78
|
-
const CORE_VERSION = '1.21.
|
|
78
|
+
const CORE_VERSION = '1.21.78'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
79
79
|
|
|
80
80
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
81
81
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// tests/goal_plan_with_claude.mjs — the goal page's "Plan with Claude" hand-off (task 1004587, ADR 0366 D4).
|
|
2
|
+
//
|
|
3
|
+
// Run: node --test tests/goal_plan_with_claude.mjs
|
|
4
|
+
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
import { test } from 'node:test';
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
import { createRequire } from 'node:module';
|
|
9
|
+
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
globalThis.location = { hostname: 'builders.example.com', origin: 'https://builders.example.com' };
|
|
12
|
+
const { buildPlanPromptForGoal, buildPromptForTask } = require('../modules/hall-ui/public/task-lib.js');
|
|
13
|
+
const src = (rel) => readFileSync(new URL('../' + rel, import.meta.url), 'utf8');
|
|
14
|
+
|
|
15
|
+
const goal = { id: 42, title: 'Ship the thing' };
|
|
16
|
+
const spec = { id: 900, title: 'Spec goal 42: its scope', description: 'Do the interview.', source_ref: 'goal-42-spec' };
|
|
17
|
+
const other = { id: 901, title: 'Other', description: 'x', source_ref: null };
|
|
18
|
+
|
|
19
|
+
test('with an unshipped spec task the prompt is that task\'s', () => {
|
|
20
|
+
assert.equal(buildPlanPromptForGoal(goal, [other, spec]), buildPromptForTask(spec));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('another goal\'s spec task is not this goal\'s', () => {
|
|
24
|
+
const p = buildPlanPromptForGoal(goal, [{ ...spec, source_ref: 'goal-43-spec' }]);
|
|
25
|
+
assert.match(p, /\/goal-create/);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('without a spec task the prompt asks for /goal-create against the goal', () => {
|
|
29
|
+
const p = buildPlanPromptForGoal(goal, [other]);
|
|
30
|
+
assert.match(p, /\/goal-create/);
|
|
31
|
+
assert.match(p, /goal 42/);
|
|
32
|
+
assert.match(p, /#\/goal\/42/);
|
|
33
|
+
assert.equal(buildPlanPromptForGoal(goal, undefined), p);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('the button is on the goal page and copies the goal prompt', () => {
|
|
37
|
+
const r = src('modules/hall-ui/public/goals-render.js');
|
|
38
|
+
const pg = src('modules/hall-ui/public/goals-page.js');
|
|
39
|
+
assert.match(r, /id="goal-plan-btn"/);
|
|
40
|
+
assert.ok(pg.includes('buildPlanPromptForGoal(g, state.work.todo)'));
|
|
41
|
+
});
|