atris 3.57.3 → 3.58.5

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.
Files changed (175) hide show
  1. package/README.md +12 -1
  2. package/atris/skills/clawhub/member-runtime/SKILL.md +9 -9
  3. package/atris/skills/create-member/SKILL.md +16 -13
  4. package/atris/skills/design/SKILL.md +27 -4
  5. package/atris/skills/engines/SKILL.md +57 -13
  6. package/atris/skills/x-search/SKILL.md +13 -5
  7. package/atris/skills/youtube/SKILL.md +39 -8
  8. package/atris/team/brainstormer/MEMBER.md +2 -2
  9. package/atris/team/executor/MEMBER.md +3 -3
  10. package/atris/team/launcher/MEMBER.md +4 -4
  11. package/atris/team/navigator/MEMBER.md +3 -3
  12. package/atris/team/researcher/MEMBER.md +2 -2
  13. package/atris/team/validator/MEMBER.md +1 -1
  14. package/atris.md +14 -0
  15. package/ax +157 -24
  16. package/bin/atris.js +79 -31
  17. package/commands/aeo.js +4 -4
  18. package/commands/agents.js +1 -1
  19. package/commands/align.js +12 -12
  20. package/commands/analytics.js +3 -3
  21. package/commands/app.js +5 -5
  22. package/commands/ask.js +175 -0
  23. package/commands/auth.js +7 -7
  24. package/commands/autoland.js +29 -5
  25. package/commands/autopilot-front.js +6 -6
  26. package/commands/autopilot.js +90 -90
  27. package/commands/avail.js +5 -5
  28. package/commands/bench.js +63 -1
  29. package/commands/browse.js +2 -2
  30. package/commands/business.js +12 -12
  31. package/commands/card.js +2 -2
  32. package/commands/clean.js +13 -13
  33. package/commands/close.js +297 -15
  34. package/commands/compile.js +13 -13
  35. package/commands/computer.js +94 -27
  36. package/commands/console.js +5 -5
  37. package/commands/decide.js +1 -1
  38. package/commands/deck.js +9 -9
  39. package/commands/drive.js +4 -4
  40. package/commands/engine.js +173 -19
  41. package/commands/errors.js +3 -3
  42. package/commands/experiments.js +18 -1
  43. package/commands/feed.js +2 -2
  44. package/commands/feedback.js +4 -4
  45. package/commands/fleet.js +12 -12
  46. package/commands/game.js +1 -1
  47. package/commands/guide.js +49 -0
  48. package/commands/improve.js +19 -17
  49. package/commands/init.js +67 -19
  50. package/commands/interview.js +7 -7
  51. package/commands/land.js +40 -15
  52. package/commands/learn.js +12 -12
  53. package/commands/lesson.js +2 -2
  54. package/commands/log.js +1 -1
  55. package/commands/loops.js +4 -4
  56. package/commands/member.js +75 -50
  57. package/commands/mission.js +97 -98
  58. package/commands/one-lap.js +1 -1
  59. package/commands/pack.js +74 -8
  60. package/commands/plugin.js +6 -6
  61. package/commands/probe.js +9 -9
  62. package/commands/pull.js +35 -35
  63. package/commands/pulse.js +1 -1
  64. package/commands/push.js +21 -21
  65. package/commands/rainmaker.js +1 -1
  66. package/commands/recap.js +7 -7
  67. package/commands/reel.js +2 -2
  68. package/commands/release.js +3 -3
  69. package/commands/report.js +1 -1
  70. package/commands/review.js +5 -5
  71. package/commands/revisions.js +1 -1
  72. package/commands/run.js +1 -1
  73. package/commands/scout.js +3 -3
  74. package/commands/security-review.js +7 -7
  75. package/commands/serve.js +9 -9
  76. package/commands/setup.js +1 -1
  77. package/commands/sign.js +4 -4
  78. package/commands/signup.js +4 -4
  79. package/commands/site.js +8 -3
  80. package/commands/skill.js +6 -6
  81. package/commands/slop.js +18 -18
  82. package/commands/social.js +3 -3
  83. package/commands/soul.js +14 -14
  84. package/commands/spaceship.js +1 -1
  85. package/commands/status.js +2 -2
  86. package/commands/strings.js +13 -13
  87. package/commands/study.js +4 -4
  88. package/commands/sync.js +8 -8
  89. package/commands/task.js +50 -25
  90. package/commands/teach.js +2 -2
  91. package/commands/team.js +1 -1
  92. package/commands/theme.js +2 -2
  93. package/commands/tree.js +34 -0
  94. package/commands/truth.js +7 -7
  95. package/commands/verify.js +12 -12
  96. package/commands/visualize.js +2 -2
  97. package/commands/workflow.js +97 -40
  98. package/commands/worktree.js +57 -1
  99. package/commands/write.js +9 -9
  100. package/commands/x-search.js +304 -15
  101. package/commands/xp.js +6 -3
  102. package/commands/youtube.js +916 -65
  103. package/lib/accept-verify-gate.js +3 -3
  104. package/lib/activity-stream.js +1 -1
  105. package/lib/apply-gate.js +13 -0
  106. package/lib/auto-accept-certified.js +28 -12
  107. package/lib/autoland.js +6 -6
  108. package/lib/bench/engines.js +59 -8
  109. package/lib/bench/report.js +1 -1
  110. package/lib/bench/runner.js +204 -5
  111. package/lib/bench/tree-render.js +76 -0
  112. package/lib/card.js +1 -1
  113. package/lib/chat-log-scan.js +1 -1
  114. package/lib/claude-boot-block.js +2 -0
  115. package/lib/deck-compose.js +1 -1
  116. package/lib/deck-history.js +2 -2
  117. package/lib/deck-layout.js +1 -1
  118. package/lib/deck-review.js +5 -5
  119. package/lib/deck-schema.js +1 -1
  120. package/lib/default-verifier.js +1 -1
  121. package/lib/developer-api.js +3 -0
  122. package/lib/engine-ask.js +66 -9
  123. package/lib/engine-registry.js +15 -2
  124. package/lib/file-ops.js +1 -1
  125. package/lib/fleet.js +71 -35
  126. package/lib/html-render.js +1 -1
  127. package/lib/intents.js +172 -0
  128. package/lib/journal.js +1 -1
  129. package/lib/known-commands.js +2 -2
  130. package/lib/land-green.js +364 -0
  131. package/lib/lesson-contradiction.js +2 -2
  132. package/lib/lesson-preflight.js +1 -1
  133. package/lib/manifest.js +5 -5
  134. package/lib/member-alive.js +9 -5
  135. package/lib/memory-view.js +3 -3
  136. package/lib/mission-protected-lane.js +1 -1
  137. package/lib/mission-root.js +2 -2
  138. package/lib/orb-context.js +10 -10
  139. package/lib/pack-capabilities.js +861 -3
  140. package/lib/permission-grants.js +2 -2
  141. package/lib/policy-lessons.js +6 -6
  142. package/lib/pulse.js +8 -8
  143. package/lib/receipt-evidence.js +1 -1
  144. package/lib/reel.js +1 -1
  145. package/lib/review-integrity.js +1 -1
  146. package/lib/runner-command.js +35 -5
  147. package/lib/scorecard.js +4 -4
  148. package/lib/security-scan.js +5 -5
  149. package/lib/self-drive.js +1 -1
  150. package/lib/site-publish.js +372 -0
  151. package/lib/site.js +1 -1
  152. package/lib/slides-deck.js +2 -2
  153. package/lib/state-detection.js +2 -2
  154. package/lib/sync-telemetry.js +2 -2
  155. package/lib/task-db.js +17 -10
  156. package/lib/task-explanation.js +1 -1
  157. package/lib/task-proof.js +2 -2
  158. package/lib/task-receipt.js +3 -3
  159. package/lib/theme.js +12 -12
  160. package/lib/todo-fallback.js +3 -3
  161. package/lib/todo-sections.js +1 -1
  162. package/lib/tree-hash.js +79 -0
  163. package/lib/usage.js +1 -1
  164. package/lib/wish-delegate.js +1 -1
  165. package/lib/workspace-safety.js +4 -4
  166. package/lib/workspace-scaffold.js +3 -3
  167. package/package.json +1 -1
  168. package/scripts/det/concierge-bakeoff.sh +26 -0
  169. package/scripts/det/ytquote-repair.js +0 -1
  170. package/scripts/det/ytrail-race.js +0 -5
  171. package/scripts/member-operate.mjs +52 -14
  172. package/scripts/outbound-artifact-gate.js +0 -3
  173. package/utils/auth.js +0 -3
  174. package/utils/config.js +0 -1
  175. package/scripts/det/checklist-score.js +0 -191
