atris 3.52.0 → 3.55.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/FOR_AGENTS.md +7 -0
- package/README.md +1 -1
- package/atris/policies/ANTISLOP.md +2 -1
- package/atris/skills/copy-editor/SKILL.md +2 -1
- package/atris/skills/design/SKILL.md +1 -1
- package/atris/skills/engines/SKILL.md +8 -7
- package/atris/skills/x-search/SKILL.md +24 -22
- package/atris/skills/youtube/SKILL.md +89 -40
- package/atris/team/_template/SOUL.md +40 -0
- package/atris/team/validator/MEMBER.md +1 -2
- package/ax +592 -91
- package/bin/atris +21 -0
- package/bin/atris.js +580 -378
- package/commands/api-key.js +170 -0
- package/commands/auth.js +453 -43
- package/commands/autoland.js +3 -1
- package/commands/autopilot-front.js +58 -11
- package/commands/avail.js +5 -4
- package/commands/balance.js +55 -0
- package/commands/bench.js +29 -1
- package/commands/brain.js +63 -12
- package/commands/brainstorm.js +18 -0
- package/commands/business.js +149 -1
- package/commands/chat-scan.js +17 -4
- package/commands/close.js +5 -1
- package/commands/computer.js +2 -2
- package/commands/doctor.js +174 -0
- package/commands/dream.js +7 -0
- package/commands/drill.js +34 -2
- package/commands/engine.js +47 -35
- package/commands/errors.js +58 -8
- package/commands/experiments.js +14 -0
- package/commands/feedback.js +61 -2
- package/commands/fleet-report.js +27 -7
- package/commands/fleet.js +98 -11
- package/commands/founder.js +60 -21
- package/commands/human-missions.js +79 -4
- package/commands/improve.js +54 -4
- package/commands/init.js +68 -92
- package/commands/install.js +40 -0
- package/commands/integrations.js +399 -30
- package/commands/interview.js +8 -0
- package/commands/land.js +48 -17
- package/commands/learn.js +29 -4
- package/commands/log.js +51 -0
- package/commands/member.js +68 -10
- package/commands/mission.js +339 -74
- package/commands/now.js +25 -6
- package/commands/orb.js +97 -2
- package/commands/pack.js +83 -9
- package/commands/playbook.js +381 -0
- package/commands/plugin.js +16 -0
- package/commands/radar.js +96 -40
- package/commands/recap.js +128 -21
- package/commands/release.js +102 -2
- package/commands/review.js +5 -10
- package/commands/revisions.js +55 -0
- package/commands/run-front.js +12 -4
- package/commands/scout.js +12 -1
- package/commands/search.js +123 -28
- package/commands/sign.js +2 -2
- package/commands/signup.js +12 -3
- package/commands/site-deploy.js +17 -4
- package/commands/site.js +2 -2
- package/commands/skill-eval.js +289 -0
- package/commands/skill.js +56 -6
- package/commands/social.js +603 -0
- package/commands/spaceship.js +69 -6
- package/commands/stream.js +8 -1
- package/commands/study.js +32 -19
- package/commands/sync.js +28 -22
- package/commands/task.js +418 -60
- package/commands/teach.js +72 -63
- package/commands/terminal.js +25 -9
- package/commands/topup.js +88 -0
- package/commands/truth.js +52 -6
- package/commands/usage.js +91 -0
- package/commands/verify.js +3 -2
- package/commands/version.js +3 -1
- package/commands/voice.js +5 -1
- package/commands/who.js +69 -11
- package/commands/wiki.js +7 -4
- package/commands/wish.js +76 -5
- package/commands/workflow.js +327 -145
- package/commands/worktree.js +1 -0
- package/commands/write.js +5 -0
- package/commands/x-search.js +340 -0
- package/commands/xp.js +5 -1
- package/commands/youtube.js +551 -33
- package/lib/account-bound.js +47 -0
- package/lib/auto-accept-certified.js +10 -2
- package/lib/auto-lessons.js +186 -0
- package/lib/autoland.js +4 -2
- package/lib/chat-log-scan.js +7 -4
- package/lib/cli-json.js +77 -0
- package/lib/cli-scope.js +26 -0
- package/lib/codex-flight.js +1 -0
- package/lib/conductor-artifacts.js +1 -1
- package/lib/context-gatherer.js +11 -0
- package/lib/developer-api.js +116 -0
- package/lib/engine-ask.js +11 -3
- package/lib/engine-registry.js +32 -7
- package/lib/feedback-triage.js +274 -0
- package/lib/first-minute.js +398 -0
- package/lib/fleet.js +115 -34
- package/lib/functional-owner.js +22 -0
- package/lib/known-commands.js +31 -5
- package/lib/member-scaffold.js +197 -0
- package/lib/mission-ledger-compact.js +127 -0
- package/lib/mission-root.js +4 -2
- package/lib/mission-runtime-loop.js +30 -2
- package/lib/next-moves.js +34 -34
- package/lib/noninteractive.js +88 -0
- package/lib/permission-grants.js +10 -1
- package/lib/policy-lessons.js +4 -1
- package/lib/revision-metric.js +279 -0
- package/lib/runner-command.js +5 -4
- package/lib/scratch-root.js +48 -0
- package/lib/skill-eval-gate.js +249 -0
- package/lib/task-db.js +22 -2
- package/lib/task-proof.js +75 -9
- package/lib/task-receipt.js +5 -1
- package/lib/verifier-quality.js +69 -0
- package/lib/wish-audit.js +2 -2
- package/lib/wish-delegate.js +10 -1
- package/lib/workspace-scaffold.js +270 -0
- package/package.json +4 -2
- package/scripts/det/checklist-score.js +191 -0
- package/scripts/det/ytsearch +31 -0
- package/scripts/outbound-artifact-gate.js +227 -0
- package/utils/update-check.js +15 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const {
|
|
7
|
+
inspectInstallGitState,
|
|
8
|
+
formatCliVersionLine,
|
|
9
|
+
isGitCheckout,
|
|
10
|
+
} = require('../utils/update-check');
|
|
11
|
+
|
|
12
|
+
const TASK_NODE_MAJOR = 22;
|
|
13
|
+
|
|
14
|
+
function parseNodeVersion(raw = process.version) {
|
|
15
|
+
const match = String(raw || '').match(/v?(\d+)\.(\d+)\.(\d+)/);
|
|
16
|
+
if (!match) return { raw: String(raw || ''), major: 0, minor: 0, patch: 0 };
|
|
17
|
+
return {
|
|
18
|
+
raw: String(raw || ''),
|
|
19
|
+
major: Number(match[1]),
|
|
20
|
+
minor: Number(match[2]),
|
|
21
|
+
patch: Number(match[3]),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function detectWorkspaceRoot(cwd = process.cwd()) {
|
|
26
|
+
let current = path.resolve(cwd);
|
|
27
|
+
for (;;) {
|
|
28
|
+
if (fs.existsSync(path.join(current, 'atris', 'atris.md'))
|
|
29
|
+
|| fs.existsSync(path.join(current, '.atris'))) {
|
|
30
|
+
return current;
|
|
31
|
+
}
|
|
32
|
+
const parent = path.dirname(current);
|
|
33
|
+
if (parent === current) return path.resolve(cwd);
|
|
34
|
+
current = parent;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function authState() {
|
|
39
|
+
try {
|
|
40
|
+
const { loadCredentials } = require('../utils/auth');
|
|
41
|
+
const creds = loadCredentials();
|
|
42
|
+
if (!creds) return { signed_in: false, email: null, source: null };
|
|
43
|
+
return {
|
|
44
|
+
signed_in: true,
|
|
45
|
+
email: creds.email || null,
|
|
46
|
+
source: process.env.ATRIS_TOKEN ? 'env' : (process.env.ATRIS_PROFILE ? 'profile' : 'credentials'),
|
|
47
|
+
};
|
|
48
|
+
} catch {
|
|
49
|
+
return { signed_in: false, email: null, source: null };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function publicBinInfo() {
|
|
54
|
+
const shimPath = path.join(__dirname, '..', 'bin', 'atris');
|
|
55
|
+
const entryPath = path.join(__dirname, '..', 'bin', 'atris.js');
|
|
56
|
+
let shimBytes = null;
|
|
57
|
+
try { shimBytes = fs.statSync(shimPath).size; } catch { shimBytes = null; }
|
|
58
|
+
let entryBytes = null;
|
|
59
|
+
try { entryBytes = fs.statSync(entryPath).size; } catch { entryBytes = null; }
|
|
60
|
+
return {
|
|
61
|
+
public_bin: 'bin/atris',
|
|
62
|
+
shim: Boolean(shimBytes != null && shimBytes < 2048),
|
|
63
|
+
shim_bytes: shimBytes,
|
|
64
|
+
entry: 'bin/atris.js',
|
|
65
|
+
entry_bytes: entryBytes,
|
|
66
|
+
note: 'public bin is a tiny POSIX shim that execs node on bin/atris.js',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function readCliVersion(packageRoot) {
|
|
71
|
+
try {
|
|
72
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
73
|
+
return typeof pkg.version === 'string' ? pkg.version : 'unknown';
|
|
74
|
+
} catch {
|
|
75
|
+
return 'unknown';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function installWarnings(packageRoot) {
|
|
80
|
+
const warnings = [];
|
|
81
|
+
if (!isGitCheckout(packageRoot)) return warnings;
|
|
82
|
+
const state = inspectInstallGitState(packageRoot);
|
|
83
|
+
if (state.dirty) {
|
|
84
|
+
warnings.push(`cli install is a dirty git checkout (${state.branch || 'detached'} @ ${state.head || 'unknown'})`);
|
|
85
|
+
} else if (state.detached) {
|
|
86
|
+
warnings.push(`cli install is a detached git checkout (@ ${state.head || 'unknown'})`);
|
|
87
|
+
}
|
|
88
|
+
return warnings;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function collectDoctor(options = {}) {
|
|
92
|
+
const packageRoot = options.packageRoot || path.join(__dirname, '..');
|
|
93
|
+
const node = parseNodeVersion(options.nodeVersion || process.version);
|
|
94
|
+
const workspace_root = detectWorkspaceRoot(options.cwd || process.cwd());
|
|
95
|
+
const task_support = node.major >= TASK_NODE_MAJOR;
|
|
96
|
+
const auth = authState();
|
|
97
|
+
const bin = publicBinInfo();
|
|
98
|
+
const cli_runnable = Boolean(process.execPath) && fs.existsSync(path.join(packageRoot, 'bin', 'atris.js'));
|
|
99
|
+
const version = readCliVersion(packageRoot);
|
|
100
|
+
const version_line = formatCliVersionLine(version, packageRoot);
|
|
101
|
+
const install_git = inspectInstallGitState(packageRoot);
|
|
102
|
+
const warnings = installWarnings(packageRoot);
|
|
103
|
+
return {
|
|
104
|
+
ok: true,
|
|
105
|
+
action: 'doctor',
|
|
106
|
+
version,
|
|
107
|
+
version_line,
|
|
108
|
+
node: {
|
|
109
|
+
version: node.raw.startsWith('v') ? node.raw : `v${node.raw}`,
|
|
110
|
+
major: node.major,
|
|
111
|
+
minor: node.minor,
|
|
112
|
+
patch: node.patch,
|
|
113
|
+
exec_path: process.execPath || null,
|
|
114
|
+
},
|
|
115
|
+
task_support,
|
|
116
|
+
task_support_requires: `node ${TASK_NODE_MAJOR}+`,
|
|
117
|
+
auth,
|
|
118
|
+
workspace_root,
|
|
119
|
+
home: os.homedir(),
|
|
120
|
+
cli_runnable,
|
|
121
|
+
bin,
|
|
122
|
+
install_git: {
|
|
123
|
+
is_git_repo: Boolean(install_git.isGitRepo),
|
|
124
|
+
dirty: Boolean(install_git.dirty),
|
|
125
|
+
branch: install_git.branch || null,
|
|
126
|
+
head: install_git.head || null,
|
|
127
|
+
},
|
|
128
|
+
warnings,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function renderDoctor(payload) {
|
|
133
|
+
const lines = [];
|
|
134
|
+
lines.push('atris doctor');
|
|
135
|
+
lines.push('');
|
|
136
|
+
lines.push(`version: ${payload.version_line || payload.version}`);
|
|
137
|
+
lines.push(`node: ${payload.node.version} (${payload.node.exec_path || 'unknown'})`);
|
|
138
|
+
lines.push(`task support (22+): ${payload.task_support ? 'yes' : 'no'}`);
|
|
139
|
+
lines.push(`auth: ${payload.auth.signed_in ? `signed in as ${payload.auth.email || 'unknown'}` : 'signed out'}`);
|
|
140
|
+
lines.push(`workspace: ${payload.workspace_root}`);
|
|
141
|
+
lines.push(`cli runnable: ${payload.cli_runnable ? 'yes' : 'no'}`);
|
|
142
|
+
lines.push(`public bin: ${payload.bin.public_bin} (${payload.bin.shim ? `${payload.bin.shim_bytes} byte shim` : 'not a shim'})`);
|
|
143
|
+
if (payload.warnings && payload.warnings.length) {
|
|
144
|
+
lines.push('');
|
|
145
|
+
for (const warning of payload.warnings) lines.push(`warning: ${warning}`);
|
|
146
|
+
}
|
|
147
|
+
if (!payload.task_support) {
|
|
148
|
+
lines.push('');
|
|
149
|
+
lines.push(`install Node ${TASK_NODE_MAJOR}+ before running atris task.`);
|
|
150
|
+
}
|
|
151
|
+
return lines.join('\n');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function doctorCommand(args = [], options = {}) {
|
|
155
|
+
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
156
|
+
console.log('Usage: atris doctor [--json]');
|
|
157
|
+
console.log('');
|
|
158
|
+
console.log('Reports node version, task-support (22+), auth, workspace root, and whether the CLI can run.');
|
|
159
|
+
console.log('Public install entry is bin/atris (tiny POSIX shim) -> bin/atris.js.');
|
|
160
|
+
return 0;
|
|
161
|
+
}
|
|
162
|
+
const payload = collectDoctor(options);
|
|
163
|
+
if (args.includes('--json')) {
|
|
164
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
165
|
+
} else {
|
|
166
|
+
console.log(renderDoctor(payload));
|
|
167
|
+
}
|
|
168
|
+
const healthy = payload.cli_runnable && payload.task_support;
|
|
169
|
+
return healthy ? 0 : 1;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = {
|
|
173
|
+
doctorCommand,
|
|
174
|
+
};
|
package/commands/dream.js
CHANGED
|
@@ -341,6 +341,13 @@ function showHelp(log = console.log) {
|
|
|
341
341
|
async function dreamCommand(args = [], root = process.cwd(), options = {}) {
|
|
342
342
|
const log = options.log || console.log;
|
|
343
343
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') return showHelp(log);
|
|
344
|
+
const { refuseHeadlessUnless } = require('../lib/noninteractive');
|
|
345
|
+
if (refuseHeadlessUnless(args, {
|
|
346
|
+
allowYes: true,
|
|
347
|
+
usage: 'Usage: atris dream [--yes]\nHeadless dream needs --yes.',
|
|
348
|
+
})) {
|
|
349
|
+
return 2;
|
|
350
|
+
}
|
|
344
351
|
const result = await runDream(root, options);
|
|
345
352
|
if (result.cards && result.cards.length) {
|
|
346
353
|
const noun = result.cards.length === 1 ? 'card' : 'cards';
|
package/commands/drill.js
CHANGED
|
@@ -19,15 +19,42 @@ function assertOk(condition, message) {
|
|
|
19
19
|
if (!condition) throw new Error(message);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function textFromWriteSync(data, offset, length) {
|
|
23
|
+
if (Buffer.isBuffer(data)) {
|
|
24
|
+
const start = Number.isInteger(offset) ? offset : 0;
|
|
25
|
+
const end = Number.isInteger(length) ? start + length : data.length;
|
|
26
|
+
return data.toString('utf8', start, end);
|
|
27
|
+
}
|
|
28
|
+
return String(data);
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
async function captureCommand(fn) {
|
|
23
32
|
const originalLog = console.log;
|
|
24
33
|
const originalError = console.error;
|
|
25
34
|
const originalExit = process.exit;
|
|
35
|
+
const originalWriteSync = fs.writeSync;
|
|
26
36
|
const originalExitCode = process.exitCode;
|
|
27
37
|
const stdout = [];
|
|
28
38
|
const stderr = [];
|
|
39
|
+
let stdoutWrites = '';
|
|
40
|
+
let stderrWrites = '';
|
|
41
|
+
const stdoutFd = process.stdout.fd;
|
|
42
|
+
const stderrFd = process.stderr.fd;
|
|
29
43
|
console.log = (...args) => stdout.push(args.map(String).join(' '));
|
|
30
44
|
console.error = (...args) => stderr.push(args.map(String).join(' '));
|
|
45
|
+
fs.writeSync = function captureWriteSync(fd, data, offset, length) {
|
|
46
|
+
if (fd === stdoutFd || fd === process.stdout.fd) {
|
|
47
|
+
const text = textFromWriteSync(data, offset, length);
|
|
48
|
+
stdoutWrites += text;
|
|
49
|
+
return Buffer.byteLength(text);
|
|
50
|
+
}
|
|
51
|
+
if (fd === stderrFd || fd === process.stderr.fd) {
|
|
52
|
+
const text = textFromWriteSync(data, offset, length);
|
|
53
|
+
stderrWrites += text;
|
|
54
|
+
return Buffer.byteLength(text);
|
|
55
|
+
}
|
|
56
|
+
return originalWriteSync.apply(this, arguments);
|
|
57
|
+
};
|
|
31
58
|
process.exitCode = undefined;
|
|
32
59
|
process.exit = (code = 0) => {
|
|
33
60
|
const error = new Error(`process.exit(${code})`);
|
|
@@ -37,16 +64,21 @@ async function captureCommand(fn) {
|
|
|
37
64
|
};
|
|
38
65
|
try {
|
|
39
66
|
const value = await fn();
|
|
40
|
-
return {
|
|
67
|
+
return {
|
|
68
|
+
value,
|
|
69
|
+
stdout: `${stdout.join('\n')}${stdoutWrites}`,
|
|
70
|
+
stderr: `${stderr.join('\n')}${stderrWrites}`,
|
|
71
|
+
};
|
|
41
72
|
} catch (error) {
|
|
42
73
|
if (error && error.isProcessExit) {
|
|
43
|
-
const output = `${stderr.join('\n')}\n${stdout.join('\n')}`.trim();
|
|
74
|
+
const output = `${stderr.join('\n')}${stderrWrites}\n${stdout.join('\n')}${stdoutWrites}`.trim();
|
|
44
75
|
error.message = output || `process.exit(${error.exitCode})`;
|
|
45
76
|
}
|
|
46
77
|
throw error;
|
|
47
78
|
} finally {
|
|
48
79
|
console.log = originalLog;
|
|
49
80
|
console.error = originalError;
|
|
81
|
+
fs.writeSync = originalWriteSync;
|
|
50
82
|
process.exit = originalExit;
|
|
51
83
|
process.exitCode = originalExitCode;
|
|
52
84
|
}
|
package/commands/engine.js
CHANGED
|
@@ -24,6 +24,7 @@ const {
|
|
|
24
24
|
RUNNER_PROFILE_NAMES,
|
|
25
25
|
buildRunnerCommand,
|
|
26
26
|
} = require('../lib/runner-command');
|
|
27
|
+
const { parseScopeFlag } = require('../lib/cli-scope');
|
|
27
28
|
const {
|
|
28
29
|
ENGINE_ROLES,
|
|
29
30
|
ENGINE_DUTIES,
|
|
@@ -901,15 +902,18 @@ async function runEngineSeedCommand(args, root, deps = {}) {
|
|
|
901
902
|
return 0;
|
|
902
903
|
}
|
|
903
904
|
|
|
904
|
-
function printRoster(root) {
|
|
905
|
+
function printRoster(root, { scope = 'workspace' } = {}) {
|
|
905
906
|
reconcileStaleEngineProbeErrors(root);
|
|
906
907
|
const list = roster(root);
|
|
907
|
-
const
|
|
908
|
+
const scoped = scope === 'global'
|
|
909
|
+
? list
|
|
910
|
+
: list.filter((engine) => engine.installed || engine.default || engine.health.status === 'ready');
|
|
911
|
+
const found = scoped.filter((e) => e.installed).length;
|
|
908
912
|
const current = resolveDefaultEngine(root);
|
|
909
913
|
console.log('');
|
|
910
|
-
console.log(` engines: ${found} intelligence${found === 1 ? '' : 's'} found`);
|
|
914
|
+
console.log(` engines: ${found} intelligence${found === 1 ? '' : 's'} found (${scope})`);
|
|
911
915
|
console.log('');
|
|
912
|
-
for (const engine of
|
|
916
|
+
for (const engine of scoped) {
|
|
913
917
|
const mark = engine.default ? '→' : ' ';
|
|
914
918
|
const state = engine.health.status === 'not_installed' ? 'not installed' : engine.health.status.replace(/_/g, ' ');
|
|
915
919
|
const roles = engine.roles.join(',');
|
|
@@ -918,12 +922,33 @@ function printRoster(root) {
|
|
|
918
922
|
if (engine.duty) details.push(`duty: ${engine.duty}`);
|
|
919
923
|
console.log(` ${details.join(' ')}`);
|
|
920
924
|
}
|
|
925
|
+
if (scope !== 'global' && list.length > scoped.length) {
|
|
926
|
+
console.log(` … ${list.length - scoped.length} not installed hidden (pass --global to list)`);
|
|
927
|
+
}
|
|
921
928
|
console.log('');
|
|
922
929
|
console.log(` default: ${current.name}${current.source === 'saved' ? ' (set here)' : current.source === 'env' ? ' (this session)' : ''}`);
|
|
923
930
|
console.log(` switch: atris engine <name> · one run: --engine <name> on mission run / autopilot / run`);
|
|
924
931
|
console.log('');
|
|
925
932
|
}
|
|
926
933
|
|
|
934
|
+
function registryPayload(root, { scope = 'workspace' } = {}) {
|
|
935
|
+
const current = resolveDefaultEngine(root);
|
|
936
|
+
const registry = readEngineRegistry(root);
|
|
937
|
+
const engines = registry.engines.map((engine) => ({
|
|
938
|
+
...engine,
|
|
939
|
+
default: engine.id === current.name,
|
|
940
|
+
}));
|
|
941
|
+
const scoped = scope === 'global'
|
|
942
|
+
? engines
|
|
943
|
+
: engines.filter((engine) => engine.installed || engine.default || (engine.health && engine.health.status === 'ready'));
|
|
944
|
+
return {
|
|
945
|
+
scope,
|
|
946
|
+
default: current.name,
|
|
947
|
+
source: current.source,
|
|
948
|
+
engines: scoped,
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
|
|
927
952
|
function chartEngineLabel(engine) {
|
|
928
953
|
const id = String(engine && (engine.id || engine.name) || '').trim();
|
|
929
954
|
const models = Array.isArray(engine && engine.models)
|
|
@@ -1057,19 +1082,6 @@ function runSetEngineCommand(args, root) {
|
|
|
1057
1082
|
}
|
|
1058
1083
|
}
|
|
1059
1084
|
|
|
1060
|
-
function registryPayload(root) {
|
|
1061
|
-
const current = resolveDefaultEngine(root);
|
|
1062
|
-
const registry = readEngineRegistry(root);
|
|
1063
|
-
return {
|
|
1064
|
-
default: current.name,
|
|
1065
|
-
source: current.source,
|
|
1066
|
-
engines: registry.engines.map((engine) => ({
|
|
1067
|
-
...engine,
|
|
1068
|
-
default: engine.id === current.name,
|
|
1069
|
-
})),
|
|
1070
|
-
};
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
1085
|
function parseSetFlag(args) {
|
|
1074
1086
|
const prefix = '--set=';
|
|
1075
1087
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -1491,16 +1503,17 @@ function engineCommand(args = [], deps = {}) {
|
|
|
1491
1503
|
return runEngineAskCommand([...shorthandArgs, '--engine', canonical], root, deps.engineAsk || {});
|
|
1492
1504
|
}
|
|
1493
1505
|
|
|
1494
|
-
const
|
|
1495
|
-
const
|
|
1506
|
+
const scope = parseScopeFlag(args);
|
|
1507
|
+
const json = scope.args.includes('--json') || args.includes('--json');
|
|
1508
|
+
const positional = scope.args.filter((a) => !a.startsWith('--'));
|
|
1496
1509
|
const sub = (positional[0] || '').trim();
|
|
1497
1510
|
|
|
1498
1511
|
if (sub === 'login') {
|
|
1499
|
-
return runEngineLoginCommand(args.slice(args.indexOf('login') + 1), root);
|
|
1512
|
+
return runEngineLoginCommand(scope.args.slice(scope.args.indexOf('login') + 1), root);
|
|
1500
1513
|
}
|
|
1501
1514
|
|
|
1502
1515
|
if (sub === 'seed') {
|
|
1503
|
-
return runEngineSeedCommand(args.slice(args.indexOf('seed') + 1), root);
|
|
1516
|
+
return runEngineSeedCommand(scope.args.slice(scope.args.indexOf('seed') + 1), root);
|
|
1504
1517
|
}
|
|
1505
1518
|
|
|
1506
1519
|
if (sub === 'seats') {
|
|
@@ -1512,32 +1525,37 @@ function engineCommand(args = [], deps = {}) {
|
|
|
1512
1525
|
}
|
|
1513
1526
|
|
|
1514
1527
|
if (sub === 'resolve') {
|
|
1515
|
-
return runResolveCommand(args.slice(args.indexOf('resolve') + 1), root);
|
|
1528
|
+
return runResolveCommand(scope.args.slice(scope.args.indexOf('resolve') + 1), root);
|
|
1516
1529
|
}
|
|
1517
1530
|
|
|
1518
1531
|
if (sub === 'health') {
|
|
1519
|
-
return runHealthCommand(args.slice(args.indexOf('health') + 1), root);
|
|
1532
|
+
return runHealthCommand(scope.args.slice(scope.args.indexOf('health') + 1), root);
|
|
1520
1533
|
}
|
|
1521
1534
|
|
|
1522
1535
|
if (sub === 'doctor') {
|
|
1523
|
-
return runDoctorCommand(args.slice(args.indexOf('doctor') + 1), root);
|
|
1536
|
+
return runDoctorCommand(scope.args.slice(scope.args.indexOf('doctor') + 1), root);
|
|
1524
1537
|
}
|
|
1525
1538
|
|
|
1526
1539
|
if (sub === 'set') {
|
|
1527
|
-
return runSetEngineCommand(args.slice(args.indexOf('set') + 1), root);
|
|
1540
|
+
return runSetEngineCommand(scope.args.slice(scope.args.indexOf('set') + 1), root);
|
|
1528
1541
|
}
|
|
1529
1542
|
|
|
1530
|
-
if (sub === 'chart' || args.includes('--chart')) {
|
|
1543
|
+
if (sub === 'chart' || scope.args.includes('--chart') || args.includes('--chart')) {
|
|
1531
1544
|
printEngineChart(root);
|
|
1532
1545
|
return 0;
|
|
1533
1546
|
}
|
|
1534
1547
|
|
|
1535
|
-
if (!sub || sub === 'list' || sub === 'status') {
|
|
1548
|
+
if (!sub || sub === 'list' || sub === 'status' || sub === 'help') {
|
|
1549
|
+
if (sub === 'help' || args.includes('--help') || args.includes('-h')) {
|
|
1550
|
+
console.log('\n atris engine watch [<id>|latest] [--no-follow]\n follow one live transcript or list running engine work');
|
|
1551
|
+
console.log('\n atris engine roster + current default\n atris engines --chart show the fleet as an org chart\n atris engine list --json full registry: default + engines with tier, roles, fallback, health\n atris engine set <name> --duty leader|errands|learning [--models "a, b"]\n arrange the fleet and save its model policy\n atris engine resolve <role> [--json]\n choose the best ready engine for navigator|executor|validator\n atris engine health <name> --set ready|not_installed|credit_out\n flip runtime health, for example when credits run out\n atris engine doctor [--json]\n probe which engine CLIs are installed here and sync that into health policy\n atris engine <name> make that engine the default here\n atris engine test [name] preflight: run the engine CLI headless, report pass/fail\n atris engine ask "<question>" --engine <name> [--engine <name> ...]\n ask several engines in parallel without allowing edits\n atris engine ask --jobs <jobs.json>\n ask different read-only questions in parallel\n atris engine validate <receipt-path|latest> [--engine <name>]\n check ask answers with a different read-only referee\n atris engine validate scoreboard\n show pass rates by worker engine\n atris engine dispatch <task-id> [<task-id> ...] --engine cursor|codex [--prompt-file <f>] [--yolo]\n one-command claim, worktree, build, verify, ship, ready\n atris engine login <provider> --yes\n upload a local provider CLI login to the backend vault\n atris engine login <provider> --computer [--seat <name>]\n atris engine login <provider> --business <id> [--seat <name>]\n sign in on an Atris computer by device flow\n atris engine login --list | --remove <provider>\n list or remove vaulted provider logins\n atris engine seats show which named accounts are ready to work\n atris engine seed <provider> --business <id>|--user\n push a vaulted login onto an Atris computer\n atris engine reset back to the house default\n --engine <name> one run on that engine (mission run / autopilot / run)\n');
|
|
1552
|
+
return 0;
|
|
1553
|
+
}
|
|
1536
1554
|
if (json) {
|
|
1537
|
-
console.log(JSON.stringify(registryPayload(root), null, 2));
|
|
1555
|
+
console.log(JSON.stringify(registryPayload(root, { scope: scope.kind }), null, 2));
|
|
1538
1556
|
return 0;
|
|
1539
1557
|
}
|
|
1540
|
-
printRoster(root);
|
|
1558
|
+
printRoster(root, { scope: scope.kind });
|
|
1541
1559
|
return 0;
|
|
1542
1560
|
}
|
|
1543
1561
|
|
|
@@ -1549,12 +1567,6 @@ function engineCommand(args = [], deps = {}) {
|
|
|
1549
1567
|
return 0;
|
|
1550
1568
|
}
|
|
1551
1569
|
|
|
1552
|
-
if (sub === 'help') {
|
|
1553
|
-
console.log('\n atris engine watch [<id>|latest] [--no-follow]\n follow one live transcript or list running engine work');
|
|
1554
|
-
console.log('\n atris engine roster + current default\n atris engines --chart show the fleet as an org chart\n atris engine list --json full registry: default + engines with tier, roles, fallback, health\n atris engine set <name> --duty leader|errands|learning [--models "a, b"]\n arrange the fleet and save its model policy\n atris engine resolve <role> [--json]\n choose the best ready engine for navigator|executor|validator\n atris engine health <name> --set ready|not_installed|credit_out\n flip runtime health, for example when credits run out\n atris engine doctor [--json]\n probe which engine CLIs are installed here and sync that into health policy\n atris engine <name> make that engine the default here\n atris engine test [name] preflight: run the engine CLI headless, report pass/fail\n atris engine ask "<question>" --engine <name> [--engine <name> ...]\n ask several engines in parallel without allowing edits\n atris engine ask --jobs <jobs.json>\n ask different read-only questions in parallel\n atris engine validate <receipt-path|latest> [--engine <name>]\n check ask answers with a different read-only referee\n atris engine validate scoreboard\n show pass rates by worker engine\n atris engine dispatch <task-id> [<task-id> ...] --engine cursor|codex [--prompt-file <f>] [--yolo]\n one-command claim, worktree, build, verify, ship, ready\n atris engine login <provider> --yes\n upload a local provider CLI login to the backend vault\n atris engine login <provider> --computer [--seat <name>]\n atris engine login <provider> --business <id> [--seat <name>]\n sign in on an Atris computer by device flow\n atris engine login --list | --remove <provider>\n list or remove vaulted provider logins\n atris engine seats show which named accounts are ready to work\n atris engine seed <provider> --business <id>|--user\n push a vaulted login onto an Atris computer\n atris engine reset back to the house default\n --engine <name> one run on that engine (mission run / autopilot / run)\n');
|
|
1555
|
-
return 0;
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
1570
|
// atris engine <name> — flip the default. An unknown name is a plain user
|
|
1559
1571
|
// typo, not a crash: report it cleanly (and as JSON on demand) instead of
|
|
1560
1572
|
// letting setEngine throw a raw stack trace at a new person.
|
package/commands/errors.js
CHANGED
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
* Errors command for Atris CLI — admin dashboard over atris_error_events.
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
|
-
* atris errors
|
|
5
|
+
* atris errors Local-only by default (no cloud dump)
|
|
6
|
+
* atris errors --account List cloud errors from last 24h
|
|
6
7
|
* atris errors --hours 72 Widen the window (max 720h / 30d)
|
|
7
8
|
* atris errors --limit 1000 Raise the raw-event cap for grouping
|
|
8
9
|
* atris errors show <id> Full detail (stack trace, message) for one event
|
|
9
10
|
*
|
|
10
|
-
* Requires admin role on the user row.
|
|
11
|
+
* Requires admin role on the user row for cloud reads.
|
|
12
|
+
* Account gate: unbound folders need --account (see lib/account-bound.js).
|
|
11
13
|
*/
|
|
12
14
|
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const path = require('path');
|
|
13
17
|
const { loadCredentials } = require('../utils/auth');
|
|
14
18
|
const { apiRequestJson } = require('../utils/api');
|
|
15
19
|
|
|
@@ -38,6 +42,44 @@ function extractFlag(args, ...names) {
|
|
|
38
42
|
return [value, remaining];
|
|
39
43
|
}
|
|
40
44
|
|
|
45
|
+
function wantsLocal(args) {
|
|
46
|
+
if (args.includes('--account') || args.includes('--cloud')) return false;
|
|
47
|
+
// --local is the default; keep the flag recognized for explicit callers.
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function listLocalErrors(json) {
|
|
52
|
+
const localPath = path.join(process.cwd(), '.atris', 'state', 'errors.jsonl');
|
|
53
|
+
const rows = [];
|
|
54
|
+
if (fs.existsSync(localPath)) {
|
|
55
|
+
for (const line of fs.readFileSync(localPath, 'utf8').split('\n')) {
|
|
56
|
+
if (!line.trim()) continue;
|
|
57
|
+
try { rows.push(JSON.parse(line)); } catch { /* skip */ }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (json) {
|
|
62
|
+
console.log(JSON.stringify({
|
|
63
|
+
ok: true,
|
|
64
|
+
scope: 'local',
|
|
65
|
+
total_events: rows.length,
|
|
66
|
+
groups: [],
|
|
67
|
+
note: 'local scope. pass --account for cloud error events.',
|
|
68
|
+
}, null, 2));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (rows.length === 0) {
|
|
73
|
+
console.log('No local errors. Pass --account for cloud error events.');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(`Local errors (${rows.length}). Pass --account for cloud error events.\n`);
|
|
78
|
+
for (const row of rows.slice(0, 20)) {
|
|
79
|
+
console.log(` ${row.message || row.error || JSON.stringify(row)}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
41
83
|
async function listErrors(args) {
|
|
42
84
|
const [hoursArg, r1] = extractFlag(args, '--hours', '-H');
|
|
43
85
|
const [limitArg, r2] = extractFlag(r1, '--limit', '-L');
|
|
@@ -45,6 +87,11 @@ async function listErrors(args) {
|
|
|
45
87
|
const hours = hoursArg ? parseInt(hoursArg, 10) : 24;
|
|
46
88
|
const limit = limitArg ? parseInt(limitArg, 10) : 500;
|
|
47
89
|
|
|
90
|
+
if (wantsLocal(r2)) {
|
|
91
|
+
listLocalErrors(json);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
48
95
|
const token = getToken();
|
|
49
96
|
const result = await apiRequestJson(`/errors?hours=${hours}&limit=${limit}`, {
|
|
50
97
|
method: 'GET',
|
|
@@ -64,7 +111,7 @@ async function listErrors(args) {
|
|
|
64
111
|
const groups = data.groups || [];
|
|
65
112
|
|
|
66
113
|
if (json) {
|
|
67
|
-
console.log(JSON.stringify({ ok: true, ...data }, null, 2));
|
|
114
|
+
console.log(JSON.stringify({ ok: true, scope: 'account', ...data }, null, 2));
|
|
68
115
|
return;
|
|
69
116
|
}
|
|
70
117
|
|
|
@@ -136,12 +183,13 @@ async function showError(errorId) {
|
|
|
136
183
|
function printHelp() {
|
|
137
184
|
console.log('');
|
|
138
185
|
console.log('Usage:');
|
|
139
|
-
console.log(' atris errors
|
|
140
|
-
console.log(' atris errors --
|
|
141
|
-
console.log(' atris errors --
|
|
142
|
-
console.log(' atris errors
|
|
186
|
+
console.log(' atris errors Local errors (default; no cloud dump)');
|
|
187
|
+
console.log(' atris errors --account List cloud errors from last 24h');
|
|
188
|
+
console.log(' atris errors --account --hours 72 Widen the cloud window (max 720h / 30d)');
|
|
189
|
+
console.log(' atris errors --account --limit 1000 Raise the raw-event cap');
|
|
190
|
+
console.log(' atris errors show <full-uuid> Full detail for one cloud event');
|
|
143
191
|
console.log('');
|
|
144
|
-
console.log('Admin role required.');
|
|
192
|
+
console.log('Admin role required for cloud reads. Unbound folders need --account.');
|
|
145
193
|
console.log('');
|
|
146
194
|
}
|
|
147
195
|
|
|
@@ -155,6 +203,8 @@ async function errorsCommand() {
|
|
|
155
203
|
}
|
|
156
204
|
|
|
157
205
|
if (sub === 'show') {
|
|
206
|
+
// show is account-scoped detail; require explicit --account in the remaining args
|
|
207
|
+
// or that the caller already passed the account gate from a bound workspace.
|
|
158
208
|
await showError(args[1]);
|
|
159
209
|
return;
|
|
160
210
|
}
|
package/commands/experiments.js
CHANGED
|
@@ -407,6 +407,18 @@ function buildBenchmarkArtifact(name, packDir, options) {
|
|
|
407
407
|
return { artifact, score };
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
+
function recordExperimentRun(experimentId) {
|
|
411
|
+
const root = process.cwd();
|
|
412
|
+
const state = daily.readDailyState(root);
|
|
413
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
414
|
+
state.last_run_date = today;
|
|
415
|
+
if (!Array.isArray(state.history)) state.history = [];
|
|
416
|
+
if (!state.history.includes(experimentId)) {
|
|
417
|
+
state.history.push(experimentId);
|
|
418
|
+
}
|
|
419
|
+
daily.writeDailyState(root, state);
|
|
420
|
+
}
|
|
421
|
+
|
|
410
422
|
function experimentsRun(name, ...args) {
|
|
411
423
|
const { experimentsDir } = ensureExperimentsFramework();
|
|
412
424
|
|
|
@@ -434,6 +446,7 @@ function experimentsRun(name, ...args) {
|
|
|
434
446
|
return;
|
|
435
447
|
}
|
|
436
448
|
runPython(loopPath, [], packDir);
|
|
449
|
+
recordExperimentRun(name);
|
|
437
450
|
return;
|
|
438
451
|
}
|
|
439
452
|
|
|
@@ -447,6 +460,7 @@ function experimentsRun(name, ...args) {
|
|
|
447
460
|
const { artifact, score } = buildBenchmarkArtifact(name, packDir, options);
|
|
448
461
|
const artifactPath = writeArtifact(packDir, artifact);
|
|
449
462
|
appendResultsRow(path.join(packDir, 'results.tsv'), artifactPath, artifact, score);
|
|
463
|
+
recordExperimentRun(name);
|
|
450
464
|
|
|
451
465
|
console.log(`✓ Endstate ${artifact.track} run recorded`);
|
|
452
466
|
console.log(` artifact: ${path.relative(process.cwd(), artifactPath)}`);
|