atris 3.57.4 → 3.58.6

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 +55 -12
  6. package/atris/skills/x-search/SKILL.md +8 -6
  7. package/atris/skills/youtube/SKILL.md +66 -21
  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 +153 -23
  16. package/bin/atris.js +78 -30
  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 +59 -31
  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 +3 -3
  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 +216 -50
  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 +90 -82
  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 +101 -48
  98. package/commands/worktree.js +1 -1
  99. package/commands/write.js +9 -9
  100. package/commands/x-search.js +93 -22
  101. package/commands/xp.js +6 -3
  102. package/commands/youtube.js +1019 -123
  103. package/lib/accept-verify-gate.js +3 -3
  104. package/lib/activity-stream.js +1 -1
  105. package/lib/auto-accept-certified.js +28 -12
  106. package/lib/autoland.js +6 -6
  107. package/lib/bench/engines.js +59 -8
  108. package/lib/bench/report.js +1 -1
  109. package/lib/bench/runner.js +204 -5
  110. package/lib/bench/tree-render.js +76 -0
  111. package/lib/card.js +1 -1
  112. package/lib/chat-log-scan.js +1 -1
  113. package/lib/claude-boot-block.js +2 -0
  114. package/lib/deck-compose.js +1 -1
  115. package/lib/deck-history.js +2 -2
  116. package/lib/deck-layout.js +1 -1
  117. package/lib/deck-review.js +5 -5
  118. package/lib/deck-schema.js +1 -1
  119. package/lib/default-verifier.js +1 -1
  120. package/lib/developer-api.js +3 -0
  121. package/lib/engine-ask.js +45 -7
  122. package/lib/engine-registry.js +15 -2
  123. package/lib/file-ops.js +1 -1
  124. package/lib/fleet.js +71 -35
  125. package/lib/html-render.js +1 -1
  126. package/lib/intents.js +172 -0
  127. package/lib/journal.js +1 -1
  128. package/lib/known-commands.js +2 -2
  129. package/lib/land-green.js +364 -0
  130. package/lib/lesson-contradiction.js +2 -2
  131. package/lib/lesson-preflight.js +1 -1
  132. package/lib/manifest.js +5 -5
  133. package/lib/member-alive.js +9 -5
  134. package/lib/memory-view.js +3 -3
  135. package/lib/mission-protected-lane.js +1 -1
  136. package/lib/mission-root.js +2 -2
  137. package/lib/orb-context.js +10 -10
  138. package/lib/pack-capabilities.js +861 -3
  139. package/lib/permission-grants.js +2 -2
  140. package/lib/policy-lessons.js +6 -6
  141. package/lib/pulse.js +8 -8
  142. package/lib/receipt-evidence.js +1 -1
  143. package/lib/reel.js +1 -1
  144. package/lib/review-integrity.js +1 -1
  145. package/lib/runner-command.js +35 -5
  146. package/lib/scorecard.js +4 -4
  147. package/lib/security-scan.js +5 -5
  148. package/lib/self-drive.js +1 -1
  149. package/lib/site-publish.js +372 -0
  150. package/lib/site.js +1 -1
  151. package/lib/slides-deck.js +2 -2
  152. package/lib/state-detection.js +2 -2
  153. package/lib/sync-telemetry.js +2 -2
  154. package/lib/task-db.js +17 -10
  155. package/lib/task-explanation.js +1 -1
  156. package/lib/task-proof.js +2 -2
  157. package/lib/task-receipt.js +3 -3
  158. package/lib/theme.js +12 -12
  159. package/lib/todo-fallback.js +3 -3
  160. package/lib/todo-sections.js +1 -1
  161. package/lib/tree-hash.js +79 -0
  162. package/lib/usage.js +1 -1
  163. package/lib/wish-delegate.js +1 -1
  164. package/lib/workspace-safety.js +4 -4
  165. package/lib/workspace-scaffold.js +3 -3
  166. package/package.json +1 -1
  167. package/scripts/det/concierge-bakeoff.sh +26 -0
  168. package/scripts/det/ytnotes +82 -5
  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 +47 -9
  174. package/utils/config.js +0 -1
  175. package/scripts/det/checklist-score.js +0 -191
