atris 3.30.12 ā 3.31.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 +3 -1
- 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 +7 -0
- package/ax +95 -3
- package/bin/atris.js +126 -153
- package/commands/autoland.js +319 -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 +1 -1
- package/commands/land.js +442 -0
- package/commands/loop-front.js +122 -4
- package/commands/member.js +519 -19
- package/commands/mission.js +3330 -290
- package/commands/play.js +1 -1
- package/commands/pulse.js +65 -7
- package/commands/run.js +3 -3
- package/commands/strings.js +301 -0
- package/commands/task.js +575 -102
- package/commands/truth.js +170 -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 +283 -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/pulse.js +74 -1
- package/lib/runner-command.js +20 -8
- package/lib/runs-prune.js +242 -0
- package/lib/task-proof.js +1 -1
- package/package.json +3 -3
- 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/ax
CHANGED
|
@@ -1165,6 +1165,51 @@ function formatApprovalTime(value) {
|
|
|
1165
1165
|
return `${months[Number(month) - 1] || month} ${Number(day)}, ${year} at ${hour12}:${minute} ${ampm}`;
|
|
1166
1166
|
}
|
|
1167
1167
|
|
|
1168
|
+
function previewText(value, limit = 80) {
|
|
1169
|
+
return String(value || '').replace(/\s+/g, ' ').trim().slice(0, limit);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
function previewContact(value) {
|
|
1173
|
+
if (!value) return '';
|
|
1174
|
+
if (typeof value === 'string') return previewText(value, 120);
|
|
1175
|
+
if (typeof value !== 'object') return previewText(value, 120);
|
|
1176
|
+
return previewText(value.email || value.address || value.value || value.name || '', 120);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
function previewContacts(value) {
|
|
1180
|
+
const values = Array.isArray(value)
|
|
1181
|
+
? value
|
|
1182
|
+
: String(value || '').includes(',')
|
|
1183
|
+
? String(value).split(',')
|
|
1184
|
+
: [value];
|
|
1185
|
+
return values
|
|
1186
|
+
.map(previewContact)
|
|
1187
|
+
.filter(Boolean)
|
|
1188
|
+
.slice(0, 3)
|
|
1189
|
+
.join(', ');
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
function gmailApprovalDetails(receipt, request, approvalEvent = null) {
|
|
1193
|
+
const payload = request && request.payload && typeof request.payload === 'object' ? request.payload : {};
|
|
1194
|
+
const taskPreview = receipt && receipt.task_preview && typeof receipt.task_preview === 'object' ? receipt.task_preview : {};
|
|
1195
|
+
const slots = taskPreview.slots && typeof taskPreview.slots === 'object' ? taskPreview.slots : {};
|
|
1196
|
+
const preview = approvalEvent && approvalEvent.preview && typeof approvalEvent.preview === 'object' ? approvalEvent.preview : {};
|
|
1197
|
+
return {
|
|
1198
|
+
to: previewContacts(payload.to || payload.recipient || payload.recipients || payload.email || slots.to || slots.recipient || preview.to),
|
|
1199
|
+
subject: previewText(payload.subject || payload.title || slots.subject || preview.subject, 80),
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
function isGmailApproval(request, approvalEvent = null, accept = {}) {
|
|
1204
|
+
const connector = canonicalConnectorId((request && request.connector) || (approvalEvent && approvalEvent.tool));
|
|
1205
|
+
const action = String(
|
|
1206
|
+
(request && (request.executor_action_type || request.action_type || request.action))
|
|
1207
|
+
|| accept.task
|
|
1208
|
+
|| ''
|
|
1209
|
+
).toLowerCase().replace(/_/g, ' ');
|
|
1210
|
+
return connector === 'gmail' && /\b(send|reply|compose)\b/.test(action);
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1168
1213
|
function formatApprovalReceipt(receipt) {
|
|
1169
1214
|
if (!receipt || typeof receipt !== 'object') return null;
|
|
1170
1215
|
const events = Array.isArray(receipt.tool_events) ? receipt.tool_events : [];
|
|
@@ -1182,6 +1227,15 @@ function formatApprovalReceipt(receipt) {
|
|
|
1182
1227
|
return `Approval needed before creation: calendar event "${String(title).slice(0, 80)}"${when ? ` ${when}` : ''}`;
|
|
1183
1228
|
}
|
|
1184
1229
|
|
|
1230
|
+
if (isGmailApproval(request, approvalEvent, accept)) {
|
|
1231
|
+
const details = gmailApprovalDetails(receipt, request, approvalEvent);
|
|
1232
|
+
const parts = [
|
|
1233
|
+
details.to ? `to ${details.to}` : '',
|
|
1234
|
+
details.subject ? `subject "${details.subject}"` : '',
|
|
1235
|
+
].filter(Boolean);
|
|
1236
|
+
return `Approval needed before sending Gmail${parts.length ? `: ${parts.join(' ')}` : ''} (body hidden until approved)`;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1185
1239
|
const connector = String(request.connector || approvalEvent.tool || 'connector').replace(/_/g, ' ');
|
|
1186
1240
|
const action = String(request.action || actionType || 'action').replace(/_/g, ' ');
|
|
1187
1241
|
return `Approval needed before ${action}: ${connector}`;
|
|
@@ -1210,6 +1264,16 @@ function formatTaskPreviewPlan(receipt) {
|
|
|
1210
1264
|
if (!taskPreview) return null;
|
|
1211
1265
|
const task = String(taskPreview.task || '').trim();
|
|
1212
1266
|
const slots = taskPreview.slots && typeof taskPreview.slots === 'object' ? taskPreview.slots : {};
|
|
1267
|
+
const approvalEvent = taskPreviewApprovalEvent(receipt);
|
|
1268
|
+
const request = approvalEvent && approvalEvent.approval_request;
|
|
1269
|
+
if (isGmailApproval(request, approvalEvent, receipt.task_accept_receipt || {}) || task === 'gmail.send_message') {
|
|
1270
|
+
const details = gmailApprovalDetails(receipt, request || { payload: slots }, approvalEvent);
|
|
1271
|
+
return [
|
|
1272
|
+
'send Gmail',
|
|
1273
|
+
details.to ? `to ${details.to}` : '',
|
|
1274
|
+
details.subject ? `subject "${details.subject}"` : '',
|
|
1275
|
+
].filter(Boolean).join(' ');
|
|
1276
|
+
}
|
|
1213
1277
|
if (task === 'calendar.create_event') {
|
|
1214
1278
|
const title = taskPreviewTitle(receipt);
|
|
1215
1279
|
const start = slots.start || (receipt.task_accept_receipt && receipt.task_accept_receipt.start);
|
|
@@ -1712,12 +1776,30 @@ function buildMessage(message, history = []) {
|
|
|
1712
1776
|
return String(message || '').trim();
|
|
1713
1777
|
}
|
|
1714
1778
|
|
|
1779
|
+
function createTurnId() {
|
|
1780
|
+
return `axt_${Date.now().toString(36)}_${crypto.randomBytes(4).toString('hex')}`;
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
function connectorTurnPolicy(message, options = {}) {
|
|
1784
|
+
if (!connectorWriteIntent(message)) return null;
|
|
1785
|
+
const policy = {
|
|
1786
|
+
schema: 'ax.connector_turn.v1',
|
|
1787
|
+
scope: 'current_turn_only',
|
|
1788
|
+
policy: 'preview_then_explicit_approval',
|
|
1789
|
+
writes_require_approval: true,
|
|
1790
|
+
};
|
|
1791
|
+
if (options.turnId) policy.turn_id = String(options.turnId);
|
|
1792
|
+
if (options.conversationId) policy.conversation_id = String(options.conversationId);
|
|
1793
|
+
return policy;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1715
1796
|
function buildPayload(message, options = {}) {
|
|
1716
1797
|
const mode = normalizeMode(options.mode);
|
|
1717
1798
|
const route = options.business ? 'local' : resolveRoute(message, options);
|
|
1718
1799
|
const local = route !== 'cloud';
|
|
1719
1800
|
const verifyCommand = String(options.verify || '').trim();
|
|
1720
1801
|
const previousMessages = structuredHistory(options.history || []);
|
|
1802
|
+
const turnId = String(options.turnId || '').trim();
|
|
1721
1803
|
const payload = {
|
|
1722
1804
|
message: buildMessage(message, options.history || []),
|
|
1723
1805
|
model: modelForMode(mode),
|
|
@@ -1730,6 +1812,14 @@ function buildPayload(message, options = {}) {
|
|
|
1730
1812
|
if (options.conversationId) {
|
|
1731
1813
|
payload.conversation_id = String(options.conversationId);
|
|
1732
1814
|
}
|
|
1815
|
+
if (turnId) {
|
|
1816
|
+
payload.turn_id = turnId;
|
|
1817
|
+
}
|
|
1818
|
+
const connectorPolicy = !local ? connectorTurnPolicy(message, { ...options, turnId }) : null;
|
|
1819
|
+
if (connectorPolicy) {
|
|
1820
|
+
payload.connector_turn = connectorPolicy;
|
|
1821
|
+
payload.external_action_policy = 'preview_then_explicit_approval';
|
|
1822
|
+
}
|
|
1733
1823
|
if (options.business) {
|
|
1734
1824
|
// Business cloud workspace: the model loop stays on the backend and every
|
|
1735
1825
|
// file/bash tool call relays here, executing on the business EC2 via the
|
|
@@ -1882,6 +1972,7 @@ async function postTurn(message, options = {}) {
|
|
|
1882
1972
|
const local = route !== 'cloud';
|
|
1883
1973
|
const endpointRoute = options.business ? 'cloud' : route;
|
|
1884
1974
|
const token = authToken();
|
|
1975
|
+
const turnId = options.turnId || createTurnId();
|
|
1885
1976
|
const shouldSendConnectionContext = options.connectionContext
|
|
1886
1977
|
|| route === 'cloud'
|
|
1887
1978
|
|| mentionsConnector(message)
|
|
@@ -1890,7 +1981,7 @@ async function postTurn(message, options = {}) {
|
|
|
1890
1981
|
? await buildConnectionContext({ token, localWorkspace: local })
|
|
1891
1982
|
: null);
|
|
1892
1983
|
const connectionUserId = !local && isLoopbackBackend({ route: endpointRoute }) ? authUserId() : '';
|
|
1893
|
-
const payload = buildPayload(message, { ...options, route, connectionContext, connectionUserId });
|
|
1984
|
+
const payload = buildPayload(message, { ...options, route, connectionContext, connectionUserId, turnId });
|
|
1894
1985
|
const postData = JSON.stringify(payload);
|
|
1895
1986
|
const output = options.output || process.stdout;
|
|
1896
1987
|
// Relayed business turns wait on EC2 terminal calls (up to 60s each) with no
|
|
@@ -2269,7 +2360,8 @@ async function chat(options = {}) {
|
|
|
2269
2360
|
const turnRoute = options.business ? 'cloud' : resolveRoute(trimmed, { route });
|
|
2270
2361
|
if (!(await ensureRuntimeReady(turnRoute))) return false;
|
|
2271
2362
|
const turnFunction = options.turnFunction || turnFunctionForMode(mode);
|
|
2272
|
-
const
|
|
2363
|
+
const turnId = options.turnId || createTurnId();
|
|
2364
|
+
const result = await turnFunction(trimmed, { mode, cwd, history, output, route, business: options.business, verify: options.verify, conversationId, turnId });
|
|
2273
2365
|
if (result.output && !result.output.endsWith('\n')) output.write('\n');
|
|
2274
2366
|
const approvalExecution = normalizeMode(mode) === 'code-fast'
|
|
2275
2367
|
? null
|
|
@@ -2331,7 +2423,7 @@ function printBackendHint(options = {}) {
|
|
|
2331
2423
|
}
|
|
2332
2424
|
|
|
2333
2425
|
function backendStartCommand() {
|
|
2334
|
-
return `cd /
|
|
2426
|
+
return `cd ${process.env.HOME}/arena/atrisos-backend/backend && ATRIS2_ALLOW_LOCAL_WORKSPACE=1 ENVIRONMENT=development ENV=development ../venv/bin/uvicorn main:app --host ${BACKEND.host} --port ${BACKEND.port}`;
|
|
2335
2427
|
}
|
|
2336
2428
|
|
|
2337
2429
|
function formatBackendHint(options = {}) {
|
package/bin/atris.js
CHANGED
|
@@ -468,6 +468,7 @@ function showHelp() {
|
|
|
468
468
|
console.log(' analytics - Show recent productivity from journals');
|
|
469
469
|
console.log(' search - Search journal history (atris search <keyword>)');
|
|
470
470
|
console.log(' clean - Housekeeping (stale tasks, archive journals, broken refs)');
|
|
471
|
+
console.log(' harvest - Find bugs and next actions from receipts, run logs, and thinking');
|
|
471
472
|
console.log(' verify - Validate work is done (tests, MAP.md, changes)');
|
|
472
473
|
console.log(' task - Local agent task plane (atomic claims, TODO import)');
|
|
473
474
|
console.log(' mission - Goal + loop + member owner + verifier + receipt');
|
|
@@ -485,8 +486,10 @@ function showHelp() {
|
|
|
485
486
|
console.log(' autopilot - Guided loop that can clarify TODOs and run plan ā do ā review');
|
|
486
487
|
console.log(' improve - Run one paid RL tick (POST /api/improve, deducts credits)');
|
|
487
488
|
console.log(' worktree - Isolated Git worktrees plus guarded ship/merge for parallel agents');
|
|
489
|
+
console.log(' land - The landing: what is actually done vs still in the air; --reap backs up + clears overdue');
|
|
490
|
+
console.log(' autoland - Approve the policy once; certified work lands itself, you keep irreversible calls');
|
|
488
491
|
console.log(' visualize - Generate a Slack/deck-ready visual from a prompt');
|
|
489
|
-
console.log(' youtube - Process YouTube videos with
|
|
492
|
+
console.log(' youtube - Process YouTube videos with timestamped transcript-first analysis');
|
|
490
493
|
console.log('');
|
|
491
494
|
console.log('Experiments:');
|
|
492
495
|
console.log(' experiments init [slug] - Prepare atris/experiments/ or scaffold a pack');
|
|
@@ -831,22 +834,27 @@ function showServeHelp() {
|
|
|
831
834
|
|
|
832
835
|
function showLoopHelp() {
|
|
833
836
|
console.log('');
|
|
834
|
-
console.log('Usage: atris loop [
|
|
837
|
+
console.log('Usage: atris loop [add|start|status|report|stop|wiki] [options]');
|
|
835
838
|
console.log('');
|
|
836
839
|
console.log('Description:');
|
|
837
|
-
console.log('
|
|
840
|
+
console.log(' One front door for the self-improvement loop. It reads ROADMAP.md,');
|
|
841
|
+
console.log(' runs bounded proof-backed work, and keeps wiki upkeep under loop wiki.');
|
|
838
842
|
console.log('');
|
|
839
|
-
console.log('
|
|
840
|
-
console.log('
|
|
841
|
-
console.log(' --
|
|
842
|
-
console.log(' --
|
|
843
|
-
console.log(' --
|
|
843
|
+
console.log('Commands:');
|
|
844
|
+
console.log(' atris loop add "<task>" Put a bounded task into the loop queue.');
|
|
845
|
+
console.log(' atris loop start [--once] Run the local loop.');
|
|
846
|
+
console.log(' atris loop start --overnight Install the durable heartbeat.');
|
|
847
|
+
console.log(' atris loop status [--json] Show heartbeat, local runs, and next moves.');
|
|
848
|
+
console.log(' atris loop report [--json] Show proof of handled and queued loop work.');
|
|
849
|
+
console.log(' atris loop stop Remove the durable heartbeat.');
|
|
850
|
+
console.log(' atris loop wiki Run the wiki upkeep loop.');
|
|
851
|
+
console.log(' --help, -h Show this help.');
|
|
844
852
|
console.log('');
|
|
845
853
|
}
|
|
846
854
|
|
|
847
855
|
function showCleanHelp() {
|
|
848
856
|
console.log('');
|
|
849
|
-
console.log('Usage: atris clean [--dry-run]');
|
|
857
|
+
console.log('Usage: atris clean [--dry-run] [--json]');
|
|
850
858
|
console.log('');
|
|
851
859
|
console.log('Description:');
|
|
852
860
|
console.log(' Check workspace housekeeping: stale tasks, MAP.md refs, old journals,');
|
|
@@ -854,6 +862,7 @@ function showCleanHelp() {
|
|
|
854
862
|
console.log('');
|
|
855
863
|
console.log('Options:');
|
|
856
864
|
console.log(' --dry-run, -n Preview cleanup without changing files.');
|
|
865
|
+
console.log(' --json Print machine-readable cleanup results.');
|
|
857
866
|
console.log(' --help, -h Show this help.');
|
|
858
867
|
console.log('');
|
|
859
868
|
}
|
|
@@ -913,12 +922,12 @@ if (command === '2' && ['fast', 'pro'].includes(String(firstCommandArg || '').to
|
|
|
913
922
|
}
|
|
914
923
|
|
|
915
924
|
// 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',
|
|
925
|
+
const knownCommands = ['init', 'log', 'now', 'radar', 'ctop', 'launchpad', 'status', 'analytics', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', '_start', 'plan', 'do', 'review', 'release',
|
|
917
926
|
'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',
|
|
927
|
+
'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',
|
|
928
|
+
'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
929
|
'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'];
|
|
930
|
+
'fork', 'browse', 'publish', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'compile', 'spaceship', 'truth'];
|
|
922
931
|
|
|
923
932
|
// Check if command is an atris.md spec file - triggers welcome visualization
|
|
924
933
|
function isSpecFile(cmd) {
|
|
@@ -940,7 +949,15 @@ if (command === '--version' || command === '-v' || process.argv.includes('--vers
|
|
|
940
949
|
// If no command OR command is not recognized, treat as natural language
|
|
941
950
|
// Voice-friendly aliases ā natural language ā command mapping
|
|
942
951
|
// Solves speech-to-text issues (inspired by gstack v0.14.6 voice-triggers)
|
|
952
|
+
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';
|
|
953
|
+
|
|
943
954
|
const voiceTriggers = {
|
|
955
|
+
'start': '_start',
|
|
956
|
+
'start now': '_start',
|
|
957
|
+
'go': '_start',
|
|
958
|
+
'keep going': '_start',
|
|
959
|
+
'keepgoing': '_start',
|
|
960
|
+
'keep-going': '_start',
|
|
944
961
|
'review my code': 'code-review',
|
|
945
962
|
'check my code': 'code-review',
|
|
946
963
|
'run a review': 'code-review',
|
|
@@ -965,7 +982,12 @@ const voiceTriggers = {
|
|
|
965
982
|
if (!command || !knownCommands.includes(command)) {
|
|
966
983
|
// Check voice triggers before falling through to natural language
|
|
967
984
|
const fullInput = process.argv.slice(2).join(' ').toLowerCase().trim();
|
|
968
|
-
const
|
|
985
|
+
const fullInputWithoutFlags = process.argv.slice(2)
|
|
986
|
+
.filter((arg, index, args) => !String(arg).startsWith('-') && !isOptionValue(args, index, RUNNER_FLAG_NAMES))
|
|
987
|
+
.join(' ')
|
|
988
|
+
.toLowerCase()
|
|
989
|
+
.trim();
|
|
990
|
+
const triggered = voiceTriggers[fullInput] || voiceTriggers[fullInputWithoutFlags];
|
|
969
991
|
if (triggered) {
|
|
970
992
|
command = triggered;
|
|
971
993
|
// Re-check ā if it's now a known command, fall through to dispatch
|
|
@@ -1355,6 +1377,12 @@ function showWelcomeVisualization() {
|
|
|
1355
1377
|
: `${tasksInReview} waiting`;
|
|
1356
1378
|
console.log(` ā ā³ Review: ${reviewText.padEnd(26)}ā`);
|
|
1357
1379
|
}
|
|
1380
|
+
let landInfo = null;
|
|
1381
|
+
try { landInfo = require('../commands/land').landSummary(process.cwd()); } catch (err) { landInfo = null; }
|
|
1382
|
+
if (landInfo && landInfo.branches > 0) {
|
|
1383
|
+
const landText = `${landInfo.branches} in the air, ${landInfo.due} overdue`;
|
|
1384
|
+
console.log(` ā š¬ Land: ${landText.padEnd(26)}ā`);
|
|
1385
|
+
}
|
|
1358
1386
|
console.log(` ā š Journal: ${(journalEntries + ' entries today').padEnd(26)}ā`);
|
|
1359
1387
|
if (endgameState.slug !== 'unset' && endgameState.horizon) {
|
|
1360
1388
|
const endgameLine = endgameState.slug + ' ā ' + endgameState.horizon;
|
|
@@ -1377,7 +1405,13 @@ function showWelcomeVisualization() {
|
|
|
1377
1405
|
if (tasksCertified > 0) {
|
|
1378
1406
|
console.log(` Ready. ${tasksCertified} certified await accept ā run 'atris task reviews'.`);
|
|
1379
1407
|
} else {
|
|
1380
|
-
|
|
1408
|
+
let landHint = null;
|
|
1409
|
+
try { landHint = require('../commands/land').landSummary(process.cwd()); } catch (err) { landHint = null; }
|
|
1410
|
+
if (landHint && landHint.due > 0) {
|
|
1411
|
+
console.log(` Ready. ${landHint.due} overdue in the landing ā run 'atris land --reap'.`);
|
|
1412
|
+
} else {
|
|
1413
|
+
console.log(` Ready. Run 'atris plan' to start.`);
|
|
1414
|
+
}
|
|
1381
1415
|
}
|
|
1382
1416
|
console.log('');
|
|
1383
1417
|
}
|
|
@@ -1398,6 +1432,40 @@ if (command === 'init') {
|
|
|
1398
1432
|
console.error(`ā Error: ${error.message || error}`);
|
|
1399
1433
|
process.exit(1);
|
|
1400
1434
|
});
|
|
1435
|
+
} else if (command === '_start') {
|
|
1436
|
+
const args = process.argv.slice(3);
|
|
1437
|
+
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
1438
|
+
console.log('');
|
|
1439
|
+
console.log('Usage: atris start [options]');
|
|
1440
|
+
console.log('');
|
|
1441
|
+
console.log('Starts the durable mission loop for one useful self-improvement mission.');
|
|
1442
|
+
console.log('');
|
|
1443
|
+
console.log('Options:');
|
|
1444
|
+
console.log(' --json Print the mission route without starting it.');
|
|
1445
|
+
console.log(' --owner X Override mission owner.');
|
|
1446
|
+
console.log(' --cadence X Override mission cadence.');
|
|
1447
|
+
console.log('');
|
|
1448
|
+
process.exit(0);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
if (args.includes('--json')) {
|
|
1452
|
+
console.log(JSON.stringify({
|
|
1453
|
+
ok: true,
|
|
1454
|
+
action: 'start_mission_run',
|
|
1455
|
+
route: `atris mission run "${START_MISSION_OBJECTIVE}"`,
|
|
1456
|
+
reason: 'casual_launch',
|
|
1457
|
+
objective: START_MISSION_OBJECTIVE,
|
|
1458
|
+
expected_loop: 'mission_run',
|
|
1459
|
+
}, null, 2));
|
|
1460
|
+
process.exit(0);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
Promise.resolve(require('../commands/mission').missionCommand(['run', START_MISSION_OBJECTIVE, ...args]))
|
|
1464
|
+
.then(() => process.exit(process.exitCode || 0))
|
|
1465
|
+
.catch((error) => {
|
|
1466
|
+
console.error(`ā Start failed: ${error.message || error}`);
|
|
1467
|
+
process.exit(1);
|
|
1468
|
+
});
|
|
1401
1469
|
} else if (command === 'task') {
|
|
1402
1470
|
// SQLite-backed task plane. ~/.atris/tasks.db, gitignored, per-workspace.
|
|
1403
1471
|
Promise.resolve(require('../commands/task').run(process.argv.slice(3)))
|
|
@@ -1421,11 +1489,24 @@ if (command === 'init') {
|
|
|
1421
1489
|
Promise.resolve(require('../commands/worktree').worktreeCommand(process.argv.slice(3)))
|
|
1422
1490
|
.then((code) => process.exit(code || 0))
|
|
1423
1491
|
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
1492
|
+
} else if (command === 'autoland') {
|
|
1493
|
+
Promise.resolve(require('../commands/autoland').autolandCommand(process.argv.slice(3)))
|
|
1494
|
+
.then((code) => process.exit(code || 0))
|
|
1495
|
+
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
1496
|
+
} else if (command === 'land') {
|
|
1497
|
+
Promise.resolve(require('../commands/land').landCommand(process.argv.slice(3)))
|
|
1498
|
+
.then((code) => process.exit(code || 0))
|
|
1499
|
+
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
1424
1500
|
} else if (command === 'radar' || command === 'ctop') {
|
|
1425
1501
|
const radarArgs = command === 'ctop' ? ['--agents', ...process.argv.slice(3)] : process.argv.slice(3);
|
|
1426
1502
|
Promise.resolve(require('../commands/radar').radarCommand(radarArgs))
|
|
1427
1503
|
.then((code) => process.exit(code || 0))
|
|
1428
1504
|
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
1505
|
+
} else if (command === 'truth') {
|
|
1506
|
+
// Truth: one table rolling up mission state, tasks, feature proof receipts, and loop heartbeats.
|
|
1507
|
+
Promise.resolve(require('../commands/truth').truthCommand(process.argv.slice(3)))
|
|
1508
|
+
.then((code) => process.exit(code || 0))
|
|
1509
|
+
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
1429
1510
|
} else if (command === 'codex-goal') {
|
|
1430
1511
|
Promise.resolve(require('../commands/codex-goal').codexGoalCommand(process.argv.slice(3)))
|
|
1431
1512
|
.then(() => process.exit(process.exitCode || 0))
|
|
@@ -1922,7 +2003,14 @@ if (command === 'init') {
|
|
|
1922
2003
|
process.exit(0);
|
|
1923
2004
|
}
|
|
1924
2005
|
const dryRun = process.argv.includes('--dry-run') || process.argv.includes('-n');
|
|
1925
|
-
|
|
2006
|
+
const json = process.argv.includes('--json');
|
|
2007
|
+
require('../commands/clean').cleanAtris({ dryRun, json });
|
|
2008
|
+
} else if (command === 'harvest') {
|
|
2009
|
+
Promise.resolve(require('../commands/harvest').harvestCommand(process.argv.slice(3)))
|
|
2010
|
+
.catch((err) => {
|
|
2011
|
+
console.error(err.message || err);
|
|
2012
|
+
process.exit(1);
|
|
2013
|
+
});
|
|
1926
2014
|
} else if (command === 'verify') {
|
|
1927
2015
|
const args = process.argv.slice(3);
|
|
1928
2016
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
@@ -2130,8 +2218,8 @@ if (command === 'init') {
|
|
|
2130
2218
|
showLoopHelp();
|
|
2131
2219
|
process.exit(0);
|
|
2132
2220
|
}
|
|
2133
|
-
require('../commands/loop').
|
|
2134
|
-
.then(() => process.exit(0))
|
|
2221
|
+
Promise.resolve(require('../commands/loop-front').loopFront(args))
|
|
2222
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2135
2223
|
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
2136
2224
|
} else if (command === 'clean-workspace' || command === 'cw') {
|
|
2137
2225
|
const { cleanWorkspace } = require('../commands/workspace-clean');
|
|
@@ -2157,6 +2245,12 @@ if (command === 'init') {
|
|
|
2157
2245
|
Promise.resolve(require('../commands/slop').slopCommand(process.argv.slice(3)))
|
|
2158
2246
|
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2159
2247
|
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
2248
|
+
} else if (command === 'strings') {
|
|
2249
|
+
// Strings: content design system from live code (no LLM). Extracts UI strings, flags variants,
|
|
2250
|
+
// enforces preferred terms at the gate. Exit 1 = variants/banned terms found, for CI + the gate.
|
|
2251
|
+
Promise.resolve(require('../commands/strings').stringsCommand(process.argv.slice(3)))
|
|
2252
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
2253
|
+
.catch((err) => { console.error(`\nā Error: ${err.message || err}`); process.exit(1); });
|
|
2160
2254
|
} else if (command === 'security-review' || command === 'secure') {
|
|
2161
2255
|
// Security review: deterministic secrets/PII/code-risk scan (no LLM). Exit 1 = HIGH finding,
|
|
2162
2256
|
// for the autopilot/mission/CI gate + a SOC 2 evidence artifact via --json.
|
|
@@ -2410,13 +2504,12 @@ async function agentAtris() {
|
|
|
2410
2504
|
// Respect -h / --help / help before any auth/state work
|
|
2411
2505
|
const firstArg = process.argv[3];
|
|
2412
2506
|
if (firstArg === '-h' || firstArg === '--help' || firstArg === 'help') {
|
|
2413
|
-
console.log('Usage: atris agent [doctor|
|
|
2507
|
+
console.log('Usage: atris agent [doctor|spawn|spawns|spawn-status]');
|
|
2414
2508
|
console.log('');
|
|
2415
2509
|
console.log(' Pick which cloud agent to chat with from this workspace.');
|
|
2416
2510
|
console.log(' Run `atris agent spawn <role> --task "..."` to create a worker request.');
|
|
2417
2511
|
console.log(' Run `atris agent spawns` to list worker requests.');
|
|
2418
2512
|
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
2513
|
console.log(' Requires `atris login` first.');
|
|
2421
2514
|
console.log('');
|
|
2422
2515
|
console.log(' After selecting, use: atris chat ["message"]');
|
|
@@ -2427,7 +2520,19 @@ async function agentAtris() {
|
|
|
2427
2520
|
agentDoctor();
|
|
2428
2521
|
}
|
|
2429
2522
|
if (firstArg === 'dogfood') {
|
|
2430
|
-
|
|
2523
|
+
// Internal diagnostic, gated off the public CLI. Operators use `atris agent doctor`.
|
|
2524
|
+
if (!process.env.ATRIS_INTERNAL_AGENT_DOGFOOD) {
|
|
2525
|
+
console.error('atris agent dogfood is an internal diagnostic and is not part of the public CLI.');
|
|
2526
|
+
console.error('Run `atris agent doctor` to verify local AI CLIs can see Atris context.');
|
|
2527
|
+
process.exit(1);
|
|
2528
|
+
}
|
|
2529
|
+
const dogfoodArgs = process.argv.slice(4);
|
|
2530
|
+
if (dogfoodArgs.includes('--help') || dogfoodArgs.includes('-h') || dogfoodArgs[0] === 'help') {
|
|
2531
|
+
console.log('Internal usage: atris agent dogfood [--live]');
|
|
2532
|
+
console.log(' Smoke-test Devin/Droid with GLM 5.2. Gated behind ATRIS_INTERNAL_AGENT_DOGFOOD.');
|
|
2533
|
+
process.exit(0);
|
|
2534
|
+
}
|
|
2535
|
+
const result = require('../commands/agent-spawn').agentDogfoodCommand(dogfoodArgs);
|
|
2431
2536
|
process.exit(result.ok ? 0 : 1);
|
|
2432
2537
|
}
|
|
2433
2538
|
if (firstArg === 'spawn') {
|
|
@@ -2840,135 +2945,3 @@ async function atrisFastOnce(credentials, message) {
|
|
|
2840
2945
|
await streamProChat(endpoint, credentials.token, body);
|
|
2841
2946
|
console.log('\n\nā Complete\n');
|
|
2842
2947
|
}
|
|
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
|
-
}
|