@@ -22,6 +22,7 @@ const { Writable } = require('stream');
22
22
  const {
23
23
  RUNNER_PROFILE_DEFS,
24
24
  RUNNER_PROFILE_NAMES,
25
+ HIDDEN_PROFILE_NAMES,
25
26
  buildRunnerCommand,
26
27
  } = require('../lib/runner-command');
27
28
  const { parseScopeFlag } = require('../lib/cli-scope');
@@ -124,10 +125,12 @@ function resolveDefaultEngine(root = process.cwd()) {
124
125
 
125
126
  function roster(root = process.cwd()) {
126
127
  const current = resolveDefaultEngine(root);
127
- return engineRegistryView(root).map((engine) => ({
128
- ...engine,
129
- default: engine.id === current.name,
130
- }));
128
+ return engineRegistryView(root)
129
+ .filter((engine) => !HIDDEN_PROFILE_NAMES.includes(engine.id))
130
+ .map((engine) => ({
131
+ ...engine,
132
+ default: engine.id === current.name,
133
+ }));
131
134
  }
132
135
 
133
136
  function setEngine(name, root = process.cwd()) {
@@ -932,13 +935,16 @@ function printRoster(root, { scope = 'workspace' } = {}) {
932
935
  console.log('');
933
936
  }
934
937
 
935
- function registryPayload(root, { scope = 'workspace' } = {}) {
938
+ function registryPayload(root, { scope = 'workspace', includeHidden = false } = {}) {
936
939
  const current = resolveDefaultEngine(root);
937
940
  const registry = readEngineRegistry(root);
938
- const engines = registry.engines.map((engine) => ({
939
- ...engine,
940
- default: engine.id === current.name,
941
- }));
941
+ const engines = registry.engines
942
+ .map((engine) => ({
943
+ ...engine,
944
+ hidden: HIDDEN_PROFILE_NAMES.includes(engine.id),
945
+ default: engine.id === current.name,
946
+ }))
947
+ .filter((engine) => includeHidden || !engine.hidden);
942
948
  const scoped = scope === 'global'
943
949
  ? engines
944
950
  : engines.filter((engine) => engine.installed || engine.default || (engine.health && engine.health.status === 'ready'));
@@ -978,7 +984,8 @@ function centerChartLine(line, width, center = Math.floor((width - 1) / 2)) {
978
984
  }
979
985
 
980
986
  function renderEngineChart(registry) {
981
- const engines = Array.isArray(registry) ? registry : ((registry && registry.engines) || []);
987
+ const engines = (Array.isArray(registry) ? registry : ((registry && registry.engines) || []))
988
+ .filter((entry) => !HIDDEN_PROFILE_NAMES.includes(entry.id));
982
989
  const specialDuties = new Set(ENGINE_DUTIES);
983
990
  const leaders = engines.filter((entry) => entry.duty === 'leader');
984
991
  const rolePool = engines.filter((entry) => !specialDuties.has(entry.duty));
@@ -1158,7 +1165,7 @@ function runDoctorCommand(args, root) {
1158
1165
  return 0;
1159
1166
  }
1160
1167
  console.log('');
1161
- for (const engine of engines) {
1168
+ for (const engine of engines.filter((engine) => !HIDDEN_PROFILE_NAMES.includes(engine.id))) {
1162
1169
  const state = engine.installed ? 'installed' : 'missing';
1163
1170
  const health = engine.health.status.replace(/_/g, ' ');
1164
1171
  console.log(` ${engine.id.padEnd(12)} ${String(engine.bin).padEnd(14)} ${state.padEnd(10)} health: ${health}`);
@@ -1301,6 +1308,147 @@ function writeProbeReceipt(result, root = process.cwd()) {
1301
1308
  }
1302
1309
  }
1303
1310
 
1311
+ function runBenchCommand(args, root, deps = {}) {
1312
+ const probe = deps.probe || probeEngine;
1313
+
1314
+ const names = [];
1315
+ let runs = 3;
1316
+ let timeout;
1317
+ let json = false;
1318
+
1319
+ for (let i = 0; i < args.length; i += 1) {
1320
+ const a = args[i];
1321
+ if (a === '--runs') { runs = parseInt(args[i + 1] || '3', 10); i += 1; continue; }
1322
+ if (a.startsWith('--runs=')) { runs = parseInt(a.slice('--runs='.length), 10); continue; }
1323
+ if (a === '--timeout') { timeout = parseInt(args[i + 1] || '0', 10) * 1000; i += 1; continue; }
1324
+ if (a.startsWith('--timeout=')) { timeout = parseInt(a.slice('--timeout='.length), 10) * 1000; continue; }
1325
+ if (a === '--json') { json = true; continue; }
1326
+ if (a.startsWith('--')) continue;
1327
+ names.push(a);
1328
+ }
1329
+
1330
+ let enginesToBench;
1331
+ if (names.length) {
1332
+ enginesToBench = names.map((n) => {
1333
+ const c = canonicalEngineName(n);
1334
+ if (!c) {
1335
+ throw new Error(`Unknown engine "${n}". Known engines: ${RUNNER_PROFILE_NAMES.join(', ')}`);
1336
+ }
1337
+ return c;
1338
+ });
1339
+ } else {
1340
+ enginesToBench = deps.installedEngines || RUNNER_PROFILE_NAMES.filter((n) => binInstalled(RUNNER_PROFILE_DEFS[n].bin));
1341
+ if (!enginesToBench.length) {
1342
+ if (json) {
1343
+ console.log(JSON.stringify({ ok: false, error: 'no installed engines to bench' }, null, 2));
1344
+ } else {
1345
+ console.error('\n no installed engines to bench\n');
1346
+ }
1347
+ return 1;
1348
+ }
1349
+ }
1350
+
1351
+ const probeOpts = {};
1352
+ if (timeout) probeOpts.timeout = timeout;
1353
+
1354
+ const results = [];
1355
+ let allHavePasses = true;
1356
+
1357
+ for (const engine of enginesToBench) {
1358
+ const passedRuns = [];
1359
+ let passes = 0;
1360
+ for (let i = 0; i < runs; i += 1) {
1361
+ const res = probe(engine, probeOpts);
1362
+ if (res.pass) {
1363
+ passedRuns.push(res.durationMs);
1364
+ passes += 1;
1365
+ }
1366
+ }
1367
+
1368
+ let medianMs = 0;
1369
+ let minMs = 0;
1370
+ let maxMs = 0;
1371
+
1372
+ if (passes > 0) {
1373
+ passedRuns.sort((a, b) => a - b);
1374
+ minMs = passedRuns[0];
1375
+ maxMs = passedRuns[passedRuns.length - 1];
1376
+ const mid = Math.floor(passes / 2);
1377
+ medianMs = passes % 2 !== 0 ? passedRuns[mid] : (passedRuns[mid - 1] + passedRuns[mid]) / 2;
1378
+ } else {
1379
+ allHavePasses = false;
1380
+ }
1381
+
1382
+ results.push({
1383
+ engine,
1384
+ passes,
1385
+ runs,
1386
+ medianMs,
1387
+ minMs,
1388
+ maxMs,
1389
+ });
1390
+ }
1391
+
1392
+ results.sort((a, b) => {
1393
+ if (a.passes === 0 && b.passes !== 0) return 1;
1394
+ if (b.passes === 0 && a.passes !== 0) return -1;
1395
+ if (a.passes === 0 && b.passes === 0) return a.engine.localeCompare(b.engine);
1396
+ return a.medianMs - b.medianMs;
1397
+ });
1398
+
1399
+ const stateFile = path.join(root, '.atris', 'state', 'engine-bench.latest.json');
1400
+ let previous = null;
1401
+ try {
1402
+ if (fs.existsSync(stateFile)) {
1403
+ previous = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
1404
+ }
1405
+ } catch {
1406
+ // best-effort read
1407
+ }
1408
+
1409
+ const stateObj = {
1410
+ at: new Date().toISOString(),
1411
+ runs,
1412
+ results,
1413
+ };
1414
+
1415
+ try {
1416
+ fs.mkdirSync(path.dirname(stateFile), { recursive: true });
1417
+ fs.writeFileSync(stateFile, `${JSON.stringify(stateObj, null, 2)}\n`);
1418
+ } catch {
1419
+ // best-effort write
1420
+ }
1421
+
1422
+ if (json) {
1423
+ console.log(JSON.stringify({ ...stateObj, previous }, null, 2));
1424
+ return allHavePasses ? 0 : 1;
1425
+ }
1426
+
1427
+ console.log('');
1428
+ for (const r of results) {
1429
+ let deltaStr = '';
1430
+ if (previous && previous.results) {
1431
+ const prevRes = previous.results.find((pr) => pr.engine === r.engine);
1432
+ if (prevRes && prevRes.passes > 0 && r.passes > 0) {
1433
+ const diff = Math.round(r.medianMs - prevRes.medianMs);
1434
+ if (diff > 0) deltaStr = ` (slower by ${diff}ms)`;
1435
+ else if (diff < 0) deltaStr = ` (faster by ${Math.abs(diff)}ms)`;
1436
+ else deltaStr = ' (no change)';
1437
+ }
1438
+ }
1439
+
1440
+ if (r.passes > 0) {
1441
+ const ms = Math.round(r.medianMs);
1442
+ console.log(` ${r.engine.padEnd(12)} ${r.passes}/${r.runs} passes, median ${ms}ms${deltaStr}`);
1443
+ } else {
1444
+ console.error(` ${r.engine.padEnd(12)} FAIL, 0/${r.runs} passes`);
1445
+ }
1446
+ }
1447
+ console.log('');
1448
+
1449
+ return allHavePasses ? 0 : 1;
1450
+ }
1451
+
1304
1452
  function runEngineTest(targets, { json, root } = {}) {
1305
1453
  let enginesToTest;
1306
1454
  if (targets && targets.length) {
@@ -1344,8 +1492,8 @@ function runEngineTest(targets, { json, root } = {}) {
1344
1492
  for (const r of results) {
1345
1493
  const mark = r.pass ? '✓' : '✗';
1346
1494
  const line = r.pass
1347
- ? ` ${mark} ${r.engine.padEnd(12)} pass ${r.message} (${r.durationMs}ms)`
1348
- : ` ${mark} ${r.engine.padEnd(12)} FAIL ${r.message}`;
1495
+ ? ` ${mark} ${r.engine.padEnd(12)} pass, ${r.message} (${r.durationMs}ms)`
1496
+ : ` ${mark} ${r.engine.padEnd(12)} FAIL, ${r.message}`;
1349
1497
  if (r.pass) console.log(line);
1350
1498
  else console.error(line);
1351
1499
  }
@@ -1354,7 +1502,7 @@ function runEngineTest(targets, { json, root } = {}) {
1354
1502
  console.error(` ${failures.length} engine${failures.length === 1 ? '' : 's'} failed: ${failures.map((f) => f.engine).join(', ')}`);
1355
1503
  console.error(` fix the login/binary, then re-run: atris engine test${targets && targets.length ? ' ' + targets.join(' ') : ''}`);
1356
1504
  } else {
1357
- console.log(` all engines responded clear for flight`);
1505
+ console.log(` all engines responded, clear for flight`);
1358
1506
  }
1359
1507
  console.log('');
1360
1508
  }
@@ -1525,6 +1673,10 @@ function engineCommand(args = [], deps = {}) {
1525
1673
  return runEngineTest(positional.slice(1), { json, root });
1526
1674
  }
1527
1675
 
1676
+ if (sub === 'bench') {
1677
+ return runBenchCommand(scope.args.slice(scope.args.indexOf('bench') + 1), root, deps);
1678
+ }
1679
+
1528
1680
  if (sub === 'resolve') {
1529
1681
  return runResolveCommand(scope.args.slice(scope.args.indexOf('resolve') + 1), root);
1530
1682
  }
@@ -1552,14 +1704,15 @@ function engineCommand(args = [], deps = {}) {
1552
1704
  if (!sub || sub === 'list' || sub === 'status' || sub === 'help') {
1553
1705
  if (sub === 'help' || args.includes('--help') || args.includes('-h')) {
1554
1706
  console.log('\n atris engine watch [<id>|latest] [--no-follow]\n follow one live transcript or list running engine work');
1555
- console.log('\n atris engine roster + current default\n atris engines --chart show the fleet as an org chart\n atris engine list --json full registry: default + engines with tier, roles, fallback, health\n atris engine set <name> --duty leader|errands|learning [--models "a, b"]\n arrange the fleet and save its model policy\n atris engine resolve <role> [--json]\n choose the best ready engine for navigator|executor|validator\n atris engine health <name> --set ready|not_installed|credit_out\n flip runtime health, for example when credits run out\n atris engine doctor [--json]\n probe which engine CLIs are installed here and sync that into health policy\n atris engine <name> make that engine the default here\n atris engine test [name] preflight: run the engine CLI headless, report pass/fail\n atris engine ask "<question>" --engine <name> [--engine <name> ...]\n ask several engines in parallel without allowing edits\n atris engine ask --jobs <jobs.json>\n ask different read-only questions in parallel\n atris engine validate <receipt-path|latest> [--engine <name>]\n check ask answers with a different read-only referee\n atris engine validate scoreboard\n show pass rates by worker engine\n atris engine dispatch <task-id> [<task-id> ...] --engine cursor|codex [--prompt-file <f>] [--yolo]\n one-command claim, worktree, build, verify, ship, ready\n atris engine login <provider> --yes\n upload a local provider CLI login to the backend vault\n atris engine login <provider> --computer [--seat <name>]\n atris engine login <provider> --business <id> [--seat <name>]\n sign in on an Atris computer by device flow\n atris engine login --list | --remove <provider>\n list or remove vaulted provider logins\n atris engine seats show which named accounts are ready to work\n atris engine seed <provider> --business <id>|--user\n push a vaulted login onto an Atris computer\n atris engine reset back to the house default\n --engine <name> one run on that engine (mission run / autopilot / run)\n');
1707
+ console.log('\n long read-only asks: atris engine ask "..." --engine agy --timeout <seconds>\n quick asks default to 120 seconds; explicit jobs allow up to 3600\n follow live work with atris engine watch latest');
1708
+ console.log('\n atris engine roster + current default\n atris engines --chart show the fleet as an org chart\n atris engine list --json [--all] full registry: default + engines with tier, roles, fallback, health (--all includes hidden engines)\n atris engine set <name> --duty leader|errands|learning [--models "a, b"]\n arrange the fleet and save its model policy\n atris engine resolve <role> [--json]\n choose the best ready engine for navigator|executor|validator\n atris engine health <name> --set ready|not_installed|credit_out\n flip runtime health, for example when credits run out\n atris engine doctor [--json]\n probe which engine CLIs are installed here and sync that into health policy\n atris engine <name> make that engine the default here\n atris engine test [name] preflight: run the engine CLI headless, report pass/fail\n atris engine bench [names...] [--runs N]\n ranked latency scoreboard of engine passes\n atris engine ask "<question>" --engine <name> [--engine <name> ...]\n ask several engines in parallel without allowing edits\n atris engine ask --jobs <jobs.json>\n ask different read-only questions in parallel\n atris engine validate <receipt-path|latest> [--engine <name>]\n check ask answers with a different read-only referee\n atris engine validate scoreboard\n show pass rates by worker engine\n atris engine dispatch <task-id> [<task-id> ...] --engine cursor|codex [--prompt-file <f>] [--yolo]\n one-command claim, worktree, build, verify, ship, ready\n atris engine login <provider> --yes\n upload a local provider CLI login to the backend vault\n atris engine login <provider> --computer [--seat <name>]\n atris engine login <provider> --business <id> [--seat <name>]\n sign in on an Atris computer by device flow\n atris engine login --list | --remove <provider>\n list or remove vaulted provider logins\n atris engine seats show which named accounts are ready to work\n atris engine seed <provider> --business <id>|--user\n push a vaulted login onto an Atris computer\n atris engine reset back to the house default\n --engine <name> one run on that engine (mission run / autopilot / run)\n');
1556
1709
  return 0;
1557
1710
  }
1558
1711
  if (isFreshWorkspace(root)) {
1559
1712
  return speakFirstMinute({ root, fresh: true, asJson: json });
1560
1713
  }
1561
1714
  if (json) {
1562
- console.log(JSON.stringify(registryPayload(root, { scope: scope.kind }), null, 2));
1715
+ console.log(JSON.stringify(registryPayload(root, { scope: scope.kind, includeHidden: args.includes('--all') }), null, 2));
1563
1716
  return 0;
1564
1717
  }
1565
1718
  printRoster(root, { scope: scope.kind });
@@ -1569,12 +1722,12 @@ function engineCommand(args = [], deps = {}) {
1569
1722
  if (sub === 'reset' || sub === 'off') {
1570
1723
  const removed = resetEngine(root);
1571
1724
  console.log(removed
1572
- ? `\n default engine reset back to ${resolveDefaultEngine(root).name}\n`
1573
- : `\n nothing to reset no engine was set here\n`);
1725
+ ? `\n default engine reset, back to ${resolveDefaultEngine(root).name}\n`
1726
+ : `\n nothing to reset, no engine was set here\n`);
1574
1727
  return 0;
1575
1728
  }
1576
1729
 
1577
- // atris engine <name> flip the default. An unknown name is a plain user
1730
+ // atris engine <name>: flip the default. An unknown name is a plain user
1578
1731
  // typo, not a crash: report it cleanly (and as JSON on demand) instead of
1579
1732
  // letting setEngine throw a raw stack trace at a new person.
1580
1733
  if (!canonicalEngineName(sub)) {
@@ -1608,6 +1761,7 @@ module.exports = {
1608
1761
  renderEngineChart,
1609
1762
  parseDispatchArgs,
1610
1763
  runDispatchCommand,
1764
+ runBenchCommand,
1611
1765
  ENGINE_LOGIN_MANIFESTS,
1612
1766
  expandHomePath,
1613
1767
  normalizeLoginProvider,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Errors command for Atris CLI admin dashboard over atris_error_events.
2
+ * Errors command for Atris CLI, admin dashboard over atris_error_events.
3
3
  *
4
4
  * Usage:
5
5
  * atris errors Local-only by default (no cloud dump)
@@ -121,7 +121,7 @@ async function listErrors(args) {
121
121
  }
122
122
 
123
123
  console.log(
124
- `Errors last ${data.window_hours}h ` +
124
+ `Errors, last ${data.window_hours}h, ` +
125
125
  `${data.total_events} events across ${data.unique_signatures} signatures\n`,
126
126
  );
127
127
 
@@ -146,7 +146,7 @@ async function listErrors(args) {
146
146
  async function showError(errorId) {
147
147
  if (!errorId) {
148
148
  console.error('Usage: atris errors show <id>');
149
- console.error('(id must be a full UUID get one from `atris errors` output)');
149
+ console.error('(id must be a full UUID, get one from `atris errors` output)');
150
150
  process.exit(1);
151
151
  }
152
152
 
@@ -179,6 +179,18 @@ function runMeasureJson(scriptPath, workspaceDir = process.cwd()) {
179
179
  return parsed;
180
180
  }
181
181
 
182
+ function printKeepRevertNext(slug) {
183
+ console.log(`next: atris experiments revert ${slug}`);
184
+ }
185
+
186
+ function printRevertKeepNext(slug) {
187
+ console.log(`next: atris experiments keep ${slug}`);
188
+ }
189
+
190
+ function printKeepWatchTickNext() {
191
+ console.log('next: atris youtube watch tick');
192
+ }
193
+
182
194
  function experimentsKeep(name) {
183
195
  const token = String(name || '').trim();
184
196
  if (!token || token === '--help' || token === '-h' || token === 'help') {
@@ -212,16 +224,19 @@ function experimentsKeep(name) {
212
224
  const measured = runMeasureJson(measurePath, workspaceDir);
213
225
  if (!measured.ok) {
214
226
  console.error(`revert ${token}: ${measured.error}. refuse keep.`);
227
+ printKeepRevertNext(token);
215
228
  process.exit(1);
216
229
  }
217
230
 
218
231
  if (measured.score === 1) {
219
232
  console.log(`keep ${token}: measure.py moved 0→1`);
233
+ printKeepWatchTickNext();
220
234
  return;
221
235
  }
222
236
 
223
237
  const stayed = measured.score === 0 ? '0' : String(measured.score);
224
238
  console.error(`revert ${token}: measure.py stayed ${stayed}. refuse keep.`);
239
+ printKeepRevertNext(token);
225
240
  process.exit(1);
226
241
  }
227
242
 
@@ -301,11 +316,13 @@ function experimentsRevert(name) {
301
316
  const measured = runMeasureJson(measurePath, workspaceDir);
302
317
  if (measured.ok) {
303
318
  console.log(`revert ${token}: reset.py ran. measure.py ${measured.score}`);
319
+ printRevertKeepNext(token);
304
320
  return;
305
321
  }
306
322
  }
307
323
 
308
324
  console.log(`revert ${token}: reset.py ran`);
325
+ printRevertKeepNext(token);
309
326
  }
310
327
 
311
328
  function experimentsInit(name) {
@@ -491,7 +508,7 @@ function buildBenchmarkArtifact(name, packDir, options) {
491
508
 
492
509
  let execution = null;
493
510
  let reviewStatus = options.dryRun ? 'draft' : 'fail';
494
- let reviewSummary = options.dryRun ? 'dry run benchmark task not executed' : 'benchmark run failed before review';
511
+ let reviewSummary = options.dryRun ? 'dry run, benchmark task not executed' : 'benchmark run failed before review';
495
512
  let tests = [{
496
513
  command: options.dryRun ? 'benchmark dry-run' : '(no explicit test command captured)',
497
514
  status: 'not_run',
package/commands/feed.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // Feed: the business group feed from the terminal read receipts, post receipts.
3
+ // Feed: the business group feed from the terminal, read receipts, post receipts.
4
4
  // Auth: existing atris login. Business: nearest .atris/business.json above cwd.
5
5
 
6
6
  const fs = require('fs');
@@ -181,7 +181,7 @@ async function feedCommand(args = []) {
181
181
  const when = String(p.created_at || '').slice(0, 16).replace('T', ' ');
182
182
  const who = authorLabel(p, aliases, selfId, selfEmail);
183
183
  if (full) {
184
- console.log(`─── ${who} ${when}`);
184
+ console.log(`─── ${who}, ${when}`);
185
185
  console.log(String(p.content || '').trim());
186
186
  console.log('');
187
187
  } else {
@@ -11,7 +11,7 @@
11
11
  * atris feedback close <id> Close as wontfix (admin)
12
12
  * atris feedback delete <id> Delete feedback (admin)
13
13
  *
14
- * IDs may be the first 8 chars of the UUID the CLI resolves the prefix
14
+ * IDs may be the first 8 chars of the UUID. the CLI resolves the prefix
15
15
  * against the live list before making the write request.
16
16
  */
17
17
 
@@ -87,7 +87,7 @@ async function submitFeedback(message, opts = {}) {
87
87
  }
88
88
  if (result.text && !result.data) parts.push(result.text.trim());
89
89
  if (!parts.length) parts.push('Failed to submit feedback (no feedback_id returned)');
90
- console.error(`Error: ${parts.join(' ')}`);
90
+ console.error(`Error: ${parts.join(', ')}`);
91
91
  process.exit(1);
92
92
  }
93
93
 
@@ -153,7 +153,7 @@ async function resolveIdPrefix(prefix, { token, businessId }) {
153
153
  if (matches.length === 0) return { error: `No feedback matches id prefix "${prefix}"` };
154
154
  if (matches.length > 1) {
155
155
  return {
156
- error: `Ambiguous id "${prefix}" matches ${matches.length} items. Use a longer prefix.`,
156
+ error: `Ambiguous id "${prefix}", matches ${matches.length} items. Use a longer prefix.`,
157
157
  };
158
158
  }
159
159
  return { id: matches[0].id, item: matches[0] };
@@ -294,7 +294,7 @@ function printHelp(write = console.log) {
294
294
 
295
295
  function resolveBusinessArg(value) {
296
296
  if (!value) return null;
297
- // Full UUID trust it
297
+ // Full UUID, trust it
298
298
  if (/^[0-9a-f-]{32,}$/i.test(value)) return value;
299
299
  // Otherwise treat as slug and look up in ~/.atris/businesses.json
300
300
  const home = require('os').homedir();
package/commands/fleet.js CHANGED
@@ -1,16 +1,16 @@
1
1
  /**
2
- * Atris Fleet Manage the agent swarm via Swarlo
2
+ * Atris Fleet: Manage the agent swarm via Swarlo
3
3
  *
4
4
  * Commands:
5
- * atris fleet Show fleet status
6
- * atris fleet status Same as above
7
- * atris fleet post <message> Post to the board
8
- * atris fleet task <prompt> Post a task for agents to claim
9
- * atris fleet claim <task_key> Claim a task
10
- * atris fleet done <task_key> Report task complete
11
- * atris fleet members List members
12
- * atris fleet prune Remove stale members
13
- * atris fleet join Register this session
5
+ * atris fleet : Show fleet status
6
+ * atris fleet status : Same as above
7
+ * atris fleet post <message> : Post to the board
8
+ * atris fleet task <prompt> : Post a task for agents to claim
9
+ * atris fleet claim <task_key> : Claim a task
10
+ * atris fleet done <task_key> : Report task complete
11
+ * atris fleet members : List members
12
+ * atris fleet prune : Remove stale members
13
+ * atris fleet join : Register this session
14
14
  */
15
15
 
16
16
  const http = require('http');
@@ -264,7 +264,7 @@ async function fleetMembers(state) {
264
264
  console.log(`\n Members (${res.data.count}):`);
265
265
  for (const m of res.data.members) {
266
266
  const seen = m.last_seen ? m.last_seen.slice(0, 16) : 'never';
267
- console.log(` ${m.member_type === 'human' ? '👤' : '🤖'} ${m.member_name} (${m.member_id}) seen: ${seen}`);
267
+ console.log(` ${m.member_type === 'human' ? '👤' : '🤖'} ${m.member_name} (${m.member_id}), seen: ${seen}`);
268
268
  }
269
269
  console.log();
270
270
  }
@@ -388,7 +388,7 @@ async function fleet(args = []) {
388
388
 
389
389
  if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h') {
390
390
  console.log('');
391
- console.log(' atris fleet coordinate agent swarm via Swarlo');
391
+ console.log(' atris fleet: coordinate agent swarm via Swarlo');
392
392
  console.log('');
393
393
  console.log(' fleet show workspace fleet (default)');
394
394
  console.log(' fleet --global query the machine Swarlo hub');
package/commands/game.js CHANGED
@@ -62,7 +62,7 @@ function publisherSupportsStoryline(script) {
62
62
 
63
63
  function clean(value, fallback = '') {
64
64
  const text = String(value == null ? '' : value)
65
- .replace(/[—–]/g, '-')
65
+ .replace(/[\u2014\u2013]/g, '-')
66
66
  .replace(/\s+/g, ' ')
67
67
  .trim();
68
68
  return text || fallback;
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ const { INTENTS, matchIntent } = require('../lib/intents');
4
+
5
+ function plainForIntent(intent) {
6
+ return `${intent.plain}${intent.confirm ? ' (asks you first)' : ''}`;
7
+ }
8
+
9
+ function printAlternatives(alternatives, limit) {
10
+ const nearest = alternatives.slice(0, limit);
11
+ if (!nearest.length) return;
12
+ console.log('you might also mean:');
13
+ nearest.forEach((intent) => console.log(`"${intent.say[0]}"`));
14
+ }
15
+
16
+ function guideCommand(args = []) {
17
+ const json = args.includes('--json');
18
+ const words = args.filter((arg) => arg !== '--json').join(' ').trim();
19
+
20
+ if (!words) {
21
+ if (json) {
22
+ console.log(JSON.stringify({ intents: INTENTS }, null, 2));
23
+ return 0;
24
+ }
25
+ INTENTS.forEach((intent) => {
26
+ console.log(`"${intent.say[0]}" -> ${plainForIntent(intent)}`);
27
+ });
28
+ return 0;
29
+ }
30
+
31
+ const result = matchIntent(words);
32
+ if (json) {
33
+ console.log(JSON.stringify(result, null, 2));
34
+ return result.intent ? 0 : 1;
35
+ }
36
+
37
+ if (!result.intent) {
38
+ console.log('not sure yet. ask one question, then try again');
39
+ printAlternatives(result.alternatives, 3);
40
+ return 1;
41
+ }
42
+
43
+ console.log(plainForIntent(result.intent));
44
+ console.log(result.intent.do);
45
+ printAlternatives(result.alternatives, 2);
46
+ return 0;
47
+ }
48
+
49
+ module.exports = { guideCommand };