atris 3.30.12 → 3.32.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 +16 -3
- package/FOR_AGENTS.md +81 -0
- package/README.md +6 -4
- package/atris/CLAUDE.md +8 -0
- package/atris/atris.md +51 -19
- package/atris/skills/README.md +1 -0
- package/atris/skills/blocks/SKILL.md +134 -0
- package/atris/skills/clawhub/philosophy-of-work/SKILL.md +56 -0
- package/atris/skills/youtube/SKILL.md +31 -11
- package/atris.md +15 -0
- package/ax +189 -7
- package/bin/atris.js +273 -225
- package/commands/autoland.js +379 -0
- package/commands/autopilot-front.js +273 -0
- package/commands/autopilot.js +94 -4
- package/commands/business.js +1 -1
- package/commands/clean.js +72 -9
- package/commands/codex-goal.js +72 -22
- package/commands/computer.js +48 -3
- package/commands/gm.js +1 -1
- package/commands/harvest.js +179 -0
- package/commands/init.js +22 -1
- package/commands/land.js +442 -0
- package/commands/loop-front.js +122 -4
- package/commands/member.js +551 -19
- package/commands/mission.js +3674 -278
- package/commands/play.js +1 -1
- package/commands/pulse.js +65 -7
- package/commands/run-front.js +144 -0
- package/commands/run.js +10 -7
- package/commands/sign.js +90 -0
- package/commands/strings.js +301 -0
- package/commands/task.js +782 -108
- package/commands/truth.js +171 -0
- package/commands/xp.js +32 -8
- package/commands/youtube.js +72 -5
- package/decks/README.md +6 -12
- package/lib/auto-accept-certified.js +10 -0
- package/lib/autoland.js +391 -0
- package/lib/context-gatherer.js +0 -8
- package/lib/mission-artifact.js +504 -0
- package/lib/mission-room.js +846 -0
- package/lib/next-moves.js +212 -6
- package/lib/operator-next.js +7 -0
- package/lib/pulse.js +78 -4
- package/lib/runner-command.js +51 -20
- package/lib/runs-prune.js +242 -0
- package/lib/task-db.js +19 -2
- package/lib/task-proof.js +1 -1
- package/package.json +4 -4
- package/decks/atris-seed-pitch-v3.json +0 -118
- package/decks/atris-seed-pitch-v4-skeleton.json +0 -106
- package/decks/atris-seed-pitch-v5.json +0 -109
- package/decks/atris-seed-pitch-v6.json +0 -137
- package/decks/atris-seed-pitch-v7.json +0 -133
- package/decks/mark-pincus-narrative.json +0 -102
- package/decks/mark-pincus-sourcery.json +0 -94
- package/decks/yash-applied-compute-detailed.json +0 -150
- package/decks/yash-applied-compute-generalist.json +0 -82
- package/decks/yash-applied-compute-narrative.json +0 -54
- package/lib/ax-chat-input.js +0 -164
- package/lib/ax-goal.js +0 -307
- package/lib/ax-prefs.js +0 -63
- package/lib/ax-shimmer.js +0 -63
package/bin/atris.js
CHANGED
|
@@ -128,7 +128,16 @@ function isOptionValue(args, index, optionNames) {
|
|
|
128
128
|
|
|
129
129
|
function applyRunnerFlags(args) {
|
|
130
130
|
const runnerProfile = readOptionArg(args, '--runner-profile');
|
|
131
|
-
if (runnerProfile)
|
|
131
|
+
if (runnerProfile) {
|
|
132
|
+
// Fail fast at the CLI boundary: an unknown profile otherwise stays silent
|
|
133
|
+
// until a heartbeat spawn resolves it mid-loop (silent overnight outage).
|
|
134
|
+
const { RUNNER_PROFILES, RUNNER_PROFILE_NAMES } = require('../lib/runner-command');
|
|
135
|
+
if (!Object.prototype.hasOwnProperty.call(RUNNER_PROFILES, runnerProfile)) {
|
|
136
|
+
console.error(`Unknown --runner-profile "${runnerProfile}". Known profiles: ${RUNNER_PROFILE_NAMES.join(', ')}.`);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
process.env.ATRIS_RUNNER_PROFILE = runnerProfile;
|
|
140
|
+
}
|
|
132
141
|
const runnerBin = readOptionArg(args, '--runner-bin');
|
|
133
142
|
if (runnerBin) {
|
|
134
143
|
process.env.ATRIS_RUNNER_BIN = runnerBin;
|
|
@@ -449,7 +458,7 @@ function showHelp() {
|
|
|
449
458
|
console.log(' plan - Create build spec with visualization');
|
|
450
459
|
console.log(' do - Execute tasks');
|
|
451
460
|
console.log(' review - Validate work (tests, safety checks, docs)');
|
|
452
|
-
console.log(' run -
|
|
461
|
+
console.log(' run - One bounded mission pursuit: start or resume, tick, complete');
|
|
453
462
|
console.log(' run logs - Browse glass run logs (phase reasoning persisted to disk)');
|
|
454
463
|
console.log(' run search - Search phase reasoning across all run logs');
|
|
455
464
|
console.log(' pulse - Durable overnight self-improvement heartbeat (OS cron, install/status/tick)');
|
|
@@ -468,6 +477,7 @@ function showHelp() {
|
|
|
468
477
|
console.log(' analytics - Show recent productivity from journals');
|
|
469
478
|
console.log(' search - Search journal history (atris search <keyword>)');
|
|
470
479
|
console.log(' clean - Housekeeping (stale tasks, archive journals, broken refs)');
|
|
480
|
+
console.log(' harvest - Find bugs and next actions from receipts, run logs, and thinking');
|
|
471
481
|
console.log(' verify - Validate work is done (tests, MAP.md, changes)');
|
|
472
482
|
console.log(' task - Local agent task plane (atomic claims, TODO import)');
|
|
473
483
|
console.log(' mission - Goal + loop + member owner + verifier + receipt');
|
|
@@ -482,11 +492,14 @@ function showHelp() {
|
|
|
482
492
|
console.log('');
|
|
483
493
|
console.log('Optional helpers:');
|
|
484
494
|
console.log(' brainstorm - Explore ideas conversationally before planning');
|
|
485
|
-
console.log(' autopilot -
|
|
495
|
+
console.log(' autopilot - Keep the workspace moving: mission/member loop until you stop it');
|
|
486
496
|
console.log(' improve - Run one paid RL tick (POST /api/improve, deducts credits)');
|
|
487
497
|
console.log(' worktree - Isolated Git worktrees plus guarded ship/merge for parallel agents');
|
|
498
|
+
console.log(' land - The landing: what is actually done vs still in the air; --reap backs up + clears overdue');
|
|
499
|
+
console.log(' autoland - Approve the policy once; certified work lands itself, you keep irreversible calls');
|
|
500
|
+
console.log(' sign - Co-author trailer on every commit in an atris workspace (on/off/status)');
|
|
488
501
|
console.log(' visualize - Generate a Slack/deck-ready visual from a prompt');
|
|
489
|
-
console.log(' youtube - Process YouTube videos with
|
|
502
|
+
console.log(' youtube - Process YouTube videos with timestamped transcript-first analysis');
|
|
490
503
|
console.log('');
|
|
491
504
|
console.log('Experiments:');
|
|
492
505
|
console.log(' experiments init [slug] - Prepare atris/experiments/ or scaffold a pack');
|
|
@@ -544,7 +557,7 @@ function showHelp() {
|
|
|
544
557
|
console.log(' soul - Show, snapshot, or fork workspace identity');
|
|
545
558
|
console.log(' fleet - Inspect local fleet status');
|
|
546
559
|
console.log(' agent - Select cloud agent, spawn worker requests, or run `agent doctor`');
|
|
547
|
-
console.log(' chat - Chat with
|
|
560
|
+
console.log(' chat - Chat with Atris 2 Fast in this workspace (--agent for cloud agent; or: atris chat scan)');
|
|
548
561
|
console.log(' fast - Chat with Atris2 Fast');
|
|
549
562
|
console.log(' login - Sign in or add another account');
|
|
550
563
|
console.log(' logout - Sign out of current account');
|
|
@@ -831,22 +844,27 @@ function showServeHelp() {
|
|
|
831
844
|
|
|
832
845
|
function showLoopHelp() {
|
|
833
846
|
console.log('');
|
|
834
|
-
console.log('Usage: atris loop [
|
|
847
|
+
console.log('Usage: atris loop [add|start|status|report|stop|wiki] [options]');
|
|
835
848
|
console.log('');
|
|
836
849
|
console.log('Description:');
|
|
837
|
-
console.log('
|
|
850
|
+
console.log(' One front door for the self-improvement loop. It reads ROADMAP.md,');
|
|
851
|
+
console.log(' runs bounded proof-backed work, and keeps wiki upkeep under loop wiki.');
|
|
838
852
|
console.log('');
|
|
839
|
-
console.log('
|
|
840
|
-
console.log('
|
|
841
|
-
console.log(' --
|
|
842
|
-
console.log(' --
|
|
843
|
-
console.log(' --
|
|
853
|
+
console.log('Commands:');
|
|
854
|
+
console.log(' atris loop add "<task>" Put a bounded task into the loop queue.');
|
|
855
|
+
console.log(' atris loop start [--once] Run the local loop.');
|
|
856
|
+
console.log(' atris loop start --overnight Install the durable heartbeat.');
|
|
857
|
+
console.log(' atris loop status [--json] Show heartbeat, local runs, and next moves.');
|
|
858
|
+
console.log(' atris loop report [--json] Show proof of handled and queued loop work.');
|
|
859
|
+
console.log(' atris loop stop Remove the durable heartbeat.');
|
|
860
|
+
console.log(' atris loop wiki Run the wiki upkeep loop.');
|
|
861
|
+
console.log(' --help, -h Show this help.');
|
|
844
862
|
console.log('');
|
|
845
863
|
}
|
|
846
864
|
|
|
847
865
|
function showCleanHelp() {
|
|
848
866
|
console.log('');
|
|
849
|
-
console.log('Usage: atris clean [--dry-run]');
|
|
867
|
+
console.log('Usage: atris clean [--dry-run] [--json]');
|
|
850
868
|
console.log('');
|
|
851
869
|
console.log('Description:');
|
|
852
870
|
console.log(' Check workspace housekeeping: stale tasks, MAP.md refs, old journals,');
|
|
@@ -854,6 +872,7 @@ function showCleanHelp() {
|
|
|
854
872
|
console.log('');
|
|
855
873
|
console.log('Options:');
|
|
856
874
|
console.log(' --dry-run, -n Preview cleanup without changing files.');
|
|
875
|
+
console.log(' --json Print machine-readable cleanup results.');
|
|
857
876
|
console.log(' --help, -h Show this help.');
|
|
858
877
|
console.log('');
|
|
859
878
|
}
|
|
@@ -876,7 +895,7 @@ function showAutopilotHelp() {
|
|
|
876
895
|
console.log(' --runner-bin PATH Runner binary for this run');
|
|
877
896
|
console.log(' --runner-template CMD Runner command template for this run');
|
|
878
897
|
console.log(' --runner-model MODEL Runner model for this run');
|
|
879
|
-
console.log(
|
|
898
|
+
console.log(` --runner-profile NAME Runner profile for this run (one of: ${require('../lib/runner-command').RUNNER_PROFILE_NAMES.join(', ')})`);
|
|
880
899
|
console.log('');
|
|
881
900
|
console.log('Examples:');
|
|
882
901
|
console.log(' atris autopilot # Suggest from existing work');
|
|
@@ -913,12 +932,12 @@ if (command === '2' && ['fast', 'pro'].includes(String(firstCommandArg || '').to
|
|
|
913
932
|
}
|
|
914
933
|
|
|
915
934
|
// Check if this is a known command or natural language input
|
|
916
|
-
const knownCommands = ['init', 'log', 'now', 'radar', 'ctop', 'launchpad', 'status', 'analytics', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', 'plan', 'do', 'review', 'release',
|
|
935
|
+
const knownCommands = ['init', 'log', 'now', 'radar', 'ctop', 'launchpad', 'status', 'analytics', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', '_start', 'plan', 'do', 'review', 'release',
|
|
917
936
|
'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',
|
|
918
|
-
'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',
|
|
919
|
-
'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'probe', 'worktree', 'aeo', 'slop', 'security-review', 'secure', 'deck', 'site', 'theme', 'card', 'reel', 'improve', 'xp', 'play', 'gm', 'x', 'recap', 'signup', 'clarity', 'moves',
|
|
937
|
+
'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',
|
|
938
|
+
'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',
|
|
920
939
|
'gmail', 'calendar', 'twitter', 'slack', 'imessage', 'integrations', 'setup', 'clean-workspace', 'cw',
|
|
921
|
-
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'compile', 'spaceship'];
|
|
940
|
+
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'compile', 'spaceship', 'truth', 'sign'];
|
|
922
941
|
|
|
923
942
|
// Check if command is an atris.md spec file - triggers welcome visualization
|
|
924
943
|
function isSpecFile(cmd) {
|
|
@@ -940,7 +959,15 @@ if (command === '--version' || command === '-v' || process.argv.includes('--vers
|
|
|
940
959
|
// If no command OR command is not recognized, treat as natural language
|
|
941
960
|
// Voice-friendly aliases — natural language → command mapping
|
|
942
961
|
// Solves speech-to-text issues (inspired by gstack v0.14.6 voice-triggers)
|
|
962
|
+
const START_MISSION_OBJECTIVE = 'self improve goal after goal: pick one useful bounded mission from current Atris state, run proof, and continue only with real next work';
|
|
963
|
+
|
|
943
964
|
const voiceTriggers = {
|
|
965
|
+
'start': '_start',
|
|
966
|
+
'start now': '_start',
|
|
967
|
+
'go': '_start',
|
|
968
|
+
'keep going': '_start',
|
|
969
|
+
'keepgoing': '_start',
|
|
970
|
+
'keep-going': '_start',
|
|
944
971
|
'review my code': 'code-review',
|
|
945
972
|
'check my code': 'code-review',
|
|
946
973
|
'run a review': 'code-review',
|
|
@@ -965,7 +992,12 @@ const voiceTriggers = {
|
|
|
965
992
|
if (!command || !knownCommands.includes(command)) {
|
|
966
993
|
// Check voice triggers before falling through to natural language
|
|
967
994
|
const fullInput = process.argv.slice(2).join(' ').toLowerCase().trim();
|
|
968
|
-
const
|
|
995
|
+
const fullInputWithoutFlags = process.argv.slice(2)
|
|
996
|
+
.filter((arg, index, args) => !String(arg).startsWith('-') && !isOptionValue(args, index, RUNNER_FLAG_NAMES))
|
|
997
|
+
.join(' ')
|
|
998
|
+
.toLowerCase()
|
|
999
|
+
.trim();
|
|
1000
|
+
const triggered = voiceTriggers[fullInput] || voiceTriggers[fullInputWithoutFlags];
|
|
969
1001
|
if (triggered) {
|
|
970
1002
|
command = triggered;
|
|
971
1003
|
// Re-check — if it's now a known command, fall through to dispatch
|
|
@@ -1355,6 +1387,12 @@ function showWelcomeVisualization() {
|
|
|
1355
1387
|
: `${tasksInReview} waiting`;
|
|
1356
1388
|
console.log(` │ ⏳ Review: ${reviewText.padEnd(26)}│`);
|
|
1357
1389
|
}
|
|
1390
|
+
let landInfo = null;
|
|
1391
|
+
try { landInfo = require('../commands/land').landSummary(process.cwd()); } catch (err) { landInfo = null; }
|
|
1392
|
+
if (landInfo && landInfo.branches > 0) {
|
|
1393
|
+
const landText = `${landInfo.branches} in the air, ${landInfo.due} overdue`;
|
|
1394
|
+
console.log(` │ 🛬 Land: ${landText.padEnd(26)}│`);
|
|
1395
|
+
}
|
|
1358
1396
|
console.log(` │ 📝 Journal: ${(journalEntries + ' entries today').padEnd(26)}│`);
|
|
1359
1397
|
if (endgameState.slug !== 'unset' && endgameState.horizon) {
|
|
1360
1398
|
const endgameLine = endgameState.slug + ' — ' + endgameState.horizon;
|
|
@@ -1377,7 +1415,13 @@ function showWelcomeVisualization() {
|
|
|
1377
1415
|
if (tasksCertified > 0) {
|
|
1378
1416
|
console.log(` Ready. ${tasksCertified} certified await accept — run 'atris task reviews'.`);
|
|
1379
1417
|
} else {
|
|
1380
|
-
|
|
1418
|
+
let landHint = null;
|
|
1419
|
+
try { landHint = require('../commands/land').landSummary(process.cwd()); } catch (err) { landHint = null; }
|
|
1420
|
+
if (landHint && landHint.due > 0) {
|
|
1421
|
+
console.log(` Ready. ${landHint.due} overdue in the landing — run 'atris land --reap'.`);
|
|
1422
|
+
} else {
|
|
1423
|
+
console.log(` Ready. Run 'atris plan' to start.`);
|
|
1424
|
+
}
|
|
1381
1425
|
}
|
|
1382
1426
|
console.log('');
|
|
1383
1427
|
}
|
|
@@ -1398,6 +1442,40 @@ if (command === 'init') {
|
|
|
1398
1442
|
console.error(`✗ Error: ${error.message || error}`);
|
|
1399
1443
|
process.exit(1);
|
|
1400
1444
|
});
|
|
1445
|
+
} else if (command === '_start') {
|
|
1446
|
+
const args = process.argv.slice(3);
|
|
1447
|
+
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
1448
|
+
console.log('');
|
|
1449
|
+
console.log('Usage: atris start [options]');
|
|
1450
|
+
console.log('');
|
|
1451
|
+
console.log('Starts the durable mission loop for one useful self-improvement mission.');
|
|
1452
|
+
console.log('');
|
|
1453
|
+
console.log('Options:');
|
|
1454
|
+
console.log(' --json Print the mission route without starting it.');
|
|
1455
|
+
console.log(' --owner X Override mission owner.');
|
|
1456
|
+
console.log(' --cadence X Override mission cadence.');
|
|
1457
|
+
console.log('');
|
|
1458
|
+
process.exit(0);
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
if (args.includes('--json')) {
|
|
1462
|
+
console.log(JSON.stringify({
|
|
1463
|
+
ok: true,
|
|
1464
|
+
action: 'start_mission_run',
|
|
1465
|
+
route: `atris mission run "${START_MISSION_OBJECTIVE}"`,
|
|
1466
|
+
reason: 'casual_launch',
|
|
1467
|
+
objective: START_MISSION_OBJECTIVE,
|
|
1468
|
+
expected_loop: 'mission_run',
|
|
1469
|
+
}, null, 2));
|
|
1470
|
+
process.exit(0);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
Promise.resolve(require('../commands/mission').missionCommand(['run', START_MISSION_OBJECTIVE, ...args]))
|
|
1474
|
+
.then(() => process.exit(process.exitCode || 0))
|
|
1475
|
+
.catch((error) => {
|
|
1476
|
+
console.error(`✗ Start failed: ${error.message || error}`);
|
|
1477
|
+
process.exit(1);
|
|
1478
|
+
});
|
|
1401
1479
|
} else if (command === 'task') {
|
|
1402
1480
|
// SQLite-backed task plane. ~/.atris/tasks.db, gitignored, per-workspace.
|
|
1403
1481
|
Promise.resolve(require('../commands/task').run(process.argv.slice(3)))
|
|
@@ -1421,11 +1499,24 @@ if (command === 'init') {
|
|
|
1421
1499
|
Promise.resolve(require('../commands/worktree').worktreeCommand(process.argv.slice(3)))
|
|
1422
1500
|
.then((code) => process.exit(code || 0))
|
|
1423
1501
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1502
|
+
} else if (command === 'autoland') {
|
|
1503
|
+
Promise.resolve(require('../commands/autoland').autolandCommand(process.argv.slice(3)))
|
|
1504
|
+
.then((code) => process.exit(code || 0))
|
|
1505
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1506
|
+
} else if (command === 'land') {
|
|
1507
|
+
Promise.resolve(require('../commands/land').landCommand(process.argv.slice(3)))
|
|
1508
|
+
.then((code) => process.exit(code || 0))
|
|
1509
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1424
1510
|
} else if (command === 'radar' || command === 'ctop') {
|
|
1425
1511
|
const radarArgs = command === 'ctop' ? ['--agents', ...process.argv.slice(3)] : process.argv.slice(3);
|
|
1426
1512
|
Promise.resolve(require('../commands/radar').radarCommand(radarArgs))
|
|
1427
1513
|
.then((code) => process.exit(code || 0))
|
|
1428
1514
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1515
|
+
} else if (command === 'truth') {
|
|
1516
|
+
// Truth: one table rolling up mission state, tasks, feature proof receipts, and loop heartbeats.
|
|
1517
|
+
Promise.resolve(require('../commands/truth').truthCommand(process.argv.slice(3)))
|
|
1518
|
+
.then((code) => process.exit(code || 0))
|
|
1519
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1429
1520
|
} else if (command === 'codex-goal') {
|
|
1430
1521
|
Promise.resolve(require('../commands/codex-goal').codexGoalCommand(process.argv.slice(3)))
|
|
1431
1522
|
.then(() => process.exit(process.exitCode || 0))
|
|
@@ -1750,23 +1841,26 @@ if (command === 'init') {
|
|
|
1750
1841
|
}
|
|
1751
1842
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
1752
1843
|
console.log('');
|
|
1753
|
-
console.log('Usage: atris run [options]');
|
|
1844
|
+
console.log('Usage: atris run ["objective"] [options]');
|
|
1754
1845
|
console.log('');
|
|
1755
|
-
console.log('
|
|
1756
|
-
console.log('
|
|
1846
|
+
console.log('One bounded mission pursuit: start a mission from the objective');
|
|
1847
|
+
console.log('(or resume the most logical runnable mission), tick it through the');
|
|
1848
|
+
console.log('mission runtime, complete on pass, then exit.');
|
|
1849
|
+
console.log('For an ongoing loop, use: atris autopilot');
|
|
1757
1850
|
console.log('');
|
|
1758
1851
|
console.log('Options:');
|
|
1759
|
-
console.log(' --
|
|
1760
|
-
console.log(' --
|
|
1761
|
-
console.log(' --
|
|
1762
|
-
console.log(' --
|
|
1763
|
-
console.log(' --
|
|
1764
|
-
console.log(' --
|
|
1765
|
-
console.log(' --
|
|
1766
|
-
console.log('
|
|
1767
|
-
console.log('
|
|
1768
|
-
console.log(' --
|
|
1769
|
-
console.log(' --
|
|
1852
|
+
console.log(' --owner NAME Mission owner (default: mission-lead)');
|
|
1853
|
+
console.log(' --minutes N | --hours N Time budget for the pursuit');
|
|
1854
|
+
console.log(' --max-ticks N Override the tick budget');
|
|
1855
|
+
console.log(' --max-wall N Override the wall clock in seconds');
|
|
1856
|
+
console.log(' --cadence C Mission cadence (e.g. 15m)');
|
|
1857
|
+
console.log(' --no-complete Skip auto-complete after a passing run');
|
|
1858
|
+
console.log(' --legacy Old plan→do→review loop (claude -p cycles)');
|
|
1859
|
+
console.log('');
|
|
1860
|
+
console.log('Legacy options (with --legacy):');
|
|
1861
|
+
console.log(' --cycles=N --once --verbose --dry-run --timeout=N --no-push');
|
|
1862
|
+
console.log(' --runner-bin PATH / --runner-template CMD / --runner-model MODEL');
|
|
1863
|
+
console.log(` --runner-profile NAME Runner profile for this run (one of: ${require('../lib/runner-command').RUNNER_PROFILE_NAMES.join(', ')})`);
|
|
1770
1864
|
console.log('');
|
|
1771
1865
|
console.log('Subcommands:');
|
|
1772
1866
|
console.log(' atris run logs [--tail N] [--cat FILE] [--json] Browse glass run logs');
|
|
@@ -1779,62 +1873,81 @@ if (command === 'init') {
|
|
|
1779
1873
|
process.exit(0);
|
|
1780
1874
|
}
|
|
1781
1875
|
|
|
1782
|
-
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
1783
|
-
const dryRun = args.includes('--dry-run');
|
|
1784
|
-
const once = args.includes('--once');
|
|
1785
|
-
const push = !args.includes('--no-push');
|
|
1786
1876
|
applyRunnerFlags(args);
|
|
1787
|
-
const cyclesArg = args.find(a => a.startsWith('--cycles='));
|
|
1788
|
-
const maxCycles = cyclesArg ? parseInt(cyclesArg.split('=')[1]) : 5;
|
|
1789
|
-
const timeoutArg = args.find(a => a.startsWith('--timeout='));
|
|
1790
|
-
const timeout = timeoutArg ? parseInt(timeoutArg.split('=')[1]) * 1000 : undefined;
|
|
1791
1877
|
|
|
1792
|
-
|
|
1793
|
-
.
|
|
1794
|
-
.
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1878
|
+
if (args.includes('--legacy')) {
|
|
1879
|
+
const legacyArgs = args.filter(a => a !== '--legacy');
|
|
1880
|
+
const verbose = legacyArgs.includes('--verbose') || legacyArgs.includes('-v');
|
|
1881
|
+
const dryRun = legacyArgs.includes('--dry-run');
|
|
1882
|
+
const once = legacyArgs.includes('--once');
|
|
1883
|
+
const push = !legacyArgs.includes('--no-push');
|
|
1884
|
+
const cyclesArg = legacyArgs.find(a => a.startsWith('--cycles='));
|
|
1885
|
+
const maxCycles = cyclesArg ? parseInt(cyclesArg.split('=')[1]) : 5;
|
|
1886
|
+
const timeoutArg = legacyArgs.find(a => a.startsWith('--timeout='));
|
|
1887
|
+
const timeout = timeoutArg ? parseInt(timeoutArg.split('=')[1]) * 1000 : undefined;
|
|
1888
|
+
|
|
1889
|
+
require('../commands/run').runAtris({ maxCycles, verbose, dryRun, once, push, timeout })
|
|
1890
|
+
.then(() => process.exit(0))
|
|
1891
|
+
.catch((error) => {
|
|
1892
|
+
console.error(`\u2717 Run failed: ${error.message || error}`);
|
|
1893
|
+
process.exit(1);
|
|
1894
|
+
});
|
|
1895
|
+
} else {
|
|
1896
|
+
require('../commands/run-front').runMissionFront(args)
|
|
1897
|
+
.then((code) => process.exit(code || 0))
|
|
1898
|
+
.catch((error) => {
|
|
1899
|
+
console.error(`\u2717 Run failed: ${error.message || error}`);
|
|
1900
|
+
process.exit(1);
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1798
1903
|
} else if (command === 'launchpad') {
|
|
1799
1904
|
const code = require('../commands/launchpad').launchpadCommand(process.argv.slice(3));
|
|
1800
1905
|
process.exit(code);
|
|
1801
1906
|
} else if (command === 'autopilot') {
|
|
1802
1907
|
const args = process.argv.slice(3);
|
|
1803
|
-
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
1804
|
-
showAutopilotHelp();
|
|
1805
|
-
process.exit(0);
|
|
1806
|
-
}
|
|
1807
|
-
|
|
1808
|
-
// Parse options
|
|
1809
|
-
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
1810
|
-
const dryRun = args.includes('--dry-run');
|
|
1811
|
-
const auto = args.includes('--auto');
|
|
1812
1908
|
applyRunnerFlags(args);
|
|
1813
|
-
const maxIterationsArg = args.find(a => a.startsWith('--iterations='));
|
|
1814
|
-
const maxIterations = maxIterationsArg ? parseInt(maxIterationsArg.split('=')[1]) : undefined;
|
|
1815
|
-
const durationArg = args.find(a => a.startsWith('--duration='));
|
|
1816
|
-
const duration = durationArg ? durationArg.split('=')[1] : null;
|
|
1817
|
-
|
|
1818
|
-
// Get description (non-flag args)
|
|
1819
|
-
const description = args.filter((a, i) => !a.startsWith('-') && !isOptionValue(args, i, RUNNER_FLAG_NAMES)).join(' ').trim() || null;
|
|
1820
|
-
|
|
1821
|
-
const options = {
|
|
1822
|
-
...(maxIterations !== undefined && { maxIterations }),
|
|
1823
|
-
verbose,
|
|
1824
|
-
dryRun,
|
|
1825
|
-
auto,
|
|
1826
|
-
duration
|
|
1827
|
-
};
|
|
1828
1909
|
|
|
1829
|
-
|
|
1830
|
-
|
|
1910
|
+
if (args.includes('--legacy')) {
|
|
1911
|
+
const legacyArgs = args.filter(a => a !== '--legacy');
|
|
1912
|
+
if (legacyArgs.includes('--help') || legacyArgs.includes('-h') || legacyArgs[0] === 'help') {
|
|
1913
|
+
showAutopilotHelp();
|
|
1914
|
+
process.exit(0);
|
|
1915
|
+
}
|
|
1831
1916
|
|
|
1832
|
-
|
|
1833
|
-
.
|
|
1834
|
-
.
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1917
|
+
// Parse options
|
|
1918
|
+
const verbose = legacyArgs.includes('--verbose') || legacyArgs.includes('-v');
|
|
1919
|
+
const dryRun = legacyArgs.includes('--dry-run');
|
|
1920
|
+
const auto = legacyArgs.includes('--auto');
|
|
1921
|
+
const maxIterationsArg = legacyArgs.find(a => a.startsWith('--iterations='));
|
|
1922
|
+
const maxIterations = maxIterationsArg ? parseInt(maxIterationsArg.split('=')[1]) : undefined;
|
|
1923
|
+
const durationArg = legacyArgs.find(a => a.startsWith('--duration='));
|
|
1924
|
+
const duration = durationArg ? durationArg.split('=')[1] : null;
|
|
1925
|
+
|
|
1926
|
+
// Get description (non-flag args)
|
|
1927
|
+
const description = legacyArgs.filter((a, i) => !a.startsWith('-') && !isOptionValue(legacyArgs, i, RUNNER_FLAG_NAMES)).join(' ').trim() || null;
|
|
1928
|
+
|
|
1929
|
+
const options = {
|
|
1930
|
+
...(maxIterations !== undefined && { maxIterations }),
|
|
1931
|
+
verbose,
|
|
1932
|
+
dryRun,
|
|
1933
|
+
auto,
|
|
1934
|
+
duration
|
|
1935
|
+
};
|
|
1936
|
+
|
|
1937
|
+
require('../commands/autopilot').autopilotAtris(description, options)
|
|
1938
|
+
.then(() => process.exit(0))
|
|
1939
|
+
.catch((error) => {
|
|
1940
|
+
console.error(`✗ Autopilot failed: ${error.message || error}`);
|
|
1941
|
+
process.exit(1);
|
|
1942
|
+
});
|
|
1943
|
+
} else {
|
|
1944
|
+
Promise.resolve(require('../commands/autopilot-front').autopilotFront(args))
|
|
1945
|
+
.then((code) => process.exit(code || 0))
|
|
1946
|
+
.catch((error) => {
|
|
1947
|
+
console.error(`✗ Autopilot failed: ${error.message || error}`);
|
|
1948
|
+
process.exit(1);
|
|
1949
|
+
});
|
|
1950
|
+
}
|
|
1838
1951
|
} else if (command === 'brainstorm') {
|
|
1839
1952
|
require('../commands/brainstorm').brainstormAtris()
|
|
1840
1953
|
.then(() => process.exit(0))
|
|
@@ -1922,7 +2035,14 @@ if (command === 'init') {
|
|
|
1922
2035
|
process.exit(0);
|
|
1923
2036
|
}
|
|
1924
2037
|
const dryRun = process.argv.includes('--dry-run') || process.argv.includes('-n');
|
|
1925
|
-
|
|
2038
|
+
const json = process.argv.includes('--json');
|
|
2039
|
+
require('../commands/clean').cleanAtris({ dryRun, json });
|
|
2040
|
+
} else if (command === 'harvest') {
|
|
2041
|
+
Promise.resolve(require('../commands/harvest').harvestCommand(process.argv.slice(3)))
|
|
2042
|
+
.catch((err) => {
|
|
2043
|
+
console.error(err.message || err);
|
|
2044
|
+
process.exit(1);
|
|
2045
|
+
});
|
|
1926
2046
|
} else if (command === 'verify') {
|
|
1927
2047
|
const args = process.argv.slice(3);
|
|
1928
2048
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
@@ -2130,8 +2250,8 @@ if (command === 'init') {
|
|
|
2130
2250
|
showLoopHelp();
|
|
2131
2251
|
process.exit(0);
|
|
2132
2252
|
}
|
|
2133
|
-
require('../commands/loop').
|
|
2134
|
-
.then(() => process.exit(0))
|
|
2253
|
+
Promise.resolve(require('../commands/loop-front').loopFront(args))
|
|
2254
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2135
2255
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2136
2256
|
} else if (command === 'clean-workspace' || command === 'cw') {
|
|
2137
2257
|
const { cleanWorkspace } = require('../commands/workspace-clean');
|
|
@@ -2152,11 +2272,21 @@ if (command === 'init') {
|
|
|
2152
2272
|
Promise.resolve(require('../commands/compile').compileCommand(subcommand, ...args))
|
|
2153
2273
|
.then(() => process.exit(process.exitCode || 0))
|
|
2154
2274
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2275
|
+
} else if (command === 'sign') {
|
|
2276
|
+
// Sign: prepare-commit-msg hook that credits Atris as co-author on commits in atris workspaces.
|
|
2277
|
+
try { process.exit(require('../commands/sign').signCommand(process.argv[3]) || 0); }
|
|
2278
|
+
catch (err) { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); }
|
|
2155
2279
|
} else if (command === 'slop') {
|
|
2156
2280
|
// Slop: deterministic frontend-slop detector (no LLM). Exit 1 = slop found, for CI + the autopilot gate.
|
|
2157
2281
|
Promise.resolve(require('../commands/slop').slopCommand(process.argv.slice(3)))
|
|
2158
2282
|
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2159
2283
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2284
|
+
} else if (command === 'strings') {
|
|
2285
|
+
// Strings: content design system from live code (no LLM). Extracts UI strings, flags variants,
|
|
2286
|
+
// enforces preferred terms at the gate. Exit 1 = variants/banned terms found, for CI + the gate.
|
|
2287
|
+
Promise.resolve(require('../commands/strings').stringsCommand(process.argv.slice(3)))
|
|
2288
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2289
|
+
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2160
2290
|
} else if (command === 'security-review' || command === 'secure') {
|
|
2161
2291
|
// Security review: deterministic secrets/PII/code-risk scan (no LLM). Exit 1 = HIGH finding,
|
|
2162
2292
|
// for the autopilot/mission/CI gate + a SOC 2 evidence artifact via --json.
|
|
@@ -2410,13 +2540,12 @@ async function agentAtris() {
|
|
|
2410
2540
|
// Respect -h / --help / help before any auth/state work
|
|
2411
2541
|
const firstArg = process.argv[3];
|
|
2412
2542
|
if (firstArg === '-h' || firstArg === '--help' || firstArg === 'help') {
|
|
2413
|
-
console.log('Usage: atris agent [doctor|
|
|
2543
|
+
console.log('Usage: atris agent [doctor|spawn|spawns|spawn-status]');
|
|
2414
2544
|
console.log('');
|
|
2415
2545
|
console.log(' Pick which cloud agent to chat with from this workspace.');
|
|
2416
2546
|
console.log(' Run `atris agent spawn <role> --task "..."` to create a worker request.');
|
|
2417
2547
|
console.log(' Run `atris agent spawns` to list worker requests.');
|
|
2418
2548
|
console.log(' Run `atris agent doctor` to verify local AI CLIs can see Atris context.');
|
|
2419
|
-
console.log(' Run `atris agent dogfood --live` to smoke-test Devin/Droid with GLM 5.2.');
|
|
2420
2549
|
console.log(' Requires `atris login` first.');
|
|
2421
2550
|
console.log('');
|
|
2422
2551
|
console.log(' After selecting, use: atris chat ["message"]');
|
|
@@ -2427,7 +2556,19 @@ async function agentAtris() {
|
|
|
2427
2556
|
agentDoctor();
|
|
2428
2557
|
}
|
|
2429
2558
|
if (firstArg === 'dogfood') {
|
|
2430
|
-
|
|
2559
|
+
// Internal diagnostic, gated off the public CLI. Operators use `atris agent doctor`.
|
|
2560
|
+
if (!process.env.ATRIS_INTERNAL_AGENT_DOGFOOD) {
|
|
2561
|
+
console.error('atris agent dogfood is an internal diagnostic and is not part of the public CLI.');
|
|
2562
|
+
console.error('Run `atris agent doctor` to verify local AI CLIs can see Atris context.');
|
|
2563
|
+
process.exit(1);
|
|
2564
|
+
}
|
|
2565
|
+
const dogfoodArgs = process.argv.slice(4);
|
|
2566
|
+
if (dogfoodArgs.includes('--help') || dogfoodArgs.includes('-h') || dogfoodArgs[0] === 'help') {
|
|
2567
|
+
console.log('Internal usage: atris agent dogfood [--live]');
|
|
2568
|
+
console.log(' Smoke-test Devin/Droid with GLM 5.2. Gated behind ATRIS_INTERNAL_AGENT_DOGFOOD.');
|
|
2569
|
+
process.exit(0);
|
|
2570
|
+
}
|
|
2571
|
+
const result = require('../commands/agent-spawn').agentDogfoodCommand(dogfoodArgs);
|
|
2431
2572
|
process.exit(result.ok ? 0 : 1);
|
|
2432
2573
|
}
|
|
2433
2574
|
if (firstArg === 'spawn') {
|
|
@@ -2533,18 +2674,21 @@ async function agentAtris() {
|
|
|
2533
2674
|
|
|
2534
2675
|
|
|
2535
2676
|
async function chatAtris() {
|
|
2536
|
-
// Get message from command line args
|
|
2537
|
-
const
|
|
2677
|
+
// Get message from command line args; --agent forces the legacy cloud-agent lane
|
|
2678
|
+
const rawArgs = process.argv.slice(3);
|
|
2679
|
+
const agentLane = rawArgs.includes('--agent');
|
|
2680
|
+
const message = rawArgs.filter(arg => arg !== '--agent').join(' ').trim();
|
|
2538
2681
|
|
|
2539
2682
|
// Respect -h / --help before any auth/state checks
|
|
2540
2683
|
if (message === '-h' || message === '--help' || message === 'help') {
|
|
2541
2684
|
console.log('Usage: atris chat ["message"]');
|
|
2542
2685
|
console.log('');
|
|
2543
|
-
console.log('
|
|
2544
|
-
console.log(' Requires `atris login
|
|
2686
|
+
console.log(' Chat with Atris 2 Fast in this workspace: tools attached, same turn as `ax --fast`.');
|
|
2687
|
+
console.log(' Requires `atris login`.');
|
|
2545
2688
|
console.log('');
|
|
2546
|
-
console.log(' atris chat Interactive
|
|
2547
|
-
console.log(' atris chat "what now?" One-shot message');
|
|
2689
|
+
console.log(' atris chat Interactive chat (ax --fast --chat)');
|
|
2690
|
+
console.log(' atris chat "what now?" One-shot message (ax --fast)');
|
|
2691
|
+
console.log(' atris chat --agent [...] Legacy cloud-agent lane (needs `atris agent`)');
|
|
2548
2692
|
process.exit(0);
|
|
2549
2693
|
}
|
|
2550
2694
|
|
|
@@ -2560,6 +2704,22 @@ async function chatAtris() {
|
|
|
2560
2704
|
process.exit(await runLocalFastMission(missionIntent));
|
|
2561
2705
|
}
|
|
2562
2706
|
|
|
2707
|
+
// Workspace standard v2: `atris chat` is the same turn as `ax --fast`,
|
|
2708
|
+
// Atris 2 Fast with tools attached, ax owning routing (local tool loop,
|
|
2709
|
+
// cloud fallback when no backend listens). The pro-chat cloud-agent lane
|
|
2710
|
+
// survives behind --agent only; it 404s the moment a saved agent is
|
|
2711
|
+
// deleted server-side and cannot see the workspace.
|
|
2712
|
+
if (!agentLane) {
|
|
2713
|
+
try {
|
|
2714
|
+
const axPath = path.join(__dirname, '..', 'ax');
|
|
2715
|
+
const axArgs = message ? ['--fast', message] : ['--fast', '--chat'];
|
|
2716
|
+
const run = spawnSync(process.execPath, [axPath, ...axArgs], { stdio: 'inherit' });
|
|
2717
|
+
process.exit(run.status || 0);
|
|
2718
|
+
} catch {
|
|
2719
|
+
// ax unavailable: fall through to the agent lane.
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2563
2723
|
printAtrisGoalBanner(process.cwd());
|
|
2564
2724
|
|
|
2565
2725
|
// Check agent selected
|
|
@@ -2609,7 +2769,13 @@ async function chatOnce(config, credentials, message) {
|
|
|
2609
2769
|
await streamProChat(endpoint, credentials.token, body);
|
|
2610
2770
|
console.log('\n\n✓ Complete\n');
|
|
2611
2771
|
} catch (error) {
|
|
2612
|
-
|
|
2772
|
+
const detail = String(error.message || error);
|
|
2773
|
+
if (/404/.test(detail) && /agent not found/i.test(detail)) {
|
|
2774
|
+
console.error(`\n✗ Error: Agent "${config.agent_name || agentId}" no longer exists on the server.`);
|
|
2775
|
+
console.error(' Run "atris agent" to pick a new one, or drop --agent to use the fast workspace lane.');
|
|
2776
|
+
} else {
|
|
2777
|
+
console.error(`\n✗ Error: ${detail}`);
|
|
2778
|
+
}
|
|
2613
2779
|
process.exit(1);
|
|
2614
2780
|
}
|
|
2615
2781
|
}
|
|
@@ -2809,6 +2975,20 @@ async function atrisFastChat() {
|
|
|
2809
2975
|
process.exit(await runLocalFastMission(missionIntent));
|
|
2810
2976
|
}
|
|
2811
2977
|
|
|
2978
|
+
// One routing brain: `atris fast` defers to ax's AX Context Standard. A
|
|
2979
|
+
// workspace-shaped question asked from inside a workspace needs local tools
|
|
2980
|
+
// (this lane is a tool-less cloud one-shot and confabulates on repo
|
|
2981
|
+
// questions — SwapBench 2026-07-02), so delegate the whole turn to ax.
|
|
2982
|
+
try {
|
|
2983
|
+
const axModule = require('../ax');
|
|
2984
|
+
if (axModule.resolveRoute(message) === 'local') {
|
|
2985
|
+
const run = spawnSync(process.execPath, [path.join(__dirname, '..', 'ax'), '--fast', message], { stdio: 'inherit' });
|
|
2986
|
+
process.exit(run.status || 0);
|
|
2987
|
+
}
|
|
2988
|
+
} catch {
|
|
2989
|
+
// ax unavailable: fall through to the plain cloud one-shot.
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2812
2992
|
printAtrisGoalBanner(process.cwd());
|
|
2813
2993
|
|
|
2814
2994
|
const ensured = await ensureValidCredentials();
|
|
@@ -2840,135 +3020,3 @@ async function atrisFastOnce(credentials, message) {
|
|
|
2840
3020
|
await streamProChat(endpoint, credentials.token, body);
|
|
2841
3021
|
console.log('\n\n✓ Complete\n');
|
|
2842
3022
|
}
|
|
2843
|
-
|
|
2844
|
-
async function atrisDevEntry(userInput = null) {
|
|
2845
|
-
// Load workspace context and present planning-ready state
|
|
2846
|
-
// userInput: optional task description for hot start
|
|
2847
|
-
const targetDir = path.join(process.cwd(), 'atris');
|
|
2848
|
-
|
|
2849
|
-
// Check if Atris is initialized
|
|
2850
|
-
if (!fs.existsSync(targetDir)) {
|
|
2851
|
-
console.log('');
|
|
2852
|
-
console.log('🚀 Welcome to Atris\n');
|
|
2853
|
-
console.log('Not initialized yet. Let\'s get started:\n');
|
|
2854
|
-
console.log(' → atris init Set up your workspace');
|
|
2855
|
-
console.log(' → atris help See all commands\n');
|
|
2856
|
-
return;
|
|
2857
|
-
}
|
|
2858
|
-
|
|
2859
|
-
ensureLogDirectory();
|
|
2860
|
-
const { logFile, dateFormatted } = getLogPath();
|
|
2861
|
-
if (!fs.existsSync(logFile)) {
|
|
2862
|
-
createLogFile(logFile, dateFormatted);
|
|
2863
|
-
}
|
|
2864
|
-
|
|
2865
|
-
// Load context
|
|
2866
|
-
const workspaceDir = process.cwd();
|
|
2867
|
-
const state = detectWorkspaceState(workspaceDir);
|
|
2868
|
-
const context = loadContext(workspaceDir);
|
|
2869
|
-
|
|
2870
|
-
// Detect existing features
|
|
2871
|
-
const featuresDir = path.join(targetDir, 'features');
|
|
2872
|
-
let existingFeatures = [];
|
|
2873
|
-
if (fs.existsSync(featuresDir)) {
|
|
2874
|
-
existingFeatures = fs.readdirSync(featuresDir)
|
|
2875
|
-
.filter(name => {
|
|
2876
|
-
const featurePath = path.join(featuresDir, name);
|
|
2877
|
-
return fs.statSync(featurePath).isDirectory() && !name.startsWith('_');
|
|
2878
|
-
});
|
|
2879
|
-
}
|
|
2880
|
-
|
|
2881
|
-
console.log('');
|
|
2882
|
-
console.log('┌─────────────────────────────────────────────────────────────┐');
|
|
2883
|
-
console.log('│ Atris Mode │');
|
|
2884
|
-
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
2885
|
-
console.log('');
|
|
2886
|
-
console.log(`📅 ${dateFormatted}`);
|
|
2887
|
-
console.log('');
|
|
2888
|
-
|
|
2889
|
-
// Show existing features
|
|
2890
|
-
if (existingFeatures.length > 0) {
|
|
2891
|
-
console.log('📦 Features: ' + existingFeatures.join(', '));
|
|
2892
|
-
console.log('');
|
|
2893
|
-
}
|
|
2894
|
-
|
|
2895
|
-
// Show active work
|
|
2896
|
-
if (context.inProgressFeatures.length > 0) {
|
|
2897
|
-
console.log('⚡ Active: ' + context.inProgressFeatures.join(', '));
|
|
2898
|
-
console.log('');
|
|
2899
|
-
}
|
|
2900
|
-
|
|
2901
|
-
// Show inbox
|
|
2902
|
-
if (context.hasInbox && context.inboxItems.length > 0) {
|
|
2903
|
-
console.log(`📥 Inbox (${context.inboxItems.length}):`);
|
|
2904
|
-
context.inboxItems.slice(0, 3).forEach((item, i) => {
|
|
2905
|
-
const preview = item.length > 50 ? item.substring(0, 47) + '...' : item;
|
|
2906
|
-
console.log(` ${i + 1}. ${preview}`);
|
|
2907
|
-
});
|
|
2908
|
-
if (context.inboxItems.length > 3) {
|
|
2909
|
-
console.log(` ... and ${context.inboxItems.length - 3} more`);
|
|
2910
|
-
}
|
|
2911
|
-
console.log('');
|
|
2912
|
-
}
|
|
2913
|
-
|
|
2914
|
-
// Show recent completions
|
|
2915
|
-
const logContent = fs.existsSync(logFile) ? fs.readFileSync(logFile, 'utf8') : '';
|
|
2916
|
-
const completedMatch = logContent.match(/## Completed ✅\n([\s\S]*?)(?=\n##|$)/);
|
|
2917
|
-
if (completedMatch && completedMatch[1].trim()) {
|
|
2918
|
-
const completedItems = completedMatch[1].trim().split('\n')
|
|
2919
|
-
.filter(line => line.match(/^- \*\*C\d+:/))
|
|
2920
|
-
.slice(-2);
|
|
2921
|
-
if (completedItems.length > 0) {
|
|
2922
|
-
console.log('✅ Recent:');
|
|
2923
|
-
completedItems.forEach(item => {
|
|
2924
|
-
const match = item.match(/^- \*\*C\d+:\s*(.+)\*\*/);
|
|
2925
|
-
if (match) {
|
|
2926
|
-
const text = match[1].length > 50 ? match[1].substring(0, 47) + '...' : match[1];
|
|
2927
|
-
console.log(` • ${text}`);
|
|
2928
|
-
}
|
|
2929
|
-
});
|
|
2930
|
-
console.log('');
|
|
2931
|
-
}
|
|
2932
|
-
}
|
|
2933
|
-
|
|
2934
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
2935
|
-
console.log('atris — navigator agent');
|
|
2936
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
2937
|
-
console.log('');
|
|
2938
|
-
|
|
2939
|
-
if (userInput) {
|
|
2940
|
-
// Hot start - user provided task
|
|
2941
|
-
console.log('User wants:');
|
|
2942
|
-
console.log(`"${userInput}"`);
|
|
2943
|
-
console.log('');
|
|
2944
|
-
} else {
|
|
2945
|
-
// Cold start - no specific task
|
|
2946
|
-
console.log('Wait for user to describe what they want.');
|
|
2947
|
-
console.log('');
|
|
2948
|
-
}
|
|
2949
|
-
|
|
2950
|
-
console.log('⚠️ APPROVAL REQUIRED — Follow this workflow:');
|
|
2951
|
-
console.log('');
|
|
2952
|
-
console.log('STEP 1: Show ASCII visualization');
|
|
2953
|
-
console.log(' Create diagrams showing architecture/flow/UI');
|
|
2954
|
-
console.log(' SHOW diagrams to user and WAIT for approval.');
|
|
2955
|
-
console.log('');
|
|
2956
|
-
console.log('STEP 2: After approval, determine scope');
|
|
2957
|
-
if (existingFeatures.length > 0) {
|
|
2958
|
-
console.log(' Existing: ' + existingFeatures.join(', '));
|
|
2959
|
-
}
|
|
2960
|
-
console.log(' NEW feature → atris/features/[name]/idea.md + build.md + validate.md');
|
|
2961
|
-
console.log(' EXISTING → Update that feature\'s docs');
|
|
2962
|
-
console.log(' SIMPLE → TODO.md only');
|
|
2963
|
-
console.log('');
|
|
2964
|
-
console.log('STEP 3: Create/update docs');
|
|
2965
|
-
console.log(' idea.md = intent (any format)');
|
|
2966
|
-
console.log(' build.md = technical spec');
|
|
2967
|
-
console.log(' validate.md = proof it works (from _templates/validate.md.template)');
|
|
2968
|
-
console.log(' lessons.md = read past lessons before planning, write new ones after validating');
|
|
2969
|
-
console.log('');
|
|
2970
|
-
console.log('⛔ DO NOT execute — that\'s for "atris do"');
|
|
2971
|
-
console.log('');
|
|
2972
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
2973
|
-
console.log('');
|
|
2974
|
-
}
|