atris 3.16.1 → 3.17.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 +400 -30
- 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 +135 -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 +55 -25
- package/commands/run.js +615 -22
- package/commands/slop.js +173 -0
- package/commands/spaceship.js +39 -0
- package/commands/sync.js +0 -2
- package/commands/task.js +429 -37
- 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/escape-regexp.js +13 -0
- package/lib/file-ops.js +6 -3
- package/lib/journal.js +1 -1
- package/lib/lesson-contradiction.js +113 -0
- package/lib/policy-lessons.js +3 -2
- package/lib/pulse.js +401 -0
- package/lib/runner-command.js +156 -0
- package/lib/slides-deck.js +236 -0
- package/lib/state-detection.js +1 -4
- package/lib/task-db.js +101 -4
- package/lib/task-proof.js +1 -1
- 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,13 @@ 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');
|
|
322
366
|
console.log(' run - Auto-chain plan→do→review (autonomous loop, auto-pushes)');
|
|
367
|
+
console.log(' run logs - Browse glass run logs (phase reasoning persisted to disk)');
|
|
368
|
+
console.log(' run search - Search phase reasoning across all run logs');
|
|
369
|
+
console.log(' pulse - Durable overnight self-improvement heartbeat (OS cron, install/status/tick)');
|
|
370
|
+
console.log(' spaceship - Bounded overnight runner that survives bad ticks and emails updates');
|
|
323
371
|
console.log('');
|
|
324
372
|
console.log('Context & tracking:');
|
|
325
373
|
console.log(' log - Add ideas to inbox');
|
|
@@ -351,6 +399,7 @@ function showHelp() {
|
|
|
351
399
|
console.log(' improve - Run one paid RL tick (POST /api/improve, deducts credits)');
|
|
352
400
|
console.log(' worktree - Isolated Git worktrees plus guarded ship/merge for parallel agents');
|
|
353
401
|
console.log(' visualize - Generate a Slack/deck-ready visual from a prompt');
|
|
402
|
+
console.log(' youtube - Process YouTube videos with Gemini native video analysis');
|
|
354
403
|
console.log('');
|
|
355
404
|
console.log('Experiments:');
|
|
356
405
|
console.log(' experiments init [slug] - Prepare atris/experiments/ or scaffold a pack');
|
|
@@ -407,8 +456,9 @@ function showHelp() {
|
|
|
407
456
|
console.log(' console - Start/attach always-on coding console (tmux daemon)');
|
|
408
457
|
console.log(' soul - Show, snapshot, or fork workspace identity');
|
|
409
458
|
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');
|
|
459
|
+
console.log(' agent - Select cloud agent, spawn worker requests, or run `agent doctor`');
|
|
460
|
+
console.log(' chat - Chat with the selected Atris agent (or: atris chat scan)');
|
|
461
|
+
console.log(' fast - Chat with Atris2 Fast');
|
|
412
462
|
console.log(' login - Sign in or add another account');
|
|
413
463
|
console.log(' logout - Sign out of current account');
|
|
414
464
|
console.log(' whoami - Show active account');
|
|
@@ -733,8 +783,12 @@ function showAutopilotHelp() {
|
|
|
733
783
|
console.log(' --auto Execute without waiting for approval');
|
|
734
784
|
console.log(' --duration=TIME Run for a time limit (e.g. 1h, 30m, 90m)');
|
|
735
785
|
console.log(' --iterations=N Max tasks before stopping');
|
|
736
|
-
console.log(' --verbose, -v Show detailed
|
|
786
|
+
console.log(' --verbose, -v Show detailed runner output');
|
|
737
787
|
console.log(' --dry-run Show suggestions without executing');
|
|
788
|
+
console.log(' --runner-bin PATH Runner binary for this run');
|
|
789
|
+
console.log(' --runner-template CMD Runner command template for this run');
|
|
790
|
+
console.log(' --runner-model MODEL Runner model for this run');
|
|
791
|
+
console.log(' --runner-profile NAME Runner profile for this run (e.g. atris-fast)');
|
|
738
792
|
console.log('');
|
|
739
793
|
console.log('Examples:');
|
|
740
794
|
console.log(' atris autopilot # Suggest from existing work');
|
|
@@ -772,11 +826,11 @@ if (command === '2' && ['fast', 'pro'].includes(String(firstCommandArg || '').to
|
|
|
772
826
|
|
|
773
827
|
// Check if this is a known command or natural language input
|
|
774
828
|
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',
|
|
829
|
+
'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',
|
|
830
|
+
'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',
|
|
831
|
+
'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'probe', 'worktree', 'aeo', 'slop', 'deck', 'improve', 'xp', 'play', 'gm', 'x', 'recap',
|
|
778
832
|
'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'];
|
|
833
|
+
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'compile', 'spaceship'];
|
|
780
834
|
|
|
781
835
|
// Check if command is an atris.md spec file - triggers welcome visualization
|
|
782
836
|
function isSpecFile(cmd) {
|
|
@@ -865,11 +919,24 @@ if (!command || !knownCommands.includes(command)) {
|
|
|
865
919
|
return;
|
|
866
920
|
}
|
|
867
921
|
|
|
922
|
+
function printAtrisOverview() {
|
|
923
|
+
console.log('');
|
|
924
|
+
console.log('Atris is an AI computer for a workspace.');
|
|
925
|
+
console.log('It keeps project context, tasks, memory, tools, and proof in one loop: plan -> do -> review.');
|
|
926
|
+
console.log('Run `atris` to load the current workspace, or `atris help` to see commands.');
|
|
927
|
+
console.log('');
|
|
928
|
+
}
|
|
929
|
+
|
|
868
930
|
async function interactiveEntry(userInput) {
|
|
869
931
|
const workspaceDir = process.cwd();
|
|
870
932
|
const state = detectWorkspaceState(workspaceDir);
|
|
871
933
|
const context = loadContext(workspaceDir);
|
|
872
934
|
|
|
935
|
+
if (isAtrisMetaQuestion(userInput)) {
|
|
936
|
+
printAtrisOverview();
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
|
|
873
940
|
// Fresh install - offer init
|
|
874
941
|
if (state.state === 'fresh') {
|
|
875
942
|
console.log('\nNo atris/ folder found. Run: atris init');
|
|
@@ -935,28 +1002,46 @@ async function interactiveEntry(userInput) {
|
|
|
935
1002
|
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
936
1003
|
|
|
937
1004
|
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 {
|
|
1005
|
+
if (shouldGatherContext({
|
|
1006
|
+
root: workspaceDir,
|
|
1007
|
+
userInput,
|
|
1008
|
+
mapStatus,
|
|
1009
|
+
liveMissionsCount,
|
|
1010
|
+
wipCount,
|
|
1011
|
+
backlogCount,
|
|
1012
|
+
inboxCount,
|
|
1013
|
+
})) {
|
|
1014
|
+
const answer = String(userInput || '').trim() || await askContextGatherer(workspaceDir);
|
|
1015
|
+
if (isAtrisMetaQuestion(answer)) {
|
|
1016
|
+
printAtrisOverview();
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
if (!answer.trim()) {
|
|
955
1020
|
console.log('');
|
|
956
|
-
console.log('
|
|
1021
|
+
console.log('No problem. When you are ready, answer in normal words.');
|
|
1022
|
+
console.log('Example: "help me organize college applications" or "help me build a small website".');
|
|
1023
|
+
return;
|
|
957
1024
|
}
|
|
958
|
-
|
|
1025
|
+
const profile = saveContextProfile(workspaceDir, answer, { source: userInput ? 'hot_start' : 'cold_start' });
|
|
1026
|
+
const starter = createStarterTask(workspaceDir, answer);
|
|
959
1027
|
console.log('');
|
|
1028
|
+
console.log('Got it. I saved your first direction.');
|
|
1029
|
+
console.log(`Focus: ${profile.first_answer}`);
|
|
1030
|
+
if (starter && starter.display_id) {
|
|
1031
|
+
console.log(`First task: ${starter.display_id} — ${starter.title}`);
|
|
1032
|
+
} else if (starter && starter.title) {
|
|
1033
|
+
console.log(`First task: ${starter.title}`);
|
|
1034
|
+
}
|
|
1035
|
+
if (mapStatus !== 'ready') {
|
|
1036
|
+
printMapBootstrap({ userInput: answer, prefix: 'Next setup step' });
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
await planCmd(answer);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
if (mapStatus !== 'ready') {
|
|
1044
|
+
printMapBootstrap({ userInput });
|
|
960
1045
|
return;
|
|
961
1046
|
}
|
|
962
1047
|
|
|
@@ -1047,9 +1132,45 @@ async function interactiveEntry(userInput) {
|
|
|
1047
1132
|
await planCmd(request);
|
|
1048
1133
|
}
|
|
1049
1134
|
|
|
1135
|
+
async function askContextGatherer(workspaceDir) {
|
|
1136
|
+
console.log(renderContextGathererPrompt({ projectName: path.basename(workspaceDir) }));
|
|
1137
|
+
const rl = readline.createInterface({
|
|
1138
|
+
input: process.stdin,
|
|
1139
|
+
output: process.stdout
|
|
1140
|
+
});
|
|
1141
|
+
const answer = await new Promise(r => rl.question('> ', r));
|
|
1142
|
+
rl.close();
|
|
1143
|
+
return answer;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
function printMapBootstrap({ userInput, prefix = 'Bootstrap required' } = {}) {
|
|
1147
|
+
console.log('');
|
|
1148
|
+
console.log('┌─────────────────────────────────────────────────────────────┐');
|
|
1149
|
+
console.log(`│ ${String(prefix).toUpperCase().padEnd(60)}│`);
|
|
1150
|
+
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
1151
|
+
console.log('');
|
|
1152
|
+
console.log('Atris needs a real `atris/MAP.md` so future steps are grounded in the workspace.');
|
|
1153
|
+
console.log('');
|
|
1154
|
+
console.log('For an agent:');
|
|
1155
|
+
console.log('─────────────────────────────────────────────────────────────');
|
|
1156
|
+
console.log('Read `atris/atris.md`, then generate a complete `atris/MAP.md` for this repo.');
|
|
1157
|
+
console.log('Rules: include file:line refs, keep it grep-friendly, do NOT change code.');
|
|
1158
|
+
if (userInput) {
|
|
1159
|
+
console.log('');
|
|
1160
|
+
console.log('After MAP is generated, continue with:');
|
|
1161
|
+
console.log(`- ${userInput}`);
|
|
1162
|
+
} else {
|
|
1163
|
+
console.log('');
|
|
1164
|
+
console.log('Then rerun: atris');
|
|
1165
|
+
}
|
|
1166
|
+
console.log('─────────────────────────────────────────────────────────────');
|
|
1167
|
+
console.log('');
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1050
1170
|
// ASCII Welcome Visualization
|
|
1051
1171
|
function showWelcomeVisualization() {
|
|
1052
1172
|
const { getTaskCounts } = require('../lib/state-detection');
|
|
1173
|
+
const { readEndgameState } = require('../commands/autopilot');
|
|
1053
1174
|
const cwd = process.cwd();
|
|
1054
1175
|
const atrisDir = path.join(cwd, 'atris');
|
|
1055
1176
|
const projectName = path.basename(cwd);
|
|
@@ -1063,6 +1184,7 @@ function showWelcomeVisualization() {
|
|
|
1063
1184
|
let journalEntries = 0;
|
|
1064
1185
|
let hasMap = false;
|
|
1065
1186
|
let isInitialized = fs.existsSync(atrisDir);
|
|
1187
|
+
let endgameState = { slug: 'unset', horizon: '' };
|
|
1066
1188
|
|
|
1067
1189
|
if (isInitialized) {
|
|
1068
1190
|
// Check MAP.md
|
|
@@ -1086,6 +1208,13 @@ function showWelcomeVisualization() {
|
|
|
1086
1208
|
// Silently fail - show 0 tasks if reading fails
|
|
1087
1209
|
}
|
|
1088
1210
|
|
|
1211
|
+
// Read endgame state
|
|
1212
|
+
try {
|
|
1213
|
+
endgameState = readEndgameState(cwd);
|
|
1214
|
+
} catch {
|
|
1215
|
+
// Silently fail - show unset if reading fails
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1089
1218
|
// Count journal entries today
|
|
1090
1219
|
const today = new Date();
|
|
1091
1220
|
const year = today.getFullYear();
|
|
@@ -1139,6 +1268,11 @@ function showWelcomeVisualization() {
|
|
|
1139
1268
|
console.log(` │ ⏳ Review: ${reviewText.padEnd(26)}│`);
|
|
1140
1269
|
}
|
|
1141
1270
|
console.log(` │ 📝 Journal: ${(journalEntries + ' entries today').padEnd(26)}│`);
|
|
1271
|
+
if (endgameState.slug !== 'unset' && endgameState.horizon) {
|
|
1272
|
+
const endgameLine = endgameState.slug + ' — ' + endgameState.horizon;
|
|
1273
|
+
const paddedEndgame = endgameLine.padEnd(26);
|
|
1274
|
+
console.log(` │ 🎯 Endgame: ${paddedEndgame}│`);
|
|
1275
|
+
}
|
|
1142
1276
|
console.log(' │ │');
|
|
1143
1277
|
console.log(' │ ┌──────────────────────────────────┐ │');
|
|
1144
1278
|
console.log(' │ │ MAP.md ←──── YOU ARE HERE │ │');
|
|
@@ -1185,6 +1319,11 @@ if (command === 'init') {
|
|
|
1185
1319
|
Promise.resolve(require('../commands/mission').missionCommand(process.argv.slice(3)))
|
|
1186
1320
|
.then(() => process.exit(0))
|
|
1187
1321
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1322
|
+
} else if (command === 'pulse') {
|
|
1323
|
+
// Pulse: durable overnight self-improvement heartbeat (OS cron) for atris-cli.
|
|
1324
|
+
Promise.resolve(require('../commands/pulse').pulseCommand(process.argv.slice(3)))
|
|
1325
|
+
.then((res) => process.exit(res && res.ok === false ? 1 : 0))
|
|
1326
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1188
1327
|
} else if (command === 'probe') {
|
|
1189
1328
|
// Chat-lane probe (TRR-22): one real /atris2/turn over the full tool relay.
|
|
1190
1329
|
Promise.resolve(require('../commands/probe').probeCommand(process.argv.slice(3)))
|
|
@@ -1203,6 +1342,16 @@ if (command === 'init') {
|
|
|
1203
1342
|
Promise.resolve(require('../commands/codex-goal').codexGoalCommand(process.argv.slice(3)))
|
|
1204
1343
|
.then(() => process.exit(process.exitCode || 0))
|
|
1205
1344
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1345
|
+
} else if (command === 'slop') {
|
|
1346
|
+
// Slop: deterministic frontend-slop detector (no LLM). Exit 1 = slop found, for CI + the autopilot gate.
|
|
1347
|
+
Promise.resolve(require('../commands/slop').slopCommand(process.argv.slice(3)))
|
|
1348
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1349
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1350
|
+
} else if (command === 'deck') {
|
|
1351
|
+
// Deck: premium Google Slides from a plain content spec, via the Atris deck engine (anti-slop design system).
|
|
1352
|
+
Promise.resolve(require('../commands/deck').run(process.argv.slice(3)))
|
|
1353
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1354
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1206
1355
|
} else if (command === 'aeo') {
|
|
1207
1356
|
// AEO: AI Engine Optimization — credit-metered citation drafting against the customer workspace.
|
|
1208
1357
|
Promise.resolve(require('../commands/aeo').run(process.argv.slice(3)))
|
|
@@ -1303,12 +1452,28 @@ if (command === 'init') {
|
|
|
1303
1452
|
}
|
|
1304
1453
|
upgradeAtris().then(() => process.exit(0)).catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1305
1454
|
} else if (command === 'chat') {
|
|
1455
|
+
if (process.argv[3] === 'scan') {
|
|
1456
|
+
try {
|
|
1457
|
+
require('../commands/chat-scan').chatScanCommand(process.argv.slice(4));
|
|
1458
|
+
process.exit(0);
|
|
1459
|
+
} catch (error) {
|
|
1460
|
+
console.error(`✗ Chat scan failed: ${error.message || error}`);
|
|
1461
|
+
process.exit(1);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1306
1464
|
chatAtris()
|
|
1307
1465
|
.then(() => process.exit(0))
|
|
1308
1466
|
.catch((error) => {
|
|
1309
1467
|
console.error(`✗ Chat failed: ${error.message || error}`);
|
|
1310
1468
|
process.exit(1);
|
|
1311
1469
|
});
|
|
1470
|
+
} else if (command === 'fast' || (command === 'ax' && process.argv[3] === 'fast')) {
|
|
1471
|
+
atrisFastChat()
|
|
1472
|
+
.then(() => process.exit(0))
|
|
1473
|
+
.catch((error) => {
|
|
1474
|
+
console.error(`✗ Fast chat failed: ${error.message || error}`);
|
|
1475
|
+
process.exit(1);
|
|
1476
|
+
});
|
|
1312
1477
|
} else if (command === 'console') {
|
|
1313
1478
|
consoleCmd();
|
|
1314
1479
|
} else if (command === 'serve') {
|
|
@@ -1395,8 +1560,116 @@ if (command === 'init') {
|
|
|
1395
1560
|
require('../commands/visualize').visualizeAtris(process.argv.slice(3))
|
|
1396
1561
|
.then(() => process.exit(0))
|
|
1397
1562
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1563
|
+
} else if (command === 'youtube') {
|
|
1564
|
+
require('../commands/youtube').youtubeCommand(process.argv.slice(3))
|
|
1565
|
+
.then(() => process.exit(0))
|
|
1566
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1398
1567
|
} else if (command === 'run') {
|
|
1399
1568
|
const args = process.argv.slice(3);
|
|
1569
|
+
if (args[0] === 'logs') {
|
|
1570
|
+
// Subcommand: atris run logs [--tail N] [--cat FILE] [--json]
|
|
1571
|
+
const { listRunLogs } = require('../commands/run');
|
|
1572
|
+
const logsArgs = args.slice(1);
|
|
1573
|
+
if (logsArgs.includes('--help') || logsArgs.includes('-h')) {
|
|
1574
|
+
console.log('');
|
|
1575
|
+
console.log('Usage: atris run logs [options]');
|
|
1576
|
+
console.log('');
|
|
1577
|
+
console.log('List and read glass run logs from atris/logs/runs/.');
|
|
1578
|
+
console.log('');
|
|
1579
|
+
console.log('Options:');
|
|
1580
|
+
console.log(' --tail N Show last N lines of each log (default: 5)');
|
|
1581
|
+
console.log(' --cat FILE Print full contents of a specific log file');
|
|
1582
|
+
console.log(' --json Output machine-readable JSON');
|
|
1583
|
+
console.log(' --help Show this help');
|
|
1584
|
+
console.log('');
|
|
1585
|
+
process.exit(0);
|
|
1586
|
+
}
|
|
1587
|
+
listRunLogs(logsArgs);
|
|
1588
|
+
process.exit(0);
|
|
1589
|
+
}
|
|
1590
|
+
if (args[0] === 'prune-logs') {
|
|
1591
|
+
// Subcommand: atris run prune-logs [--keep N] [--dry-run]
|
|
1592
|
+
const { pruneRunLogs } = require('../commands/run');
|
|
1593
|
+
const pruneArgs = args.slice(1);
|
|
1594
|
+
if (pruneArgs.includes('--help') || pruneArgs.includes('-h')) {
|
|
1595
|
+
console.log('');
|
|
1596
|
+
console.log('Usage: atris run prune-logs [options]');
|
|
1597
|
+
console.log('');
|
|
1598
|
+
console.log('Prune old run logs, keeping only the most recent N files.');
|
|
1599
|
+
console.log('');
|
|
1600
|
+
console.log('Options:');
|
|
1601
|
+
console.log(' --keep N Number of recent logs to keep (default: 50)');
|
|
1602
|
+
console.log(' --dry-run Show what would be deleted without deleting');
|
|
1603
|
+
console.log(' --help Show this help');
|
|
1604
|
+
console.log('');
|
|
1605
|
+
process.exit(0);
|
|
1606
|
+
}
|
|
1607
|
+
pruneRunLogs(pruneArgs);
|
|
1608
|
+
process.exit(0);
|
|
1609
|
+
}
|
|
1610
|
+
if (args[0] === 'search') {
|
|
1611
|
+
// Subcommand: atris run search <keyword> [--phase P] [--limit N]
|
|
1612
|
+
const { searchRunLogs } = require('../commands/run');
|
|
1613
|
+
const searchArgs = args.slice(1);
|
|
1614
|
+
if (searchArgs.includes('--help') || searchArgs.includes('-h') || searchArgs.length === 0) {
|
|
1615
|
+
console.log('');
|
|
1616
|
+
console.log('Usage: atris run search <keyword> [options]');
|
|
1617
|
+
console.log('');
|
|
1618
|
+
console.log('Search phase reasoning across all run logs.');
|
|
1619
|
+
console.log('');
|
|
1620
|
+
console.log('Options:');
|
|
1621
|
+
console.log(' --phase P Limit search to a phase (plan, do, review, error)');
|
|
1622
|
+
console.log(' --limit N Max results to show (default: 20)');
|
|
1623
|
+
console.log(' --help Show this help');
|
|
1624
|
+
console.log('');
|
|
1625
|
+
process.exit(0);
|
|
1626
|
+
}
|
|
1627
|
+
searchRunLogs(searchArgs);
|
|
1628
|
+
process.exit(0);
|
|
1629
|
+
}
|
|
1630
|
+
if (args[0] === 'stats') {
|
|
1631
|
+
// Subcommand: atris run stats
|
|
1632
|
+
const { statsRunLogs } = require('../commands/run');
|
|
1633
|
+
statsRunLogs();
|
|
1634
|
+
process.exit(0);
|
|
1635
|
+
}
|
|
1636
|
+
if (args[0] === 'export') {
|
|
1637
|
+
// Subcommand: atris run export [--out FILE]
|
|
1638
|
+
const { exportRunLogs } = require('../commands/run');
|
|
1639
|
+
const exportArgs = args.slice(1);
|
|
1640
|
+
if (exportArgs.includes('--help') || exportArgs.includes('-h')) {
|
|
1641
|
+
console.log('');
|
|
1642
|
+
console.log('Usage: atris run export [options]');
|
|
1643
|
+
console.log('');
|
|
1644
|
+
console.log('Export all run logs as a JSON bundle for backup or transfer.');
|
|
1645
|
+
console.log('');
|
|
1646
|
+
console.log('Options:');
|
|
1647
|
+
console.log(' --out FILE Write to a specific file (default: atris/logs/runs/export.json)');
|
|
1648
|
+
console.log(' --help Show this help');
|
|
1649
|
+
console.log('');
|
|
1650
|
+
process.exit(0);
|
|
1651
|
+
}
|
|
1652
|
+
exportRunLogs(exportArgs);
|
|
1653
|
+
process.exit(0);
|
|
1654
|
+
}
|
|
1655
|
+
if (args[0] === 'diff') {
|
|
1656
|
+
// Subcommand: atris run diff <file1> <file2>
|
|
1657
|
+
const { diffRunLogs } = require('../commands/run');
|
|
1658
|
+
const diffArgs = args.slice(1);
|
|
1659
|
+
if (diffArgs.includes('--help') || diffArgs.includes('-h') || diffArgs.length === 0) {
|
|
1660
|
+
console.log('');
|
|
1661
|
+
console.log('Usage: atris run diff <file1> <file2>');
|
|
1662
|
+
console.log('');
|
|
1663
|
+
console.log('Compare two run logs side by side, showing phase-level differences.');
|
|
1664
|
+
console.log('');
|
|
1665
|
+
console.log('Options:');
|
|
1666
|
+
console.log(' --help Show this help');
|
|
1667
|
+
console.log('');
|
|
1668
|
+
process.exit(0);
|
|
1669
|
+
}
|
|
1670
|
+
diffRunLogs(diffArgs);
|
|
1671
|
+
process.exit(0);
|
|
1672
|
+
}
|
|
1400
1673
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
1401
1674
|
console.log('');
|
|
1402
1675
|
console.log('Usage: atris run [options]');
|
|
@@ -1407,12 +1680,24 @@ if (command === 'init') {
|
|
|
1407
1680
|
console.log('Options:');
|
|
1408
1681
|
console.log(' --cycles=N Max cycles (default: 5)');
|
|
1409
1682
|
console.log(' --once Single plan→do→review cycle');
|
|
1410
|
-
console.log(' --verbose Show
|
|
1683
|
+
console.log(' --verbose Show configured runner output');
|
|
1411
1684
|
console.log(' --dry-run Preview without executing');
|
|
1412
1685
|
console.log(' --timeout=N Phase timeout in seconds (default: 600)');
|
|
1686
|
+
console.log(' --runner-bin PATH Runner binary for this run');
|
|
1687
|
+
console.log(' --runner-template CMD Runner command template for this run');
|
|
1688
|
+
console.log(' --runner-model MODEL Runner model for this run');
|
|
1689
|
+
console.log(' --runner-profile NAME Runner profile for this run (e.g. atris-fast)');
|
|
1413
1690
|
console.log(' --push Auto-push after each cycle (default: true)');
|
|
1414
1691
|
console.log(' --no-push Skip auto-push after each cycle');
|
|
1415
1692
|
console.log('');
|
|
1693
|
+
console.log('Subcommands:');
|
|
1694
|
+
console.log(' atris run logs [--tail N] [--cat FILE] [--json] Browse glass run logs');
|
|
1695
|
+
console.log(' atris run prune-logs [--keep N] [--dry-run] Prune old run logs');
|
|
1696
|
+
console.log(' atris run search <keyword> [--phase P] [--limit N] Search run logs');
|
|
1697
|
+
console.log(' atris run stats Show run log stats');
|
|
1698
|
+
console.log(' atris run export [--out FILE] Export logs as JSON');
|
|
1699
|
+
console.log(' atris run diff <file1> <file2> Compare two run logs');
|
|
1700
|
+
console.log('');
|
|
1416
1701
|
process.exit(0);
|
|
1417
1702
|
}
|
|
1418
1703
|
|
|
@@ -1420,6 +1705,7 @@ if (command === 'init') {
|
|
|
1420
1705
|
const dryRun = args.includes('--dry-run');
|
|
1421
1706
|
const once = args.includes('--once');
|
|
1422
1707
|
const push = !args.includes('--no-push');
|
|
1708
|
+
applyRunnerFlags(args);
|
|
1423
1709
|
const cyclesArg = args.find(a => a.startsWith('--cycles='));
|
|
1424
1710
|
const maxCycles = cyclesArg ? parseInt(cyclesArg.split('=')[1]) : 5;
|
|
1425
1711
|
const timeoutArg = args.find(a => a.startsWith('--timeout='));
|
|
@@ -1442,13 +1728,14 @@ if (command === 'init') {
|
|
|
1442
1728
|
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
1443
1729
|
const dryRun = args.includes('--dry-run');
|
|
1444
1730
|
const auto = args.includes('--auto');
|
|
1731
|
+
applyRunnerFlags(args);
|
|
1445
1732
|
const maxIterationsArg = args.find(a => a.startsWith('--iterations='));
|
|
1446
1733
|
const maxIterations = maxIterationsArg ? parseInt(maxIterationsArg.split('=')[1]) : undefined;
|
|
1447
1734
|
const durationArg = args.find(a => a.startsWith('--duration='));
|
|
1448
1735
|
const duration = durationArg ? durationArg.split('=')[1] : null;
|
|
1449
1736
|
|
|
1450
1737
|
// Get description (non-flag args)
|
|
1451
|
-
const description = args.filter(a => !a.startsWith('-')).join(' ').trim() || null;
|
|
1738
|
+
const description = args.filter((a, i) => !a.startsWith('-') && !isOptionValue(args, i, RUNNER_FLAG_NAMES)).join(' ').trim() || null;
|
|
1452
1739
|
|
|
1453
1740
|
const options = {
|
|
1454
1741
|
...(maxIterations !== undefined && { maxIterations }),
|
|
@@ -1737,6 +2024,11 @@ if (command === 'init') {
|
|
|
1737
2024
|
require('../commands/fleet').fleet(args)
|
|
1738
2025
|
.then(() => process.exit(0))
|
|
1739
2026
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2027
|
+
} else if (command === 'spaceship') {
|
|
2028
|
+
const args = process.argv.slice(3);
|
|
2029
|
+
require('../commands/spaceship').spaceship(args)
|
|
2030
|
+
.then(() => process.exit(0))
|
|
2031
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1740
2032
|
} else if (command === 'code-review' || command === 'cr') {
|
|
1741
2033
|
const args = process.argv.slice(3);
|
|
1742
2034
|
require('../commands/review').reviewCommand(...args)
|
|
@@ -1949,7 +2241,7 @@ function inspectAgentCliWiring() {
|
|
|
1949
2241
|
},
|
|
1950
2242
|
];
|
|
1951
2243
|
|
|
1952
|
-
const binaries = ['atris', 'claude', 'codex', 'cursor-agent', 'devin'].map((name) => ({
|
|
2244
|
+
const binaries = ['atris', 'ax', 'claude', 'codex', 'cursor-agent', 'devin', 'droid'].map((name) => ({
|
|
1953
2245
|
name,
|
|
1954
2246
|
path: commandOnPath(name),
|
|
1955
2247
|
}));
|
|
@@ -1986,10 +2278,13 @@ async function agentAtris() {
|
|
|
1986
2278
|
// Respect -h / --help / help before any auth/state work
|
|
1987
2279
|
const firstArg = process.argv[3];
|
|
1988
2280
|
if (firstArg === '-h' || firstArg === '--help' || firstArg === 'help') {
|
|
1989
|
-
console.log('Usage: atris agent [doctor]');
|
|
2281
|
+
console.log('Usage: atris agent [doctor|dogfood|spawn|spawns|spawn-status]');
|
|
1990
2282
|
console.log('');
|
|
1991
2283
|
console.log(' Pick which cloud agent to chat with from this workspace.');
|
|
2284
|
+
console.log(' Run `atris agent spawn <role> --task "..."` to create a worker request.');
|
|
2285
|
+
console.log(' Run `atris agent spawns` to list worker requests.');
|
|
1992
2286
|
console.log(' Run `atris agent doctor` to verify local AI CLIs can see Atris context.');
|
|
2287
|
+
console.log(' Run `atris agent dogfood --live` to smoke-test Devin/Droid with GLM 5.2.');
|
|
1993
2288
|
console.log(' Requires `atris login` first.');
|
|
1994
2289
|
console.log('');
|
|
1995
2290
|
console.log(' After selecting, use: atris chat ["message"]');
|
|
@@ -1999,6 +2294,22 @@ async function agentAtris() {
|
|
|
1999
2294
|
if (firstArg === 'doctor') {
|
|
2000
2295
|
agentDoctor();
|
|
2001
2296
|
}
|
|
2297
|
+
if (firstArg === 'dogfood') {
|
|
2298
|
+
const result = require('../commands/agent-spawn').agentDogfoodCommand(process.argv.slice(4));
|
|
2299
|
+
process.exit(result.ok ? 0 : 1);
|
|
2300
|
+
}
|
|
2301
|
+
if (firstArg === 'spawn') {
|
|
2302
|
+
require('../commands/agent-spawn').agentSpawnCommand(process.argv.slice(4));
|
|
2303
|
+
return;
|
|
2304
|
+
}
|
|
2305
|
+
if (firstArg === 'spawns' || firstArg === 'spawn-list' || firstArg === 'list-spawns') {
|
|
2306
|
+
require('../commands/agent-spawn').agentSpawnListCommand(process.argv.slice(4));
|
|
2307
|
+
return;
|
|
2308
|
+
}
|
|
2309
|
+
if (firstArg === 'spawn-status' || firstArg === 'spawn-show') {
|
|
2310
|
+
require('../commands/agent-spawn').agentSpawnStatusCommand(process.argv.slice(4));
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2002
2313
|
|
|
2003
2314
|
const targetDir = path.join(process.cwd(), 'atris');
|
|
2004
2315
|
|
|
@@ -2242,6 +2553,65 @@ async function chatInteractive(config, credentials) {
|
|
|
2242
2553
|
});
|
|
2243
2554
|
}
|
|
2244
2555
|
|
|
2556
|
+
function atrisFastMessageFromArgs() {
|
|
2557
|
+
const offset = command === 'ax' ? 4 : 3;
|
|
2558
|
+
return process.argv.slice(offset).join(' ').trim();
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
async function atrisFastChat() {
|
|
2562
|
+
if (command === 'ax' && process.argv[3] !== 'fast') {
|
|
2563
|
+
console.error('Usage: atris ax fast "message"');
|
|
2564
|
+
process.exit(1);
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
const message = atrisFastMessageFromArgs();
|
|
2568
|
+
|
|
2569
|
+
if (message === '-h' || message === '--help' || message === 'help') {
|
|
2570
|
+
console.log('Usage: atris fast ["message"]');
|
|
2571
|
+
console.log('');
|
|
2572
|
+
console.log(' Chat with Atris2 Fast through /api/atris2/turn.');
|
|
2573
|
+
console.log(' Requires `atris login`.');
|
|
2574
|
+
console.log('');
|
|
2575
|
+
console.log(' atris fast "what now?" One-shot message');
|
|
2576
|
+
console.log(' atris ax fast "what now?" Alias');
|
|
2577
|
+
process.exit(0);
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
if (!message) {
|
|
2581
|
+
console.error('Usage: atris fast "message"');
|
|
2582
|
+
process.exit(1);
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
const ensured = await ensureValidCredentials();
|
|
2586
|
+
if (ensured.error === 'not_logged_in' || !ensured.credentials?.token) {
|
|
2587
|
+
console.error('✗ Error: Not logged in. Run "atris login" first.');
|
|
2588
|
+
process.exit(1);
|
|
2589
|
+
}
|
|
2590
|
+
if (ensured.error) {
|
|
2591
|
+
console.error(`✗ Error: Authentication failed: ${ensured.detail || ensured.error}. Run "atris login" to re-authenticate.`);
|
|
2592
|
+
process.exit(1);
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
const credentials = ensured.credentials;
|
|
2596
|
+
await atrisFastOnce(credentials, message);
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
async function atrisFastOnce(credentials, message) {
|
|
2600
|
+
console.log('\nAtris2 Fast');
|
|
2601
|
+
console.log('');
|
|
2602
|
+
|
|
2603
|
+
const apiUrl = getApiBaseUrl().replace(/\/api$/, '');
|
|
2604
|
+
const endpoint = `${apiUrl}/api/atris2/turn`;
|
|
2605
|
+
const body = JSON.stringify({
|
|
2606
|
+
message,
|
|
2607
|
+
model: 'atris:fast',
|
|
2608
|
+
max_turns: 1,
|
|
2609
|
+
});
|
|
2610
|
+
|
|
2611
|
+
await streamProChat(endpoint, credentials.token, body);
|
|
2612
|
+
console.log('\n\n✓ Complete\n');
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2245
2615
|
async function atrisDevEntry(userInput = null) {
|
|
2246
2616
|
// Load workspace context and present planning-ready state
|
|
2247
2617
|
// userInput: optional task description for hot start
|