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.
@@ -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'}`,
@@ -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 && GOAL_LOOP_STATUSES.has(String(mission.status || ''));
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 || '').split('\n').filter(Boolean)[0]?.slice(0, 240) || (ok ? 'no-text' : 'error'),
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 = ticks.length + 1;
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) ? 'running' :
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 = 'game-manager';
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
- id: task.id,
119
- display_id: task.display_id,
120
- legacy_ref: task.legacy_ref,
121
- title: task.title,
122
- status: task.status,
123
- tag: task.tag,
124
- workspace_root: task.workspace_root,
125
- claimed_by: task.claimed_by,
126
- assigned_to: task.metadata?.assigned_to || task.assigned_to || null,
127
- metadata: task.metadata || {},
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 activeTask = tasks.find(t => t.status === 'claimed' || t.status === 'open');
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; one more agent review pass certifies continuation. AgentXP waits for human accept.',
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({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "3.15.51",
3
+ "version": "3.15.52",
4
4
  "main": "bin/atris.js",
5
5
  "bin": {
6
6
  "atris": "bin/atris.js",