atris 3.15.51 → 3.15.52
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/commands/business.js +4 -2
- package/commands/mission.js +43 -4
- package/commands/play.js +1 -1
- package/commands/radar.js +43 -13
- package/commands/task.js +1 -1
- package/package.json +1 -1
package/commands/business.js
CHANGED
|
@@ -909,6 +909,7 @@ function renderBusinessShareHandoff(state, options = {}) {
|
|
|
909
909
|
`Local path: ${workspacePath}`,
|
|
910
910
|
`Ready to share: ${state.ready ? 'yes' : 'no'}`,
|
|
911
911
|
`Remote pull: ${state.remoteReady ? 'available' : 'local-only'}`,
|
|
912
|
+
`Agent setup: ${(state.missingRootAgentAdapters && state.missingRootAgentAdapters.length) ? 'missing root agent adapters' : 'ready'}`,
|
|
912
913
|
'',
|
|
913
914
|
'## Get The Workspace',
|
|
914
915
|
'',
|
|
@@ -946,9 +947,9 @@ function renderBusinessShareHandoff(state, options = {}) {
|
|
|
946
947
|
'',
|
|
947
948
|
'## What To Read',
|
|
948
949
|
'',
|
|
950
|
+
`- Protocol: atris/atris.md`,
|
|
949
951
|
`- Map: atris/MAP.md`,
|
|
950
952
|
`- Queue: atris/TODO.md`,
|
|
951
|
-
`- Agent adapters: ${state.rootAgentAdapters && state.rootAgentAdapters.length ? state.rootAgentAdapters.join(', ') : 'missing'}`,
|
|
952
953
|
`- Team start: ${state.teamStart || 'missing'}`,
|
|
953
954
|
`- Starter brief: ${state.starterBrief || 'missing'}`,
|
|
954
955
|
`- First loop: ${state.firstLoop || 'missing'}`,
|
|
@@ -1014,11 +1015,12 @@ function renderBusinessStartCard(state, options = {}) {
|
|
|
1014
1015
|
`Workspace: ${workspacePath}`,
|
|
1015
1016
|
`Ready: ${state.ready ? 'yes' : 'no'}`,
|
|
1016
1017
|
`Remote pull: ${state.remoteReady ? 'available' : 'local-only'}`,
|
|
1018
|
+
`Agent setup: ${(state.missingRootAgentAdapters && state.missingRootAgentAdapters.length) ? 'missing root agent adapters' : 'ready'}`,
|
|
1017
1019
|
'',
|
|
1018
1020
|
'Read:',
|
|
1021
|
+
`- atris/atris.md`,
|
|
1019
1022
|
`- atris/MAP.md`,
|
|
1020
1023
|
`- atris/TODO.md`,
|
|
1021
|
-
`- ${(state.rootAgentAdapters && state.rootAgentAdapters.length === 3) ? state.rootAgentAdapters.join(', ') : 'missing root agent adapters'}`,
|
|
1022
1024
|
`- ${state.teamStart || 'missing team start guide'}`,
|
|
1023
1025
|
`- ${state.starterBrief || 'missing starter brief'}`,
|
|
1024
1026
|
`- ${state.firstLoop || 'missing first loop'}`,
|
package/commands/mission.js
CHANGED
|
@@ -763,8 +763,15 @@ function secondsUntilMissionDue(mission, now = new Date()) {
|
|
|
763
763
|
return Math.max(0, Math.ceil((dueAt - now.getTime()) / 1000));
|
|
764
764
|
}
|
|
765
765
|
|
|
766
|
+
function missionHasHumanAsks(mission) {
|
|
767
|
+
return Array.isArray(mission?.human_asks)
|
|
768
|
+
&& mission.human_asks.some((ask) => String(ask || '').trim());
|
|
769
|
+
}
|
|
770
|
+
|
|
766
771
|
function missionIsRunnable(mission) {
|
|
767
|
-
return mission
|
|
772
|
+
return mission
|
|
773
|
+
&& GOAL_LOOP_STATUSES.has(String(mission.status || ''))
|
|
774
|
+
&& !missionHasHumanAsks(mission);
|
|
768
775
|
}
|
|
769
776
|
|
|
770
777
|
function missionSortTime(mission) {
|
|
@@ -1176,7 +1183,8 @@ function spawnClaudeTick(mission, opts) {
|
|
|
1176
1183
|
exitCode: code,
|
|
1177
1184
|
sessionIds: Array.from(observedSessionIds),
|
|
1178
1185
|
result: finalText,
|
|
1179
|
-
summary: (finalText
|
|
1186
|
+
summary: usefulClaudeReceiptSummary(finalText, ok ? 'no-text' : 'error'),
|
|
1187
|
+
receipt_text: cappedClaudeReceiptText(finalText),
|
|
1180
1188
|
api_equivalent_estimate: costEstimate,
|
|
1181
1189
|
duration_api_ms: durationApiMs,
|
|
1182
1190
|
duration_total_ms: Date.now() - startedAt,
|
|
@@ -1196,6 +1204,33 @@ function spawnClaudeTick(mission, opts) {
|
|
|
1196
1204
|
});
|
|
1197
1205
|
}
|
|
1198
1206
|
|
|
1207
|
+
function stripClaudeReceiptLine(line) {
|
|
1208
|
+
return String(line || '')
|
|
1209
|
+
.trim()
|
|
1210
|
+
.replace(/^#{1,6}\s+/, '')
|
|
1211
|
+
.replace(/^[-*]\s+/, '')
|
|
1212
|
+
.replace(/^\d+[.)]\s+/, '')
|
|
1213
|
+
.trim();
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
function usefulClaudeReceiptSummary(text, fallback = 'no-text') {
|
|
1217
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
1218
|
+
for (const line of lines) {
|
|
1219
|
+
const clean = stripClaudeReceiptLine(line);
|
|
1220
|
+
if (!clean) continue;
|
|
1221
|
+
if (/^(receipt|summary|final|final answer|result)$/i.test(clean)) continue;
|
|
1222
|
+
return clean.slice(0, 240);
|
|
1223
|
+
}
|
|
1224
|
+
return fallback;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
function cappedClaudeReceiptText(text, limit = 4000) {
|
|
1228
|
+
const clean = String(text || '').trim();
|
|
1229
|
+
if (!clean) return '';
|
|
1230
|
+
if (clean.length <= limit) return clean;
|
|
1231
|
+
return clean.slice(0, limit - 16).trimEnd() + '\n...[truncated]';
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1199
1234
|
async function runMission(args) {
|
|
1200
1235
|
const asJson = wantsJson(args);
|
|
1201
1236
|
const dueMode = hasFlag(args, '--due');
|
|
@@ -1323,7 +1358,7 @@ async function runMission(args) {
|
|
|
1323
1358
|
if (mission.verifier !== frozen.verifier) { pauseReason = 'verifier-mutated'; break; }
|
|
1324
1359
|
if ((mission.lane || 'workspace') !== frozen.lane) { pauseReason = 'lane-mutated'; break; }
|
|
1325
1360
|
|
|
1326
|
-
const tickIdx =
|
|
1361
|
+
const tickIdx = Number(mission.last_tick_index || 0) + 1;
|
|
1327
1362
|
const tickStart = stampIso();
|
|
1328
1363
|
const tickWorktreeBefore = gitWorktreeSnapshot(cwd);
|
|
1329
1364
|
let result = { status: 'skipped', reason: 'unknown', tick_index: tickIdx, ran: false, started_at: tickStart };
|
|
@@ -1358,6 +1393,7 @@ async function runMission(args) {
|
|
|
1358
1393
|
result.claude = {
|
|
1359
1394
|
ok: claudeResult.ok,
|
|
1360
1395
|
summary: claudeResult.summary,
|
|
1396
|
+
receipt_text: claudeResult.receipt_text,
|
|
1361
1397
|
stop_reason: claudeResult.stop_reason,
|
|
1362
1398
|
api_equivalent_estimate: claudeResult.api_equivalent_estimate,
|
|
1363
1399
|
duration_total_ms: claudeResult.duration_total_ms,
|
|
@@ -1424,7 +1460,7 @@ async function runMission(args) {
|
|
|
1424
1460
|
});
|
|
1425
1461
|
|
|
1426
1462
|
const xpReadyAction = missionXpReadyAction(mission, receiptPath);
|
|
1427
|
-
const newStatus = (verifierResult?.passed && mission.always_on) ? '
|
|
1463
|
+
const newStatus = (verifierResult?.passed && mission.always_on) ? 'ready' :
|
|
1428
1464
|
(verifierResult?.passed && xpReadyAction) ? 'ready' :
|
|
1429
1465
|
(verifierResult?.passed && completeOnPass) ? 'complete' :
|
|
1430
1466
|
(verifierResult?.passed ? 'ready' :
|
|
@@ -1448,6 +1484,7 @@ async function runMission(args) {
|
|
|
1448
1484
|
last_tick_at: finishedAt,
|
|
1449
1485
|
last_tick_status: result.status,
|
|
1450
1486
|
last_tick_reason: result.reason,
|
|
1487
|
+
last_tick_index: tickIdx,
|
|
1451
1488
|
verifier_result: verifierResult || mission.verifier_result || null,
|
|
1452
1489
|
receipt_path: receiptPath,
|
|
1453
1490
|
next_action: nextAction,
|
|
@@ -1915,4 +1952,6 @@ module.exports = {
|
|
|
1915
1952
|
renderMissionStatus,
|
|
1916
1953
|
selectDueMission,
|
|
1917
1954
|
selectCodexGoalMission,
|
|
1955
|
+
usefulClaudeReceiptSummary,
|
|
1956
|
+
cappedClaudeReceiptText,
|
|
1918
1957
|
};
|
package/commands/play.js
CHANGED
|
@@ -327,7 +327,7 @@ function playWorkspaceRoot(taskDb, workspaceArg) {
|
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
function nextCommands(task, player) {
|
|
330
|
-
const helper = '
|
|
330
|
+
const helper = player || 'player';
|
|
331
331
|
if (!task) {
|
|
332
332
|
return [
|
|
333
333
|
`atris task delegate "AgentXP first rep: one proof-backed mission" --to ${player} --tag agent-xp`,
|
package/commands/radar.js
CHANGED
|
@@ -114,18 +114,26 @@ function loadTasks(root, deps) {
|
|
|
114
114
|
if (!deps.exists(file)) return [];
|
|
115
115
|
const payload = safeJson(deps.readFile(file, 'utf8'), {});
|
|
116
116
|
const tasks = Array.isArray(payload.tasks) ? payload.tasks : [];
|
|
117
|
-
return tasks.map(task =>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
117
|
+
return tasks.map(task => {
|
|
118
|
+
const messages = Array.isArray(task.messages) ? task.messages : [];
|
|
119
|
+
const row = {
|
|
120
|
+
id: task.id,
|
|
121
|
+
display_id: task.display_id,
|
|
122
|
+
legacy_ref: task.legacy_ref,
|
|
123
|
+
title: task.title,
|
|
124
|
+
status: task.status,
|
|
125
|
+
tag: task.tag,
|
|
126
|
+
workspace_root: task.workspace_root,
|
|
127
|
+
claimed_by: task.claimed_by,
|
|
128
|
+
assigned_to: task.metadata?.assigned_to || task.assigned_to || null,
|
|
129
|
+
metadata: task.metadata || {},
|
|
130
|
+
};
|
|
131
|
+
Object.defineProperty(row, 'routing_text', {
|
|
132
|
+
enumerable: false,
|
|
133
|
+
value: messages.map(message => message && message.content).filter(Boolean).join(' '),
|
|
134
|
+
});
|
|
135
|
+
return row;
|
|
136
|
+
});
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
function findTaskWorkspaceRoot(cwd, deps) {
|
|
@@ -439,9 +447,31 @@ function summarize(tasks, missions, worktrees, agents) {
|
|
|
439
447
|
};
|
|
440
448
|
}
|
|
441
449
|
|
|
450
|
+
function ownerActionRequired(task) {
|
|
451
|
+
const metadata = task?.metadata || {};
|
|
452
|
+
if (metadata.owner_action_required === true || metadata.agent_executable === false) return true;
|
|
453
|
+
if (String(metadata.agent_executable || '').toLowerCase() === 'false') return true;
|
|
454
|
+
const text = [
|
|
455
|
+
task?.title,
|
|
456
|
+
task?.tag,
|
|
457
|
+
metadata.status,
|
|
458
|
+
metadata.blocker,
|
|
459
|
+
metadata.human_revision_note,
|
|
460
|
+
metadata.latest_agent_proof,
|
|
461
|
+
metadata.latest_agent_lesson,
|
|
462
|
+
task?.routing_text,
|
|
463
|
+
].filter(Boolean).join(' ').toLowerCase();
|
|
464
|
+
if (text.includes('owner_action_required') || text.includes('agent_executable=false')) return true;
|
|
465
|
+
if (text.includes('owner-only') || text.includes('owner only') || text.includes('not agent-executable')) return true;
|
|
466
|
+
return text.includes('owner') && text.includes('billing') && (text.includes('spending limit') || text.includes('failed payments'));
|
|
467
|
+
}
|
|
468
|
+
|
|
442
469
|
function nextAction(tasks, missions, worktrees, agents, os = {}) {
|
|
443
|
-
const
|
|
470
|
+
const activeTasks = tasks.filter(t => t.status === 'claimed' || t.status === 'open');
|
|
471
|
+
const activeTask = activeTasks.find(t => !ownerActionRequired(t));
|
|
444
472
|
if (activeTask) return `work ${taskRef(activeTask)}: ${activeTask.title || 'active task'}`;
|
|
473
|
+
const ownerTask = activeTasks.find(ownerActionRequired);
|
|
474
|
+
if (ownerTask) return `owner action required ${taskRef(ownerTask)}: ${ownerTask.title || 'owner-only task'}`;
|
|
445
475
|
const needsReview = tasks.find(t => t.status === 'review' && !(t.metadata && t.metadata.agent_certified));
|
|
446
476
|
if (needsReview) return `review ${taskRef(needsReview)}: ${needsReview.title || 'uncertified review task'}`;
|
|
447
477
|
const certified = tasks.find(t => t.status === 'review' && t.metadata && t.metadata.agent_certified);
|
package/commands/task.js
CHANGED
|
@@ -1708,7 +1708,7 @@ function cmdReady(args) {
|
|
|
1708
1708
|
next_action: agentCertified ? 'continue_work' : 'agent_review_again',
|
|
1709
1709
|
rule: agentCertified
|
|
1710
1710
|
? 'Agent double-check complete; continue work. AgentXP waits for human accept.'
|
|
1711
|
-
: 'Proof is in Review;
|
|
1711
|
+
: 'Proof is in Review; human accept can award AgentXP now. A second agent review only certifies autonomous continuation.',
|
|
1712
1712
|
};
|
|
1713
1713
|
if (wantsJson(args)) {
|
|
1714
1714
|
printJson({
|