atris 3.33.3 → 3.35.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/AGENTS.md +0 -2
- package/FOR_AGENTS.md +5 -3
- package/atris/skills/engines/SKILL.md +16 -7
- package/atris/skills/render-cli/SKILL.md +88 -0
- package/atris.md +19 -0
- package/ax +475 -17
- package/bin/atris.js +206 -44
- package/commands/aeo.js +52 -0
- package/commands/autoland.js +313 -19
- package/commands/business.js +91 -8
- package/commands/codex-goal.js +26 -2
- package/commands/drive.js +187 -0
- package/commands/engine.js +73 -2
- package/commands/feed.js +202 -0
- package/commands/github.js +38 -0
- package/commands/gm.js +262 -3
- package/commands/init.js +13 -1
- package/commands/integrations.js +39 -11
- package/commands/interview.js +143 -0
- package/commands/land.js +114 -13
- package/commands/lesson.js +112 -1
- package/commands/linear.js +38 -0
- package/commands/loops.js +212 -0
- package/commands/member.js +398 -42
- package/commands/mission.js +598 -64
- package/commands/now.js +25 -1
- package/commands/radar.js +259 -14
- package/commands/serve.js +54 -0
- package/commands/status.js +50 -5
- package/commands/stripe.js +38 -0
- package/commands/supabase.js +39 -0
- package/commands/task.js +935 -71
- package/commands/truth.js +29 -3
- package/commands/unknowns.js +627 -0
- package/commands/update.js +44 -0
- package/commands/vercel.js +38 -0
- package/commands/worktree.js +68 -10
- package/commands/write.js +399 -0
- package/lib/auto-accept-certified.js +70 -19
- package/lib/autoland.js +39 -3
- package/lib/fleet.js +256 -13
- package/lib/memory-view.js +14 -5
- package/lib/mission-runtime-loop.js +7 -0
- package/lib/official-cli-integration.js +174 -0
- package/lib/outbound-send-gate.js +165 -0
- package/lib/permission-grants.js +293 -0
- package/lib/review-integrity.js +147 -0
- package/lib/runner-command.js +23 -0
- package/lib/task-db.js +220 -7
- package/lib/task-proof.js +20 -0
- package/lib/task-receipt.js +93 -0
- package/package.json +1 -1
- package/utils/update-check.js +27 -6
- package/atris/learnings.jsonl +0 -1
package/bin/atris.js
CHANGED
|
@@ -29,7 +29,6 @@ try {
|
|
|
29
29
|
const {
|
|
30
30
|
checkForUpdates,
|
|
31
31
|
showUpdateNotification,
|
|
32
|
-
autoUpdate,
|
|
33
32
|
inspectInstallGitState,
|
|
34
33
|
formatInstallGitWarning,
|
|
35
34
|
} = require('../utils/update-check');
|
|
@@ -91,14 +90,10 @@ const skipUpdateCheck = Boolean(process.env.ATRIS_SKIP_UPDATE_CHECK || process.e
|
|
|
91
90
|
if (!skipUpdateCheck && (!updateCommand || (updateCommand && !['version', 'update'].includes(updateCommand)))) {
|
|
92
91
|
updateCheckPromise = checkForUpdates()
|
|
93
92
|
.then((updateInfo) => {
|
|
94
|
-
// Show notification if update available (after command completes)
|
|
95
93
|
if (updateInfo) {
|
|
96
|
-
|
|
94
|
+
showUpdateNotification(updateInfo, {
|
|
97
95
|
packageRoot: path.join(__dirname, '..'),
|
|
98
96
|
});
|
|
99
|
-
if (!autoUpdateStarted) {
|
|
100
|
-
showUpdateNotification(updateInfo);
|
|
101
|
-
}
|
|
102
97
|
}
|
|
103
98
|
return updateInfo;
|
|
104
99
|
})
|
|
@@ -469,8 +464,8 @@ function showHelp() {
|
|
|
469
464
|
console.log(' 3. Atris acts with context, memory, tools, and a review loop');
|
|
470
465
|
console.log('');
|
|
471
466
|
console.log('Common invocations:');
|
|
472
|
-
console.log(' atris init
|
|
473
|
-
console.log(' npx atris init
|
|
467
|
+
console.log(' atris init [--yes] Global install: initialize this project');
|
|
468
|
+
console.log(' npx atris init [--yes] Local install: initialize this project');
|
|
474
469
|
console.log(' atris computer');
|
|
475
470
|
console.log(' atris business init "My Company"');
|
|
476
471
|
console.log(' atris run');
|
|
@@ -487,7 +482,7 @@ function showHelp() {
|
|
|
487
482
|
console.log('');
|
|
488
483
|
console.log('Setup:');
|
|
489
484
|
console.log(' setup - Guided first-time setup (login, pick business, pull)');
|
|
490
|
-
console.log(' init - Initialize Atris in current project');
|
|
485
|
+
console.log(' init - Initialize Atris in current project (--yes skips prompts)');
|
|
491
486
|
console.log(' update - Update local files to latest version');
|
|
492
487
|
console.log(' upgrade - Install latest Atris from npm');
|
|
493
488
|
console.log('');
|
|
@@ -517,6 +512,12 @@ function showHelp() {
|
|
|
517
512
|
console.log(' harvest - Find bugs and next actions from receipts, run logs, and thinking');
|
|
518
513
|
console.log(' verify - Validate work is done (tests, MAP.md, changes)');
|
|
519
514
|
console.log(' task - Local agent task plane (atomic claims, TODO import)');
|
|
515
|
+
console.log(' golden path (zero human turns):');
|
|
516
|
+
console.log(' atris task delegate "fix the login bug" --to <member>');
|
|
517
|
+
console.log(' atris task claim <id> --as <member>');
|
|
518
|
+
console.log(' ... build ...');
|
|
519
|
+
console.log(' atris task ready <id> --verify');
|
|
520
|
+
console.log(' atris autoland tick # second check runs, task lands');
|
|
520
521
|
console.log(' mission - Goal + loop + member owner + verifier + receipt');
|
|
521
522
|
console.log(' release - Tag release, bump version, create GitHub release, draft /launch');
|
|
522
523
|
console.log(' learn - Project learnings (patterns, pitfalls, preferences)');
|
|
@@ -526,6 +527,7 @@ function showHelp() {
|
|
|
526
527
|
console.log(' query - Local-first wiki query against atris/wiki/');
|
|
527
528
|
console.log(' lint - Local-first wiki lint for atris/wiki/');
|
|
528
529
|
console.log(' loop - Local wiki upkeep loop (stale pages, orphans, next ingest)');
|
|
530
|
+
console.log(' write - Guided writing sessions: you write every word, atris structures + reviews');
|
|
529
531
|
console.log('');
|
|
530
532
|
console.log('Optional helpers:');
|
|
531
533
|
console.log(' brainstorm - Explore ideas conversationally before planning');
|
|
@@ -533,8 +535,9 @@ function showHelp() {
|
|
|
533
535
|
console.log(' improve - Run one paid RL tick (POST /api/improve, deducts credits)');
|
|
534
536
|
console.log(' worktree - Isolated Git worktrees plus guarded ship/merge for parallel agents');
|
|
535
537
|
console.log(' land - The landing: what is actually done vs still in the air; --reap backs up + clears overdue');
|
|
538
|
+
console.log(' drive - One self-driving tick: mission doctor -> auto-fix -> count disengagements');
|
|
536
539
|
console.log(' autoland - Approve the policy once; certified work lands itself, you keep irreversible calls');
|
|
537
|
-
console.log(' engine - Bring any intelligence: roster of installed coding CLIs, default engine, --engine per run, `engine test` preflight');
|
|
540
|
+
console.log(' engine - Bring any intelligence: roster of installed coding CLIs, default engine, --engine per run, `engine test` preflight, `engine dispatch <task-id> --engine <name>` one-command claim/build/verify/ship');
|
|
538
541
|
console.log(' sign - Co-author trailer on every commit in an atris workspace (on/off/status)');
|
|
539
542
|
console.log(' visualize - Generate a Slack/deck-ready visual from a prompt');
|
|
540
543
|
console.log(' youtube - Process YouTube videos with timestamped transcript-first analysis');
|
|
@@ -594,6 +597,7 @@ function showHelp() {
|
|
|
594
597
|
console.log(' console - Start/attach always-on coding console (tmux daemon)');
|
|
595
598
|
console.log(' soul - Show, snapshot, or fork workspace identity');
|
|
596
599
|
console.log(' fleet - Inspect local fleet status');
|
|
600
|
+
console.log(' loops - Background loops board: what runs, what died, start/stop');
|
|
597
601
|
console.log(' agent - Select cloud agent, spawn worker requests, or run `agent doctor`');
|
|
598
602
|
console.log(' chat - Chat with Atris 2 Fast in this workspace (--agent for cloud agent; or: atris chat scan)');
|
|
599
603
|
console.log(' fast - Chat with Atris2 Fast');
|
|
@@ -605,6 +609,11 @@ function showHelp() {
|
|
|
605
609
|
console.log(' accounts - Manage accounts (list, add, remove)');
|
|
606
610
|
console.log('');
|
|
607
611
|
console.log('Integrations:');
|
|
612
|
+
console.log(' github - github cli wrapper (doctor, auth, pr list/create/checks/view)');
|
|
613
|
+
console.log(' vercel - vercel cli wrapper (doctor, auth, deploy/ls/logs/inspect)');
|
|
614
|
+
console.log(' supabase - supabase cli wrapper (doctor, auth, status/db/functions)');
|
|
615
|
+
console.log(' linear - linear cli wrapper (doctor, auth, issue list/create/view/update)');
|
|
616
|
+
console.log(' stripe - stripe cli wrapper (doctor, auth, listen/trigger/products)');
|
|
608
617
|
console.log(' gmail - Email commands (inbox, read, archive)');
|
|
609
618
|
console.log(' calendar - Calendar commands (today, week)');
|
|
610
619
|
console.log(' twitter - Twitter commands (post)');
|
|
@@ -765,7 +774,8 @@ function showVerifyHelp() {
|
|
|
765
774
|
|
|
766
775
|
function showUpdateHelp(commandName = 'update') {
|
|
767
776
|
console.log('');
|
|
768
|
-
|
|
777
|
+
const selfFlag = commandName === 'update' ? ' [--self]' : '';
|
|
778
|
+
console.log(`Usage: atris ${commandName} [--all] [--dry-run] [--force]${selfFlag}`);
|
|
769
779
|
console.log('');
|
|
770
780
|
console.log('Description:');
|
|
771
781
|
console.log(' Sync Atris workspace files from the installed CLI templates.');
|
|
@@ -774,6 +784,9 @@ function showUpdateHelp(commandName = 'update') {
|
|
|
774
784
|
console.log(' --all Update Atris files across projects under the current tree.');
|
|
775
785
|
console.log(' --dry-run Preview update work without writing files.');
|
|
776
786
|
console.log(' --force Overwrite existing template files where supported.');
|
|
787
|
+
if (commandName === 'update') {
|
|
788
|
+
console.log(' --self Update the installed atris cli from npm (packaged installs only).');
|
|
789
|
+
}
|
|
777
790
|
console.log(' --help, -h Show this help.');
|
|
778
791
|
console.log('');
|
|
779
792
|
}
|
|
@@ -973,9 +986,9 @@ if (command === '2' && ['fast', 'pro'].includes(String(firstCommandArg || '').to
|
|
|
973
986
|
const knownCommands = ['init', 'log', 'now', 'radar', 'ctop', 'launchpad', 'status', 'analytics', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', '_start', 'plan', 'do', 'review', 'release',
|
|
974
987
|
'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',
|
|
975
988
|
'clean', 'harvest', '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',
|
|
976
|
-
'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'probe', 'worktree', 'land', 'autoland', 'aeo', 'slop', 'strings', 'security-review', 'secure', 'deck', 'site', 'theme', 'card', 'reel', 'improve', 'xp', 'play', 'gm', 'x', 'recap', 'signup', 'clarity', 'moves',
|
|
977
|
-
'gmail', 'calendar', 'twitter', 'slack', 'imessage', 'integrations', 'setup', 'clean-workspace', 'cw',
|
|
978
|
-
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'compile', 'spaceship', 'truth', 'sign', 'engine', 'engines'];
|
|
989
|
+
'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'probe', 'worktree', 'land', 'autoland', 'drive', 'aeo', 'slop', 'strings', 'write', 'security-review', 'secure', 'deck', 'site', 'theme', 'card', 'reel', 'improve', 'xp', 'play', 'gm', 'x', 'recap', 'signup', 'clarity', 'interview', 'moves', 'unknowns',
|
|
990
|
+
'github', 'vercel', 'supabase', 'linear', 'stripe', 'gmail', 'calendar', 'twitter', 'slack', 'imessage', 'integrations', 'setup', 'clean-workspace', 'cw',
|
|
991
|
+
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'loops', 'compile', 'spaceship', 'truth', 'sign', 'engine', 'engines', 'feed'];
|
|
979
992
|
|
|
980
993
|
// Check if command is an atris.md spec file - triggers welcome visualization
|
|
981
994
|
function isSpecFile(cmd) {
|
|
@@ -1085,6 +1098,19 @@ function printAtrisOverview() {
|
|
|
1085
1098
|
console.log('');
|
|
1086
1099
|
}
|
|
1087
1100
|
|
|
1101
|
+
function useInteractiveAtrisUi() {
|
|
1102
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY && !process.env.ATRIS_NO_INTERACTIVE);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
function initNonInteractiveFlag() {
|
|
1106
|
+
const args = process.argv.slice(2);
|
|
1107
|
+
return args.includes('--yes') || args.includes('-y');
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
function shouldSkipContextGatherer() {
|
|
1111
|
+
return !useInteractiveAtrisUi() || initNonInteractiveFlag();
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1088
1114
|
async function interactiveEntry(userInput) {
|
|
1089
1115
|
const workspaceDir = process.cwd();
|
|
1090
1116
|
const state = detectWorkspaceState(workspaceDir);
|
|
@@ -1173,33 +1199,62 @@ async function interactiveEntry(userInput) {
|
|
|
1173
1199
|
backlogCount,
|
|
1174
1200
|
inboxCount,
|
|
1175
1201
|
})) {
|
|
1176
|
-
const
|
|
1177
|
-
if (
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1202
|
+
const hotAnswer = String(userInput || '').trim();
|
|
1203
|
+
if (hotAnswer) {
|
|
1204
|
+
const answer = hotAnswer;
|
|
1205
|
+
if (isAtrisMetaQuestion(answer)) {
|
|
1206
|
+
printAtrisOverview();
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
const profile = saveContextProfile(workspaceDir, answer, { source: 'hot_start' });
|
|
1210
|
+
const starter = createStarterTask(workspaceDir, answer);
|
|
1182
1211
|
console.log('');
|
|
1183
|
-
console.log('
|
|
1184
|
-
console.log(
|
|
1212
|
+
console.log('Got it. I saved your first direction.');
|
|
1213
|
+
console.log(`Focus: ${profile.first_answer}`);
|
|
1214
|
+
if (starter && starter.display_id) {
|
|
1215
|
+
console.log(`First task: ${starter.display_id} — ${starter.title}`);
|
|
1216
|
+
} else if (starter && starter.title) {
|
|
1217
|
+
console.log(`First task: ${starter.title}`);
|
|
1218
|
+
}
|
|
1219
|
+
if (mapStatus !== 'ready') {
|
|
1220
|
+
printMapBootstrap({ userInput: answer, prefix: 'Next setup step' });
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
await planCmd(answer);
|
|
1185
1224
|
return;
|
|
1186
1225
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1226
|
+
if (shouldSkipContextGatherer()) {
|
|
1227
|
+
console.log('');
|
|
1228
|
+
console.log("context gatherer skipped (non-interactive). run 'atris plan' when you're ready.");
|
|
1229
|
+
} else {
|
|
1230
|
+
const answer = await askContextGatherer(workspaceDir);
|
|
1231
|
+
if (isAtrisMetaQuestion(answer)) {
|
|
1232
|
+
printAtrisOverview();
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
if (!answer.trim()) {
|
|
1236
|
+
console.log('');
|
|
1237
|
+
console.log('No problem. When you are ready, answer in normal words.');
|
|
1238
|
+
console.log('Example: "help me organize college applications" or "help me build a small website".');
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
const profile = saveContextProfile(workspaceDir, answer, { source: 'cold_start' });
|
|
1242
|
+
const starter = createStarterTask(workspaceDir, answer);
|
|
1243
|
+
console.log('');
|
|
1244
|
+
console.log('Got it. I saved your first direction.');
|
|
1245
|
+
console.log(`Focus: ${profile.first_answer}`);
|
|
1246
|
+
if (starter && starter.display_id) {
|
|
1247
|
+
console.log(`First task: ${starter.display_id} — ${starter.title}`);
|
|
1248
|
+
} else if (starter && starter.title) {
|
|
1249
|
+
console.log(`First task: ${starter.title}`);
|
|
1250
|
+
}
|
|
1251
|
+
if (mapStatus !== 'ready') {
|
|
1252
|
+
printMapBootstrap({ userInput: answer, prefix: 'Next setup step' });
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
await planCmd(answer);
|
|
1199
1256
|
return;
|
|
1200
1257
|
}
|
|
1201
|
-
await planCmd(answer);
|
|
1202
|
-
return;
|
|
1203
1258
|
}
|
|
1204
1259
|
|
|
1205
1260
|
if (mapStatus !== 'ready') {
|
|
@@ -1435,6 +1490,44 @@ function showWelcomeVisualization() {
|
|
|
1435
1490
|
const landText = `${landInfo.branches} in the air, ${landInfo.due} overdue`;
|
|
1436
1491
|
console.log(` │ 🛬 Land: ${landText.padEnd(26)}│`);
|
|
1437
1492
|
}
|
|
1493
|
+
let rotInfo = null;
|
|
1494
|
+
try {
|
|
1495
|
+
const { parseLessons } = require('../lib/memory-view');
|
|
1496
|
+
const resolved = path.resolve(cwd);
|
|
1497
|
+
const parent = path.dirname(resolved);
|
|
1498
|
+
const grandparent = path.dirname(parent);
|
|
1499
|
+
let worktreeDir;
|
|
1500
|
+
if (path.basename(grandparent) === '.agent-worktrees') {
|
|
1501
|
+
worktreeDir = parent;
|
|
1502
|
+
} else {
|
|
1503
|
+
worktreeDir = path.join(path.dirname(resolved), '.agent-worktrees', path.basename(resolved));
|
|
1504
|
+
}
|
|
1505
|
+
let worktrees = 0;
|
|
1506
|
+
if (fs.existsSync(worktreeDir)) {
|
|
1507
|
+
worktrees = fs.readdirSync(worktreeDir, { withFileTypes: true })
|
|
1508
|
+
.filter((entry) => entry.isDirectory()).length;
|
|
1509
|
+
}
|
|
1510
|
+
let lessonsText = '';
|
|
1511
|
+
try {
|
|
1512
|
+
lessonsText = fs.readFileSync(path.join(atrisDir, 'lessons.md'), 'utf8');
|
|
1513
|
+
} catch (err) {
|
|
1514
|
+
lessonsText = '';
|
|
1515
|
+
}
|
|
1516
|
+
// rot = fail lessons nobody has resolved. A `pass` lesson is knowledge
|
|
1517
|
+
// that worked — it has nothing to resolve and counting it guilt-trips
|
|
1518
|
+
// the operator with a number (600+) no one can ever drive to zero.
|
|
1519
|
+
const unresolvedLessons = parseLessons(lessonsText)
|
|
1520
|
+
.filter((lesson) => lesson.status === 'fail' && !lesson.resolved && !/\[resolved\]/i.test(lesson.text)).length;
|
|
1521
|
+
if (worktrees > 0 || unresolvedLessons > 0) {
|
|
1522
|
+
rotInfo = { worktrees, lessons: unresolvedLessons };
|
|
1523
|
+
}
|
|
1524
|
+
} catch (err) {
|
|
1525
|
+
rotInfo = null;
|
|
1526
|
+
}
|
|
1527
|
+
if (rotInfo) {
|
|
1528
|
+
const rotText = `${rotInfo.worktrees} stale worktree${rotInfo.worktrees === 1 ? '' : 's'}, ${rotInfo.lessons} unresolved lesson${rotInfo.lessons === 1 ? '' : 's'}`;
|
|
1529
|
+
console.log(` │ 🧹 rot: ${rotText.padEnd(26)}│`);
|
|
1530
|
+
}
|
|
1438
1531
|
console.log(` │ 📝 Journal: ${(journalEntries + ' entries today').padEnd(26)}│`);
|
|
1439
1532
|
if (endgameState.slug !== 'unset' && endgameState.horizon) {
|
|
1440
1533
|
const endgameLine = endgameState.slug + ' — ' + endgameState.horizon;
|
|
@@ -1549,6 +1642,11 @@ if (command === 'init') {
|
|
|
1549
1642
|
Promise.resolve(require('../commands/land').landCommand(process.argv.slice(3)))
|
|
1550
1643
|
.then((code) => process.exit(code || 0))
|
|
1551
1644
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1645
|
+
} else if (command === 'drive') {
|
|
1646
|
+
// Drive: one self-driving tick — mission doctor -> auto-fix safe findings -> count disengagements.
|
|
1647
|
+
Promise.resolve(require('../commands/drive').driveCommand(process.argv.slice(3)))
|
|
1648
|
+
.then((code) => process.exit(code || 0))
|
|
1649
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1552
1650
|
} else if (command === 'radar' || command === 'ctop') {
|
|
1553
1651
|
const radarArgs = command === 'ctop' ? ['--agents', ...process.argv.slice(3)] : process.argv.slice(3);
|
|
1554
1652
|
Promise.resolve(require('../commands/radar').radarCommand(radarArgs))
|
|
@@ -1642,6 +1740,11 @@ if (command === 'init') {
|
|
|
1642
1740
|
showUpdateHelp(command);
|
|
1643
1741
|
process.exit(0);
|
|
1644
1742
|
}
|
|
1743
|
+
if (command === 'update' && args.includes('--self')) {
|
|
1744
|
+
const { updateSelf } = require('../commands/update');
|
|
1745
|
+
const result = updateSelf({ packageRoot: path.join(__dirname, '..') });
|
|
1746
|
+
process.exit(result.ok ? 0 : 1);
|
|
1747
|
+
}
|
|
1645
1748
|
if (isBusinessSync) {
|
|
1646
1749
|
Promise.resolve(require('../commands/business-sync').businessSync(process.argv.slice(3)))
|
|
1647
1750
|
.then(() => process.exit(0))
|
|
@@ -2125,6 +2228,21 @@ if (command === 'init') {
|
|
|
2125
2228
|
require('../commands/gm').gmCommand(...process.argv.slice(3))
|
|
2126
2229
|
.then(() => process.exit(0))
|
|
2127
2230
|
.catch((err) => { console.error(`✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2231
|
+
} else if (command === 'github') {
|
|
2232
|
+
const status = require('../commands/github').githubCommand(process.argv.slice(3));
|
|
2233
|
+
process.exit(status);
|
|
2234
|
+
} else if (command === 'vercel') {
|
|
2235
|
+
const status = require('../commands/vercel').vercelCommand(process.argv.slice(3));
|
|
2236
|
+
process.exit(status);
|
|
2237
|
+
} else if (command === 'supabase') {
|
|
2238
|
+
const status = require('../commands/supabase').supabaseCommand(process.argv.slice(3));
|
|
2239
|
+
process.exit(status);
|
|
2240
|
+
} else if (command === 'linear') {
|
|
2241
|
+
const status = require('../commands/linear').linearCommand(process.argv.slice(3));
|
|
2242
|
+
process.exit(status);
|
|
2243
|
+
} else if (command === 'stripe') {
|
|
2244
|
+
const status = require('../commands/stripe').stripeCommand(process.argv.slice(3));
|
|
2245
|
+
process.exit(status);
|
|
2128
2246
|
} else if (command === 'gmail') {
|
|
2129
2247
|
const { gmailCommand } = require('../commands/integrations');
|
|
2130
2248
|
const subcommand = process.argv[3];
|
|
@@ -2267,6 +2385,14 @@ if (command === 'init') {
|
|
|
2267
2385
|
require('../commands/fleet').fleet(args)
|
|
2268
2386
|
.then(() => process.exit(0))
|
|
2269
2387
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2388
|
+
} else if (command === 'loops') {
|
|
2389
|
+
try {
|
|
2390
|
+
require('../commands/loops').loopsCommand(process.argv[3], ...process.argv.slice(4));
|
|
2391
|
+
process.exit(0);
|
|
2392
|
+
} catch (error) {
|
|
2393
|
+
console.error(`\n✗ Error: ${error.message || error}`);
|
|
2394
|
+
process.exit(1);
|
|
2395
|
+
}
|
|
2270
2396
|
} else if (command === 'spaceship') {
|
|
2271
2397
|
const args = process.argv.slice(3);
|
|
2272
2398
|
require('../commands/spaceship').spaceship(args)
|
|
@@ -2317,10 +2443,13 @@ if (command === 'init') {
|
|
|
2317
2443
|
} else if (command === 'engine' || command === 'engines') {
|
|
2318
2444
|
// Engine: bring any intelligence — roster of installed coding CLIs, default
|
|
2319
2445
|
// engine per workspace, --engine <name> rides any loop for one run.
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2446
|
+
// `engine dispatch` runs an async claim -> build -> ship flight, so the
|
|
2447
|
+
// return value may be a promise or a plain number; Promise.resolve handles
|
|
2448
|
+
// both (mirrors the `compile` command dispatch just above).
|
|
2449
|
+
const engineArgs = command === 'engines' && process.argv.length <= 3 ? [] : process.argv.slice(3);
|
|
2450
|
+
Promise.resolve(require('../commands/engine').engineCommand(engineArgs))
|
|
2451
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2452
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2324
2453
|
} else if (command === 'sign') {
|
|
2325
2454
|
// Sign: prepare-commit-msg hook that credits Atris as co-author on commits in atris workspaces.
|
|
2326
2455
|
try { process.exit(require('../commands/sign').signCommand(process.argv[3]) || 0); }
|
|
@@ -2330,6 +2459,11 @@ if (command === 'init') {
|
|
|
2330
2459
|
Promise.resolve(require('../commands/slop').slopCommand(process.argv.slice(3)))
|
|
2331
2460
|
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2332
2461
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2462
|
+
} else if (command === 'write') {
|
|
2463
|
+
// Write: guided writing sessions — human types every word, atris structures + reviews (plan-do-review for prose).
|
|
2464
|
+
Promise.resolve(require('../commands/write').writeCommand(process.argv.slice(3)))
|
|
2465
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2466
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2333
2467
|
} else if (command === 'strings') {
|
|
2334
2468
|
// Strings: content design system from live code (no LLM). Extracts UI strings, flags variants,
|
|
2335
2469
|
// enforces preferred terms at the gate. Exit 1 = variants/banned terms found, for CI + the gate.
|
|
@@ -2352,11 +2486,27 @@ if (command === 'init') {
|
|
|
2352
2486
|
Promise.resolve(require('../commands/moves').movesCommand(process.argv.slice(3)))
|
|
2353
2487
|
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2354
2488
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2489
|
+
} else if (command === 'unknowns') {
|
|
2490
|
+
// Unknowns: blindspot pass from local territory context into the SQLite ledger.
|
|
2491
|
+
Promise.resolve(require('../commands/unknowns').unknownsCommand(process.argv.slice(3)))
|
|
2492
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2493
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2494
|
+
} else if (command === 'feed') {
|
|
2495
|
+
// Feed: read and post the business group feed — receipts and state changes only.
|
|
2496
|
+
// Sets exitCode instead of process.exit() so large --json output flushes fully.
|
|
2497
|
+
Promise.resolve(require('../commands/feed').feedCommand(process.argv.slice(3)))
|
|
2498
|
+
.then((code) => { process.exitCode = typeof code === 'number' ? code : 0; })
|
|
2499
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exitCode = 1; });
|
|
2355
2500
|
} else if (command === 'clarity') {
|
|
2356
2501
|
// Clarity: interview yourself once; agents read how you work so you stop repeating it.
|
|
2357
2502
|
Promise.resolve(require('../commands/clarity').clarityCommand(process.argv.slice(3)))
|
|
2358
2503
|
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2359
2504
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2505
|
+
} else if (command === 'interview') {
|
|
2506
|
+
// Interview: the interlinked 1-on-1 — live interview that extracts judgment into a member file.
|
|
2507
|
+
Promise.resolve(require('../commands/interview').interviewCommand(process.argv.slice(3)))
|
|
2508
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2509
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2360
2510
|
} else if (command === 'deck') {
|
|
2361
2511
|
// Deck: premium Google Slides from a plain content spec, via the Atris deck engine (anti-slop design system).
|
|
2362
2512
|
Promise.resolve(require('../commands/deck').run(process.argv.slice(3)))
|
|
@@ -2725,8 +2875,19 @@ async function agentAtris() {
|
|
|
2725
2875
|
async function chatAtris() {
|
|
2726
2876
|
// Get message from command line args; --agent forces the legacy cloud-agent lane
|
|
2727
2877
|
const rawArgs = process.argv.slice(3);
|
|
2728
|
-
const
|
|
2729
|
-
const
|
|
2878
|
+
const fastLaneFlags = [];
|
|
2879
|
+
const messageArgs = [];
|
|
2880
|
+
let agentLane = false;
|
|
2881
|
+
for (const arg of rawArgs) {
|
|
2882
|
+
if (arg === '--agent') {
|
|
2883
|
+
agentLane = true;
|
|
2884
|
+
} else if (arg === '--print' || arg === '--headless') {
|
|
2885
|
+
fastLaneFlags.push(arg);
|
|
2886
|
+
} else {
|
|
2887
|
+
messageArgs.push(arg);
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
const message = messageArgs.join(' ').trim();
|
|
2730
2891
|
|
|
2731
2892
|
// Respect -h / --help before any auth/state checks
|
|
2732
2893
|
if (message === '-h' || message === '--help' || message === 'help') {
|
|
@@ -2737,6 +2898,7 @@ async function chatAtris() {
|
|
|
2737
2898
|
console.log('');
|
|
2738
2899
|
console.log(' atris chat Interactive chat (ax --fast --chat)');
|
|
2739
2900
|
console.log(' atris chat "what now?" One-shot message (ax --fast)');
|
|
2901
|
+
console.log(' atris chat --print "..." Headless JSON result (ax --fast --print)');
|
|
2740
2902
|
console.log(' atris chat --agent [...] Legacy cloud-agent lane (needs `atris agent`)');
|
|
2741
2903
|
process.exit(0);
|
|
2742
2904
|
}
|
|
@@ -2748,7 +2910,7 @@ async function chatAtris() {
|
|
|
2748
2910
|
process.exit(1);
|
|
2749
2911
|
}
|
|
2750
2912
|
|
|
2751
|
-
const missionIntent = missionRunIntentFromFastMessage(message);
|
|
2913
|
+
const missionIntent = fastLaneFlags.length ? null : missionRunIntentFromFastMessage(message);
|
|
2752
2914
|
if (missionIntent) {
|
|
2753
2915
|
process.exit(await runLocalFastMission(missionIntent));
|
|
2754
2916
|
}
|
|
@@ -2761,7 +2923,7 @@ async function chatAtris() {
|
|
|
2761
2923
|
if (!agentLane) {
|
|
2762
2924
|
try {
|
|
2763
2925
|
const axPath = path.join(__dirname, '..', 'ax');
|
|
2764
|
-
const axArgs = message ? ['--fast', message] : ['--fast', '--chat'];
|
|
2926
|
+
const axArgs = message || fastLaneFlags.length ? ['--fast', ...fastLaneFlags, message].filter(Boolean) : ['--fast', '--chat'];
|
|
2765
2927
|
const run = spawnSync(process.execPath, [axPath, ...axArgs], { stdio: 'inherit' });
|
|
2766
2928
|
process.exit(run.status || 0);
|
|
2767
2929
|
} catch {
|
package/commands/aeo.js
CHANGED
|
@@ -157,6 +157,9 @@ function pickSlug(args) {
|
|
|
157
157
|
|
|
158
158
|
function printHelp() {
|
|
159
159
|
console.log('Usage:');
|
|
160
|
+
console.log(' Live scan (no login needed):');
|
|
161
|
+
console.log(' atris aeo scan <url> [--vs <competitor-url>] [--json]');
|
|
162
|
+
console.log('');
|
|
160
163
|
console.log(' Backend / EC2:');
|
|
161
164
|
console.log(' atris aeo init [--workspace <slug>]');
|
|
162
165
|
console.log(' atris aeo draft "<topic>" [--workspace <slug>] [--queries q1,q2] [--slug X] [--url URL]');
|
|
@@ -178,6 +181,54 @@ function printHelp() {
|
|
|
178
181
|
console.log(' atris aeo discover https://atris.ai/aeo --canonical-url https://atris.ai/aeo');
|
|
179
182
|
}
|
|
180
183
|
|
|
184
|
+
const FREE_SCAN_BASE = process.env.ATRIS_API_BASE || 'https://api.atris.ai';
|
|
185
|
+
|
|
186
|
+
async function aeoScan(args) {
|
|
187
|
+
const asJson = args.includes('--json');
|
|
188
|
+
const vs = readArg(args, '--vs');
|
|
189
|
+
const url = args.filter((a) => !a.startsWith('--') && a !== vs)[0];
|
|
190
|
+
if (!url) {
|
|
191
|
+
console.error('Usage: atris aeo scan <url> [--vs <competitor-url>] [--json]');
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
const target = /^https?:\/\//i.test(url) ? url : `https://${url}`;
|
|
195
|
+
const qs = new URLSearchParams({ url: target });
|
|
196
|
+
if (vs) qs.set('vs', /^https?:\/\//i.test(vs) ? vs : `https://${vs}`);
|
|
197
|
+
const endpoint = `${FREE_SCAN_BASE}/api/business/aeo/free-scan?${qs}`;
|
|
198
|
+
let data;
|
|
199
|
+
try {
|
|
200
|
+
const res = await fetch(endpoint, { signal: AbortSignal.timeout(60000) });
|
|
201
|
+
if (!res.ok) {
|
|
202
|
+
const body = await res.text().catch(() => '');
|
|
203
|
+
console.error(`Scan failed (${res.status}): ${body.slice(0, 200)}`);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
data = await res.json();
|
|
207
|
+
} catch (e) {
|
|
208
|
+
console.error(`Scan failed: ${e.message}`);
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
if (asJson) { console.log(JSON.stringify(data, null, 2)); return; }
|
|
212
|
+
console.log(`\n ${data.name || target}`);
|
|
213
|
+
console.log(` Score: ${data.score}/100 (${data.grade}) — ${data.status}`);
|
|
214
|
+
if (data.gap_statement) console.log(`\n ${data.gap_statement}`);
|
|
215
|
+
const gaps = data.gaps || [];
|
|
216
|
+
if (gaps.length) {
|
|
217
|
+
console.log('\n Gaps:');
|
|
218
|
+
for (const g of gaps) console.log(` ✗ ${g.title || g.key}: ${g.fix || ''}`);
|
|
219
|
+
}
|
|
220
|
+
const comp = data.competitors || [];
|
|
221
|
+
if (comp.length) {
|
|
222
|
+
console.log('\n Head-to-head:');
|
|
223
|
+
for (const c of comp) console.log(` ${pad(String(c.score ?? '?'), 4)} ${c.url || c.name}`);
|
|
224
|
+
}
|
|
225
|
+
if (data.draft_llms_txt) {
|
|
226
|
+
console.log('\n Draft llms.txt included — save it with:');
|
|
227
|
+
console.log(` atris aeo scan ${url} --json | jq -r .draft_llms_txt > llms.txt`);
|
|
228
|
+
}
|
|
229
|
+
console.log('');
|
|
230
|
+
}
|
|
231
|
+
|
|
181
232
|
async function aeoInit(args) {
|
|
182
233
|
const slug = pickSlug(args);
|
|
183
234
|
if (!slug) {
|
|
@@ -545,6 +596,7 @@ async function run(args = []) {
|
|
|
545
596
|
const sub = args[0];
|
|
546
597
|
if (!sub || sub === 'help' || sub === '--help' || sub === '-h') return printHelp();
|
|
547
598
|
const rest = args.slice(1);
|
|
599
|
+
if (sub === 'scan') return aeoScan(rest);
|
|
548
600
|
if (sub === 'init') return aeoInit(rest);
|
|
549
601
|
if (sub === 'draft') return aeoDraft(rest);
|
|
550
602
|
if (sub === 'log') return aeoLog(rest);
|