atris 3.57.4 → 3.58.5
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/README.md +12 -1
- package/atris/skills/clawhub/member-runtime/SKILL.md +9 -9
- package/atris/skills/create-member/SKILL.md +16 -13
- package/atris/skills/design/SKILL.md +27 -4
- package/atris/skills/engines/SKILL.md +55 -12
- package/atris/skills/x-search/SKILL.md +8 -6
- package/atris/skills/youtube/SKILL.md +37 -8
- package/atris/team/brainstormer/MEMBER.md +2 -2
- package/atris/team/executor/MEMBER.md +3 -3
- package/atris/team/launcher/MEMBER.md +4 -4
- package/atris/team/navigator/MEMBER.md +3 -3
- package/atris/team/researcher/MEMBER.md +2 -2
- package/atris/team/validator/MEMBER.md +1 -1
- package/atris.md +14 -0
- package/ax +153 -23
- package/bin/atris.js +78 -30
- package/commands/aeo.js +4 -4
- package/commands/agents.js +1 -1
- package/commands/align.js +12 -12
- package/commands/analytics.js +3 -3
- package/commands/app.js +5 -5
- package/commands/ask.js +175 -0
- package/commands/auth.js +7 -7
- package/commands/autoland.js +29 -5
- package/commands/autopilot-front.js +6 -6
- package/commands/autopilot.js +90 -90
- package/commands/avail.js +5 -5
- package/commands/bench.js +63 -1
- package/commands/browse.js +2 -2
- package/commands/business.js +12 -12
- package/commands/card.js +2 -2
- package/commands/clean.js +13 -13
- package/commands/close.js +3 -3
- package/commands/compile.js +13 -13
- package/commands/computer.js +94 -27
- package/commands/console.js +5 -5
- package/commands/decide.js +1 -1
- package/commands/deck.js +9 -9
- package/commands/drive.js +4 -4
- package/commands/engine.js +173 -19
- package/commands/errors.js +3 -3
- package/commands/experiments.js +18 -1
- package/commands/feed.js +2 -2
- package/commands/feedback.js +4 -4
- package/commands/fleet.js +12 -12
- package/commands/game.js +1 -1
- package/commands/guide.js +49 -0
- package/commands/improve.js +19 -17
- package/commands/init.js +67 -19
- package/commands/interview.js +7 -7
- package/commands/land.js +40 -15
- package/commands/learn.js +12 -12
- package/commands/lesson.js +2 -2
- package/commands/log.js +1 -1
- package/commands/loops.js +4 -4
- package/commands/member.js +75 -50
- package/commands/mission.js +90 -82
- package/commands/one-lap.js +1 -1
- package/commands/pack.js +74 -8
- package/commands/plugin.js +6 -6
- package/commands/probe.js +9 -9
- package/commands/pull.js +35 -35
- package/commands/pulse.js +1 -1
- package/commands/push.js +21 -21
- package/commands/rainmaker.js +1 -1
- package/commands/recap.js +7 -7
- package/commands/reel.js +2 -2
- package/commands/release.js +3 -3
- package/commands/report.js +1 -1
- package/commands/review.js +5 -5
- package/commands/revisions.js +1 -1
- package/commands/run.js +1 -1
- package/commands/scout.js +3 -3
- package/commands/security-review.js +7 -7
- package/commands/serve.js +9 -9
- package/commands/setup.js +1 -1
- package/commands/sign.js +4 -4
- package/commands/signup.js +4 -4
- package/commands/site.js +8 -3
- package/commands/skill.js +6 -6
- package/commands/slop.js +18 -18
- package/commands/social.js +3 -3
- package/commands/soul.js +14 -14
- package/commands/spaceship.js +1 -1
- package/commands/status.js +2 -2
- package/commands/strings.js +13 -13
- package/commands/study.js +4 -4
- package/commands/sync.js +8 -8
- package/commands/task.js +50 -25
- package/commands/teach.js +2 -2
- package/commands/team.js +1 -1
- package/commands/theme.js +2 -2
- package/commands/tree.js +34 -0
- package/commands/truth.js +7 -7
- package/commands/verify.js +12 -12
- package/commands/visualize.js +2 -2
- package/commands/workflow.js +97 -40
- package/commands/worktree.js +1 -1
- package/commands/write.js +9 -9
- package/commands/x-search.js +89 -17
- package/commands/xp.js +6 -3
- package/commands/youtube.js +601 -48
- package/lib/accept-verify-gate.js +3 -3
- package/lib/activity-stream.js +1 -1
- package/lib/auto-accept-certified.js +28 -12
- package/lib/autoland.js +6 -6
- package/lib/bench/engines.js +59 -8
- package/lib/bench/report.js +1 -1
- package/lib/bench/runner.js +204 -5
- package/lib/bench/tree-render.js +76 -0
- package/lib/card.js +1 -1
- package/lib/chat-log-scan.js +1 -1
- package/lib/claude-boot-block.js +2 -0
- package/lib/deck-compose.js +1 -1
- package/lib/deck-history.js +2 -2
- package/lib/deck-layout.js +1 -1
- package/lib/deck-review.js +5 -5
- package/lib/deck-schema.js +1 -1
- package/lib/default-verifier.js +1 -1
- package/lib/developer-api.js +3 -0
- package/lib/engine-ask.js +45 -7
- package/lib/engine-registry.js +15 -2
- package/lib/file-ops.js +1 -1
- package/lib/fleet.js +71 -35
- package/lib/html-render.js +1 -1
- package/lib/intents.js +172 -0
- package/lib/journal.js +1 -1
- package/lib/known-commands.js +2 -2
- package/lib/land-green.js +364 -0
- package/lib/lesson-contradiction.js +2 -2
- package/lib/lesson-preflight.js +1 -1
- package/lib/manifest.js +5 -5
- package/lib/member-alive.js +9 -5
- package/lib/memory-view.js +3 -3
- package/lib/mission-protected-lane.js +1 -1
- package/lib/mission-root.js +2 -2
- package/lib/orb-context.js +10 -10
- package/lib/pack-capabilities.js +861 -3
- package/lib/permission-grants.js +2 -2
- package/lib/policy-lessons.js +6 -6
- package/lib/pulse.js +8 -8
- package/lib/receipt-evidence.js +1 -1
- package/lib/reel.js +1 -1
- package/lib/review-integrity.js +1 -1
- package/lib/runner-command.js +35 -5
- package/lib/scorecard.js +4 -4
- package/lib/security-scan.js +5 -5
- package/lib/self-drive.js +1 -1
- package/lib/site-publish.js +372 -0
- package/lib/site.js +1 -1
- package/lib/slides-deck.js +2 -2
- package/lib/state-detection.js +2 -2
- package/lib/sync-telemetry.js +2 -2
- package/lib/task-db.js +17 -10
- package/lib/task-explanation.js +1 -1
- package/lib/task-proof.js +2 -2
- package/lib/task-receipt.js +3 -3
- package/lib/theme.js +12 -12
- package/lib/todo-fallback.js +3 -3
- package/lib/todo-sections.js +1 -1
- package/lib/tree-hash.js +79 -0
- package/lib/usage.js +1 -1
- package/lib/wish-delegate.js +1 -1
- package/lib/workspace-safety.js +4 -4
- package/lib/workspace-scaffold.js +3 -3
- package/package.json +1 -1
- package/scripts/det/concierge-bakeoff.sh +26 -0
- package/scripts/det/ytquote-repair.js +0 -1
- package/scripts/det/ytrail-race.js +0 -5
- package/scripts/member-operate.mjs +52 -14
- package/scripts/outbound-artifact-gate.js +0 -3
- package/utils/auth.js +0 -3
- package/utils/config.js +0 -1
- package/scripts/det/checklist-score.js +0 -191
package/commands/log.js
CHANGED
|
@@ -119,7 +119,7 @@ function logAtris() {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
console.log(`┌─────────────────────────────────────────────────────────┐`);
|
|
122
|
-
console.log(`│ Daily Log
|
|
122
|
+
console.log(`│ Daily Log, ${dateFormatted} [type "exit" to quit] │`);
|
|
123
123
|
console.log(`└─────────────────────────────────────────────────────────┘`);
|
|
124
124
|
console.log('');
|
|
125
125
|
|
package/commands/loops.js
CHANGED
|
@@ -308,7 +308,7 @@ function auditLoops(cwd = process.cwd()) {
|
|
|
308
308
|
console.log('No atris/loops directory found.');
|
|
309
309
|
console.log('Run: atris loops init');
|
|
310
310
|
console.log('');
|
|
311
|
-
console.log('SELF-IMPROVING: NOT YET
|
|
311
|
+
console.log('SELF-IMPROVING: NOT YET, 1 open');
|
|
312
312
|
return 1;
|
|
313
313
|
}
|
|
314
314
|
|
|
@@ -320,7 +320,7 @@ function auditLoops(cwd = process.cwd()) {
|
|
|
320
320
|
console.log('No loop files found in atris/loops.');
|
|
321
321
|
console.log('Run: atris loops init');
|
|
322
322
|
console.log('');
|
|
323
|
-
console.log('SELF-IMPROVING: NOT YET
|
|
323
|
+
console.log('SELF-IMPROVING: NOT YET, 1 open');
|
|
324
324
|
return 1;
|
|
325
325
|
}
|
|
326
326
|
|
|
@@ -352,7 +352,7 @@ function auditLoops(cwd = process.cwd()) {
|
|
|
352
352
|
console.log('SELF-IMPROVING: YES');
|
|
353
353
|
return 0;
|
|
354
354
|
}
|
|
355
|
-
console.log(`SELF-IMPROVING: NOT YET
|
|
355
|
+
console.log(`SELF-IMPROVING: NOT YET, ${open} open`);
|
|
356
356
|
return 1;
|
|
357
357
|
}
|
|
358
358
|
|
|
@@ -382,7 +382,7 @@ function showLoopsHelp() {
|
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
function loopsCommand(subcommand, ...args) {
|
|
385
|
-
// `loops <sub> --help` is a help request, not a run
|
|
385
|
+
// `loops <sub> --help` is a help request, not a run, tick/start/stop/init
|
|
386
386
|
// mutate loop state, so never execute a subcommand just to show usage.
|
|
387
387
|
if (subcommand === '--help' || subcommand === '-h' || subcommand === 'help'
|
|
388
388
|
|| args.includes('--help') || args.includes('-h')) {
|
package/commands/member.js
CHANGED
|
@@ -215,7 +215,7 @@ function memberPaths(name) {
|
|
|
215
215
|
// Steering signals live in the workspace's single .atris/state store. Resolve
|
|
216
216
|
// the shared workspace root (spine -> git -> cwd) so a member run from a
|
|
217
217
|
// subdirectory reads steering from the real store instead of a nonexistent
|
|
218
|
-
// nested .atris
|
|
218
|
+
// nested .atris, the same resolver the mission/task/usage/autopilot state
|
|
219
219
|
// uses. (teamDir markdown discovery is a separate cwd concern, filed.)
|
|
220
220
|
const workspaceRoot = require('../lib/mission-root').resolveWorkspaceRoot(process.cwd());
|
|
221
221
|
return {
|
|
@@ -482,7 +482,7 @@ function memberRunRunnableMissionId(candidateId, missionMap) {
|
|
|
482
482
|
|
|
483
483
|
function memberRunOwnedActiveMissionId(name, missionMap) {
|
|
484
484
|
// Discovery fallback when the member's own pointers are stale: resume the
|
|
485
|
-
// member's newest moving mission. ready is excluded
|
|
485
|
+
// member's newest moving mission. ready is excluded, it waits for review.
|
|
486
486
|
const owner = String(name || '').trim().toLowerCase();
|
|
487
487
|
const candidates = Array.from(missionMap.values())
|
|
488
488
|
.filter((mission) => String(mission?.owner || '').trim().toLowerCase() === owner)
|
|
@@ -833,7 +833,7 @@ function buildMemberRunStartArgs(owner, missionText, args = [], cwd = process.cw
|
|
|
833
833
|
pushFlagValue(startArgs, args, '--hours');
|
|
834
834
|
pushFlagValue(startArgs, args, '--base');
|
|
835
835
|
// A member-run mission is driven immediately by its runner, not parked on
|
|
836
|
-
// the queue
|
|
836
|
+
// the queue, so the mission-start verifier gate (built for parked planning
|
|
837
837
|
// wishes) would only kill autonomous legs like autopilot's "member chooses
|
|
838
838
|
// useful work". When the caller named no verifier, opt out explicitly.
|
|
839
839
|
if (hasFlag(args, '--no-verify') || !readFlag(args, '--verify', '')) {
|
|
@@ -847,7 +847,7 @@ function buildMemberRunStartArgs(owner, missionText, args = [], cwd = process.cw
|
|
|
847
847
|
pushFlagWhenPresent(startArgs, args, '--stop-when-done');
|
|
848
848
|
// Default to an isolated worktree only when there is a git repo to cut it
|
|
849
849
|
// from. A plain (non-git) workspace would fail every mission start with
|
|
850
|
-
// "fatal: not a git repository"
|
|
850
|
+
// "fatal: not a git repository", degrade to the shared checkout instead.
|
|
851
851
|
if (!hasFlag(args, '--shared-checkout') && !hasFlag(args, '--no-worktree') && insideGitRepo(cwd)) {
|
|
852
852
|
startArgs.push('--worktree');
|
|
853
853
|
}
|
|
@@ -881,7 +881,7 @@ function startMemberRunMission(name, missionText, args = []) {
|
|
|
881
881
|
}
|
|
882
882
|
}
|
|
883
883
|
|
|
884
|
-
// atris member ping <name> "<message>"
|
|
884
|
+
// atris member ping <name> "<message>": talk to a busy member mid-run.
|
|
885
885
|
// Two delivery lanes: the member's most recently touched live mission
|
|
886
886
|
// (including --worktree missions in sibling checkouts), whose next tick
|
|
887
887
|
// consumes the note, and the member's claimed task dialogue, which task-loop
|
|
@@ -958,8 +958,8 @@ function memberPing(name, ...args) {
|
|
|
958
958
|
task_id: taskNote ? taskNote.task_id : null,
|
|
959
959
|
}));
|
|
960
960
|
} else {
|
|
961
|
-
if (mission) console.log(`pinged ${mission.id}
|
|
962
|
-
if (taskNote) console.log(`pinged task ${taskNote.task_id} dialogue
|
|
961
|
+
if (mission) console.log(`pinged ${mission.id}, the next tick reads it (${pendingPings} unread).`);
|
|
962
|
+
if (taskNote) console.log(`pinged task ${taskNote.task_id} dialogue, ${name} reads it on the next step.`);
|
|
963
963
|
}
|
|
964
964
|
return { mission, task_note: taskNote };
|
|
965
965
|
}
|
|
@@ -2665,6 +2665,7 @@ function buildMemberAliveCronScript(name, args = [], paths = memberLoopPaths(nam
|
|
|
2665
2665
|
'--json',
|
|
2666
2666
|
...(hasFlag(args, '--execute') ? ['--execute'] : []),
|
|
2667
2667
|
...(hasFlag(args, '--confirm-autonomy-policy') ? ['--confirm-autonomy-policy'] : []),
|
|
2668
|
+
...(hasFlag(args, '--shared-checkout') ? ['--shared-checkout'] : []),
|
|
2668
2669
|
];
|
|
2669
2670
|
const agent = String(readFlag(args, '--agent', '') || '').trim();
|
|
2670
2671
|
const model = String(readFlag(args, '--model', '') || '').trim();
|
|
@@ -3027,7 +3028,7 @@ function collectAutoImproverLogSignals(root) {
|
|
|
3027
3028
|
].filter((candidate) => fs.existsSync(candidate));
|
|
3028
3029
|
const passLessonText = safeReadText(path.join(root, 'atris', 'lessons.md'), 500000)
|
|
3029
3030
|
.split(/\r?\n/)
|
|
3030
|
-
.filter((line) => /\s+pass\s
|
|
3031
|
+
.filter((line) => /\s+pass\s*[-\u2014:,]/.test(line))
|
|
3031
3032
|
.join('\n');
|
|
3032
3033
|
const failureRegex = /\b(error|failed|failure|blocked|timeout|regression|crash|missing proof|naraka|suffering)\b/i;
|
|
3033
3034
|
const unclearRegex = /\b(tbd|unclear|unknown|needs user|needs owner|needs proof|no next|blocked)\b/i;
|
|
@@ -3046,6 +3047,15 @@ function collectAutoImproverLogSignals(root) {
|
|
|
3046
3047
|
|| /^atris\/team\/[^/]+\/goals\.(md|json)$/.test(relative)
|
|
3047
3048
|
|| relative === 'atris/wiki/log.md';
|
|
3048
3049
|
if (!isRuntimeLog) continue;
|
|
3050
|
+
// Only scan logs from the last 7 days. Historical log lines keep
|
|
3051
|
+
// triggering false-positive findings long after their root cause is
|
|
3052
|
+
// fixed (e.g. "goal-from-mission blocked" from July when MISSION.md
|
|
3053
|
+
// was repaired in August). Old evidence stays on disk for audits;
|
|
3054
|
+
// it just stops feeding the pain score, so pain can actually drop.
|
|
3055
|
+
if (logDate && isRuntimeLog) {
|
|
3056
|
+
const logAgeDays = (Date.now() - new Date(logDate + 'T12:00:00').getTime()) / 864e5;
|
|
3057
|
+
if (logAgeDays > 7) continue;
|
|
3058
|
+
}
|
|
3049
3059
|
const text = safeReadText(filePath);
|
|
3050
3060
|
if (!text) continue;
|
|
3051
3061
|
filesScanned += 1;
|
|
@@ -3419,7 +3429,7 @@ function collectAutoImproverScan(root = process.cwd()) {
|
|
|
3419
3429
|
}
|
|
3420
3430
|
|
|
3421
3431
|
// Lifecycle filter for wake dedupe: a task that already crossed the review boundary
|
|
3422
|
-
// (done/failed/archived, or human-accepted) must never be re-selected as the wake target
|
|
3432
|
+
// (done/failed/archived, or human-accepted) must never be re-selected as the wake target,
|
|
3423
3433
|
// that loop produced an endless "existing_task_found OBL-1433" no-op spiral (OBL-1469).
|
|
3424
3434
|
const AUTO_IMPROVER_INACTIVE_STATUSES = new Set(['done', 'failed', 'archived']);
|
|
3425
3435
|
|
|
@@ -3604,7 +3614,7 @@ async function runAutoImproverWake(name, paths, { execute = false, confirmed = f
|
|
|
3604
3614
|
};
|
|
3605
3615
|
const previousLatest = readJson(path.join(process.cwd(), '.atris', 'state', 'auto-improver-dogfood-latest.json'));
|
|
3606
3616
|
const finalWrite = writeAutoImproverReceipt(name, payload, plannedReceiptPath);
|
|
3607
|
-
// A no-op scan identical to the previous tick earns a receipt but not a journal entry
|
|
3617
|
+
// A no-op scan identical to the previous tick earns a receipt but not a journal entry,
|
|
3608
3618
|
// the cadence loop was appending the same "found: N, prevented: 0" row every ~4 minutes
|
|
3609
3619
|
// and flooding the daily log (2026-06-10 had 100+ identical entries).
|
|
3610
3620
|
const createdNewTask = Boolean(payload.created_task) && payload.created_task.existing === false;
|
|
@@ -3801,7 +3811,7 @@ function appendProjectLog(title, fields = {}) {
|
|
|
3801
3811
|
function parseFrontmatter(content) {
|
|
3802
3812
|
// \r?\n so a CRLF-line-ending MEMBER.md (Windows-edited) still parses; otherwise
|
|
3803
3813
|
// the delimiter never matched (and trailing \r broke the per-line key matchers),
|
|
3804
|
-
// silently dropping the member's entire frontmatter
|
|
3814
|
+
// silently dropping the member's entire frontmatter: role, skills, permissions, tools.
|
|
3805
3815
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
3806
3816
|
if (!match) return null;
|
|
3807
3817
|
|
|
@@ -4047,14 +4057,6 @@ async function memberCreate(name, ...flags) {
|
|
|
4047
4057
|
process.exit(1);
|
|
4048
4058
|
}
|
|
4049
4059
|
|
|
4050
|
-
// Scaffold
|
|
4051
|
-
fs.mkdirSync(memberDir, { recursive: true });
|
|
4052
|
-
fs.mkdirSync(path.join(memberDir, 'skills'), { recursive: true });
|
|
4053
|
-
fs.mkdirSync(path.join(memberDir, 'tools'), { recursive: true });
|
|
4054
|
-
fs.mkdirSync(path.join(memberDir, 'context'), { recursive: true });
|
|
4055
|
-
const logPath = ensureMemberLog(memberDir, { name, role, description: description || `Handles ${role.toLowerCase()} tasks` });
|
|
4056
|
-
ensureMissionFile(memberDir, { name, role, description: description || `Handles ${role.toLowerCase()} tasks` });
|
|
4057
|
-
|
|
4058
4060
|
const content = `---
|
|
4059
4061
|
name: ${name}
|
|
4060
4062
|
role: ${role}
|
|
@@ -4114,11 +4116,20 @@ tools: []
|
|
|
4114
4116
|
2. Rule two
|
|
4115
4117
|
`;
|
|
4116
4118
|
|
|
4117
|
-
|
|
4119
|
+
const memberDescription = description || `Handles ${role.toLowerCase()} tasks`;
|
|
4120
|
+
const { logPath } = ensureMemberBundle(memberDir, {
|
|
4121
|
+
name,
|
|
4122
|
+
role,
|
|
4123
|
+
description: memberDescription,
|
|
4124
|
+
source: 'cli',
|
|
4125
|
+
memberContent: content,
|
|
4126
|
+
});
|
|
4118
4127
|
|
|
4119
4128
|
console.log('');
|
|
4120
4129
|
console.log(`✓ Created team/${name}/MEMBER.md`);
|
|
4130
|
+
console.log(`✓ Created team/${name}/SOUL.md`);
|
|
4121
4131
|
console.log(`✓ Created team/${name}/MISSION.md`);
|
|
4132
|
+
console.log(`✓ Created team/${name}/goals.json + goals.md`);
|
|
4122
4133
|
console.log(`✓ Created team/${name}/skills/`);
|
|
4123
4134
|
console.log(`✓ Created team/${name}/tools/`);
|
|
4124
4135
|
console.log(`✓ Created team/${name}/context/`);
|
|
@@ -4317,17 +4328,18 @@ function memberUpgrade(name) {
|
|
|
4317
4328
|
process.exit(1);
|
|
4318
4329
|
}
|
|
4319
4330
|
|
|
4320
|
-
// Move flat file to directory format
|
|
4331
|
+
// Move flat file to directory format, then backfill the complete identity bundle.
|
|
4321
4332
|
fs.mkdirSync(memberDir, { recursive: true });
|
|
4322
|
-
fs.mkdirSync(path.join(memberDir, 'skills'), { recursive: true });
|
|
4323
|
-
fs.mkdirSync(path.join(memberDir, 'tools'), { recursive: true });
|
|
4324
|
-
fs.mkdirSync(path.join(memberDir, 'context'), { recursive: true });
|
|
4325
|
-
const logPath = ensureMemberLog(memberDir, { name, source: 'upgrade' });
|
|
4326
4333
|
fs.renameSync(legacyFile, memberFile);
|
|
4327
|
-
|
|
4334
|
+
const { logPath } = ensureMemberBundle(memberDir, {
|
|
4335
|
+
name,
|
|
4336
|
+
role: name,
|
|
4337
|
+
description: 'Define why this member exists and how it chooses goals.',
|
|
4338
|
+
source: 'upgrade',
|
|
4339
|
+
});
|
|
4328
4340
|
|
|
4329
4341
|
console.log(`✓ Upgraded team/${name}.md → team/${name}/MEMBER.md`);
|
|
4330
|
-
console.log(`✓ Created MISSION.md, skills/, tools/, context/, logs/${path.basename(logPath)}`);
|
|
4342
|
+
console.log(`✓ Created SOUL.md, MISSION.md, goals.json, goals.md, skills/, tools/, context/, logs/${path.basename(logPath)}`);
|
|
4331
4343
|
}
|
|
4332
4344
|
|
|
4333
4345
|
// --- PUSH subcommand ---
|
|
@@ -4695,7 +4707,7 @@ function memberGoalFromMission(name, ...args) {
|
|
|
4695
4707
|
);
|
|
4696
4708
|
return;
|
|
4697
4709
|
}
|
|
4698
|
-
// The title IS the mission focus
|
|
4710
|
+
// The title IS the mission focus, no boilerplate prefix; the acceptance list already
|
|
4699
4711
|
// says "one bounded step" and the why carries the full sentence.
|
|
4700
4712
|
const title = compactSentence(runtimeFocus, 96);
|
|
4701
4713
|
const existing = state.goals.find((goal) => (
|
|
@@ -4753,7 +4765,7 @@ function memberGoalFromMission(name, ...args) {
|
|
|
4753
4765
|
mission_status: runtime.status || null,
|
|
4754
4766
|
};
|
|
4755
4767
|
// Collapse repeated no-op reuse ticks (same mission state) instead of recording an identical entry
|
|
4756
|
-
// every cadence
|
|
4768
|
+
// every cadence, that grew one member's goals.json to 2,200+ duplicate entries / 13K lines. Real
|
|
4757
4769
|
// transitions (created, changed mission id/status) are still kept; only consecutive dupes are dropped.
|
|
4758
4770
|
const lastEntry = goal.history[goal.history.length - 1];
|
|
4759
4771
|
const isDuplicateReuse = existing && lastEntry
|
|
@@ -4935,7 +4947,7 @@ function fallbackProposalForGoal(goal, context = {}) {
|
|
|
4935
4947
|
const drill = scoreEvidence?.drill || null;
|
|
4936
4948
|
const fileEvidence = context?.evidence?.goal_files || context?.goal_files || null;
|
|
4937
4949
|
const primaryFile = (fileEvidence?.files || []).find((file) => file.exists && file.excerpt) || null;
|
|
4938
|
-
// Don't restate the goal title inside the experiment
|
|
4950
|
+
// Don't restate the goal title inside the experiment, the experiment lives under the goal.
|
|
4939
4951
|
const title = drill && target
|
|
4940
4952
|
? `Run ${target.label || target.slug} drill: ${compactSentence(drill, 96)}`
|
|
4941
4953
|
: drill
|
|
@@ -5170,6 +5182,13 @@ Wiki content:
|
|
|
5170
5182
|
${pageContent}`;
|
|
5171
5183
|
}
|
|
5172
5184
|
|
|
5185
|
+
function isWikiMinerNoiseName(value) {
|
|
5186
|
+
const name = compactSentence(value || '', 120);
|
|
5187
|
+
if (!name) return true;
|
|
5188
|
+
if (/^[A-Z]{2,}$/.test(name)) return false;
|
|
5189
|
+
return /^(?:i|me|my|mine|myself|we|us|our|ours|ourselves|you|your|yours|yourself|yourselves|he|him|his|himself|she|her|hers|herself|it|its|itself|they|them|their|theirs|themselves|this|that|these|those|the|wiki|mission)$/i.test(name);
|
|
5190
|
+
}
|
|
5191
|
+
|
|
5173
5192
|
function normalizeWikiMinerExtraction(raw) {
|
|
5174
5193
|
if (!raw || typeof raw !== 'object') return null;
|
|
5175
5194
|
const allowedEntityTypes = new Set(['person', 'system', 'concept']);
|
|
@@ -5179,14 +5198,14 @@ function normalizeWikiMinerExtraction(raw) {
|
|
|
5179
5198
|
type: allowedEntityTypes.has(String(entity?.type || '').toLowerCase()) ? String(entity.type).toLowerCase() : 'concept',
|
|
5180
5199
|
name: compactSentence(entity?.name || '', 120),
|
|
5181
5200
|
}))
|
|
5182
|
-
.filter((entity) => entity.name);
|
|
5201
|
+
.filter((entity) => !isWikiMinerNoiseName(entity.name));
|
|
5183
5202
|
const relationships = (Array.isArray(raw.relationships) ? raw.relationships : [])
|
|
5184
5203
|
.map((relationship) => ({
|
|
5185
5204
|
from: compactSentence(relationship?.from || '', 120),
|
|
5186
5205
|
to: compactSentence(relationship?.to || '', 120),
|
|
5187
5206
|
type: allowedRelationTypes.has(String(relationship?.type || '').toLowerCase()) ? String(relationship.type).toLowerCase() : 'uses',
|
|
5188
5207
|
}))
|
|
5189
|
-
.filter((relationship) => relationship.from && relationship.to);
|
|
5208
|
+
.filter((relationship) => !isWikiMinerNoiseName(relationship.from) && !isWikiMinerNoiseName(relationship.to));
|
|
5190
5209
|
return { entities, relationships };
|
|
5191
5210
|
}
|
|
5192
5211
|
|
|
@@ -5202,7 +5221,7 @@ function heuristicWikiMinerExtraction(pagePath, pageContent) {
|
|
|
5202
5221
|
let match = pattern.exec(pageContent);
|
|
5203
5222
|
while (match) {
|
|
5204
5223
|
const value = compactSentence(match[1] || match[0], 80);
|
|
5205
|
-
if (
|
|
5224
|
+
if (!isWikiMinerNoiseName(value)) candidates.add(value);
|
|
5206
5225
|
match = pattern.exec(pageContent);
|
|
5207
5226
|
}
|
|
5208
5227
|
}
|
|
@@ -5249,6 +5268,7 @@ async function callWikiMinerLlm(pagePath, pageContent, pageIndex) {
|
|
|
5249
5268
|
function mergeWikiGraph(graph, extraction, sourcePath) {
|
|
5250
5269
|
const entityMap = new Map();
|
|
5251
5270
|
for (const entity of graph.entities || []) {
|
|
5271
|
+
if (isWikiMinerNoiseName(entity.name)) continue;
|
|
5252
5272
|
const key = `${String(entity.type || 'concept').toLowerCase()}:${lowerCompact(entity.name)}`;
|
|
5253
5273
|
entityMap.set(key, { ...entity, sources: Array.isArray(entity.sources) ? entity.sources : [] });
|
|
5254
5274
|
}
|
|
@@ -5261,6 +5281,7 @@ function mergeWikiGraph(graph, extraction, sourcePath) {
|
|
|
5261
5281
|
|
|
5262
5282
|
const relationshipMap = new Map();
|
|
5263
5283
|
for (const relationship of graph.relationships || []) {
|
|
5284
|
+
if (isWikiMinerNoiseName(relationship.from) || isWikiMinerNoiseName(relationship.to)) continue;
|
|
5264
5285
|
const key = `${lowerCompact(relationship.from)}|${String(relationship.type || 'uses').toLowerCase()}|${lowerCompact(relationship.to)}`;
|
|
5265
5286
|
relationshipMap.set(key, { ...relationship, sources: Array.isArray(relationship.sources) ? relationship.sources : [] });
|
|
5266
5287
|
}
|
|
@@ -7250,13 +7271,13 @@ function readMemberScope(name, paths) {
|
|
|
7250
7271
|
if (typeof p === 'string' && p.trim()) scope.push(p.trim());
|
|
7251
7272
|
}
|
|
7252
7273
|
}
|
|
7253
|
-
} catch { /* ignore
|
|
7274
|
+
} catch { /* ignore, fall through with default scope */ }
|
|
7254
7275
|
}
|
|
7255
7276
|
return scope;
|
|
7256
7277
|
}
|
|
7257
7278
|
|
|
7258
7279
|
// Auto-generated artifacts that wake/tick produce as side-effects. Dirty here is expected
|
|
7259
|
-
// and must not gate the next wake
|
|
7280
|
+
// and must not gate the next wake, otherwise the loop deadlocks on its own log writes.
|
|
7260
7281
|
function isAutoGeneratedArtifact(filePath, name) {
|
|
7261
7282
|
const memberLogs = `atris/team/${name}/logs/`;
|
|
7262
7283
|
if (filePath.startsWith(memberLogs)) return true;
|
|
@@ -7421,7 +7442,7 @@ function wakeRuleAutonomousErrorTask(ctx) {
|
|
|
7421
7442
|
};
|
|
7422
7443
|
}
|
|
7423
7444
|
|
|
7424
|
-
// Rule: no active goal
|
|
7445
|
+
// Rule: no active goal, adopt a discovered problem as the objective, else stop.
|
|
7425
7446
|
function wakeRuleNeedsGoal(ctx) {
|
|
7426
7447
|
if (ctx.goal) return null;
|
|
7427
7448
|
const discoveredProblem = ctx.evidence.problem_discovery?.selected || null;
|
|
@@ -7495,7 +7516,7 @@ function wakeRuleDirtyMemberScope(ctx) {
|
|
|
7495
7516
|
return {
|
|
7496
7517
|
decision: 'wait',
|
|
7497
7518
|
reason: 'workspace_dirty_in_member_scope',
|
|
7498
|
-
next_command: `commit/stash files in atris/team/${ctx.name}/ (or member scope)
|
|
7519
|
+
next_command: `commit/stash files in atris/team/${ctx.name}/ (or member scope), or rerun: atris member wake ${ctx.name} --force`,
|
|
7499
7520
|
goal: ctx.goal,
|
|
7500
7521
|
current_experiment: null,
|
|
7501
7522
|
};
|
|
@@ -7784,7 +7805,7 @@ const WAKE_REASON_TEXT = {
|
|
|
7784
7805
|
mission_missing_or_placeholder: "it has no North Star yet, and it won't guess at important work",
|
|
7785
7806
|
no_active_goal: 'it has no active goal to push on yet',
|
|
7786
7807
|
execute_requires_confirm_autonomy_policy: 'autonomous execution waits for your explicit go-ahead',
|
|
7787
|
-
workspace_dirty_in_member_scope: "there are uncommitted changes in its own lane
|
|
7808
|
+
workspace_dirty_in_member_scope: "there are uncommitted changes in its own lane, it won't build on a dirty floor",
|
|
7788
7809
|
blocked_experiment: 'its current experiment is blocked on a human answer',
|
|
7789
7810
|
tick_executed_experiment_proposed: 'it proposed one bounded experiment and queued it for your review',
|
|
7790
7811
|
safe_next_bounded_step: 'it found a safe bounded next step',
|
|
@@ -8184,6 +8205,7 @@ function memberLoopAliveTick(name, run, index, tickStartedAt) {
|
|
|
8184
8205
|
maxWallSeconds: options.operateMaxWall,
|
|
8185
8206
|
autoAcceptLimit: options.autoAcceptLimit,
|
|
8186
8207
|
noPrime: index > 0,
|
|
8208
|
+
sharedCheckout: options.sharedCheckout,
|
|
8187
8209
|
});
|
|
8188
8210
|
const key = `${alive.status || 'alive'}:${alive.reason || 'tick'}`;
|
|
8189
8211
|
state.decisions[key] = (state.decisions[key] || 0) + 1;
|
|
@@ -8194,7 +8216,7 @@ function memberLoopAliveTick(name, run, index, tickStartedAt) {
|
|
|
8194
8216
|
ok: alive.ok !== false,
|
|
8195
8217
|
decision: alive.status || 'alive_tick',
|
|
8196
8218
|
reason: alive.reason || null,
|
|
8197
|
-
executed: options.execute,
|
|
8219
|
+
executed: options.execute && alive.operate?.payload?.executed !== false,
|
|
8198
8220
|
needs_user: alive.needs_user === true,
|
|
8199
8221
|
next_command: alive.next_command || null,
|
|
8200
8222
|
has_mission: alive.has_mission === true,
|
|
@@ -8208,6 +8230,7 @@ function memberLoopAliveTick(name, run, index, tickStartedAt) {
|
|
|
8208
8230
|
alive,
|
|
8209
8231
|
};
|
|
8210
8232
|
state.tickResults.push(tick);
|
|
8233
|
+
if (!tick.ok) state.failed = true;
|
|
8211
8234
|
fs.appendFileSync(state.tickLogPath, JSON.stringify(tick) + '\n', 'utf8');
|
|
8212
8235
|
}
|
|
8213
8236
|
|
|
@@ -8340,13 +8363,14 @@ function memberLoopRecordResult(name, paths, lease, run) {
|
|
|
8340
8363
|
const { hourly, forever, runId, ticks, intervalMs, durationMs, startedAt } = plan;
|
|
8341
8364
|
const { tickResults, decisions, stopped, failed, earlyExit, tickLogPath } = state;
|
|
8342
8365
|
const finishedAt = stampIso();
|
|
8366
|
+
const plannedOnly = aliveMode && tickResults.length > 0 && tickResults.every((tick) => tick.decision === 'planned');
|
|
8343
8367
|
const summary = {
|
|
8344
8368
|
ok: !failed,
|
|
8345
8369
|
action: aliveMode ? 'alive' : 'loop',
|
|
8346
8370
|
schema: aliveMode ? 'atris.member_alive.v1' : 'atris.member_loop.v1',
|
|
8347
8371
|
member: name,
|
|
8348
8372
|
alive: aliveMode,
|
|
8349
|
-
status: failed ? 'failed' : stopped ? 'stopped' : earlyExit ? (earlyExit.blocked_on_human ? 'blocked_on_human' : 'idle') : 'completed',
|
|
8373
|
+
status: failed ? 'failed' : stopped ? 'stopped' : plannedOnly ? 'planned' : earlyExit ? (earlyExit.blocked_on_human ? 'blocked_on_human' : 'idle') : 'completed',
|
|
8350
8374
|
mode: execute ? 'execute' : 'dry_run',
|
|
8351
8375
|
cadence: hourly ? 'hourly' : 'custom',
|
|
8352
8376
|
forever,
|
|
@@ -8406,7 +8430,8 @@ async function memberLoop(name, ...args) {
|
|
|
8406
8430
|
const model = String(readFlag(args, '--model', '') || '').trim() || undefined;
|
|
8407
8431
|
const operateMaxWall = Math.max(60, Math.min(1800, Number(readNumberFlag(args, '--operate-max-wall', readNumberFlag(args, '--max-wall', 900)))));
|
|
8408
8432
|
const autoAcceptLimit = Math.max(1, Math.floor(Number(readNumberFlag(args, '--auto-accept-limit', 8))));
|
|
8409
|
-
const
|
|
8433
|
+
const sharedCheckout = hasFlag(args, '--shared-checkout');
|
|
8434
|
+
const options = { asJson, aliveMode, execute, confirmed, force, agent, model, operateMaxWall, autoAcceptLimit, sharedCheckout };
|
|
8410
8435
|
const paths = memberLoopPaths(name);
|
|
8411
8436
|
fs.mkdirSync(paths.stateDir, { recursive: true });
|
|
8412
8437
|
|
|
@@ -8932,7 +8957,7 @@ function memberScopeQuery(flags) {
|
|
|
8932
8957
|
return q;
|
|
8933
8958
|
}
|
|
8934
8959
|
|
|
8935
|
-
// atris member live
|
|
8960
|
+
// atris member live, what the iPhone app and web see: GET /api/members projection.
|
|
8936
8961
|
async function memberLive(...args) {
|
|
8937
8962
|
const { flags } = parseLiveFlags(args);
|
|
8938
8963
|
const creds = loadCredentials();
|
|
@@ -8951,7 +8976,7 @@ async function memberLive(...args) {
|
|
|
8951
8976
|
return;
|
|
8952
8977
|
}
|
|
8953
8978
|
console.log('');
|
|
8954
|
-
console.log(`live members (${flags.scope}${flags.scopeId ? `:${flags.scopeId}` : ''})
|
|
8979
|
+
console.log(`live members (${flags.scope}${flags.scopeId ? `:${flags.scopeId}` : ''}), same projection the app renders`);
|
|
8955
8980
|
console.log('');
|
|
8956
8981
|
for (const m of members) {
|
|
8957
8982
|
const loop = m.loop_status || {};
|
|
@@ -8965,7 +8990,7 @@ async function memberLive(...args) {
|
|
|
8965
8990
|
console.log('');
|
|
8966
8991
|
}
|
|
8967
8992
|
|
|
8968
|
-
// atris member heartbeat
|
|
8993
|
+
// atris member heartbeat, tell the backend this member is running/done, so
|
|
8969
8994
|
// every surface (iOS, web) shows it live. POST /api/members/{name}/heartbeat.
|
|
8970
8995
|
async function memberHeartbeat(name, ...args) {
|
|
8971
8996
|
if (!name) {
|
|
@@ -8996,10 +9021,10 @@ async function memberHeartbeat(name, ...args) {
|
|
|
8996
9021
|
return;
|
|
8997
9022
|
}
|
|
8998
9023
|
const d = result.data || {};
|
|
8999
|
-
console.log(`${d.running ? '●' : '○'} ${d.member || name} → ${d.state}${d.working_on ?
|
|
9024
|
+
console.log(`${d.running ? '●' : '○'} ${d.member || name} → ${d.state}${d.working_on ? `, ${d.working_on}` : ''} (visible on every surface)`);
|
|
9000
9025
|
}
|
|
9001
9026
|
|
|
9002
|
-
// atris member improvements
|
|
9027
|
+
// atris member improvements, what the business computer improved, day by day.
|
|
9003
9028
|
// GET /api/business/{id}/improvements/daily.
|
|
9004
9029
|
async function memberImprovements(businessId, ...args) {
|
|
9005
9030
|
if (!businessId) {
|
|
@@ -9024,15 +9049,15 @@ async function memberImprovements(businessId, ...args) {
|
|
|
9024
9049
|
}
|
|
9025
9050
|
const history = result.data?.history || [];
|
|
9026
9051
|
console.log('');
|
|
9027
|
-
console.log(`daily improvements
|
|
9052
|
+
console.log(`daily improvements: business ${businessId}`);
|
|
9028
9053
|
console.log('');
|
|
9029
9054
|
if (history.length === 0) {
|
|
9030
|
-
console.log(' (no improvement history yet
|
|
9055
|
+
console.log(' (no improvement history yet, first entry lands after the next nightly self-improve run)');
|
|
9031
9056
|
}
|
|
9032
9057
|
for (const day of history) {
|
|
9033
9058
|
console.log(` ${day.date}: ${day.agents_improved}/${day.agents_total} agents improved`);
|
|
9034
9059
|
for (const agent of day.agents || []) {
|
|
9035
|
-
const note = agent.note ?
|
|
9060
|
+
const note = agent.note ? `, ${agent.note}` : '';
|
|
9036
9061
|
console.log(` ${agent.kept_count > 0 ? '+' : ' '} ${agent.name} (kept ${agent.kept_count}, score ${agent.best_score})${note}`);
|
|
9037
9062
|
}
|
|
9038
9063
|
}
|
|
@@ -9063,7 +9088,7 @@ async function memberChat(name, ...rest) {
|
|
|
9063
9088
|
async function memberCommand(subcommand, ...args) {
|
|
9064
9089
|
// Subcommands that take a member name as args[0] otherwise treat `--help` as
|
|
9065
9090
|
// a name and error with "Member '--help' not found". `create`/`new` handle
|
|
9066
|
-
// help themselves (with subcommand-specific usage)
|
|
9091
|
+
// help themselves (with subcommand-specific usage), leave those alone.
|
|
9067
9092
|
const HELP_AWARE_SUBCOMMANDS = new Set(['create', 'new', 'run', 'install']);
|
|
9068
9093
|
if (!HELP_AWARE_SUBCOMMANDS.has(subcommand) && (args[0] === '-h' || args[0] === '--help')) {
|
|
9069
9094
|
subcommand = undefined;
|