package/utils/auth.js CHANGED
@@ -352,9 +352,13 @@ function autoSaveProfile(credentials) {
352
352
  }
353
353
  }
354
354
 
355
- function saveCredentials(token, refreshToken, email, userId, provider) {
355
+ function saveCredentials(token, refreshToken, email, userId, provider, extras = {}) {
356
+ if (decodeJwtClaims(token)?.type === 'agent_access') {
357
+ throw new Error('Refusing to save a scoped agent token as the login token; keep it under agent_token');
358
+ }
356
359
  const credentialsPath = getCredentialsPath();
357
360
  const credentials = {
361
+ ...extras,
358
362
  token,
359
363
  refresh_token: refreshToken || null,
360
364
  email: email || null,
@@ -374,7 +378,43 @@ function saveCredentials(token, refreshToken, email, userId, provider) {
374
378
  autoSaveProfile(credentials);
375
379
  }
376
380
 
377
- function loadCredentials() {
381
+ // Supplying the auth client enables asynchronous repair. Local-only readers stay synchronous.
382
+ function loadCredentials(apiRequestJson) {
383
+ const credentials = readCredentials();
384
+ if (!credentials || credentials.source || decodeJwtClaims(credentials.token)?.type !== 'agent_access') {
385
+ return credentials;
386
+ }
387
+ if (!credentials.refresh_token) {
388
+ console.error('atris login');
389
+ return credentials;
390
+ }
391
+ if (!apiRequestJson) return credentials;
392
+ return repairLoginCredentials(credentials, apiRequestJson);
393
+ }
394
+
395
+ async function repairLoginCredentials(credentials, apiRequestJson) {
396
+ const refreshed = await refreshAccessToken(credentials.refresh_token, null, apiRequestJson);
397
+ const token = refreshed.data?.access_token;
398
+ if (!refreshed.ok || !token || decodeJwtClaims(token)?.type === 'agent_access') {
399
+ throw new Error('Could not repair login file. Run atris login');
400
+ }
401
+ const claims = decodeJwtClaims(credentials.token);
402
+ const { source_profile, ...rest } = credentials;
403
+ const next = {
404
+ ...rest,
405
+ token,
406
+ refresh_token: refreshed.data.refresh_token || credentials.refresh_token,
407
+ agent_token: credentials.token,
408
+ agent_token_scopes: claims.scopes || [],
409
+ agent_token_expires_at: typeof claims.exp === 'number' ? new Date(claims.exp * 1000).toISOString() : null,
410
+ };
411
+ if (source_profile) saveProfile(source_profile, next);
412
+ else saveCredentials(token, next.refresh_token, next.email, next.user_id, next.provider, next);
413
+ console.error('Repaired login file: moved a scoped agent token aside.');
414
+ return { ...next, ...(source_profile ? { source_profile } : {}) };
415
+ }
416
+
417
+ function readCredentials() {
378
418
  // Priority: ATRIS_TOKEN env var → placed agent token → ATRIS_PROFILE env var
379
419
  // → per-terminal session file → global credentials.json. A fresh placed token
380
420
  // overrides a different env token because cloud images can carry a stale one.
@@ -552,7 +592,7 @@ async function performTokenRefresh(credentials, apiRequestJson) {
552
592
  saved_at: new Date().toISOString(),
553
593
  });
554
594
  } else {
555
- saveCredentials(accessToken, newRefreshToken, email, userId, provider);
595
+ saveCredentials(accessToken, newRefreshToken, email, userId, provider, credentials);
556
596
  }
557
597
  };
558
598
 
@@ -586,7 +626,7 @@ async function performTokenRefresh(credentials, apiRequestJson) {
586
626
  saved_at: new Date().toISOString(),
587
627
  });
588
628
  } else {
589
- saveCredentials(accessToken, newRefreshToken, updatedEmail, updatedUserId, updatedProvider);
629
+ saveCredentials(accessToken, newRefreshToken, updatedEmail, updatedUserId, updatedProvider, credentials);
590
630
  }
