atris 3.80.0 → 3.82.1
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/LICENSE +21 -0
- package/README.md +10 -0
- package/atris/atris.md +14 -0
- package/atris/features/README.md +15 -0
- package/atris/policies/README.md +24 -0
- package/atris/skills/README.md +61 -45
- package/atris/skills/design/SKILL.md +6 -5
- package/atris/skills/taste/SKILL.md +39 -0
- package/atris/skills/taste/notes.md +29 -0
- package/atris/skills/taste/principles.md +23 -0
- package/atris/skills/wiki/SKILL.md +14 -2
- package/atris/skills/wiki/index-lines.md +30 -0
- package/atris/skills/wiki/measure.md +20 -0
- package/atris/skills/wiki/note-shape.md +16 -0
- package/atris/skills/wiki/upkeep.md +16 -0
- package/atris/team/README.md +38 -0
- package/atris.md +14 -0
- package/bin/atris.js +1 -1
- package/commands/activate.js +1 -1
- package/commands/auth.js +2 -2
- package/commands/autoland.js +25 -26
- package/commands/autopilot-front.js +46 -1
- package/commands/autopilot.js +55 -25
- package/commands/clean.js +22 -11
- package/commands/computer.js +166 -2413
- package/commands/doc-health.js +48 -1
- package/commands/improve.js +16 -3
- package/commands/init.js +4 -0
- package/commands/integrations.js +69 -1616
- package/commands/mission.js +109 -13
- package/commands/release.js +41 -10
- package/commands/security-review.js +5 -1
- package/commands/site-deploy.js +5 -1
- package/commands/status.js +1 -1
- package/commands/sync.js +12 -8
- package/commands/task.js +144 -118
- package/commands/unknowns.js +9 -5
- package/commands/visualize.js +1 -12
- package/commands/workflow.js +4 -3
- package/commands/worktree.js +68 -1602
- package/commands/xp.js +23 -2113
- package/commands/youtube.js +192 -3110
- package/lib/business-core.js +3 -4
- package/lib/campaign-run-lock.js +12 -1
- package/lib/computer-core.js +2447 -0
- package/lib/engine-ask.js +1 -1
- package/lib/engine-receipt-sweep.js +64 -0
- package/lib/file-lock.js +175 -0
- package/lib/fleet.js +1 -1
- package/lib/integrations-core.js +1695 -0
- package/lib/json-file.js +22 -1
- package/lib/loop-doctor.js +36 -2
- package/lib/map-refs.js +68 -8
- package/lib/member-engine.js +1 -1
- package/lib/member-map-fold.js +49 -11
- package/lib/member-map-inbox.js +2 -1
- package/lib/mission-core.js +9 -2
- package/lib/recall-exam.js +171 -0
- package/lib/roster-markdown.js +2 -2
- package/lib/runner-command.js +5 -5
- package/lib/security-audit-classes.js +20 -2
- package/lib/security-audit.js +31 -1
- package/lib/task-db.js +105 -37
- package/lib/taste-notes.js +35 -0
- package/lib/team-lineup.js +3 -3
- package/lib/todo.js +2 -0
- package/lib/wiki.js +11 -3
- package/lib/worktree-core.js +1517 -0
- package/lib/xp-core.js +2172 -0
- package/lib/youtube-core.js +3178 -0
- package/lib/zen-apply.js +3 -1
- package/package.json +10 -3
- package/utils/auth.js +18 -4
package/commands/doc-health.js
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const { resolveWorkspaceRoot } = require('../lib/mission-root');
|
|
6
6
|
const { readText } = require('./brain');
|
|
7
7
|
const { checkMapDocs, fixMapDocs } = require('../lib/map-refs');
|
|
8
|
+
const { runRecallExam } = require('../lib/recall-exam');
|
|
8
9
|
|
|
9
10
|
const BOOT_FILES = [
|
|
10
11
|
'CLAUDE.md', 'AGENTS.md', 'atris/atris.md', 'atris/MAP.md',
|
|
@@ -357,12 +358,58 @@ function renderDocHealth(payload) {
|
|
|
357
358
|
return lines.join('\n');
|
|
358
359
|
}
|
|
359
360
|
|
|
361
|
+
function flagValue(args, name) {
|
|
362
|
+
const index = args.indexOf(name);
|
|
363
|
+
if (index >= 0 && args[index + 1] && !args[index + 1].startsWith('--')) return args[index + 1];
|
|
364
|
+
return args.find(arg => arg.startsWith(`${name}=`))?.slice(name.length + 1);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function renderRecall(report, summaryOnly) {
|
|
368
|
+
const pct = value => (value === null ? 'n/a' : `${Math.round(value * 100)}%`);
|
|
369
|
+
const lines = [
|
|
370
|
+
`recall exam: ${report.found}/${report.questions} found (${pct(report.found_share)})`,
|
|
371
|
+
`boot read first: ${report.boot_tokens} tokens`,
|
|
372
|
+
`files opened after boot: median ${report.files_opened.median}, mean ${report.files_opened.mean === null ? 'n/a' : report.files_opened.mean.toFixed(2)}`,
|
|
373
|
+
`wrong opens (opened but not on the path to the answer): total ${report.wrong_opens.total}, mean ${report.wrong_opens.mean === null ? 'n/a' : report.wrong_opens.mean.toFixed(2)}`,
|
|
374
|
+
`tokens opened after boot: median ${report.tokens_opened.median}, mean ${report.tokens_opened.mean}, median when found ${report.tokens_opened_when_found.median}`,
|
|
375
|
+
...table(['area', 'found', 'total'], Object.entries(report.by_area).sort().map(([area, row]) => [area, row.found, row.total])),
|
|
376
|
+
];
|
|
377
|
+
if (report.invalid_lines.length) lines.push(`invalid question lines skipped: ${report.invalid_lines.join(', ')}`);
|
|
378
|
+
if (!summaryOnly) {
|
|
379
|
+
lines.push('', ...table(['id', 'found', 'opened', 'wrong', 'tokens', 'answer in'],
|
|
380
|
+
report.results.map(row => [row.id || '-', row.found ? 'yes' : 'no', row.files_opened, row.wrong_opens, row.tokens_opened, row.found_in || '-'])));
|
|
381
|
+
}
|
|
382
|
+
return lines.join('\n');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function recallCommand(args, options, file) {
|
|
386
|
+
const root = resolveWorkspaceRoot(options.cwd || process.cwd());
|
|
387
|
+
const questionsFile = path.resolve(options.cwd || process.cwd(), file);
|
|
388
|
+
if (!stat(questionsFile)?.isFile()) {
|
|
389
|
+
console.log(`no recall questions at ${file}. one object per line: {"q":"...","needle":"exact answer phrase"}`);
|
|
390
|
+
return 1;
|
|
391
|
+
}
|
|
392
|
+
const maxOpens = Number(flagValue(args, '--max-opens')) || undefined;
|
|
393
|
+
const report = runRecallExam(root, questionsFile, { bootFiles: BOOT_FILES, maxOpens });
|
|
394
|
+
// A held-out set is scored without echoing its questions back to the improver.
|
|
395
|
+
const summaryOnly = args.includes('--summary');
|
|
396
|
+
if (args.includes('--json')) {
|
|
397
|
+
const { results, ...totals } = report;
|
|
398
|
+
console.log(JSON.stringify({ ok: true, action: 'doc-health recall', ...totals, ...(summaryOnly ? {} : { results }) }, null, 2));
|
|
399
|
+
} else console.log(renderRecall(report, summaryOnly));
|
|
400
|
+
return 0;
|
|
401
|
+
}
|
|
402
|
+
|
|
360
403
|
function docHealthCommand(args = [], options = {}) {
|
|
361
404
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
362
|
-
console.log('usage: atris doc-health [--json] [--questions <path>] [--fix-refs]');
|
|
405
|
+
console.log('usage: atris doc-health [--json] [--questions <path>] [--fix-refs] [--recall <path> [--summary] [--max-opens N]]');
|
|
363
406
|
console.log(' --fix-refs rewrite map line refs whose code moved; list the ones a human must fix');
|
|
407
|
+
console.log(' --recall follow links from the boot files to answer each question; report found, files opened, tokens read');
|
|
408
|
+
console.log(' --summary with --recall, print totals only so a held-out set stays unseen');
|
|
364
409
|
return 0;
|
|
365
410
|
}
|
|
411
|
+
const recallFile = flagValue(args, '--recall');
|
|
412
|
+
if (recallFile) return recallCommand(args, options, recallFile);
|
|
366
413
|
if (args.includes('--fix-refs')) {
|
|
367
414
|
const root = resolveWorkspaceRoot(options.cwd || process.cwd());
|
|
368
415
|
if (!stat(path.join(root, 'atris', 'MAP.md'))?.isFile()) {
|
package/commands/improve.js
CHANGED
|
@@ -96,6 +96,7 @@ function parseImproveArgs(argv = []) {
|
|
|
96
96
|
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
97
97
|
help: false,
|
|
98
98
|
history: false,
|
|
99
|
+
unknownCommand: null,
|
|
99
100
|
};
|
|
100
101
|
|
|
101
102
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -113,6 +114,7 @@ function parseImproveArgs(argv = []) {
|
|
|
113
114
|
if (a.startsWith('--timeout=')) { const v = Number(a.split('=')[1]); if (v > 0) opts.timeoutMs = Math.round(v * 1000); continue; }
|
|
114
115
|
// positional mode (plan|full|delegate)
|
|
115
116
|
if (!a.startsWith('-') && VALID_MODES.has(a)) { opts.mode = a; continue; }
|
|
117
|
+
if (i === 0 && !a.startsWith('-')) { opts.unknownCommand = a; continue; }
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
if (!VALID_MODES.has(opts.mode)) opts.mode = 'full';
|
|
@@ -300,7 +302,7 @@ function formatTickHistory(summary = {}) {
|
|
|
300
302
|
if (summary.rewardTrend && summary.rewardTrend.length) {
|
|
301
303
|
lines.push(` trend: ${summary.rewardTrend.map((r) => (r == null ? '·' : r)).join(' → ')}`);
|
|
302
304
|
}
|
|
303
|
-
if (!summary.ticks) lines.push(' (no ticks yet, run `atris improve`)');
|
|
305
|
+
if (!summary.ticks) lines.push(' (no ticks yet, run `atris improve tick`)');
|
|
304
306
|
return lines.join('\n');
|
|
305
307
|
}
|
|
306
308
|
|
|
@@ -1049,6 +1051,7 @@ const REVISION_WINDOW_HOURS = 72;
|
|
|
1049
1051
|
const REVISION_IGNORED_FILES = [
|
|
1050
1052
|
/^atris\/MAP\.md$/,
|
|
1051
1053
|
/^atris\/refs\/MAP-NOTES\.md$/,
|
|
1054
|
+
/^atris\/refs\/map\/[^/]+\.md$/,
|
|
1052
1055
|
/^test\/fast-tests\.txt$/,
|
|
1053
1056
|
/^atris\/logs\//,
|
|
1054
1057
|
/^atris\/runs\//,
|
|
@@ -1507,7 +1510,7 @@ Modes (positional or --mode):
|
|
|
1507
1510
|
|
|
1508
1511
|
Options:
|
|
1509
1512
|
--member <name> attribute the tick to a member (the loop's owner)
|
|
1510
|
-
--model <id> override the model (e.g.
|
|
1513
|
+
--model <id> override the model (e.g. sonnet)
|
|
1511
1514
|
--dry-run plan and run but do not commit
|
|
1512
1515
|
--no-fallback do not fall back to a local tick if the backend is down
|
|
1513
1516
|
--workspace <p> workspace path (default: cwd)
|
|
@@ -1523,7 +1526,11 @@ the backend is unreachable or you are not logged in.`);
|
|
|
1523
1526
|
}
|
|
1524
1527
|
|
|
1525
1528
|
function isBareVitalsArgs(argv = []) {
|
|
1526
|
-
|
|
1529
|
+
if (argv.length === 0 || (argv.length === 1 && argv[0] === '--json')) return true;
|
|
1530
|
+
if (argv[0] === 'status' || argv[0] === 'vitals') {
|
|
1531
|
+
return argv.length === 1 || (argv.length === 2 && argv[1] === '--json');
|
|
1532
|
+
}
|
|
1533
|
+
return false;
|
|
1527
1534
|
}
|
|
1528
1535
|
|
|
1529
1536
|
const LOOP_DOCTOR_OPEN_STATUSES = new Set(['planning', 'ready', 'running', 'paused', 'blocked']);
|
|
@@ -1693,6 +1700,12 @@ async function run(argv = [], deps = {}) {
|
|
|
1693
1700
|
const routedArgs = args[0] === 'tick' ? args.slice(1) : args;
|
|
1694
1701
|
const opts = parseImproveArgs(routedArgs);
|
|
1695
1702
|
if (opts.help) { showHelp(); return 0; }
|
|
1703
|
+
if (opts.unknownCommand) {
|
|
1704
|
+
const error = `unknown improve subcommand "${opts.unknownCommand}". try: atris improve, atris improve tick, atris improve history, atris improve doctor, or atris improve revisions.`;
|
|
1705
|
+
if (opts.json) console.log(JSON.stringify({ ok: false, error, subcommand: opts.unknownCommand }));
|
|
1706
|
+
else console.error(error);
|
|
1707
|
+
return 1;
|
|
1708
|
+
}
|
|
1696
1709
|
|
|
1697
1710
|
if (opts.history) {
|
|
1698
1711
|
const summary = summarizeTickHistory(readTickHistory(opts.workspace));
|
package/commands/init.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const { ensureProjectTasteFile } = require('../lib/taste-notes');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const { ensureMemberBundle } = require('../lib/member-scaffold');
|
|
4
5
|
const { ensureExperimentsFramework } = require('./experiments');
|
|
@@ -507,6 +508,9 @@ function initAtris() {
|
|
|
507
508
|
markReady('workspace', 'lessons.md', '✓ Created lessons.md');
|
|
508
509
|
}
|
|
509
510
|
|
|
511
|
+
// Project taste starts empty and is never overwritten; sync leaves it alone.
|
|
512
|
+
if (ensureProjectTasteFile(targetDir)) markReady('workspace', 'taste/TASTE.md', '✓ Created taste/TASTE.md');
|
|
513
|
+
|
|
510
514
|
// Create features directory and README
|
|
511
515
|
const featuresDir = path.join(targetDir, 'features');
|
|
512
516
|
const templatesDir = path.join(featuresDir, '_templates');
|