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
package/bin/atris.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Catch-all for uncaught async errors prevents silent crashes
3
+ // Catch-all for uncaught async errors, prevents silent crashes
4
4
  process.on('unhandledRejection', (err) => {
5
5
  console.error(`\n✗ Unexpected error: ${err?.message || err}`);
6
6
  process.exit(1);
@@ -77,7 +77,7 @@ const {
77
77
  const { getLogPath, ensureLogDirectory, createLogFile } = require('../lib/file-ops');
78
78
  const { getConfigPath, loadConfig, saveConfig, loadLogSyncState, saveLogSyncState } = require('../utils/config');
79
79
 
80
- // Auth & API (canonical modules eliminates duplicate inline code)
80
+ // Auth & API (canonical modules, eliminates duplicate inline code)
81
81
  const {
82
82
  decodeJwtClaims, getTokenExpiryEpochSeconds, shouldRefreshToken,
83
83
  getCredentialsPath, saveCredentials, loadCredentials, deleteCredentials,
@@ -316,7 +316,7 @@ if (!helpRequested && !dryRunRequested && (
316
316
  *
317
317
  * Each mission: { id, owner, objective, status, verifier, verifier_passed, next_action, lane }.
318
318
  *
319
- * Returns [] if file missing or malformed never throws.
319
+ * Returns [] if file missing or malformed, never throws.
320
320
  */
321
321
  function loadActiveMissions(workspaceDir) {
322
322
  try {
@@ -350,7 +350,7 @@ function loadActiveMissions(workspaceDir) {
350
350
  runner: m.runner || null,
351
351
  });
352
352
  }
353
- // Most recently started first (rough relies on insertion order from reversed walk)
353
+ // Most recently started first (rough, relies on insertion order from reversed walk)
354
354
  return live;
355
355
  } catch {
356
356
  return [];
@@ -499,6 +499,7 @@ function showHelpShort() {
499
499
  console.log('');
500
500
  console.log(' atris "what do you want here?" empty folder');
501
501
  console.log(' atris later "..." remember without a room');
502
+ console.log(' atris guide "..." translate your words');
502
503
  console.log(' atris do work already here');
503
504
  console.log(' atris spaceship Keep working for a few hours');
504
505
  console.log(' atris autopilot Keep working until you stop');
@@ -510,6 +511,7 @@ function showHelpShort() {
510
511
  function helpCatalog() {
511
512
  return [
512
513
  { name: 'init', summary: 'scaffold atris/ in this project', json: false, interactive_risk: 'medium' },
514
+ { name: 'guide', summary: 'translate plain english into the right atris move', json: true, interactive_risk: 'none' },
513
515
  { name: 'task', summary: 'local task plane: new, claim, ready, accept', json: true, interactive_risk: 'low' },
514
516
  { name: 'review', summary: 'validate work and capture learnings', json: false, interactive_risk: 'low' },
515
517
  { name: 'recap', summary: 'spoken recap of what your team did', json: true, interactive_risk: 'low' },
@@ -528,6 +530,7 @@ function showHelpAll() {
528
530
  console.log('you say what you want. already won. one next step.');
529
531
  console.log('');
530
532
  console.log(' atris later "..." remember without a room');
533
+ console.log(' atris guide "..." translate your words');
531
534
  console.log(' atris do work already here');
532
535
  console.log(' atris spaceship Keep working for a few hours');
533
536
  console.log(' atris autopilot Keep working until you stop');
@@ -559,6 +562,7 @@ function showHelpAll() {
559
562
  console.log(' spaceship - Bounded overnight runner that survives bad ticks and emails updates');
560
563
  console.log('');
561
564
  console.log('Context & tracking:');
565
+ console.log(' guide - Translate plain english into the right Atris move');
562
566
  console.log(' log - Add ideas to inbox (`atris log "note"`; `log --repl` for the editor; see also `wish`)');
563
567
  console.log(' wish - Say one plain sentence, then Atris asks only for gaps or delegates it');
564
568
  console.log(' now - Show atris/now.md, the current operating truth');
@@ -581,9 +585,10 @@ function showHelpAll() {
581
585
  console.log(' xp - Show Career XP and contribution graph');
582
586
  console.log(' analytics - Show recent productivity from journals');
583
587
  console.log(' revisions - show possible human revisions after atris-assisted landings');
588
+ console.log(' tree hash - hash the live agent text tree (--json for manifest)');
584
589
  console.log(' search - Search workspace memory (atris search <keyword>)');
585
590
  console.log(' clean - Housekeeping (stale tasks, archive journals, broken refs)');
586
- console.log(' close - track open loops with deadlines and daily escalation');
591
+ console.log(' close - keep ten active loops and park the rest with their history');
587
592
  console.log(' harvest - Find bugs and next actions from receipts, run logs, and thinking');
588
593
  console.log(' verify - Validate work is done (tests, MAP.md, changes)');
589
594
  console.log(' slop - Deterministic slop detector: frontend/prose tells, dead code (slop dead --exports)');
@@ -638,7 +643,7 @@ function showHelpAll() {
638
643
  console.log(' experiments keep <slug> - Keep a pack only when measure.py moves 0 to 1');
639
644
  console.log(' experiments revert <slug> - Run a pack reset.py after a refused keep');
640
645
  console.log(' experiments benchmark [m] - Run validate/runtime experiment benchmarks');
641
- console.log(' bench - run core benchmark gates');
646
+ console.log(' bench - run benchmark gates or compare trees with bench pair');
642
647
  console.log('');
643
648
  console.log('Compile loop (learn like AI, run like code):');
644
649
  console.log(' compile record <name> - Append an execution record (--input/--output)');
@@ -1112,7 +1117,7 @@ if (command === 'help' || command === '--help' || command === '-h') {
1112
1117
  process.exit(0);
1113
1118
  }
1114
1119
 
1115
- // Core command handlers loaded eagerly (used by interactiveEntry default path)
1120
+ // Core command handlers, loaded eagerly (used by interactiveEntry default path)
1116
1121
  const { initAtris: initCmd } = require('../commands/init');
1117
1122
  const { syncAtris: syncCmd, syncAtrisAll: syncAllCmd } = require('../commands/sync');
1118
1123
  const { logAtris: logCmd } = require('../commands/log');
@@ -1154,7 +1159,7 @@ if (command === '--version' || command === '-v' || process.argv.includes('--vers
1154
1159
  }
1155
1160
 
1156
1161
  // If no command OR command is not recognized, treat as natural language
1157
- // Voice-friendly aliases natural language → command mapping
1162
+ // Voice-friendly aliases, natural language → command mapping
1158
1163
  // Solves speech-to-text issues (inspired by gstack v0.14.6 voice-triggers)
1159
1164
  // One-word voice aliases like start/go/audit/deploy must not spawn runners.
1160
1165
  // Unmatched single verbs exit 2 with did-you-mean (see below). Keep phrases
@@ -1197,11 +1202,11 @@ if (!command || !knownCommands.includes(command)) {
1197
1202
  const triggered = voiceTriggers[fullInput] || voiceTriggers[fullInputWithoutFlags];
1198
1203
  if (triggered) {
1199
1204
  command = triggered;
1200
- // Re-check if it's now a known command, fall through to dispatch
1205
+ // Re-check, if it's now a known command, fall through to dispatch
1201
1206
  if (knownCommands.includes(command)) {
1202
1207
  // Rewrite argv so dispatch works
1203
1208
  process.argv[2] = command;
1204
- // Don't return let it fall through to the command dispatch below
1209
+ // Don't return, let it fall through to the command dispatch below
1205
1210
  }
1206
1211
  }
1207
1212
  }
@@ -1454,7 +1459,7 @@ async function interactiveEntry(userInput, options = {}) {
1454
1459
  ? context.inProgressFeaturesCount
1455
1460
  : (context.inProgressFeatures || []).length;
1456
1461
 
1457
- // Pull active missions (durable goals) these outrank dev-pipeline state
1462
+ // Pull active missions (durable goals), these outrank dev-pipeline state
1458
1463
  // because a mission with an unverified verifier is a Keshav-attributable
1459
1464
  // commitment that hasn't been closed yet.
1460
1465
  const activeMissions = loadActiveMissions(workspaceDir);
@@ -1554,7 +1559,7 @@ async function interactiveEntry(userInput, options = {}) {
1554
1559
  console.log('Got it. I saved your first direction.');
1555
1560
  console.log(`Focus: ${profile.first_answer}`);
1556
1561
  if (starter && starter.display_id) {
1557
- console.log(`First task: ${starter.display_id} ${starter.title}`);
1562
+ console.log(`First task: ${starter.display_id}, ${starter.title}`);
1558
1563
  } else if (starter && starter.title) {
1559
1564
  console.log(`First task: ${starter.title}`);
1560
1565
  }
@@ -1581,7 +1586,7 @@ async function interactiveEntry(userInput, options = {}) {
1581
1586
  console.log('Got it. I saved your first direction.');
1582
1587
  console.log(`Focus: ${profile.first_answer}`);
1583
1588
  if (starter && starter.display_id) {
1584
- console.log(`First task: ${starter.display_id} ${starter.title}`);
1589
+ console.log(`First task: ${starter.display_id}, ${starter.title}`);
1585
1590
  } else if (starter && starter.title) {
1586
1591
  console.log(`First task: ${starter.title}`);
1587
1592
  }
@@ -1609,6 +1614,7 @@ async function askContextGatherer(workspaceDir) {
1609
1614
  // this output it stays compact so it costs almost nothing in context.
1610
1615
  function showWelcomeVisualization() {
1611
1616
  const { getTaskGlance } = require('../lib/state-detection');
1617
+ const { INTENTS } = require('../lib/intents');
1612
1618
  const { readEndgameState } = require('../commands/autopilot');
1613
1619
  const cwd = process.cwd();
1614
1620
  const atrisDir = path.join(cwd, 'atris');
@@ -1816,6 +1822,17 @@ function showWelcomeVisualization() {
1816
1822
  console.log(row('goal', endgameState.horizon || endgameState.slug));
1817
1823
  }
1818
1824
 
1825
+ const hasNoTasks = glance.active === 0
1826
+ && glance.review === 0
1827
+ && glance.reviewCertified === 0;
1828
+ if (hasNoTasks) {
1829
+ const phrases = INTENTS
1830
+ .filter((intent) => intent.offer === 'boot_empty')
1831
+ .map((intent) => intent.say[0])
1832
+ .slice(0, 2);
1833
+ console.log(row('say', `"${phrases[0]}" or "${phrases[1]}" (your agent translates)`));
1834
+ }
1835
+
1819
1836
  // The next command always carries a plain-english gloss: a newcomer should
1820
1837
  // know what typing it will do before they type it.
1821
1838
  let next;
@@ -1833,7 +1850,10 @@ function showWelcomeVisualization() {
1833
1850
  console.log('');
1834
1851
  }
1835
1852
 
1836
- if (command === 'init') {
1853
+ if (command === 'guide') {
1854
+ const code = require('../commands/guide').guideCommand(process.argv.slice(3));
1855
+ process.exit(typeof code === 'number' ? code : 0);
1856
+ } else if (command === 'init') {
1837
1857
  // Help flag must short-circuit before initCmd() (which scaffolds files)
1838
1858
  // and before interactiveEntry (which loads workspace context).
1839
1859
  const initArg = process.argv[3];
@@ -1884,7 +1904,7 @@ if (command === 'init') {
1884
1904
  } else if (command === 'decide') {
1885
1905
  // process.exit() can outrun a piped stdout: writes beyond the 64KB pipe
1886
1906
  // buffer are async, so large --json payloads truncate at 64KB multiples.
1887
- // Queue an empty write and exit from its callback it fires only after
1907
+ // Queue an empty write and exit from its callback, it fires only after
1888
1908
  // every earlier buffered write has drained (BCK-1306).
1889
1909
  const exitAfterStdoutDrain = (code) => {
1890
1910
  if (process.stdout.writableLength === 0) process.exit(code);
@@ -1912,7 +1932,7 @@ if (command === 'init') {
1912
1932
  } else if (command === 'mission') {
1913
1933
  // process.exit() can outrun a piped stdout: writes beyond the 64KB pipe
1914
1934
  // buffer are async, so large --json payloads truncate at 64KB multiples.
1915
- // Queue an empty write and exit from its callback it fires only after
1935
+ // Queue an empty write and exit from its callback, it fires only after
1916
1936
  // every earlier buffered write has drained (BCK-1306).
1917
1937
  const exitAfterStdoutDrain = (code) => {
1918
1938
  if (process.stdout.writableLength === 0) process.exit(code);
@@ -1975,7 +1995,7 @@ if (command === 'init') {
1975
1995
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
1976
1996
  .catch((err) => { console.error(`\nerror: ${err.message || err}`); process.exit(1); });
1977
1997
  } else if (command === 'drive') {
1978
- // Drive: one self-driving tick mission doctor -> auto-fix safe findings -> count disengagements.
1998
+ // Drive: one self-driving tick, mission doctor -> auto-fix safe findings -> count disengagements.
1979
1999
  Promise.resolve(require('../commands/drive').driveCommand(process.argv.slice(3)))
1980
2000
  .then((code) => process.exit(code || 0))
1981
2001
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
@@ -2002,7 +2022,7 @@ if (command === 'init') {
2002
2022
  .then(() => process.exit(process.exitCode || 0))
2003
2023
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2004
2024
  } else if (command === 'aeo') {
2005
- // AEO: AI Engine Optimization credit-metered citation drafting against the customer workspace.
2025
+ // AEO: AI Engine Optimization, credit-metered citation drafting against the customer workspace.
2006
2026
  Promise.resolve(require('../commands/aeo').run(process.argv.slice(3)))
2007
2027
  .then(() => process.exit(0))
2008
2028
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
@@ -2163,6 +2183,13 @@ if (command === 'init') {
2163
2183
  process.exit(0);
2164
2184
  }
2165
2185
  upgradeAtris().then(() => process.exit(0)).catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2186
+ } else if (command === 'chat' && (process.argv[3] === '--personal' || process.argv[3] === '-p')) {
2187
+ require('../commands/ask').askAtris(process.argv.slice(4))
2188
+ .then(() => process.exit(0))
2189
+ .catch((error) => {
2190
+ console.error(`✗ Ask failed: ${error.message || error}`);
2191
+ process.exit(1);
2192
+ });
2166
2193
  } else if (command === 'chat') {
2167
2194
  if (process.argv[3] === 'scan') {
2168
2195
  try {
@@ -2189,7 +2216,7 @@ if (command === 'init') {
2189
2216
  } else if (command === 'console') {
2190
2217
  consoleCmd();
2191
2218
  } else if (command === 'serve') {
2192
- // Start the local AI Computer bridge make this directory addressable
2219
+ // Start the local AI Computer bridge, make this directory addressable
2193
2220
  // by cloud agents via the Atris API
2194
2221
  const serveArgs = process.argv.slice(3);
2195
2222
  if (serveArgs.includes('--help') || serveArgs.includes('-h') || serveArgs[0] === 'help') {
@@ -2291,7 +2318,7 @@ if (command === 'init') {
2291
2318
  // Hidden: copy profile to credentials.json (global switch, legacy)
2292
2319
  require('../commands/auth').activateGlobal();
2293
2320
  } else if (command === '_switch-session') {
2294
- // Hidden: per-terminal switch writes session file so each tab keeps its own account
2321
+ // Hidden: per-terminal switch, writes session file so each tab keeps its own account
2295
2322
  require('../commands/auth').switchSession();
2296
2323
  } else if (command === 'shell-init') {
2297
2324
  require('../commands/auth').shellInit();
@@ -3062,7 +3089,7 @@ if (command === 'init') {
3062
3089
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3063
3090
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
3064
3091
  } else if (command === 'write') {
3065
- // Write: guided writing sessions human types every word, atris structures + reviews (plan-do-review for prose).
3092
+ // Write: guided writing sessions, human types every word, atris structures + reviews (plan-do-review for prose).
3066
3093
  Promise.resolve(require('../commands/write').writeCommand(process.argv.slice(3)))
3067
3094
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3068
3095
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
@@ -3084,7 +3111,7 @@ if (command === 'init') {
3084
3111
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3085
3112
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
3086
3113
  } else if (command === 'moves') {
3087
- // Moves: your 3 next moves approve one into the loop, kill, or skip.
3114
+ // Moves: your 3 next moves, approve one into the loop, kill, or skip.
3088
3115
  Promise.resolve(require('../commands/moves').movesCommand(process.argv.slice(3)))
3089
3116
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3090
3117
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
@@ -3094,7 +3121,7 @@ if (command === 'init') {
3094
3121
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3095
3122
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
3096
3123
  } else if (command === 'feed') {
3097
- // Feed: read and post the business group feed receipts and state changes only.
3124
+ // Feed: read and post the business group feed, receipts and state changes only.
3098
3125
  // Sets exitCode instead of process.exit() so large --json output flushes fully.
3099
3126
  Promise.resolve(require('../commands/feed').feedCommand(process.argv.slice(3)))
3100
3127
  .then((code) => { process.exitCode = typeof code === 'number' ? code : 0; })
@@ -3105,7 +3132,7 @@ if (command === 'init') {
3105
3132
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3106
3133
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
3107
3134
  } else if (command === 'interview') {
3108
- // Interview: the interlinked 1-on-1 live interview that extracts judgment into a member file.
3135
+ // Interview: the interlinked 1-on-1, live interview that extracts judgment into a member file.
3109
3136
  Promise.resolve(require('../commands/interview').interviewCommand(process.argv.slice(3)))
3110
3137
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3111
3138
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
@@ -3115,7 +3142,7 @@ if (command === 'init') {
3115
3142
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3116
3143
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
3117
3144
  } else if (command === 'site') {
3118
- // Site: beautiful static site from a folder of markdown, in the anti-slop design system.
3145
+ // Site: build markdown sites or publish static web folders.
3119
3146
  {
3120
3147
  const raw = process.argv.slice(3);
3121
3148
  const deployWrite = raw[0] === 'deploy'
@@ -3151,6 +3178,11 @@ if (command === 'init') {
3151
3178
  Promise.resolve(require('../commands/reel').run(process.argv.slice(3)))
3152
3179
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
3153
3180
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
3181
+ } else if (command === 'tree') {
3182
+ const subcommand = process.argv[3];
3183
+ const args = process.argv.slice(4);
3184
+ const code = require('../commands/tree').treeCommand(subcommand, ...args);
3185
+ process.exit(code || 0);
3154
3186
  } else if (command === 'receipt' || command === 'proof' || command === 'openclaw') {
3155
3187
  const subcommand = process.argv[3];
3156
3188
  const args = process.argv.slice(4);
@@ -3550,10 +3582,19 @@ async function chatAtris() {
3550
3582
  const fastLaneFlags = [];
3551
3583
  const messageArgs = [];
3552
3584
  let agentLane = false;
3553
- for (const arg of rawArgs) {
3585
+ for (let index = 0; index < rawArgs.length; index += 1) {
3586
+ const arg = rawArgs[index];
3554
3587
  if (arg === '--agent') {
3555
3588
  agentLane = true;
3556
- } else if (arg === '--print' || arg === '--headless' || arg === '--rapid' || arg === '--auto-approve') {
3589
+ } else if (arg === '--effort') {
3590
+ const next = rawArgs[index + 1];
3591
+ if (next && !next.startsWith('-')) {
3592
+ fastLaneFlags.push('--effort', next);
3593
+ index += 1;
3594
+ } else {
3595
+ fastLaneFlags.push('--effort');
3596
+ }
3597
+ } else if (arg === '--print' || arg === '--headless' || arg === '--rapid' || arg === '--alpha' || arg === '--auto-approve') {
3557
3598
  fastLaneFlags.push(arg);
3558
3599
  } else {
3559
3600
  messageArgs.push(arg);
@@ -3567,10 +3608,13 @@ async function chatAtris() {
3567
3608
  console.log('');
3568
3609
  console.log(' Chat with Atris 2 Fast in this workspace: tools attached, same turn as `ax --fast`.');
3569
3610
  console.log(' Pass --rapid to use Atris Rapid instead.');
3611
+ console.log(' Pass --alpha to use Atris Alpha (experimental preview lane).');
3612
+ console.log(' Pass --effort medium|high|xhigh to override reasoning depth for the turn/session.');
3570
3613
  console.log(' Requires `atris login`.');
3571
3614
  console.log('');
3572
3615
  console.log(' atris chat Interactive chat (ax --fast --chat)');
3573
3616
  console.log(' atris chat --rapid Interactive Rapid chat (ax --rapid --chat)');
3617
+ console.log(' atris chat --alpha Interactive Alpha chat (ax --alpha --chat)');
3574
3618
  console.log(' atris chat --rapid --auto-approve Rapid chat that auto-approves safe git push');
3575
3619
  console.log(' atris chat "what now?" One-shot message (ax --fast)');
3576
3620
  console.log(' atris chat --print "..." Headless JSON result (ax --fast --print)');
@@ -3598,8 +3642,12 @@ async function chatAtris() {
3598
3642
  if (!agentLane) {
3599
3643
  try {
3600
3644
  const axPath = path.join(__dirname, '..', 'ax');
3601
- const lane = fastLaneFlags.includes('--rapid') ? '--rapid' : '--fast';
3602
- const extraFlags = fastLaneFlags.filter((flag) => flag !== '--rapid');
3645
+ const lane = fastLaneFlags.includes('--alpha')
3646
+ ? '--alpha'
3647
+ : fastLaneFlags.includes('--rapid')
3648
+ ? '--rapid'
3649
+ : '--fast';
3650
+ const extraFlags = fastLaneFlags.filter((flag) => flag !== '--rapid' && flag !== '--alpha');
3603
3651
  const axArgs = message
3604
3652
  ? [lane, ...extraFlags, message].filter(Boolean)
3605
3653
  : [lane, ...extraFlags, '--chat'];
@@ -3680,7 +3728,7 @@ async function chatInteractive(config, credentials) {
3680
3728
  const conversationId = `cli-${Date.now()}`;
3681
3729
 
3682
3730
  console.log('┌────────────────────────────────────────────────────────────┐');
3683
- console.log(`│ Atris Chat ${agentName.padEnd(44)} │`);
3731
+ console.log(`│ Atris Chat, ${agentName.padEnd(44)} │`);
3684
3732
  console.log('├────────────────────────────────────────────────────────────┤');
3685
3733
  console.log('│ Type your message and press Enter │');
3686
3734
  console.log('│ Type "exit" to quit │');
@@ -3871,7 +3919,7 @@ async function atrisFastChat() {
3871
3919
  // One routing brain: `atris fast` defers to ax's AX Context Standard. A
3872
3920
  // workspace-shaped question asked from inside a workspace needs local tools
3873
3921
  // (this lane is a tool-less cloud one-shot and confabulates on repo
3874
- // questions SwapBench 2026-07-02), so delegate the whole turn to ax.
3922
+ // questions, SwapBench 2026-07-02), so delegate the whole turn to ax.
3875
3923
  try {
3876
3924
  const axModule = require('../ax');
3877
3925
  if (axModule.resolveRoute(message) === 'local') {
package/commands/aeo.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * atris aeo AI Engine Optimization commands
2
+ * atris aeo, AI Engine Optimization commands
3
3
  *
4
4
  * Backend-routed (require EC2):
5
5
  * atris aeo init # create entity-graph skeleton
@@ -213,7 +213,7 @@ async function aeoScan(args) {
213
213
  }
214
214
  if (asJson) { console.log(JSON.stringify(data, null, 2)); return; }
215
215
  console.log(`\n ${data.name || target}`);
216
- console.log(` Score: ${data.score}/100 (${data.grade}) ${data.status}`);
216
+ console.log(` Score: ${data.score}/100 (${data.grade}), ${data.status}`);
217
217
  if (data.gap_statement) console.log(`\n ${data.gap_statement}`);
218
218
  const gaps = data.gaps || [];
219
219
  if (gaps.length) {
@@ -226,7 +226,7 @@ async function aeoScan(args) {
226
226
  for (const c of comp) console.log(` ${pad(String(c.score ?? '?'), 4)} ${c.url || c.name}`);
227
227
  }
228
228
  if (data.draft_llms_txt) {
229
- console.log('\n Draft llms.txt included save it with:');
229
+ console.log('\n Draft llms.txt included, save it with:');
230
230
  console.log(` atris aeo scan ${url} --json | jq -r .draft_llms_txt > llms.txt`);
231
231
  }
232
232
  console.log('');
@@ -511,7 +511,7 @@ async function aeoPacket(args) {
511
511
  const onlyObjects = (v) => (Array.isArray(v) ? v.filter((x) => x && typeof x === 'object') : []);
512
512
  const friction = onlyObjects(u.baseline_friction_points);
513
513
  const fixes = onlyObjects(u.fix_backlog);
514
- console.log(`AEO buyer packet ${slug}`);
514
+ console.log(`AEO buyer packet, ${slug}`);
515
515
  console.log(` surface: ${data.surface || ''}`);
516
516
  console.log(` target url: ${data.target_url || ''}`);
517
517
  console.log(` claim status: ${data.claim_status || ''}`);
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // atris agents one glanceable view of every member's state.
3
+ // atris agents, one glanceable view of every member's state.
4
4
  // Reads .atris/state/missions.jsonl (schema atris.mission.v1) plus the
5
5
  // directories in atris/team/, and prints who is stuck, waiting on you,
6
6
  // working, or resting. Built from a dream card: "validator cannot plan
package/commands/align.js CHANGED
@@ -100,7 +100,7 @@ function walkLocal(rootDir) {
100
100
  * Why this instead of recursive /files walk: the recursive walk is rate-limited
101
101
  * (60/min) and hangs on workspaces with many subdirs. The /snapshot endpoint
102
102
  * returns the full file tree in one call. Trade-off: snapshot can be incomplete
103
- * for very deep hierarchies (server-side bug we've seen) but it's vastly faster
103
+ * for very deep hierarchies (server-side bug we've seen), but it's vastly faster
104
104
  * and we accept that risk in exchange for not hanging.
105
105
  */
106
106
  async function walkCloud(token, businessId, workspaceId) {
@@ -126,14 +126,14 @@ async function walkCloud(token, businessId, workspaceId) {
126
126
  out[p] = { hash: f.hash || null, size: f.size || 0 };
127
127
  }
128
128
  // CRITICAL: only return if snapshot actually had files. Empty snapshot is
129
- // a known server-side bug fall back to recursive walk in that case so
129
+ // a known server-side bug, fall back to recursive walk in that case so
130
130
  // we don't report every local file as "only on local" against a phantom empty cloud.
131
131
  if (Object.keys(out).length > 0) {
132
132
  return { files: out, errors };
133
133
  }
134
134
  errors.push({ path: '<snapshot>', status: 'empty', fallback: 'recursive walk' });
135
135
  } else {
136
- // Snapshot failed entirely fall back to recursive walk
136
+ // Snapshot failed entirely, fall back to recursive walk
137
137
  errors.push({ path: '<snapshot>', status: snapshotResult.status, fallback: 'recursive walk' });
138
138
  }
139
139
 
@@ -288,7 +288,7 @@ async function alignHardLocalToCloud(token, biz, localDir) {
288
288
  const { buildManifest, saveManifest, computeLocalHashes } = require('../lib/manifest');
289
289
 
290
290
  // 1. List top-level entries on cloud via /files (1 fast API call).
291
- // We deliberately AVOID /snapshot here its hangs/timeouts on bloated
291
+ // We deliberately AVOID /snapshot here, its hangs/timeouts on bloated
292
292
  // workspaces are the whole reason --hard exists. /files at depth 0 is
293
293
  // a single dir-listing call that returns reliably.
294
294
  //
@@ -319,12 +319,12 @@ async function alignHardLocalToCloud(token, biz, localDir) {
319
319
  const cloudTopEntries = (topResult.data && topResult.data.files) || [];
320
320
  console.log(`${cloudTopEntries.length} entries`);
321
321
 
322
- // The `workspace` top-level entry is the workspace root itself it's
322
+ // The `workspace` top-level entry is the workspace root itself, it's
323
323
  // protected server-side (DELETE returns 400) and is NEVER cruft. Don't
324
324
  // try to delete it; pretend it isn't there for the diff.
325
325
  const PROTECTED_TOP = new Set(['workspace']);
326
326
 
327
- // 2. Top-level local entries track names AND types so we can detect
327
+ // 2. Top-level local entries, track names AND types so we can detect
328
328
  // type-mismatch (cloud has file `foo`, local has dir `foo/`).
329
329
  const localTopByName = new Map(); // name -> 'dir' | 'file'
330
330
  for (const e of fs.readdirSync(localDir, { withFileTypes: true })) {
@@ -341,7 +341,7 @@ async function alignHardLocalToCloud(token, biz, localDir) {
341
341
  //
342
342
  // NOTE: --hard intentionally does NOT respect SKIP_DIRS/SKIP_FILES here.
343
343
  // Those skip lists exist for the diff/walk path so we don't enumerate
344
- // node_modules/venv/__pycache__ locally they are NOT protections that
344
+ // node_modules/venv/__pycache__ locally, they are NOT protections that
345
345
  // mean "don't delete on cloud." A bloated cloud workspace might genuinely
346
346
  // contain stale `default/`, `venv/`, `__pycache__/` etc that the user
347
347
  // wants nuked. --hard means "make cloud match local"; if local doesn't
@@ -354,7 +354,7 @@ async function alignHardLocalToCloud(token, biz, localDir) {
354
354
  if (PROTECTED_TOP.has(name)) return false;
355
355
  const localType = localTopByName.get(name);
356
356
  if (!localType) return true; // not in local at all
357
- if (localType !== entry.type) return true; // type mismatch must clear
357
+ if (localType !== entry.type) return true; // type mismatch, must clear
358
358
  return false;
359
359
  });
360
360
 
@@ -413,7 +413,7 @@ async function alignHardLocalToCloud(token, biz, localDir) {
413
413
  const r = await pushFiles(token, businessId, workspaceId, batch, 180000);
414
414
  if (r.ok) {
415
415
  // The server returns SyncResponse{written, unchanged, errors, results}
416
- // inside a 200. A successful HTTP doesn't mean every file landed
416
+ // inside a 200. A successful HTTP doesn't mean every file landed,
417
417
  // results can include status="error" entries (path-traversal attempts,
418
418
  // permission errors, full disk, etc). Trust the server's count and
419
419
  // record any per-file errors against batchFailures so we don't write
@@ -446,7 +446,7 @@ async function alignHardLocalToCloud(token, biz, localDir) {
446
446
  if (failedPaths.length > 8) console.log(` ... +${failedPaths.length - 8} more`);
447
447
  }
448
448
 
449
- // 5. Save manifest so subsequent push/pull diffs work but ONLY if every
449
+ // 5. Save manifest so subsequent push/pull diffs work, but ONLY if every
450
450
  // batch, every per-file write, AND every cloud delete succeeded. If
451
451
  // anything failed, leaving the manifest stale is safer than recording
452
452
  // a mirror that doesn't actually exist on cloud (the manifest would
@@ -553,7 +553,7 @@ async function alignAtris() {
553
553
  // --hard: skip the slow file-by-file walk. Nuke top-level cloud entries
554
554
  // not present locally (1 DELETE per top-level dir, recursive on the server),
555
555
  // then bulk-push every local file via /sync. Designed for "cloud is bloated,
556
- // local is canonical, just make them match" the force-push escape hatch.
556
+ // local is canonical, just make them match", the force-push escape hatch.
557
557
  if (hard && fix) {
558
558
  console.log(` Local: ${localDir}`);
559
559
  console.log(` Cloud: ${endpoint}`);
@@ -635,7 +635,7 @@ async function alignAtris() {
635
635
  }
636
636
 
637
637
  // FIX MODE
638
- console.log(` Fixing ${fromSide} is canonical:`);
638
+ console.log(` Fixing, ${fromSide} is canonical:`);
639
639
 
640
640
  if (fromSide === 'local') {
641
641
  // Delete cloud-only files (they're cruft)
@@ -68,8 +68,8 @@ function analyticsAtris() {
68
68
  }
69
69
 
70
70
  // Parse timestamps for productivity hours. Match the journal heading
71
- // format `### Title HH:MM` and the legacy `**HH:MM:SS**` form.
72
- const timestampMatches = content.match(/(?:—|--)\s*(\d{2}):\d{2}(?::\d{2})?\b|\*\*(\d{2}):\d{2}(?::\d{2})?\*\*/g);
71
+ // format `### Title -- HH:MM` (the dashed form) and the legacy `**HH:MM:SS**` form.
72
+ const timestampMatches = content.match(/(?:\u2014|--)\s*(\d{2}):\d{2}(?::\d{2})?\b|\*\*(\d{2}):\d{2}(?::\d{2})?\*\*/g);
73
73
  if (timestampMatches) {
74
74
  timestampMatches.forEach(ts => {
75
75
  const m = ts.match(/(\d{2}):/);
@@ -110,7 +110,7 @@ function analyticsAtris() {
110
110
  const dateFormatted = `${year}-${month}-${day}`;
111
111
  console.log('');
112
112
  console.log('┌─────────────────────────────────────────────────────────────┐');
113
- console.log(`│ Atris Analytics ${dateFormatted}${' '.repeat(34 - dateFormatted.length)}│`);
113
+ console.log(`│ Atris Analytics, ${dateFormatted}${' '.repeat(35 - dateFormatted.length)}│`);
114
114
  console.log('└─────────────────────────────────────────────────────────────┘');
115
115
  console.log('');
116
116
 
package/commands/app.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * atris app manage APP.md manifests in the current workspace.
2
+ * atris app, manage APP.md manifests in the current workspace.
3
3
  *
4
4
  * Subcommands:
5
5
  * atris app init <slug> [--runtime ec2|local|webhook|external|web|ios|template]
@@ -181,9 +181,9 @@ function readmeFor(slug) {
181
181
  '',
182
182
  '## Files',
183
183
  '',
184
- '- `APP.md` app manifest (frontmatter + instructions). Source of truth.',
185
- '- `data/` per-run outputs.',
186
- '- `logs/` stdout/stderr per trigger.',
184
+ '- `APP.md`, app manifest (frontmatter + instructions). Source of truth.',
185
+ '- `data/`, per-run outputs.',
186
+ '- `logs/`, stdout/stderr per trigger.',
187
187
  '',
188
188
  '## Secrets',
189
189
  '',
@@ -271,7 +271,7 @@ async function show(slug) {
271
271
  }
272
272
 
273
273
  async function help() {
274
- console.log('atris app manage APP.md manifests');
274
+ console.log('atris app, manage APP.md manifests');
275
275
  console.log('');
276
276
  console.log('Subcommands:');
277
277
  console.log(' init <slug> [--runtime <kind>] Scaffold a new app folder');