591
631
  latestCreds = loadCredentials();
592
632
  }
@@ -603,7 +643,7 @@ async function performTokenRefresh(credentials, apiRequestJson) {
603
643
  }
604
644
 
605
645
  async function ensureValidCredentials(apiRequestJson, options = {}) {
606
- let credentials = loadCredentials();
646
+ let credentials = await loadCredentials(apiRequestJson);
607
647
  if (!credentials || !credentials.token) {
608
648
  return { error: 'not_logged_in' };
609
649
  }
@@ -659,7 +699,8 @@ async function ensureValidCredentials(apiRequestJson, options = {}) {
659
699
  credentials.refresh_token,
660
700
  updatedEmail,
661
701
  updatedUserId,
662
- updatedProvider
702
+ updatedProvider,
703
+ credentials
663
704
  );
664
705
  }
665
706
  }
@@ -760,11 +801,9 @@ module.exports = {
760
801
  promptUser,
761
802
  validateAccessToken,
762
803
  refreshAccessToken,
763
- refreshProviderHint,
764
804
  performTokenRefresh,
765
805
  ensureValidCredentials,
766
806
  isAuthFailure,
767
- printAuthRequired,
768
807
  abortOnAuthFailure,
769
808
  fetchMyAgents,
770
809
  displayAccountSummary,
@@ -774,7 +813,6 @@ module.exports = {
774
813
  listProfiles,
775
814
  deleteProfile,
776
815
  profileNameFromEmail,
777
- autoSaveProfile,
778
816
  // Per-terminal sessions
779
817
  getTerminalSessionId,
780
818
  getSessionsDir,
package/utils/config.js CHANGED
@@ -88,7 +88,6 @@ module.exports = {
88
88
  getConfigPath,
89
89
  loadConfig,
90
90
  saveConfig,
91
- getLogSyncStatePath,
92
91
  loadLogSyncState,
93
92
  saveLogSyncState,
94
93
  };
@@ -1,191 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- // Pareto-3 checklist quality score.
5
- //
6
- // Measures the three front doors a brand-new person actually hits, the way
7
- // they would hit them: from an empty folder, with no context, reading only
8
- // what the tool prints. Every point is earned by a live probe, never opinion.
9
- //
10
- // 1. onboard - `atris init --yes` in a fresh folder
11
- // 2. chat - one real answered message through `ax`
12
- // 3. mission - the end-to-end loop drill in its own sandbox
13
- //
14
- // Rubric per feature (100 points):
15
- // cold start works, zero setup ......... 40
16
- // speed to first value ................. 20 (full marks at target, 0 at 4x)
17
- // plain language on the first screen ... 20 (fraction of clean lines)
18
- // graceful failure on wrong input ...... 20 (honest exit + plain reason,
19
- // no stack trace)
20
- //
21
- // Usage: node scripts/det/checklist-score.js [--json]
22
-
23
- const { spawnSync } = require('node:child_process');
24
- const fs = require('node:fs');
25
- const os = require('node:os');
26
- const path = require('node:path');
27
-
28
- const repoRoot = path.resolve(__dirname, '..', '..');
29
- const cliPath = path.join(repoRoot, 'bin', 'atris.js');
30
- const axPath = path.join(repoRoot, 'ax');
31
- const { scanText } = require(path.join(repoRoot, 'lib', 'voice-gate'));
32
-
33
- // System nouns a person with no idea should never have to decode on a first
34
- // screen. Backticked command examples are exempt (they are copy targets).
35
- const SYSTEM_NOUNS = /\b(?:verifier|worktree|subagent|jsonl|projection|runner[- ]profile|heartbeat|orchestrat\w+|frontmatter|monorepo)\b/i;
36
- const STACK_FRAME = /^\s+at .+:\d+:\d+\)?$/;
37
-
38
- function run(cmd, args, options = {}) {
39
- const started = Date.now();
40
- const result = spawnSync(cmd, args, {
41
- cwd: options.cwd,
42
- encoding: 'utf8',
43
- timeout: options.timeoutMs || 180000,
44
- env: { ...process.env, ATRIS_SKIP_UPDATE_CHECK: '1', ...(options.env || {}) },
45
- });
46
- return {
47
- status: result.status,
48
- error: result.error || null,
49
- stdout: result.stdout || '',
50
- stderr: result.stderr || '',
51
- ms: Date.now() - started,
52
- };
53
- }
54
-
55
- function speedPoints(ms, targetMs) {
56
- if (ms <= targetMs) return 20;
57
- const over = (ms - targetMs) / (targetMs * 3);
58
- return Math.max(0, Math.round(20 * (1 - over)));
59
- }
60
-
61
- function plainPoints(text) {
62
- const lines = String(text || '')
63
- .split(/\r?\n/)
64
- .map((line) => line.trim())
65
- .filter(Boolean)
66
- .slice(0, 30);
67
- if (!lines.length) return { points: 0, dirty: ['(no output at all)'] };
68
- const dirty = [];
69
- for (const line of lines) {
70
- // Command examples are copy targets, not prose; the reader with no idea
71
- // reads the description column, so scan only the human words.
72
- if (/^`.*`$/.test(line) || /^\$\s/.test(line) || /^(?:ax|atris|npx)\s/.test(line)) continue;
73
- const bare = line
74
- .replace(/`[^`]*`/g, '')
75
- .replace(/--[\w-]+/g, '')
76
- .replace(/\[[^\]]*\]/g, '')
77
- .replace(/<[^>]*>/g, '');
78
- if (STACK_FRAME.test(line) || /\u2014/.test(bare) || SYSTEM_NOUNS.test(bare) || scanText(bare).length) {
79
- dirty.push(line.slice(0, 80));
80
- }
81
- }
82
- const clean = lines.length - dirty.length;
83
- return { points: Math.round((20 * clean) / lines.length), dirty };
84
- }
85
-
86
- function failurePoints(result) {
87
- const text = `${result.stdout}\n${result.stderr}`;
88
- const honest = result.status !== 0 && !result.error;
89
- const noStack = !text.split(/\r?\n/).some((line) => STACK_FRAME.test(line))
90
- && !/\b(?:TypeError|ReferenceError|SyntaxError)\b/.test(text);
91
- const saysWhy = /\b(?:unknown|not found|no such|missing|usage|help|try|error)\b/i.test(text);
92
- let points = 0;
93
- if (honest) points += 8;
94
- if (noStack) points += 6;
95
- if (saysWhy) points += 6;
96
- return points;
97
- }
98
-
99
- function scoreOnboard(base) {
100
- const dir = fs.mkdtempSync(path.join(base, 'onboard-'));
101
- const cold = run(process.execPath, [cliPath, 'init', '--yes'], { cwd: dir });
102
- const artifact = fs.existsSync(path.join(dir, 'atris'));
103
- const coldPoints = cold.status === 0 && artifact ? 40 : 0;
104
- const plain = plainPoints(cold.stdout);
105
- const bad = run(process.execPath, [cliPath, 'definitely-not-a-command'], { cwd: dir });
106
- return {
107
- feature: 'onboard: atris init in an empty folder',
108
- dir,
109
- cold: coldPoints,
110
- speed: speedPoints(cold.ms, 10000),
111
- plain: plain.points,
112
- failure: failurePoints(bad),
113
- ms: cold.ms,
114
- dirty_lines: plain.dirty,
115
- };
116
- }
117
-
118
- function scoreChat(base, workspaceDir) {
119
- const cold = run(process.execPath, [axPath, '--fast', '--print', 'Reply with exactly: checklist-ok'], {
120
- cwd: workspaceDir,
121
- timeoutMs: 120000,
122
- });
123
- let answered = false;
124
- try {
125
- const payload = JSON.parse(cold.stdout.slice(cold.stdout.indexOf('{')));
126
- answered = payload.ok === true && /checklist-ok/.test(String(payload.output || ''));
127
- } catch {}
128
- const helpScreen = run(process.execPath, [axPath, '--help'], { cwd: workspaceDir, timeoutMs: 30000 });
129
- const plain = plainPoints(helpScreen.stdout);
130
- const bad = run(process.execPath, [axPath, '--fast', '--print'], { cwd: workspaceDir, timeoutMs: 30000 });
131
- return {
132
- feature: 'chat: one real answered message through ax',
133
- cold: cold.status !== null && answered ? 40 : 0,
134
- speed: speedPoints(cold.ms, 15000),
135
- plain: plain.points,
136
- failure: failurePoints(bad),
137
- ms: cold.ms,
138
- dirty_lines: plain.dirty,
139
- };
140
- }
141
-
142
- function scoreMission(base, workspaceDir) {
143
- const cold = run(process.execPath, [cliPath, 'drill', '--json'], { cwd: workspaceDir, timeoutMs: 300000 });
144
- let passed = false;
145
- let stages = 0;
146
- try {
147
- const payload = JSON.parse(cold.stdout.slice(cold.stdout.indexOf('{')));
148
- passed = payload.pass === true;
149
- stages = Array.isArray(payload.stages) ? payload.stages.length : 0;
150
- } catch {}
151
- const status = run(process.execPath, [cliPath, 'mission'], { cwd: workspaceDir, timeoutMs: 60000 });
152
- const plain = plainPoints(status.stdout);
153
- const bad = run(process.execPath, [cliPath, 'mission', 'run', '9999'], { cwd: workspaceDir, timeoutMs: 60000 });
154
- return {
155
- feature: `mission: full loop drill (${stages} stages) plus status screen`,
156
- cold: passed ? 40 : 0,
157
- speed: speedPoints(cold.ms, 90000),
158
- plain: plain.points,
159
- failure: failurePoints(bad),
160
- ms: cold.ms,
161
- dirty_lines: plain.dirty,
162
- };
163
- }
164
-
165
- function main() {
166
- const asJson = process.argv.includes('--json');
167
- const base = fs.mkdtempSync(path.join(os.tmpdir(), 'atris-checklist-'));
168
- const onboard = scoreOnboard(base);
169
- const chat = scoreChat(base, onboard.dir);
170
- const mission = scoreMission(base, onboard.dir);
171
- const features = [onboard, chat, mission].map((f) => ({
172
- ...f,
173
- total: f.cold + f.speed + f.plain + f.failure,
174
- }));
175
- const overall = Math.round(features.reduce((sum, f) => sum + f.total, 0) / features.length);
176
- const report = { schema: 'atris.checklist_score.v1', overall, features };
177
- fs.rmSync(base, { recursive: true, force: true });
178
- if (asJson) {
179
- console.log(JSON.stringify(report, null, 2));
180
- return;
181
- }
182
- console.log('Pareto-3 checklist quality score\n');
183
- for (const f of features) {
184
- console.log(` ${f.feature}`);
185
- console.log(` cold start ${f.cold}/40 · speed ${f.speed}/20 (${(f.ms / 1000).toFixed(1)}s) · plain words ${f.plain}/20 · graceful failure ${f.failure}/20 => ${f.total}/100`);
186
- if (f.dirty_lines.length) console.log(` lines that need plain words: ${f.dirty_lines.length}`);
187
- }
188
- console.log(`\n overall: ${overall}/100`);
189
- }
190
-
191
- main();