toolroll 0.9.85 → 0.9.87
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/CHANGELOG.md +83 -0
- package/dist/agent-fence.d.ts +6 -2
- package/dist/agent-fence.js +3 -2
- package/dist/agents-board.d.ts +12 -0
- package/dist/agents-board.js +26 -0
- package/dist/approval-rules-ui.d.ts +4 -1
- package/dist/approval-rules-ui.js +31 -15
- package/dist/assignment-ui.js +1 -1
- package/dist/assignment.js +4 -3
- package/dist/backup-ui.d.ts +5 -4
- package/dist/backup-ui.js +65 -32
- package/dist/browser/terminal.css +1 -1
- package/dist/browser/terminal.js +57 -54
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +35 -68
- package/dist/browser-crew.js +1 -1
- package/dist/browser-workspace.d.ts +363 -177
- package/dist/browser-workspace.js +10 -9
- package/dist/chat-actions.d.ts +11 -1
- package/dist/chat-actions.js +53 -1
- package/dist/chat-channel.js +1 -0
- package/dist/chat-controls.d.ts +1 -1
- package/dist/chat-controls.js +1 -1
- package/dist/chat-quiet.js +3 -2
- package/dist/chat-settings-page.d.ts +29 -9
- package/dist/chat-settings-page.js +59 -28
- package/dist/check-levels-ui.d.ts +2 -1
- package/dist/check-levels-ui.js +67 -58
- package/dist/claim.d.ts +3 -0
- package/dist/claim.js +4 -1
- package/dist/contracts/chat-actions.d.ts +9 -0
- package/dist/contracts/chat-actions.js +3 -0
- package/dist/contracts/cli.d.ts +43 -0
- package/dist/contracts/cli.js +4 -0
- package/dist/contracts/console-api.d.ts +4 -1
- package/dist/contracts/console-api.js +4 -1
- package/dist/contracts/flow-propose.d.ts +4 -1
- package/dist/contracts/flow-propose.js +1 -1
- package/dist/contracts/flow.d.ts +41 -0
- package/dist/contracts/flow.js +4 -2
- package/dist/contracts/lead-tools.d.ts +21 -0
- package/dist/contracts/lead-tools.js +2 -0
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/contracts/trigger-payloads.d.ts +20 -0
- package/dist/contracts/trigger-payloads.js +4 -0
- package/dist/coordinator.js +1 -0
- package/dist/credentials-ui.d.ts +5 -3
- package/dist/credentials-ui.js +58 -31
- package/dist/deploy-gate.js +4 -0
- package/dist/design/kit.css +685 -0
- package/dist/design/kit.d.ts +208 -0
- package/dist/design/kit.js +177 -0
- package/dist/design/tokens.css +19 -1
- package/dist/discord-settings.js +8 -4
- package/dist/dispatch.d.ts +3 -0
- package/dist/dispatch.js +4 -1
- package/dist/export-ui.d.ts +6 -4
- package/dist/export-ui.js +18 -8
- package/dist/flow-browser.d.ts +103 -0
- package/dist/flow-browser.js +204 -0
- package/dist/flow-changed.d.ts +14 -0
- package/dist/flow-changed.js +53 -0
- package/dist/flow-code.d.ts +5 -1
- package/dist/flow-code.js +4 -1
- package/dist/flow-engine.js +16 -0
- package/dist/flow-gallery-ui.d.ts +41 -4
- package/dist/flow-gallery-ui.js +95 -63
- package/dist/flow-live.js +9 -1
- package/dist/flow-pull-request.js +15 -7
- package/dist/flow-share.js +3 -1
- package/dist/flow-starters-ui.d.ts +3 -9
- package/dist/flow-starters-ui.js +12 -23
- package/dist/flow-steps.d.ts +9 -1
- package/dist/flow-steps.js +55 -5
- package/dist/flow-triggers.js +55 -0
- package/dist/flow-unattended-words.d.ts +20 -0
- package/dist/flow-unattended-words.js +24 -0
- package/dist/flow-unattended.d.ts +9 -5
- package/dist/flow-unattended.js +45 -23
- package/dist/flows-cli.d.ts +19 -0
- package/dist/flows-cli.js +54 -5
- package/dist/flows-ui.d.ts +12 -6
- package/dist/flows-ui.js +152 -32
- package/dist/flows.js +5 -2
- package/dist/integrations-ui.d.ts +6 -4
- package/dist/integrations-ui.js +34 -40
- package/dist/integrations.d.ts +2 -2
- package/dist/integrations.js +4 -4
- package/dist/kits-ui.d.ts +8 -10
- package/dist/kits-ui.js +29 -33
- package/dist/kits.js +1 -1
- package/dist/knowledge-ui.js +76 -19
- package/dist/lead-tools.js +35 -6
- package/dist/lead-voice.js +16 -5
- package/dist/ledger-view.d.ts +2 -0
- package/dist/ledger-view.js +41 -38
- package/dist/models-ui.d.ts +8 -3
- package/dist/models-ui.js +82 -59
- package/dist/monitoring-ui.d.ts +4 -2
- package/dist/monitoring-ui.js +44 -13
- package/dist/needs-you.d.ts +1 -1
- package/dist/needs-you.js +8 -0
- package/dist/operate-remote-arguments.js +1 -0
- package/dist/operate-remote.js +1 -1
- package/dist/operate.d.ts +1 -1
- package/dist/operate.js +249 -6
- package/dist/passwordless.d.ts +1 -1
- package/dist/passwordless.js +1 -1
- package/dist/people-audit-ui.d.ts +2 -1
- package/dist/people-audit-ui.js +25 -23
- package/dist/policy-ui.d.ts +3 -2
- package/dist/policy-ui.js +27 -21
- package/dist/policy.d.ts +3 -0
- package/dist/policy.js +14 -1
- package/dist/project-delete-ui.d.ts +4 -2
- package/dist/project-delete-ui.js +135 -126
- package/dist/project-delete.js +7 -3
- package/dist/project-knowledge.d.ts +10 -10
- package/dist/publish.d.ts +11 -0
- package/dist/publish.js +16 -3
- package/dist/pull-request-flow.js +35 -4
- package/dist/pull-request-ui.d.ts +2 -1
- package/dist/pull-request-ui.js +39 -28
- package/dist/recipe-ui.d.ts +4 -2
- package/dist/recipe-ui.js +14 -4
- package/dist/release-adapters.d.ts +3 -0
- package/dist/release-adapters.js +22 -2
- package/dist/release-cli.js +81 -9
- package/dist/release.d.ts +21 -0
- package/dist/release.js +40 -4
- package/dist/releases.js +1 -1
- package/dist/request-budget-ui.d.ts +4 -2
- package/dist/request-budget-ui.js +30 -19
- package/dist/result-follow-ups.js +4 -0
- package/dist/retention-ui.d.ts +4 -3
- package/dist/retention-ui.js +15 -12
- package/dist/scope.d.ts +8 -0
- package/dist/scope.js +13 -0
- package/dist/serve.d.ts +0 -1
- package/dist/serve.js +51 -7
- package/dist/server/agents-computers.d.ts +9 -0
- package/dist/server/agents-computers.js +67 -0
- package/dist/server/chat.js +20 -18
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +19 -9
- package/dist/server/console.css +31 -2
- package/dist/server/flows.js +79 -36
- package/dist/server/home.d.ts +35 -0
- package/dist/server/home.js +104 -0
- package/dist/server/http.d.ts +3 -0
- package/dist/server/http.js +5 -0
- package/dist/server/kit-standalone.d.ts +22 -0
- package/dist/server/kit-standalone.js +69 -0
- package/dist/server/kit.d.ts +405 -0
- package/dist/server/kit.js +361 -0
- package/dist/server/pages.d.ts +2 -1
- package/dist/server/pages.js +213 -174
- package/dist/server/people-tokens.js +26 -85
- package/dist/server/render-history.d.ts +51 -0
- package/dist/server/render-history.js +228 -0
- package/dist/server/render-new-task.d.ts +29 -0
- package/dist/server/render-new-task.js +96 -0
- package/dist/server/render-next.d.ts +63 -0
- package/dist/server/render-next.js +109 -0
- package/dist/server/render-pages.d.ts +35 -190
- package/dist/server/render-pages.js +154 -563
- package/dist/server/render-people.d.ts +24 -3
- package/dist/server/render-people.js +93 -72
- package/dist/server/render-projects.d.ts +103 -0
- package/dist/server/render-projects.js +247 -0
- package/dist/server/render-results.d.ts +5 -24
- package/dist/server/render-results.js +48 -185
- package/dist/server/render-settings.d.ts +5 -74
- package/dist/server/render-settings.js +102 -493
- package/dist/server/render-tasks.d.ts +43 -5
- package/dist/server/render-tasks.js +131 -91
- package/dist/server/route-table.js +31 -5
- package/dist/server/settings.js +276 -255
- package/dist/server/task-views.d.ts +8 -0
- package/dist/server/task-views.js +90 -2
- package/dist/server/tasks.d.ts +18 -0
- package/dist/server/tasks.js +148 -41
- package/dist/server/terminals.js +1 -1
- package/dist/server/welcome.d.ts +22 -0
- package/dist/server/welcome.js +69 -0
- package/dist/settings-groups-ui.d.ts +279 -0
- package/dist/settings-groups-ui.js +615 -0
- package/dist/settings-kit.d.ts +42 -6
- package/dist/settings-kit.js +69 -7
- package/dist/settings-proofs.js +1 -0
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills-ui.js +59 -7
- package/dist/slack-settings.js +12 -5
- package/dist/spend-ui.d.ts +45 -26
- package/dist/spend-ui.js +124 -56
- package/dist/sso-ui.d.ts +5 -2
- package/dist/sso-ui.js +63 -31
- package/dist/storage-ui.d.ts +3 -2
- package/dist/storage-ui.js +56 -50
- package/dist/store.d.ts +182 -5
- package/dist/store.js +512 -38
- package/dist/surface.js +23 -3
- package/dist/task-archive.d.ts +10 -0
- package/dist/task-archive.js +16 -0
- package/dist/task-control.d.ts +1 -1
- package/dist/teams-settings.d.ts +2 -1
- package/dist/teams-settings.js +24 -41
- package/dist/telegram-settings.d.ts +0 -4
- package/dist/telegram-settings.js +52 -25
- package/dist/tidy.d.ts +130 -0
- package/dist/tidy.js +503 -0
- package/dist/toolroll-update-ui.d.ts +8 -4
- package/dist/toolroll-update-ui.js +55 -45
- package/dist/tools-ui.d.ts +5 -3
- package/dist/tools-ui.js +107 -42
- package/dist/work-index.d.ts +24 -0
- package/dist/work-index.js +56 -30
- package/dist/workspace-ui.d.ts +1 -1
- package/dist/workspace-ui.js +8 -4
- package/package.json +1 -1
package/dist/work-index.js
CHANGED
|
@@ -22,10 +22,12 @@ import { ASKS, NEED_ASK, NEEDS, askChipOf, failedAttemptSentence, processNeedOf,
|
|
|
22
22
|
import { LEAD_CLAIM_SQL, LEAD_IDLE_MS } from './lead-voice.js';
|
|
23
23
|
export const WORK_INDEX_PAGE_LIMIT = 40;
|
|
24
24
|
export const WORK_INDEX_MAX_LIMIT = 100;
|
|
25
|
-
const EMPTY = { all: 0, 'needs-you': 0, running: 0, completed: 0 };
|
|
25
|
+
const EMPTY = { all: 0, 'needs-you': 0, running: 0, queued: 0, completed: 0, archived: 0 };
|
|
26
26
|
const NO_GROUPS = { decide: 0, review: 0, unblock: 0, building: 0, rest: 0 };
|
|
27
27
|
const FAMILY_PROBLEM = 'Task history is unavailable or incomplete. This task is shown separately.';
|
|
28
|
-
const VIEWS = ['all', 'needs-you', 'running', 'completed'];
|
|
28
|
+
const VIEWS = ['all', 'needs-you', 'running', 'queued', 'completed', 'archived'];
|
|
29
|
+
/** The family's current version is put away (v145): it waits on nobody and only the Archived view lists it. */
|
|
30
|
+
const ARCHIVED = `EXISTS(SELECT 1 FROM task_archive ta WHERE ta.task_ref=c.ref_id)`;
|
|
29
31
|
const n = (row, key) => Number(row[key] ?? 0);
|
|
30
32
|
const s = (row, key) => row[key] == null ? null : String(row[key]);
|
|
31
33
|
/** The running agent's oldest open question (agent-board.ts), from its open newest attempt only. */
|
|
@@ -93,24 +95,25 @@ const PROJECTION = `WITH RECURSIVE admitted AS MATERIALIZED (
|
|
|
93
95
|
(SELECT id FROM run WHERE task_ref=a.ref_id AND outcome IS NULL ORDER BY id DESC LIMIT 1) unfinished,
|
|
94
96
|
CASE WHEN a.state='done' THEN (SELECT id FROM run WHERE task_ref=a.ref_id AND finished_at IS NOT NULL AND role IN ('builder','scout') ORDER BY id DESC LIMIT 1) END result_id,
|
|
95
97
|
(SELECT h.id FROM hold h WHERE h.task_ref=a.ref_id AND (h.until IS NULL OR h.until>$now) ORDER BY h.held_at,h.id LIMIT 1) hold_id,
|
|
96
|
-
q.decision_id,${AGENT_ASK} agent_ask,(cu.task_ref IS NOT NULL OR a.ref_id IN (SELECT value FROM json_each($workspaceCustody)))
|
|
98
|
+
q.decision_id,${AGENT_ASK} agent_ask,EXISTS(SELECT 1 FROM task_archive ta WHERE ta.task_ref=a.ref_id) member_archived,(cu.task_ref IS NOT NULL OR a.ref_id IN (SELECT value FROM json_each($workspaceCustody)))
|
|
97
99
|
AND a.ref_id NOT IN (SELECT value FROM json_each($settledCustody)) custody_unresolved
|
|
98
100
|
FROM admitted a LEFT JOIN lineage l ON l.ref_id=a.ref_id
|
|
99
101
|
LEFT JOIN questions q ON q.task_ref=a.ref_id LEFT JOIN custody cu ON cu.task_ref=a.ref_id
|
|
100
102
|
), family_heads AS MATERIALIZED (
|
|
101
103
|
SELECT root_ref,COUNT(*) version_count,MAX(updated_at) family_updated,
|
|
102
104
|
CAST(substr(MAX((CASE WHEN ref_id=root_ref THEN '0' ELSE '1' END)||created_at||printf('%020d',ref_id)),-20) AS INTEGER) current_ref,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
MAX(live_lease IS NOT NULL)
|
|
105
|
+
-- A put-away version (v145) is history: it never counts as an earlier active version or brings its question along.
|
|
106
|
+
SUM(NOT member_archived AND (state IN ('queued','running') OR live_lease IS NOT NULL OR unfinished IS NOT NULL OR custody_unresolved)) active_count,
|
|
107
|
+
MIN(CASE WHEN NOT member_archived AND (state IN ('queued','running') OR live_lease IS NOT NULL OR unfinished IS NOT NULL OR custody_unresolved) THEN ref_id END) first_active,
|
|
108
|
+
MAX(CASE WHEN NOT member_archived AND (state IN ('queued','running') OR live_lease IS NOT NULL OR unfinished IS NOT NULL OR custody_unresolved) THEN ref_id END) last_active,
|
|
109
|
+
MAX(live_lease IS NOT NULL) family_running,MIN(CASE WHEN NOT member_archived THEN decision_id END) question_id
|
|
107
110
|
FROM members GROUP BY root_ref
|
|
108
111
|
), ordered AS MATERIALIZED (
|
|
109
112
|
SELECT m.*,CASE WHEN m.ref_id=f.current_ref THEN 1 ELSE 2 END version_rank
|
|
110
113
|
FROM members m JOIN family_heads f USING(root_ref)
|
|
111
114
|
), families AS MATERIALIZED (
|
|
112
115
|
SELECT f.root_ref,f.version_count,f.family_updated,f.family_running,
|
|
113
|
-
f.active_count-(c.state IN ('queued','running') OR c.live_lease IS NOT NULL OR c.unfinished IS NOT NULL OR c.custody_unresolved) earlier_active,
|
|
116
|
+
f.active_count-(NOT c.member_archived AND (c.state IN ('queued','running') OR c.live_lease IS NOT NULL OR c.unfinished IS NOT NULL OR c.custody_unresolved)) earlier_active,
|
|
114
117
|
earlier.id earlier_id,COALESCE(c.decision_id,f.question_id) question_id
|
|
115
118
|
FROM family_heads f JOIN members c ON c.ref_id=f.current_ref
|
|
116
119
|
LEFT JOIN admitted earlier ON earlier.ref_id=CASE WHEN f.first_active=f.current_ref THEN f.last_active ELSE f.first_active END
|
|
@@ -236,8 +239,9 @@ const PROJECTION = `WITH RECURSIVE admitted AS MATERIALIZED (
|
|
|
236
239
|
SELECT c.*,CASE WHEN code IN ('cancelled','complete') THEN 0 ELSE ${LEAD_CLAIM_SQL} END lead_claim FROM classified c
|
|
237
240
|
), ranked AS MATERIALIZED (
|
|
238
241
|
-- A task the person's lead is on (lead-voice.ts) waits on nobody: it leaves Needs you until the claim ends or lapses.
|
|
239
|
-
SELECT c.*,code NOT IN ('cancelled','complete','running','updating','retry-scheduled','waiting-dependency','worker-at-capacity','planning-ready','scouting-ready','queued') AND NOT ${CUSTODY_WAITS} AND lead_claim<>1 needs,
|
|
240
|
-
code NOT IN ('cancelled','complete','running','updating','retry-scheduled','waiting-dependency','worker-at-capacity','planning-ready','scouting-ready','queued') AND NOT ${CUSTODY_WAITS} person_need,
|
|
242
|
+
SELECT c.*,code NOT IN ('cancelled','complete','running','updating','retry-scheduled','waiting-dependency','worker-at-capacity','planning-ready','scouting-ready','queued') AND NOT ${CUSTODY_WAITS} AND lead_claim<>1 AND NOT ${ARCHIVED} needs,
|
|
243
|
+
code NOT IN ('cancelled','complete','running','updating','retry-scheduled','waiting-dependency','worker-at-capacity','planning-ready','scouting-ready','queued') AND NOT ${CUSTODY_WAITS} AND NOT ${ARCHIVED} person_need,
|
|
244
|
+
${ARCHIVED} archived,
|
|
241
245
|
CASE WHEN code='complete' THEN 3 WHEN code='cancelled' THEN 4 WHEN code='running' THEN 1
|
|
242
246
|
WHEN ${CUSTODY_WAITS} OR code IN ('updating','retry-scheduled','waiting-dependency','worker-at-capacity','planning-ready','scouting-ready','queued') THEN 2 ELSE 0 END rank,
|
|
243
247
|
${ASK_RANK} ask_rank,
|
|
@@ -329,11 +333,15 @@ function parameters(now, access, options, custody) {
|
|
|
329
333
|
$leadOf: access.principal === 'operator' && access.viewer != null && access.viewer !== '' ? `lead for ${access.viewer}` : null };
|
|
330
334
|
}
|
|
331
335
|
function counts(row) {
|
|
332
|
-
return { all: n(row, 'all_count'), 'needs-you': n(row, 'needs_count'), running: n(row, 'running_count'), completed: n(row, 'completed_count') };
|
|
336
|
+
return { all: n(row, 'all_count'), 'needs-you': n(row, 'needs_count'), running: n(row, 'running_count'), queued: n(row, 'queued_count'), completed: n(row, 'completed_count'), archived: n(row, 'archived_count') };
|
|
333
337
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
338
|
+
// Put-away families (v145) count only as archived.
|
|
339
|
+
// Queued: waits on someone or something else (rank 2), not a person and not a build of its own family.
|
|
340
|
+
const QUEUED = `rank=2 AND family_running=0 AND archived=0`;
|
|
341
|
+
const TOTALS = `COALESCE(SUM(archived=0),0) all_count,COALESCE(SUM(needs),0) needs_count,COALESCE(SUM(family_running AND archived=0),0) running_count,`
|
|
342
|
+
+ `COALESCE(SUM(${QUEUED}),0) queued_count,COALESCE(SUM(code='complete' AND archived=0),0) completed_count,COALESCE(SUM(archived),0) archived_count`;
|
|
343
|
+
const GROUP_TOTALS = `COALESCE(SUM(rank=0 AND ask_rank=0 AND archived=0),0) decide_count,COALESCE(SUM(rank=0 AND ask_rank=1 AND archived=0),0) review_count,COALESCE(SUM(rank=0 AND ask_rank=2 AND archived=0),0) unblock_count,`
|
|
344
|
+
+ `COALESCE(SUM(rank=1 AND archived=0),0) building_count,COALESCE(SUM(rank>1 AND archived=0),0) rest_count`;
|
|
337
345
|
function groupCounts(row) {
|
|
338
346
|
return { decide: n(row, 'decide_count'), review: n(row, 'review_count'), unblock: n(row, 'unblock_count'), building: n(row, 'building_count'), rest: n(row, 'rest_count') };
|
|
339
347
|
}
|
|
@@ -383,18 +391,20 @@ function readWorkIndexPage(store, now, access, options, taskId = null) {
|
|
|
383
391
|
const view = VIEWS.includes(options.view ?? 'all') ? options.view ?? 'all' : 'all';
|
|
384
392
|
const limit = Number.isFinite(options.limit) ? Math.max(1, Math.min(WORK_INDEX_MAX_LIMIT, Math.floor(options.limit))) : WORK_INDEX_PAGE_LIMIT;
|
|
385
393
|
const scope = cursorScope(access, options, view), cursor = readCursor(options.cursor, scope);
|
|
386
|
-
const filter = view === 'needs-you' ? 'needs=1' : view === 'running' ? 'family_running=1' : view === 'completed' ? "code='complete'" : '
|
|
394
|
+
const filter = view === 'archived' ? 'archived=1' : view === 'needs-you' ? 'needs=1' : view === 'running' ? 'family_running=1 AND archived=0' : view === 'queued' ? QUEUED : view === 'completed' ? "code='complete' AND archived=0" : 'archived=0';
|
|
387
395
|
const rows = prepared(store, `${projection}, selected_page AS MATERIALIZED (
|
|
388
|
-
SELECT * FROM ranked WHERE ${filter} AND ($taskId IS NULL OR root_ref IN (SELECT root_ref FROM members WHERE id=$taskId)) AND ($roots IS NULL OR root_id IN (SELECT value FROM json_each($roots))) AND ($cursorRoot=0 OR
|
|
396
|
+
SELECT * FROM ranked WHERE ($taskId IS NOT NULL OR ${filter}) AND ($taskId IS NULL OR root_ref IN (SELECT root_ref FROM members WHERE id=$taskId)) AND ($roots IS NULL OR root_id IN (SELECT value FROM json_each($roots))) AND ($cursorRoot=0 OR
|
|
389
397
|
${ORDER}>$cursorRank OR (${ORDER}=$cursorRank AND (sort_at<$cursorAt OR (sort_at=$cursorAt AND root_ref<$cursorRoot))))
|
|
390
398
|
ORDER BY ${ORDER},sort_at DESC,root_ref DESC LIMIT $limit
|
|
391
399
|
), page AS (SELECT p.*,COALESCE(p.result_id,(SELECT id FROM run WHERE task_ref=p.ref_id AND finished_at IS NOT NULL AND role IN ('builder','scout') ORDER BY id DESC LIMIT 1)) page_result_id FROM selected_page p), totals AS (SELECT ${TOTALS},${GROUP_TOTALS} FROM ranked), project_totals AS (
|
|
392
|
-
SELECT repo,${TOTALS},SUM(state='queued' AND family_running=0) queued,
|
|
393
|
-
SUM(state='done' AND family_running=0 AND updated_at>=$recent) done_recently FROM ranked GROUP BY repo
|
|
400
|
+
SELECT repo,${TOTALS},SUM(state='queued' AND family_running=0 AND archived=0) queued,
|
|
401
|
+
SUM(state='done' AND family_running=0 AND archived=0 AND updated_at>=$recent) done_recently FROM ranked GROUP BY repo
|
|
394
402
|
)
|
|
395
403
|
SELECT 0 record_kind,totals.*,(SELECT json_group_array(json_object('repo',repo,'all_count',all_count,'needs_count',needs_count,
|
|
396
|
-
'running_count',running_count,'completed_count',completed_count,'queued',queued,'done_recently',done_recently)) FROM project_totals) row_json FROM totals
|
|
397
|
-
UNION ALL SELECT 1,0,0,0,0,0,0,0,0,0,json_object('
|
|
404
|
+
'running_count',running_count,'queued_count',queued_count,'completed_count',completed_count,'archived_count',archived_count,'queued',queued,'done_recently',done_recently)) FROM project_totals) row_json FROM totals
|
|
405
|
+
UNION ALL SELECT 1,0,0,0,0,0,0,0,0,0,0,0,json_object('archived',archived,'archived_by',(SELECT by FROM task_archive WHERE task_ref=page.ref_id),
|
|
406
|
+
'archived_kind',(SELECT by_kind FROM task_archive WHERE task_ref=page.ref_id),'archived_reason',(SELECT reason FROM task_archive WHERE task_ref=page.ref_id),
|
|
407
|
+
'archived_at',(SELECT at FROM task_archive WHERE task_ref=page.ref_id),'root_ref',root_ref,'root_id',root_id,'id',id,'root_title',root_title,'repo',repo,
|
|
398
408
|
'state',state,'created_at',created_at,'family_updated',family_updated,'version_count',version_count,'earlier_active',earlier_active,
|
|
399
409
|
'earlier_id',earlier_id,'broken',broken,'live_run',live_run,'result_id',page_result_id,'result_outcome',(SELECT outcome FROM run WHERE id=page_result_id),'attempt_reason',(SELECT substr(reason,1,1000) FROM run WHERE task_ref IN (SELECT ref_id FROM members WHERE root_ref=page.root_ref) AND (finished_at IS NOT NULL OR outcome IS NOT NULL) AND role NOT IN ('planner','reviewer') ORDER BY id DESC LIMIT 1),
|
|
400
410
|
'publication_url',(SELECT pr_url FROM publication WHERE run=page_result_id),
|
|
@@ -434,8 +444,8 @@ function readWorkIndexPage(store, now, access, options, taskId = null) {
|
|
|
434
444
|
}
|
|
435
445
|
export function workCountsByProject(store, now, access) {
|
|
436
446
|
const projection = registerValidators(store);
|
|
437
|
-
return store.handle.prepare(`${projection} SELECT repo,${TOTALS},SUM(state='queued' AND family_running=0) queued,
|
|
438
|
-
SUM(state='done' AND family_running=0 AND updated_at>=$recent) done_recently FROM ranked GROUP BY repo ORDER BY repo`)
|
|
447
|
+
return store.handle.prepare(`${projection} SELECT repo,${TOTALS},SUM(state='queued' AND family_running=0 AND archived=0) queued,
|
|
448
|
+
SUM(state='done' AND family_running=0 AND archived=0 AND updated_at>=$recent) done_recently FROM ranked GROUP BY repo ORDER BY repo`)
|
|
439
449
|
.all({ ...parameters(now, access, {}, custodyReadings(store)), $recent: new Date(now.getTime() - 86_400_000).toISOString() })
|
|
440
450
|
.map(row => ({ repo: s(row, 'repo'), totals: counts(row), queued: n(row, 'queued'), doneRecently: n(row, 'done_recently') }));
|
|
441
451
|
}
|
|
@@ -447,7 +457,7 @@ export function workStateRows(store, now, access) {
|
|
|
447
457
|
COALESCE((SELECT created_at FROM decision WHERE id=question_id),''),COALESCE((SELECT asked_at FROM agent_question WHERE id=agent_ask),''),
|
|
448
458
|
COALESCE((SELECT held_at FROM hold WHERE id=hold_id),''),COALESCE((SELECT requested_at FROM run_stop WHERE run=stop_run),'')),''),sort_at) ask_at,
|
|
449
459
|
COALESCE(live_run,(SELECT run FROM decision WHERE id=question_id),(SELECT run FROM agent_question WHERE id=agent_ask)) ask_run,
|
|
450
|
-
(SELECT json_group_array(m.ref_id) FROM members m WHERE m.root_ref=ranked.root_ref) members FROM ranked`)
|
|
460
|
+
(SELECT json_group_array(m.ref_id) FROM members m WHERE m.root_ref=ranked.root_ref) members FROM ranked WHERE archived=0`)
|
|
451
461
|
.all(parameters(now, access, {}, custodyReadings(store)))
|
|
452
462
|
.map(row => ({ repo: s(row, 'repo'), rootId: String(row['root_id']), code: String(row['code']), needs: n(row, 'needs') === 1, personNeed: n(row, 'person_need') === 1,
|
|
453
463
|
leadClaim: n(row, 'lead_claim') === 1, liveRun: row['live_run'] == null ? null : n(row, 'live_run'), unfinished: row['unfinished'] == null ? null : n(row, 'unfinished'),
|
|
@@ -458,8 +468,8 @@ export function workStateRows(store, now, access) {
|
|
|
458
468
|
* attempts are aggregated in SQLite, never loaded as an unbounded history. */
|
|
459
469
|
export function workOutcomeRows(store, now, access, project, since, limit) {
|
|
460
470
|
return store.handle.prepare(`${registerValidators(store)}, selected AS MATERIALIZED (
|
|
461
|
-
SELECT * FROM ranked WHERE code='ready-to-check' OR code='history-problem'
|
|
462
|
-
OR (code='complete' AND checked_at >= $since AND checked_at <= $now)
|
|
471
|
+
SELECT * FROM ranked WHERE archived=0 AND (code='ready-to-check' OR code='history-problem'
|
|
472
|
+
OR (code='complete' AND checked_at >= $since AND checked_at <= $now))
|
|
463
473
|
ORDER BY sort_at DESC,root_ref DESC LIMIT $outcomeLimit
|
|
464
474
|
), amounts AS (
|
|
465
475
|
-- reported-usage.ts runAmountOf, row for row: only evidenced billing on a run whose cost was reported is known;
|
|
@@ -701,12 +711,16 @@ function itemOf(row, principal, probe, leadName, readiness, readable = false) {
|
|
|
701
711
|
if (asked !== null)
|
|
702
712
|
detail = `The agent asks: ${asked}`;
|
|
703
713
|
}
|
|
704
|
-
const
|
|
705
|
-
|
|
714
|
+
const archived = n(row, 'archived') === 1 ? { by: String(row['archived_by'] ?? ''), byKind: row['archived_kind'] === 'tidy' ? 'tidy' : 'person',
|
|
715
|
+
reason: String(row['archived_reason'] ?? ''), at: String(row['archived_at'] ?? '') } : null;
|
|
716
|
+
const views = archived !== null ? ['archived'] : ['all'];
|
|
717
|
+
if (archived === null && need)
|
|
706
718
|
views.push('needs-you');
|
|
707
|
-
if (running)
|
|
719
|
+
if (archived === null && running)
|
|
708
720
|
views.push('running');
|
|
709
|
-
if (
|
|
721
|
+
if (archived === null && !need && !running && n(row, 'rank') === 2)
|
|
722
|
+
views.push('queued');
|
|
723
|
+
if (archived === null && code === 'complete')
|
|
710
724
|
views.push('completed');
|
|
711
725
|
return { rootId: String(row['root_id']), activeTaskId: id, title: String(row['root_title']), repo: s(row, 'repo'),
|
|
712
726
|
state: String(row['state']), assignmentState, createdAt: String(row['created_at']), updatedAt: String(row['sort_at']),
|
|
@@ -718,5 +732,17 @@ function itemOf(row, principal, probe, leadName, readiness, readable = false) {
|
|
|
718
732
|
ask: need ? ASKS[n(row, 'ask_rank')] ?? 'unblock' : null,
|
|
719
733
|
chip: need ? askChipOf({ headline: shared.headline, need: shared.need?.key ?? null, planChanged, mismatch: verdict === 'refuted' && n(row, 'proof_failed_check') !== 1, ask: ASKS[n(row, 'ask_rank')] ?? 'unblock' }) : null,
|
|
720
734
|
primaryAction, completion: code === 'complete' ? { actor: String(row['checked_actor']), at: String(row['checked_at']), digest: String(row['checked_digest']), ...(landed === null ? {} : { landed }) } : null,
|
|
721
|
-
evidence: 'recorded', ...(lead === 'on-it' ? { lead: leadOnIt(leadName) } : {}) };
|
|
735
|
+
evidence: 'recorded', ...(lead === 'on-it' ? { lead: leadOnIt(leadName) } : {}), ...(archived === null ? {} : { archived }) };
|
|
736
|
+
}
|
|
737
|
+
export function workTidyRows(store, now, access) {
|
|
738
|
+
const projection = registerValidators(store);
|
|
739
|
+
return store.handle.prepare(`${projection} SELECT root_id,id,root_title,repo,state,code,archived,broken,family_updated,
|
|
740
|
+
(family_running OR live_lease IS NOT NULL OR unfinished IS NOT NULL OR custody_unresolved OR stop_run IS NOT NULL AND stop_settled IS NULL OR state='running') live,
|
|
741
|
+
(SELECT json_group_array(m.ref_id) FROM members m WHERE m.root_ref=ranked.root_ref) members,
|
|
742
|
+
(SELECT json_group_array(m.id) FROM members m WHERE m.root_ref=ranked.root_ref) member_ids FROM ranked`)
|
|
743
|
+
.all(parameters(now, access, {}, custodyReadings(store)))
|
|
744
|
+
.map(row => ({ rootId: String(row['root_id']), currentId: String(row['id']), title: String(row['root_title']), repo: s(row, 'repo'),
|
|
745
|
+
state: String(row['state']), code: String(row['code']), live: n(row, 'live') === 1, archived: n(row, 'archived') === 1, broken: n(row, 'broken') === 1,
|
|
746
|
+
updatedAt: String(row['family_updated'] ?? ''), members: JSON.parse(String(row['members'] ?? '[]')).map(Number),
|
|
747
|
+
memberIds: JSON.parse(String(row['member_ids'] ?? '[]')).map(String) }));
|
|
722
748
|
}
|
package/dist/workspace-ui.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { type ChecksFact } from "./task-status.js";
|
|
|
26
26
|
import { type Html } from "./html.js";
|
|
27
27
|
/** The Work destination's views — shortcuts over the same rows, never a
|
|
28
28
|
* persisted state. All is the default. */
|
|
29
|
-
export type WorkView = "all" | "needs-you" | "running" | "completed";
|
|
29
|
+
export type WorkView = "all" | "needs-you" | "running" | "queued" | "completed" | "archived";
|
|
30
30
|
export declare const WORK_VIEWS: readonly {
|
|
31
31
|
key: WorkView;
|
|
32
32
|
label: string;
|
package/dist/workspace-ui.js
CHANGED
|
@@ -25,11 +25,13 @@ import { html, postForm } from "./html.js";
|
|
|
25
25
|
export const WORK_VIEWS = [
|
|
26
26
|
{ key: "all", label: "All", hint: "Every task in view, most urgent first.", empty: "Nothing is in progress. Describe work in chat or add a task, and it appears here." },
|
|
27
27
|
{ key: "needs-you", label: "Needs you", hint: "Tasks waiting on an answer, approval, or your inspection.", empty: "Nothing needs you right now. Queued and running work continues on its own." },
|
|
28
|
-
{ key: "running", label: "
|
|
29
|
-
{ key: "
|
|
28
|
+
{ key: "running", label: "Running", hint: "Attempts a builder owns right now.", empty: "Nothing is running right now. Approved tasks start when a builder with capacity is connected." },
|
|
29
|
+
{ key: "queued", label: "Queued", hint: "Tasks that start on their own: waiting for a builder, a dependency or a retry.", empty: "Nothing is queued." },
|
|
30
|
+
{ key: "completed", label: "Finished", hint: "Tasks the lead or user has marked complete. Recorded check results remain available.", empty: "Nothing has finished in this view yet." },
|
|
31
|
+
{ key: "archived", label: "Archived", hint: "Tasks put away by you or by tidy. Their history and results are kept.", empty: "Nothing is put away." },
|
|
30
32
|
];
|
|
31
33
|
export function parseWorkView(raw) {
|
|
32
|
-
return raw === "needs-you" || raw === "running" || raw === "completed" ? raw : "all";
|
|
34
|
+
return raw === "needs-you" || raw === "running" || raw === "queued" || raw === "completed" || raw === "archived" ? raw : "all";
|
|
33
35
|
}
|
|
34
36
|
/** The review facts from the store's bounded retry projection — the same
|
|
35
37
|
* reading `diagnoseTaskDispatch` makes, so every surface starts from one
|
|
@@ -468,6 +470,8 @@ function workStatusWordsOf(facts, resultDisplay) {
|
|
|
468
470
|
views.push("needs-you");
|
|
469
471
|
if (running)
|
|
470
472
|
views.push("running");
|
|
473
|
+
if (!needs && !running && facts.state === "queued")
|
|
474
|
+
views.push("queued");
|
|
471
475
|
if (facts.state === "done")
|
|
472
476
|
views.push("completed");
|
|
473
477
|
const dispatchWords = (tone, rank, action) => ({
|
|
@@ -525,7 +529,7 @@ function workStatusWordsOf(facts, resultDisplay) {
|
|
|
525
529
|
}
|
|
526
530
|
/** The counts each view tab wears — from the same rows the page lists. */
|
|
527
531
|
export function workCounts(rows) {
|
|
528
|
-
const counts = { all: 0, "needs-you": 0, running: 0, completed: 0 };
|
|
532
|
+
const counts = { all: 0, "needs-you": 0, running: 0, queued: 0, completed: 0, archived: 0 };
|
|
529
533
|
for (const row of rows)
|
|
530
534
|
for (const view of row.views)
|
|
531
535
|
counts[view] += 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolroll",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.87",
|
|
4
4
|
"description": "A control plane for unattended coding agents — queue tasks, walk away, come back to pull requests. Agents build in leased worktrees, never touch your default branch, and interrupt you only for decisions that need a human.",
|
|
5
5
|
"directories": {
|
|
6
6
|
"doc": "docs"
|