atris 3.16.1 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -7
- package/atris/skills/atris/SKILL.md +15 -2
- package/atris/skills/atris-feedback/SKILL.md +7 -0
- package/atris/skills/design/SKILL.md +29 -2
- package/atris/skills/engines/SKILL.md +44 -0
- package/atris/skills/flow/SKILL.md +1 -1
- package/atris/skills/wake/SKILL.md +37 -0
- package/atris/skills/youtube/SKILL.md +13 -39
- package/atris/team/validator/MEMBER.md +1 -0
- package/atris/wiki/concepts/agent-activation-contract.md +3 -3
- package/atris/wiki/concepts/workspace-initialization-contract.md +3 -3
- package/atris/wiki/index.md +1 -0
- package/atris.md +43 -19
- package/bin/atris.js +413 -31
- package/commands/agent-spawn.js +480 -0
- package/commands/analytics.js +6 -3
- package/commands/apps.js +11 -0
- package/commands/autopilot.js +42 -18
- package/commands/brain.js +74 -7
- package/commands/brainstorm.js +9 -58
- package/commands/clean.js +1 -4
- package/commands/compile.js +9 -4
- package/commands/console.js +8 -3
- package/commands/deck.js +184 -0
- package/commands/init.js +22 -11
- package/commands/lesson.js +76 -0
- package/commands/member.js +252 -48
- package/commands/mission.js +405 -13
- package/commands/now.js +4 -2
- package/commands/probe.js +105 -27
- package/commands/pulse.js +504 -0
- package/commands/radar.js +1 -0
- package/commands/recap.js +71 -25
- package/commands/run.js +615 -22
- package/commands/site.js +48 -0
- package/commands/slop.js +307 -0
- package/commands/spaceship.js +39 -0
- package/commands/sync.js +0 -2
- package/commands/task.js +429 -37
- package/commands/theme.js +217 -0
- package/commands/verify.js +7 -3
- package/lib/activity-stream.js +166 -0
- package/lib/auto-accept-certified.js +23 -1
- package/lib/context-gatherer.js +170 -0
- package/lib/deck-from-md.js +110 -0
- package/lib/escape-regexp.js +13 -0
- package/lib/file-ops.js +6 -3
- package/lib/html-render.js +257 -0
- package/lib/journal.js +1 -1
- package/lib/lesson-contradiction.js +113 -0
- package/lib/memory-view.js +95 -0
- package/lib/policy-lessons.js +3 -2
- package/lib/pulse.js +401 -0
- package/lib/runner-command.js +156 -0
- package/lib/site.js +114 -0
- package/lib/slides-deck.js +237 -0
- package/lib/state-detection.js +1 -4
- package/lib/task-db.js +101 -4
- package/lib/task-proof.js +1 -1
- package/lib/theme.js +264 -0
- package/lib/todo-fallback.js +2 -1
- package/lib/todo-sections.js +33 -0
- package/package.json +1 -2
- package/utils/api.js +14 -2
- package/atris/atrisDev.md +0 -717
package/bin/atris.js
CHANGED
|
@@ -36,6 +36,13 @@ const {
|
|
|
36
36
|
|
|
37
37
|
// State detection for smart default
|
|
38
38
|
const { detectWorkspaceState, loadContext } = require('../lib/state-detection');
|
|
39
|
+
const {
|
|
40
|
+
saveContextProfile,
|
|
41
|
+
createStarterTask,
|
|
42
|
+
shouldGatherContext,
|
|
43
|
+
isAtrisMetaQuestion,
|
|
44
|
+
renderPrompt: renderContextGathererPrompt,
|
|
45
|
+
} = require('../lib/context-gatherer');
|
|
39
46
|
|
|
40
47
|
// Journal & config utilities (canonical modules)
|
|
41
48
|
const { getLogPath, ensureLogDirectory, createLogFile } = require('../lib/file-ops');
|
|
@@ -107,6 +114,41 @@ if (!skipUpdateCheck && (!updateCommand || (updateCommand && !['version', 'updat
|
|
|
107
114
|
let command = process.argv[2];
|
|
108
115
|
const commandArgs = process.argv.slice(3);
|
|
109
116
|
const firstCommandArg = process.argv[3];
|
|
117
|
+
const RUNNER_FLAG_NAMES = ['--runner-bin', '--runner-template', '--runner-model', '--runner-profile'];
|
|
118
|
+
|
|
119
|
+
function readOptionArg(args, name) {
|
|
120
|
+
const prefix = `${name}=`;
|
|
121
|
+
const inline = args.find((arg) => arg.startsWith(prefix));
|
|
122
|
+
if (inline) return inline.slice(prefix.length);
|
|
123
|
+
const index = args.indexOf(name);
|
|
124
|
+
if (index !== -1 && index < args.length - 1 && !String(args[index + 1]).startsWith('--')) return args[index + 1];
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function isOptionValue(args, index, optionNames) {
|
|
129
|
+
return index > 0 && optionNames.includes(args[index - 1]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function applyRunnerFlags(args) {
|
|
133
|
+
const runnerProfile = readOptionArg(args, '--runner-profile');
|
|
134
|
+
if (runnerProfile) process.env.ATRIS_RUNNER_PROFILE = runnerProfile;
|
|
135
|
+
const runnerBin = readOptionArg(args, '--runner-bin');
|
|
136
|
+
if (runnerBin) {
|
|
137
|
+
process.env.ATRIS_RUNNER_BIN = runnerBin;
|
|
138
|
+
process.env.ATRIS_CLAUDE_BIN = runnerBin;
|
|
139
|
+
}
|
|
140
|
+
const runnerTemplate = readOptionArg(args, '--runner-template');
|
|
141
|
+
if (runnerTemplate) {
|
|
142
|
+
process.env.ATRIS_RUNNER_COMMAND_TEMPLATE = runnerTemplate;
|
|
143
|
+
process.env.ATRIS_CLAUDE_COMMAND_TEMPLATE = runnerTemplate;
|
|
144
|
+
}
|
|
145
|
+
const runnerModel = readOptionArg(args, '--runner-model');
|
|
146
|
+
if (runnerModel) {
|
|
147
|
+
process.env.ATRIS_RUNNER_MODEL = runnerModel;
|
|
148
|
+
process.env.ATRIS_CLAUDE_MODEL = runnerModel;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
110
152
|
const isBusinessSyncSafetyCommand = command === 'sync'
|
|
111
153
|
&& (
|
|
112
154
|
commandArgs.includes('--status')
|
|
@@ -319,7 +361,15 @@ function showHelp() {
|
|
|
319
361
|
console.log(' plan - Create build spec with visualization');
|
|
320
362
|
console.log(' do - Execute tasks');
|
|
321
363
|
console.log(' review - Validate work (tests, safety checks, docs)');
|
|
364
|
+
console.log(' slop - Detect frontend AI-slop tells (deterministic, exit 1 = found)');
|
|
365
|
+
console.log(' deck - Generate a premium Google Slides deck from a content spec');
|
|
366
|
+
console.log(' site - Build a beautiful static site from a folder of markdown');
|
|
367
|
+
console.log(' theme - Brand themes: "theme create" builds your own by feel (deck/html/site)');
|
|
322
368
|
console.log(' run - Auto-chain plan→do→review (autonomous loop, auto-pushes)');
|
|
369
|
+
console.log(' run logs - Browse glass run logs (phase reasoning persisted to disk)');
|
|
370
|
+
console.log(' run search - Search phase reasoning across all run logs');
|
|
371
|
+
console.log(' pulse - Durable overnight self-improvement heartbeat (OS cron, install/status/tick)');
|
|
372
|
+
console.log(' spaceship - Bounded overnight runner that survives bad ticks and emails updates');
|
|
323
373
|
console.log('');
|
|
324
374
|
console.log('Context & tracking:');
|
|
325
375
|
console.log(' log - Add ideas to inbox');
|
|
@@ -328,7 +378,7 @@ function showHelp() {
|
|
|
328
378
|
console.log(' radar - Show live agents joined with tasks, missions, and worktrees');
|
|
329
379
|
console.log(' ctop - Show a process-first live agent CPU/memory view');
|
|
330
380
|
console.log(' status - See local work and completions (`atris status <business>` for remote)');
|
|
331
|
-
console.log(' recap - What your AI team did, in plain English (--share for
|
|
381
|
+
console.log(' recap - What your AI team did, in plain English (--share, or --html for a memory page)');
|
|
332
382
|
console.log(' xp - Show Career XP and contribution graph');
|
|
333
383
|
console.log(' analytics - Show recent productivity from journals');
|
|
334
384
|
console.log(' search - Search journal history (atris search <keyword>)');
|
|
@@ -351,6 +401,7 @@ function showHelp() {
|
|
|
351
401
|
console.log(' improve - Run one paid RL tick (POST /api/improve, deducts credits)');
|
|
352
402
|
console.log(' worktree - Isolated Git worktrees plus guarded ship/merge for parallel agents');
|
|
353
403
|
console.log(' visualize - Generate a Slack/deck-ready visual from a prompt');
|
|
404
|
+
console.log(' youtube - Process YouTube videos with Gemini native video analysis');
|
|
354
405
|
console.log('');
|
|
355
406
|
console.log('Experiments:');
|
|
356
407
|
console.log(' experiments init [slug] - Prepare atris/experiments/ or scaffold a pack');
|
|
@@ -407,8 +458,9 @@ function showHelp() {
|
|
|
407
458
|
console.log(' console - Start/attach always-on coding console (tmux daemon)');
|
|
408
459
|
console.log(' soul - Show, snapshot, or fork workspace identity');
|
|
409
460
|
console.log(' fleet - Inspect local fleet status');
|
|
410
|
-
console.log(' agent - Select cloud agent, or run `agent doctor`
|
|
411
|
-
console.log(' chat - Chat with the selected Atris agent');
|
|
461
|
+
console.log(' agent - Select cloud agent, spawn worker requests, or run `agent doctor`');
|
|
462
|
+
console.log(' chat - Chat with the selected Atris agent (or: atris chat scan)');
|
|
463
|
+
console.log(' fast - Chat with Atris2 Fast');
|
|
412
464
|
console.log(' login - Sign in or add another account');
|
|
413
465
|
console.log(' logout - Sign out of current account');
|
|
414
466
|
console.log(' whoami - Show active account');
|
|
@@ -733,8 +785,12 @@ function showAutopilotHelp() {
|
|
|
733
785
|
console.log(' --auto Execute without waiting for approval');
|
|
734
786
|
console.log(' --duration=TIME Run for a time limit (e.g. 1h, 30m, 90m)');
|
|
735
787
|
console.log(' --iterations=N Max tasks before stopping');
|
|
736
|
-
console.log(' --verbose, -v Show detailed
|
|
788
|
+
console.log(' --verbose, -v Show detailed runner output');
|
|
737
789
|
console.log(' --dry-run Show suggestions without executing');
|
|
790
|
+
console.log(' --runner-bin PATH Runner binary for this run');
|
|
791
|
+
console.log(' --runner-template CMD Runner command template for this run');
|
|
792
|
+
console.log(' --runner-model MODEL Runner model for this run');
|
|
793
|
+
console.log(' --runner-profile NAME Runner profile for this run (e.g. atris-fast)');
|
|
738
794
|
console.log('');
|
|
739
795
|
console.log('Examples:');
|
|
740
796
|
console.log(' atris autopilot # Suggest from existing work');
|
|
@@ -772,11 +828,11 @@ if (command === '2' && ['fast', 'pro'].includes(String(firstCommandArg || '').to
|
|
|
772
828
|
|
|
773
829
|
// Check if this is a known command or natural language input
|
|
774
830
|
const knownCommands = ['init', 'log', 'now', 'radar', 'ctop', 'status', 'analytics', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', 'plan', 'do', 'review', 'release',
|
|
775
|
-
'activate', '_activate', 'agent', 'chat', 'console', 'serve', 'login', 'logout', 'whoami', 'switch', 'use', 'accounts', '_resolve', '_profile-email', '_switch-session', 'shell-init', 'update', 'upgrade', 'version', 'help', 'next', 'atris',
|
|
776
|
-
'clean', 'verify', 'search', 'skill', 'member', 'codex-goal', 'app', 'apps', 'learn', 'lesson', 'plugin', 'experiments', 'receipt', 'proof', 'openclaw', 'pull', 'push', 'live', 'align', 'terminal', 'computer', 'diff', 'business', 'sync',
|
|
777
|
-
'ingest', 'query', 'lint', 'loop', 'task', 'mission', 'probe', 'worktree', 'aeo', 'improve', 'xp', 'play', 'gm', 'x', 'recap',
|
|
831
|
+
'activate', '_activate', 'agent', 'chat', 'fast', 'ax', 'console', 'serve', 'login', 'logout', 'whoami', 'switch', 'use', 'accounts', '_resolve', '_profile-email', '_switch-session', 'shell-init', 'update', 'upgrade', 'version', 'help', 'next', 'atris',
|
|
832
|
+
'clean', 'verify', 'search', 'skill', 'member', 'codex-goal', 'app', 'apps', 'learn', 'lesson', 'plugin', 'experiments', 'receipt', 'proof', 'openclaw', 'pull', 'push', 'live', 'align', 'terminal', 'computer', 'diff', 'business', 'sync', 'youtube',
|
|
833
|
+
'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'probe', 'worktree', 'aeo', 'slop', 'deck', 'site', 'theme', 'improve', 'xp', 'play', 'gm', 'x', 'recap',
|
|
778
834
|
'gmail', 'calendar', 'twitter', 'slack', 'imessage', 'integrations', 'setup', 'clean-workspace', 'cw',
|
|
779
|
-
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'compile'];
|
|
835
|
+
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'compile', 'spaceship'];
|
|
780
836
|
|
|
781
837
|
// Check if command is an atris.md spec file - triggers welcome visualization
|
|
782
838
|
function isSpecFile(cmd) {
|
|
@@ -865,11 +921,24 @@ if (!command || !knownCommands.includes(command)) {
|
|
|
865
921
|
return;
|
|
866
922
|
}
|
|
867
923
|
|
|
924
|
+
function printAtrisOverview() {
|
|
925
|
+
console.log('');
|
|
926
|
+
console.log('Atris is an AI computer for a workspace.');
|
|
927
|
+
console.log('It keeps project context, tasks, memory, tools, and proof in one loop: plan -> do -> review.');
|
|
928
|
+
console.log('Run `atris` to load the current workspace, or `atris help` to see commands.');
|
|
929
|
+
console.log('');
|
|
930
|
+
}
|
|
931
|
+
|
|
868
932
|
async function interactiveEntry(userInput) {
|
|
869
933
|
const workspaceDir = process.cwd();
|
|
870
934
|
const state = detectWorkspaceState(workspaceDir);
|
|
871
935
|
const context = loadContext(workspaceDir);
|
|
872
936
|
|
|
937
|
+
if (isAtrisMetaQuestion(userInput)) {
|
|
938
|
+
printAtrisOverview();
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
|
|
873
942
|
// Fresh install - offer init
|
|
874
943
|
if (state.state === 'fresh') {
|
|
875
944
|
console.log('\nNo atris/ folder found. Run: atris init');
|
|
@@ -935,28 +1004,46 @@ async function interactiveEntry(userInput) {
|
|
|
935
1004
|
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
936
1005
|
|
|
937
1006
|
const mapStatus = context.mapStatus || (context.mapExists ? 'ready' : 'missing');
|
|
938
|
-
if (
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
console.log(`- atris ${userInput}`);
|
|
954
|
-
} else {
|
|
1007
|
+
if (shouldGatherContext({
|
|
1008
|
+
root: workspaceDir,
|
|
1009
|
+
userInput,
|
|
1010
|
+
mapStatus,
|
|
1011
|
+
liveMissionsCount,
|
|
1012
|
+
wipCount,
|
|
1013
|
+
backlogCount,
|
|
1014
|
+
inboxCount,
|
|
1015
|
+
})) {
|
|
1016
|
+
const answer = String(userInput || '').trim() || await askContextGatherer(workspaceDir);
|
|
1017
|
+
if (isAtrisMetaQuestion(answer)) {
|
|
1018
|
+
printAtrisOverview();
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
if (!answer.trim()) {
|
|
955
1022
|
console.log('');
|
|
956
|
-
console.log('
|
|
1023
|
+
console.log('No problem. When you are ready, answer in normal words.');
|
|
1024
|
+
console.log('Example: "help me organize college applications" or "help me build a small website".');
|
|
1025
|
+
return;
|
|
957
1026
|
}
|
|
958
|
-
|
|
1027
|
+
const profile = saveContextProfile(workspaceDir, answer, { source: userInput ? 'hot_start' : 'cold_start' });
|
|
1028
|
+
const starter = createStarterTask(workspaceDir, answer);
|
|
959
1029
|
console.log('');
|
|
1030
|
+
console.log('Got it. I saved your first direction.');
|
|
1031
|
+
console.log(`Focus: ${profile.first_answer}`);
|
|
1032
|
+
if (starter && starter.display_id) {
|
|
1033
|
+
console.log(`First task: ${starter.display_id} — ${starter.title}`);
|
|
1034
|
+
} else if (starter && starter.title) {
|
|
1035
|
+
console.log(`First task: ${starter.title}`);
|
|
1036
|
+
}
|
|
1037
|
+
if (mapStatus !== 'ready') {
|
|
1038
|
+
printMapBootstrap({ userInput: answer, prefix: 'Next setup step' });
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
await planCmd(answer);
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
if (mapStatus !== 'ready') {
|
|
1046
|
+
printMapBootstrap({ userInput });
|
|
960
1047
|
return;
|
|
961
1048
|
}
|
|
962
1049
|
|
|
@@ -1047,9 +1134,45 @@ async function interactiveEntry(userInput) {
|
|
|
1047
1134
|
await planCmd(request);
|
|
1048
1135
|
}
|
|
1049
1136
|
|
|
1137
|
+
async function askContextGatherer(workspaceDir) {
|
|
1138
|
+
console.log(renderContextGathererPrompt({ projectName: path.basename(workspaceDir) }));
|
|
1139
|
+
const rl = readline.createInterface({
|
|
1140
|
+
input: process.stdin,
|
|
1141
|
+
output: process.stdout
|
|
1142
|
+
});
|
|
1143
|
+
const answer = await new Promise(r => rl.question('> ', r));
|
|
1144
|
+
rl.close();
|
|
1145
|
+
return answer;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
function printMapBootstrap({ userInput, prefix = 'Bootstrap required' } = {}) {
|
|
1149
|
+
console.log('');
|
|
1150
|
+
console.log('┌─────────────────────────────────────────────────────────────┐');
|
|
1151
|
+
console.log(`│ ${String(prefix).toUpperCase().padEnd(60)}│`);
|
|
1152
|
+
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
1153
|
+
console.log('');
|
|
1154
|
+
console.log('Atris needs a real `atris/MAP.md` so future steps are grounded in the workspace.');
|
|
1155
|
+
console.log('');
|
|
1156
|
+
console.log('For an agent:');
|
|
1157
|
+
console.log('─────────────────────────────────────────────────────────────');
|
|
1158
|
+
console.log('Read `atris/atris.md`, then generate a complete `atris/MAP.md` for this repo.');
|
|
1159
|
+
console.log('Rules: include file:line refs, keep it grep-friendly, do NOT change code.');
|
|
1160
|
+
if (userInput) {
|
|
1161
|
+
console.log('');
|
|
1162
|
+
console.log('After MAP is generated, continue with:');
|
|
1163
|
+
console.log(`- ${userInput}`);
|
|
1164
|
+
} else {
|
|
1165
|
+
console.log('');
|
|
1166
|
+
console.log('Then rerun: atris');
|
|
1167
|
+
}
|
|
1168
|
+
console.log('─────────────────────────────────────────────────────────────');
|
|
1169
|
+
console.log('');
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1050
1172
|
// ASCII Welcome Visualization
|
|
1051
1173
|
function showWelcomeVisualization() {
|
|
1052
1174
|
const { getTaskCounts } = require('../lib/state-detection');
|
|
1175
|
+
const { readEndgameState } = require('../commands/autopilot');
|
|
1053
1176
|
const cwd = process.cwd();
|
|
1054
1177
|
const atrisDir = path.join(cwd, 'atris');
|
|
1055
1178
|
const projectName = path.basename(cwd);
|
|
@@ -1063,6 +1186,7 @@ function showWelcomeVisualization() {
|
|
|
1063
1186
|
let journalEntries = 0;
|
|
1064
1187
|
let hasMap = false;
|
|
1065
1188
|
let isInitialized = fs.existsSync(atrisDir);
|
|
1189
|
+
let endgameState = { slug: 'unset', horizon: '' };
|
|
1066
1190
|
|
|
1067
1191
|
if (isInitialized) {
|
|
1068
1192
|
// Check MAP.md
|
|
@@ -1086,6 +1210,13 @@ function showWelcomeVisualization() {
|
|
|
1086
1210
|
// Silently fail - show 0 tasks if reading fails
|
|
1087
1211
|
}
|
|
1088
1212
|
|
|
1213
|
+
// Read endgame state
|
|
1214
|
+
try {
|
|
1215
|
+
endgameState = readEndgameState(cwd);
|
|
1216
|
+
} catch {
|
|
1217
|
+
// Silently fail - show unset if reading fails
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1089
1220
|
// Count journal entries today
|
|
1090
1221
|
const today = new Date();
|
|
1091
1222
|
const year = today.getFullYear();
|
|
@@ -1139,6 +1270,11 @@ function showWelcomeVisualization() {
|
|
|
1139
1270
|
console.log(` │ ⏳ Review: ${reviewText.padEnd(26)}│`);
|
|
1140
1271
|
}
|
|
1141
1272
|
console.log(` │ 📝 Journal: ${(journalEntries + ' entries today').padEnd(26)}│`);
|
|
1273
|
+
if (endgameState.slug !== 'unset' && endgameState.horizon) {
|
|
1274
|
+
const endgameLine = endgameState.slug + ' — ' + endgameState.horizon;
|
|
1275
|
+
const paddedEndgame = endgameLine.padEnd(26);
|
|
1276
|
+
console.log(` │ 🎯 Endgame: ${paddedEndgame}│`);
|
|
1277
|
+
}
|
|
1142
1278
|
console.log(' │ │');
|
|
1143
1279
|
console.log(' │ ┌──────────────────────────────────┐ │');
|
|
1144
1280
|
console.log(' │ │ MAP.md ←──── YOU ARE HERE │ │');
|
|
@@ -1185,6 +1321,11 @@ if (command === 'init') {
|
|
|
1185
1321
|
Promise.resolve(require('../commands/mission').missionCommand(process.argv.slice(3)))
|
|
1186
1322
|
.then(() => process.exit(0))
|
|
1187
1323
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1324
|
+
} else if (command === 'pulse') {
|
|
1325
|
+
// Pulse: durable overnight self-improvement heartbeat (OS cron) for atris-cli.
|
|
1326
|
+
Promise.resolve(require('../commands/pulse').pulseCommand(process.argv.slice(3)))
|
|
1327
|
+
.then((res) => process.exit(res && res.ok === false ? 1 : 0))
|
|
1328
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1188
1329
|
} else if (command === 'probe') {
|
|
1189
1330
|
// Chat-lane probe (TRR-22): one real /atris2/turn over the full tool relay.
|
|
1190
1331
|
Promise.resolve(require('../commands/probe').probeCommand(process.argv.slice(3)))
|
|
@@ -1203,6 +1344,26 @@ if (command === 'init') {
|
|
|
1203
1344
|
Promise.resolve(require('../commands/codex-goal').codexGoalCommand(process.argv.slice(3)))
|
|
1204
1345
|
.then(() => process.exit(process.exitCode || 0))
|
|
1205
1346
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1347
|
+
} else if (command === 'slop') {
|
|
1348
|
+
// Slop: deterministic frontend-slop detector (no LLM). Exit 1 = slop found, for CI + the autopilot gate.
|
|
1349
|
+
Promise.resolve(require('../commands/slop').slopCommand(process.argv.slice(3)))
|
|
1350
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1351
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1352
|
+
} else if (command === 'deck') {
|
|
1353
|
+
// Deck: premium Google Slides from a plain content spec, via the Atris deck engine (anti-slop design system).
|
|
1354
|
+
Promise.resolve(require('../commands/deck').run(process.argv.slice(3)))
|
|
1355
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1356
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1357
|
+
} else if (command === 'site') {
|
|
1358
|
+
// Site: beautiful static site from a folder of markdown, in the anti-slop design system.
|
|
1359
|
+
Promise.resolve(require('../commands/site').run(process.argv.slice(3)))
|
|
1360
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1361
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1362
|
+
} else if (command === 'theme') {
|
|
1363
|
+
// Theme: brand themes (.atris/theme.json) for the whole design system (deck/html/site).
|
|
1364
|
+
Promise.resolve(require('../commands/theme').run(process.argv.slice(3)))
|
|
1365
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1366
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1206
1367
|
} else if (command === 'aeo') {
|
|
1207
1368
|
// AEO: AI Engine Optimization — credit-metered citation drafting against the customer workspace.
|
|
1208
1369
|
Promise.resolve(require('../commands/aeo').run(process.argv.slice(3)))
|
|
@@ -1303,12 +1464,28 @@ if (command === 'init') {
|
|
|
1303
1464
|
}
|
|
1304
1465
|
upgradeAtris().then(() => process.exit(0)).catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1305
1466
|
} else if (command === 'chat') {
|
|
1467
|
+
if (process.argv[3] === 'scan') {
|
|
1468
|
+
try {
|
|
1469
|
+
require('../commands/chat-scan').chatScanCommand(process.argv.slice(4));
|
|
1470
|
+
process.exit(0);
|
|
1471
|
+
} catch (error) {
|
|
1472
|
+
console.error(`✗ Chat scan failed: ${error.message || error}`);
|
|
1473
|
+
process.exit(1);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1306
1476
|
chatAtris()
|
|
1307
1477
|
.then(() => process.exit(0))
|
|
1308
1478
|
.catch((error) => {
|
|
1309
1479
|
console.error(`✗ Chat failed: ${error.message || error}`);
|
|
1310
1480
|
process.exit(1);
|
|
1311
1481
|
});
|
|
1482
|
+
} else if (command === 'fast' || (command === 'ax' && process.argv[3] === 'fast')) {
|
|
1483
|
+
atrisFastChat()
|
|
1484
|
+
.then(() => process.exit(0))
|
|
1485
|
+
.catch((error) => {
|
|
1486
|
+
console.error(`✗ Fast chat failed: ${error.message || error}`);
|
|
1487
|
+
process.exit(1);
|
|
1488
|
+
});
|
|
1312
1489
|
} else if (command === 'console') {
|
|
1313
1490
|
consoleCmd();
|
|
1314
1491
|
} else if (command === 'serve') {
|
|
@@ -1395,8 +1572,116 @@ if (command === 'init') {
|
|
|
1395
1572
|
require('../commands/visualize').visualizeAtris(process.argv.slice(3))
|
|
1396
1573
|
.then(() => process.exit(0))
|
|
1397
1574
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1575
|
+
} else if (command === 'youtube') {
|
|
1576
|
+
require('../commands/youtube').youtubeCommand(process.argv.slice(3))
|
|
1577
|
+
.then(() => process.exit(0))
|
|
1578
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1398
1579
|
} else if (command === 'run') {
|
|
1399
1580
|
const args = process.argv.slice(3);
|
|
1581
|
+
if (args[0] === 'logs') {
|
|
1582
|
+
// Subcommand: atris run logs [--tail N] [--cat FILE] [--json]
|
|
1583
|
+
const { listRunLogs } = require('../commands/run');
|
|
1584
|
+
const logsArgs = args.slice(1);
|
|
1585
|
+
if (logsArgs.includes('--help') || logsArgs.includes('-h')) {
|
|
1586
|
+
console.log('');
|
|
1587
|
+
console.log('Usage: atris run logs [options]');
|
|
1588
|
+
console.log('');
|
|
1589
|
+
console.log('List and read glass run logs from atris/logs/runs/.');
|
|
1590
|
+
console.log('');
|
|
1591
|
+
console.log('Options:');
|
|
1592
|
+
console.log(' --tail N Show last N lines of each log (default: 5)');
|
|
1593
|
+
console.log(' --cat FILE Print full contents of a specific log file');
|
|
1594
|
+
console.log(' --json Output machine-readable JSON');
|
|
1595
|
+
console.log(' --help Show this help');
|
|
1596
|
+
console.log('');
|
|
1597
|
+
process.exit(0);
|
|
1598
|
+
}
|
|
1599
|
+
listRunLogs(logsArgs);
|
|
1600
|
+
process.exit(0);
|
|
1601
|
+
}
|
|
1602
|
+
if (args[0] === 'prune-logs') {
|
|
1603
|
+
// Subcommand: atris run prune-logs [--keep N] [--dry-run]
|
|
1604
|
+
const { pruneRunLogs } = require('../commands/run');
|
|
1605
|
+
const pruneArgs = args.slice(1);
|
|
1606
|
+
if (pruneArgs.includes('--help') || pruneArgs.includes('-h')) {
|
|
1607
|
+
console.log('');
|
|
1608
|
+
console.log('Usage: atris run prune-logs [options]');
|
|
1609
|
+
console.log('');
|
|
1610
|
+
console.log('Prune old run logs, keeping only the most recent N files.');
|
|
1611
|
+
console.log('');
|
|
1612
|
+
console.log('Options:');
|
|
1613
|
+
console.log(' --keep N Number of recent logs to keep (default: 50)');
|
|
1614
|
+
console.log(' --dry-run Show what would be deleted without deleting');
|
|
1615
|
+
console.log(' --help Show this help');
|
|
1616
|
+
console.log('');
|
|
1617
|
+
process.exit(0);
|
|
1618
|
+
}
|
|
1619
|
+
pruneRunLogs(pruneArgs);
|
|
1620
|
+
process.exit(0);
|
|
1621
|
+
}
|
|
1622
|
+
if (args[0] === 'search') {
|
|
1623
|
+
// Subcommand: atris run search <keyword> [--phase P] [--limit N]
|
|
1624
|
+
const { searchRunLogs } = require('../commands/run');
|
|
1625
|
+
const searchArgs = args.slice(1);
|
|
1626
|
+
if (searchArgs.includes('--help') || searchArgs.includes('-h') || searchArgs.length === 0) {
|
|
1627
|
+
console.log('');
|
|
1628
|
+
console.log('Usage: atris run search <keyword> [options]');
|
|
1629
|
+
console.log('');
|
|
1630
|
+
console.log('Search phase reasoning across all run logs.');
|
|
1631
|
+
console.log('');
|
|
1632
|
+
console.log('Options:');
|
|
1633
|
+
console.log(' --phase P Limit search to a phase (plan, do, review, error)');
|
|
1634
|
+
console.log(' --limit N Max results to show (default: 20)');
|
|
1635
|
+
console.log(' --help Show this help');
|
|
1636
|
+
console.log('');
|
|
1637
|
+
process.exit(0);
|
|
1638
|
+
}
|
|
1639
|
+
searchRunLogs(searchArgs);
|
|
1640
|
+
process.exit(0);
|
|
1641
|
+
}
|
|
1642
|
+
if (args[0] === 'stats') {
|
|
1643
|
+
// Subcommand: atris run stats
|
|
1644
|
+
const { statsRunLogs } = require('../commands/run');
|
|
1645
|
+
statsRunLogs();
|
|
1646
|
+
process.exit(0);
|
|
1647
|
+
}
|
|
1648
|
+
if (args[0] === 'export') {
|
|
1649
|
+
// Subcommand: atris run export [--out FILE]
|
|
1650
|
+
const { exportRunLogs } = require('../commands/run');
|
|
1651
|
+
const exportArgs = args.slice(1);
|
|
1652
|
+
if (exportArgs.includes('--help') || exportArgs.includes('-h')) {
|
|
1653
|
+
console.log('');
|
|
1654
|
+
console.log('Usage: atris run export [options]');
|
|
1655
|
+
console.log('');
|
|
1656
|
+
console.log('Export all run logs as a JSON bundle for backup or transfer.');
|
|
1657
|
+
console.log('');
|
|
1658
|
+
console.log('Options:');
|
|
1659
|
+
console.log(' --out FILE Write to a specific file (default: atris/logs/runs/export.json)');
|
|
1660
|
+
console.log(' --help Show this help');
|
|
1661
|
+
console.log('');
|
|
1662
|
+
process.exit(0);
|
|
1663
|
+
}
|
|
1664
|
+
exportRunLogs(exportArgs);
|
|
1665
|
+
process.exit(0);
|
|
1666
|
+
}
|
|
1667
|
+
if (args[0] === 'diff') {
|
|
1668
|
+
// Subcommand: atris run diff <file1> <file2>
|
|
1669
|
+
const { diffRunLogs } = require('../commands/run');
|
|
1670
|
+
const diffArgs = args.slice(1);
|
|
1671
|
+
if (diffArgs.includes('--help') || diffArgs.includes('-h') || diffArgs.length === 0) {
|
|
1672
|
+
console.log('');
|
|
1673
|
+
console.log('Usage: atris run diff <file1> <file2>');
|
|
1674
|
+
console.log('');
|
|
1675
|
+
console.log('Compare two run logs side by side, showing phase-level differences.');
|
|
1676
|
+
console.log('');
|
|
1677
|
+
console.log('Options:');
|
|
1678
|
+
console.log(' --help Show this help');
|
|
1679
|
+
console.log('');
|
|
1680
|
+
process.exit(0);
|
|
1681
|
+
}
|
|
1682
|
+
diffRunLogs(diffArgs);
|
|
1683
|
+
process.exit(0);
|
|
1684
|
+
}
|
|
1400
1685
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
1401
1686
|
console.log('');
|
|
1402
1687
|
console.log('Usage: atris run [options]');
|
|
@@ -1407,12 +1692,24 @@ if (command === 'init') {
|
|
|
1407
1692
|
console.log('Options:');
|
|
1408
1693
|
console.log(' --cycles=N Max cycles (default: 5)');
|
|
1409
1694
|
console.log(' --once Single plan→do→review cycle');
|
|
1410
|
-
console.log(' --verbose Show
|
|
1695
|
+
console.log(' --verbose Show configured runner output');
|
|
1411
1696
|
console.log(' --dry-run Preview without executing');
|
|
1412
1697
|
console.log(' --timeout=N Phase timeout in seconds (default: 600)');
|
|
1698
|
+
console.log(' --runner-bin PATH Runner binary for this run');
|
|
1699
|
+
console.log(' --runner-template CMD Runner command template for this run');
|
|
1700
|
+
console.log(' --runner-model MODEL Runner model for this run');
|
|
1701
|
+
console.log(' --runner-profile NAME Runner profile for this run (e.g. atris-fast)');
|
|
1413
1702
|
console.log(' --push Auto-push after each cycle (default: true)');
|
|
1414
1703
|
console.log(' --no-push Skip auto-push after each cycle');
|
|
1415
1704
|
console.log('');
|
|
1705
|
+
console.log('Subcommands:');
|
|
1706
|
+
console.log(' atris run logs [--tail N] [--cat FILE] [--json] Browse glass run logs');
|
|
1707
|
+
console.log(' atris run prune-logs [--keep N] [--dry-run] Prune old run logs');
|
|
1708
|
+
console.log(' atris run search <keyword> [--phase P] [--limit N] Search run logs');
|
|
1709
|
+
console.log(' atris run stats Show run log stats');
|
|
1710
|
+
console.log(' atris run export [--out FILE] Export logs as JSON');
|
|
1711
|
+
console.log(' atris run diff <file1> <file2> Compare two run logs');
|
|
1712
|
+
console.log('');
|
|
1416
1713
|
process.exit(0);
|
|
1417
1714
|
}
|
|
1418
1715
|
|
|
@@ -1420,6 +1717,7 @@ if (command === 'init') {
|
|
|
1420
1717
|
const dryRun = args.includes('--dry-run');
|
|
1421
1718
|
const once = args.includes('--once');
|
|
1422
1719
|
const push = !args.includes('--no-push');
|
|
1720
|
+
applyRunnerFlags(args);
|
|
1423
1721
|
const cyclesArg = args.find(a => a.startsWith('--cycles='));
|
|
1424
1722
|
const maxCycles = cyclesArg ? parseInt(cyclesArg.split('=')[1]) : 5;
|
|
1425
1723
|
const timeoutArg = args.find(a => a.startsWith('--timeout='));
|
|
@@ -1442,13 +1740,14 @@ if (command === 'init') {
|
|
|
1442
1740
|
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
1443
1741
|
const dryRun = args.includes('--dry-run');
|
|
1444
1742
|
const auto = args.includes('--auto');
|
|
1743
|
+
applyRunnerFlags(args);
|
|
1445
1744
|
const maxIterationsArg = args.find(a => a.startsWith('--iterations='));
|
|
1446
1745
|
const maxIterations = maxIterationsArg ? parseInt(maxIterationsArg.split('=')[1]) : undefined;
|
|
1447
1746
|
const durationArg = args.find(a => a.startsWith('--duration='));
|
|
1448
1747
|
const duration = durationArg ? durationArg.split('=')[1] : null;
|
|
1449
1748
|
|
|
1450
1749
|
// Get description (non-flag args)
|
|
1451
|
-
const description = args.filter(a => !a.startsWith('-')).join(' ').trim() || null;
|
|
1750
|
+
const description = args.filter((a, i) => !a.startsWith('-') && !isOptionValue(args, i, RUNNER_FLAG_NAMES)).join(' ').trim() || null;
|
|
1452
1751
|
|
|
1453
1752
|
const options = {
|
|
1454
1753
|
...(maxIterations !== undefined && { maxIterations }),
|
|
@@ -1737,6 +2036,11 @@ if (command === 'init') {
|
|
|
1737
2036
|
require('../commands/fleet').fleet(args)
|
|
1738
2037
|
.then(() => process.exit(0))
|
|
1739
2038
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2039
|
+
} else if (command === 'spaceship') {
|
|
2040
|
+
const args = process.argv.slice(3);
|
|
2041
|
+
require('../commands/spaceship').spaceship(args)
|
|
2042
|
+
.then(() => process.exit(0))
|
|
2043
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1740
2044
|
} else if (command === 'code-review' || command === 'cr') {
|
|
1741
2045
|
const args = process.argv.slice(3);
|
|
1742
2046
|
require('../commands/review').reviewCommand(...args)
|
|
@@ -1949,7 +2253,7 @@ function inspectAgentCliWiring() {
|
|
|
1949
2253
|
},
|
|
1950
2254
|
];
|
|
1951
2255
|
|
|
1952
|
-
const binaries = ['atris', 'claude', 'codex', 'cursor-agent', 'devin'].map((name) => ({
|
|
2256
|
+
const binaries = ['atris', 'ax', 'claude', 'codex', 'cursor-agent', 'devin', 'droid'].map((name) => ({
|
|
1953
2257
|
name,
|
|
1954
2258
|
path: commandOnPath(name),
|
|
1955
2259
|
}));
|
|
@@ -1986,10 +2290,13 @@ async function agentAtris() {
|
|
|
1986
2290
|
// Respect -h / --help / help before any auth/state work
|
|
1987
2291
|
const firstArg = process.argv[3];
|
|
1988
2292
|
if (firstArg === '-h' || firstArg === '--help' || firstArg === 'help') {
|
|
1989
|
-
console.log('Usage: atris agent [doctor]');
|
|
2293
|
+
console.log('Usage: atris agent [doctor|dogfood|spawn|spawns|spawn-status]');
|
|
1990
2294
|
console.log('');
|
|
1991
2295
|
console.log(' Pick which cloud agent to chat with from this workspace.');
|
|
2296
|
+
console.log(' Run `atris agent spawn <role> --task "..."` to create a worker request.');
|
|
2297
|
+
console.log(' Run `atris agent spawns` to list worker requests.');
|
|
1992
2298
|
console.log(' Run `atris agent doctor` to verify local AI CLIs can see Atris context.');
|
|
2299
|
+
console.log(' Run `atris agent dogfood --live` to smoke-test Devin/Droid with GLM 5.2.');
|
|
1993
2300
|
console.log(' Requires `atris login` first.');
|
|
1994
2301
|
console.log('');
|
|
1995
2302
|
console.log(' After selecting, use: atris chat ["message"]');
|
|
@@ -1999,6 +2306,22 @@ async function agentAtris() {
|
|
|
1999
2306
|
if (firstArg === 'doctor') {
|
|
2000
2307
|
agentDoctor();
|
|
2001
2308
|
}
|
|
2309
|
+
if (firstArg === 'dogfood') {
|
|
2310
|
+
const result = require('../commands/agent-spawn').agentDogfoodCommand(process.argv.slice(4));
|
|
2311
|
+
process.exit(result.ok ? 0 : 1);
|
|
2312
|
+
}
|
|
2313
|
+
if (firstArg === 'spawn') {
|
|
2314
|
+
require('../commands/agent-spawn').agentSpawnCommand(process.argv.slice(4));
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2317
|
+
if (firstArg === 'spawns' || firstArg === 'spawn-list' || firstArg === 'list-spawns') {
|
|
2318
|
+
require('../commands/agent-spawn').agentSpawnListCommand(process.argv.slice(4));
|
|
2319
|
+
return;
|
|
2320
|
+
}
|
|
2321
|
+
if (firstArg === 'spawn-status' || firstArg === 'spawn-show') {
|
|
2322
|
+
require('../commands/agent-spawn').agentSpawnStatusCommand(process.argv.slice(4));
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2002
2325
|
|
|
2003
2326
|
const targetDir = path.join(process.cwd(), 'atris');
|
|
2004
2327
|
|
|
@@ -2242,6 +2565,65 @@ async function chatInteractive(config, credentials) {
|
|
|
2242
2565
|
});
|
|
2243
2566
|
}
|
|
2244
2567
|
|
|
2568
|
+
function atrisFastMessageFromArgs() {
|
|
2569
|
+
const offset = command === 'ax' ? 4 : 3;
|
|
2570
|
+
return process.argv.slice(offset).join(' ').trim();
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
async function atrisFastChat() {
|
|
2574
|
+
if (command === 'ax' && process.argv[3] !== 'fast') {
|
|
2575
|
+
console.error('Usage: atris ax fast "message"');
|
|
2576
|
+
process.exit(1);
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
const message = atrisFastMessageFromArgs();
|
|
2580
|
+
|
|
2581
|
+
if (message === '-h' || message === '--help' || message === 'help') {
|
|
2582
|
+
console.log('Usage: atris fast ["message"]');
|
|
2583
|
+
console.log('');
|
|
2584
|
+
console.log(' Chat with Atris2 Fast through /api/atris2/turn.');
|
|
2585
|
+
console.log(' Requires `atris login`.');
|
|
2586
|
+
console.log('');
|
|
2587
|
+
console.log(' atris fast "what now?" One-shot message');
|
|
2588
|
+
console.log(' atris ax fast "what now?" Alias');
|
|
2589
|
+
process.exit(0);
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
if (!message) {
|
|
2593
|
+
console.error('Usage: atris fast "message"');
|
|
2594
|
+
process.exit(1);
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
const ensured = await ensureValidCredentials();
|
|
2598
|
+
if (ensured.error === 'not_logged_in' || !ensured.credentials?.token) {
|
|
2599
|
+
console.error('✗ Error: Not logged in. Run "atris login" first.');
|
|
2600
|
+
process.exit(1);
|
|
2601
|
+
}
|
|
2602
|
+
if (ensured.error) {
|
|
2603
|
+
console.error(`✗ Error: Authentication failed: ${ensured.detail || ensured.error}. Run "atris login" to re-authenticate.`);
|
|
2604
|
+
process.exit(1);
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
const credentials = ensured.credentials;
|
|
2608
|
+
await atrisFastOnce(credentials, message);
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
async function atrisFastOnce(credentials, message) {
|
|
2612
|
+
console.log('\nAtris2 Fast');
|
|
2613
|
+
console.log('');
|
|
2614
|
+
|
|
2615
|
+
const apiUrl = getApiBaseUrl().replace(/\/api$/, '');
|
|
2616
|
+
const endpoint = `${apiUrl}/api/atris2/turn`;
|
|
2617
|
+
const body = JSON.stringify({
|
|
2618
|
+
message,
|
|
2619
|
+
model: 'atris:fast',
|
|
2620
|
+
max_turns: 1,
|
|
2621
|
+
});
|
|
2622
|
+
|
|
2623
|
+
await streamProChat(endpoint, credentials.token, body);
|
|
2624
|
+
console.log('\n\n✓ Complete\n');
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2245
2627
|
async function atrisDevEntry(userInput = null) {
|
|
2246
2628
|
// Load workspace context and present planning-ready state
|
|
2247
2629
|
// userInput: optional task description for hot start
|