atris 3.58.7 → 3.59.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 +3 -2
- package/GETTING_STARTED.md +2 -2
- package/PERSONA.md +11 -11
- package/README.md +1 -1
- package/atris/GEMINI.md +7 -6
- package/atris/PERSONA.md +4 -4
- package/atris/features/README.md +77 -6
- package/atris/skills/README.md +44 -15
- package/atris/skills/aeo/SKILL.md +10 -10
- package/atris/skills/atris/SKILL.md +1 -1
- package/atris/skills/engines/SKILL.md +69 -50
- package/atris/skills/meta/SKILL.md +4 -4
- package/bin/atris.js +8 -6
- package/commands/aeo.js +9 -12
- package/commands/analytics.js +8 -11
- package/commands/autopilot.js +79 -8
- package/commands/avail.js +1 -1
- package/commands/brain.js +3 -1
- package/commands/business.js +13 -8
- package/commands/clean.js +17 -0
- package/commands/close.js +2 -1
- package/commands/computer.js +15 -10
- package/commands/context-sync.js +3 -3
- package/commands/doc-health.js +55 -2
- package/commands/engine.js +384 -4
- package/commands/experiments.js +13 -4
- package/commands/host.js +53 -0
- package/commands/improve.js +1 -1
- package/commands/integrations.js +2 -5
- package/commands/learn.js +1 -1
- package/commands/member.js +231 -53
- package/commands/mission.js +129 -19
- package/commands/one-lap.js +58 -3
- package/commands/pack.js +2 -2
- package/commands/probe.js +11 -5
- package/commands/pull.js +1 -1
- package/commands/push.js +1 -1
- package/commands/rainmaker.js +3 -16
- package/commands/run.js +4 -1
- package/commands/scout.js +1 -1
- package/commands/search.js +5 -3
- package/commands/spaceship.js +1 -1
- package/commands/stream.js +27 -2
- package/commands/study.js +15 -9
- package/commands/sync.js +1 -1
- package/commands/task.js +13 -2
- package/commands/unknowns.js +5 -0
- package/commands/verify.js +12 -4
- package/commands/visualize.js +20 -3
- package/commands/workflow.js +23 -7
- package/lib/codex-flight.js +28 -5
- package/lib/dispatch-scout.js +31 -22
- package/lib/engine-registry.js +1482 -13
- package/lib/feedback-triage.js +2 -0
- package/lib/fleet.js +111 -12
- package/lib/host.js +336 -0
- package/lib/improve-vitals-html.js +3 -2
- package/lib/known-commands.js +1 -1
- package/lib/lesson-contradiction.js +2 -2
- package/lib/map-refs.js +226 -0
- package/lib/member-engine.js +253 -0
- package/lib/mission-room.js +4 -4
- package/lib/noninteractive.js +15 -4
- package/lib/policy-lessons.js +1 -1
- package/lib/receipt-block.js +137 -28
- package/lib/roster-markdown.js +206 -0
- package/lib/roster-models.js +179 -0
- package/lib/runner-command.js +95 -15
- package/lib/scorecard.js +4 -4
- package/lib/self-drive.js +9 -1
- package/lib/sleep-sync.js +11 -0
- package/lib/state-detection.js +28 -9
- package/lib/task-db.js +3 -2
- package/lib/todo-fallback.js +1 -1
- package/lib/wish-audit.js +10 -6
- package/lib/wish-delegate.js +29 -5
- package/mcp/atris-mcp/index.mjs +77 -24
- package/package.json +2 -5
- package/scripts/det/det.js +2 -2
- package/scripts/det/pr-description.js +2 -2
- package/scripts/det/test.js +2 -2
- package/templates/members/host/MEMBER.md +23 -0
- package/templates/members/host/MISSION.md +11 -0
- package/templates/members/host/SOUL.md +7 -0
- package/templates/members/host/context/why.md +3 -0
- package/templates/members/host/goals.json +5 -0
- package/templates/members/host/goals.md +3 -0
- package/templates/members/host/skills/host/SKILL.md +13 -0
- package/utils/api.js +1 -1
- package/utils/auth.js +17 -7
- package/utils/backend-root.js +31 -0
- package/utils/config.js +5 -4
- package/utils/owner-identity.js +61 -0
- package/atris/policies/LESSONS.md +0 -13
- package/atris/skills/autopilot/atris-autopilot.md +0 -71
package/commands/member.js
CHANGED
|
@@ -4,10 +4,12 @@ const crypto = require('crypto');
|
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const { execFileSync, spawnSync } = require('child_process');
|
|
6
6
|
const { loadCredentials } = require('../utils/auth');
|
|
7
|
+
const { resolveBackendRoot } = require('../utils/backend-root');
|
|
7
8
|
const { apiRequestJson } = require('../utils/api');
|
|
8
9
|
const { runAliveTick } = require('../lib/member-alive');
|
|
9
10
|
const { defaultObjectiveRunner } = require('../lib/default-runner');
|
|
10
11
|
const { readJson, writeJson } = require('../lib/json-file');
|
|
12
|
+
const { sleepSync } = require('../lib/sleep-sync');
|
|
11
13
|
const { hasFlag, readFlag, readNumberFlag } = require('../lib/arg-parser');
|
|
12
14
|
const { ensureMemberBundle, memberBundlePresent } = require('../lib/member-scaffold');
|
|
13
15
|
const { memberProcessPrompt, MEMBER_PROCESS_PATH } = require('../lib/member-context');
|
|
@@ -686,6 +688,15 @@ const MEMBER_RUN_START_VALUE_FLAGS = [
|
|
|
686
688
|
'--mission-id',
|
|
687
689
|
'--owner',
|
|
688
690
|
'--runner',
|
|
691
|
+
'--engine',
|
|
692
|
+
'--budget',
|
|
693
|
+
'--repo',
|
|
694
|
+
'--native-goal-status',
|
|
695
|
+
'--native-goal-objective',
|
|
696
|
+
'--visible-goal-status',
|
|
697
|
+
'--visible-goal-objective',
|
|
698
|
+
'--max-idle-ticks',
|
|
699
|
+
'--slots',
|
|
689
700
|
'--lane',
|
|
690
701
|
'--cadence',
|
|
691
702
|
'--verify',
|
|
@@ -717,10 +728,49 @@ const MEMBER_RUN_START_BOOLEAN_FLAGS = [
|
|
|
717
728
|
'--stop-when-done',
|
|
718
729
|
'--choose-work',
|
|
719
730
|
'--auto',
|
|
731
|
+
'--headless',
|
|
732
|
+
'--self-drive',
|
|
733
|
+
'--no-claude',
|
|
734
|
+
'--complete-on-pass',
|
|
735
|
+
'--no-drain',
|
|
736
|
+
'--create-next',
|
|
737
|
+
'--preflight',
|
|
738
|
+
'--no-preflight',
|
|
739
|
+
'--room-preflight',
|
|
740
|
+
'--no-room-preflight',
|
|
741
|
+
'--room-auto-run',
|
|
742
|
+
'--no-room-auto-run',
|
|
743
|
+
'--manual-ack',
|
|
744
|
+
'--allow-native-goal-supersede',
|
|
745
|
+
'--supersede-paused-native-goal',
|
|
746
|
+
'--take-goal-slot',
|
|
747
|
+
'--due',
|
|
748
|
+
'--detach',
|
|
749
|
+
'--fleet',
|
|
750
|
+
'--dry-run',
|
|
751
|
+
'--land',
|
|
752
|
+
'--cloud',
|
|
720
753
|
];
|
|
721
754
|
|
|
755
|
+
function memberRunMissionWordIndices(args = []) {
|
|
756
|
+
const values = new Set(MEMBER_RUN_START_VALUE_FLAGS);
|
|
757
|
+
const booleans = new Set(['--full', '--verbose', ...MEMBER_RUN_START_BOOLEAN_FLAGS]);
|
|
758
|
+
const indices = [];
|
|
759
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
760
|
+
const arg = String(args[i]);
|
|
761
|
+
const key = arg.includes('=') ? arg.slice(0, arg.indexOf('=')) : arg;
|
|
762
|
+
if (booleans.has(key)) continue;
|
|
763
|
+
if (values.has(key)) {
|
|
764
|
+
if (!arg.includes('=') && args[i + 1] && !String(args[i + 1]).startsWith('--')) i += 1;
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
indices.push(i);
|
|
768
|
+
}
|
|
769
|
+
return indices;
|
|
770
|
+
}
|
|
771
|
+
|
|
722
772
|
function memberRunMissionText(args = []) {
|
|
723
|
-
return
|
|
773
|
+
return memberRunMissionWordIndices(args).map((index) => args[index]).join(' ').trim();
|
|
724
774
|
}
|
|
725
775
|
|
|
726
776
|
function cleanMemberRunPhrase(value) {
|
|
@@ -811,6 +861,22 @@ function pushFlagWhenPresent(out, args, name) {
|
|
|
811
861
|
if (hasFlag(args, name)) out.push(name);
|
|
812
862
|
}
|
|
813
863
|
|
|
864
|
+
// The runner a new member mission starts with. An explicit --runner or
|
|
865
|
+
// --engine wins. With neither, a member the roster names runs on "auto", so
|
|
866
|
+
// every tick picks the member's engine from ROSTER.md (edits apply on the next
|
|
867
|
+
// tick). Otherwise the old default holds.
|
|
868
|
+
function memberRunRunner(owner, args = [], cwd = process.cwd()) {
|
|
869
|
+
const explicit = readFlag(args, '--runner', '');
|
|
870
|
+
if (explicit) return explicit;
|
|
871
|
+
// codex_goal stalls unattended (no live codex session drives its native goal
|
|
872
|
+
// slot). Default to claude unless a live codex session is signalled; explicit
|
|
873
|
+
// --runner still wins. Proven footgun 2026-07-16. See lib/default-runner.js.
|
|
874
|
+
const fallback = defaultObjectiveRunner(args);
|
|
875
|
+
if (fallback !== 'claude' || readFlag(args, '--engine', '')) return fallback;
|
|
876
|
+
const { memberRosterEngine } = require('../lib/member-engine');
|
|
877
|
+
return memberRosterEngine(owner, cwd) ? 'auto' : fallback;
|
|
878
|
+
}
|
|
879
|
+
|
|
814
880
|
function buildMemberRunStartArgs(owner, missionText, args = [], cwd = process.cwd()) {
|
|
815
881
|
const startArgs = [
|
|
816
882
|
'mission',
|
|
@@ -818,11 +884,8 @@ function buildMemberRunStartArgs(owner, missionText, args = [], cwd = process.cw
|
|
|
818
884
|
missionText,
|
|
819
885
|
'--owner',
|
|
820
886
|
owner,
|
|
821
|
-
// codex_goal stalls unattended (no live codex session drives its native goal
|
|
822
|
-
// slot). Default to claude unless a live codex session is signalled; explicit
|
|
823
|
-
// --runner still wins. Proven footgun 2026-07-16. See lib/default-runner.js.
|
|
824
887
|
'--runner',
|
|
825
|
-
|
|
888
|
+
memberRunRunner(owner, args, cwd),
|
|
826
889
|
'--lane',
|
|
827
890
|
readFlag(args, '--lane', 'workspace'),
|
|
828
891
|
];
|
|
@@ -834,10 +897,8 @@ function buildMemberRunStartArgs(owner, missionText, args = [], cwd = process.cw
|
|
|
834
897
|
pushFlagValue(startArgs, args, '--minutes');
|
|
835
898
|
pushFlagValue(startArgs, args, '--hours');
|
|
836
899
|
pushFlagValue(startArgs, args, '--base');
|
|
837
|
-
//
|
|
838
|
-
//
|
|
839
|
-
// wishes) would only kill autonomous legs like autopilot's "member chooses
|
|
840
|
-
// useful work". When the caller named no verifier, opt out explicitly.
|
|
900
|
+
// Member runs choose and drive work immediately, so an absent check must not
|
|
901
|
+
// leave autonomous callers with a mission that never ran.
|
|
841
902
|
if (hasFlag(args, '--no-verify') || !readFlag(args, '--verify', '')) {
|
|
842
903
|
startArgs.push('--no-verify');
|
|
843
904
|
}
|
|
@@ -853,7 +914,7 @@ function buildMemberRunStartArgs(owner, missionText, args = [], cwd = process.cw
|
|
|
853
914
|
if (!hasFlag(args, '--shared-checkout') && !hasFlag(args, '--no-worktree') && insideGitRepo(cwd)) {
|
|
854
915
|
startArgs.push('--worktree');
|
|
855
916
|
}
|
|
856
|
-
|
|
917
|
+
startArgs.push('--json');
|
|
857
918
|
return startArgs;
|
|
858
919
|
}
|
|
859
920
|
|
|
@@ -871,15 +932,52 @@ function startMemberRunMission(name, missionText, args = []) {
|
|
|
871
932
|
const paths = requireMemberDir(name);
|
|
872
933
|
const owner = paths.storageName || name;
|
|
873
934
|
const startArgs = buildMemberRunStartArgs(owner, missionText, args);
|
|
935
|
+
return memberRunCli(startArgs, process.cwd());
|
|
936
|
+
}
|
|
874
937
|
|
|
938
|
+
function memberRunCli(args, cwd, { live = false, missionId = '' } = {}) {
|
|
875
939
|
const cliPath = path.join(__dirname, '..', 'bin', 'atris.js');
|
|
940
|
+
const runsDir = path.join(cwd, 'atris', 'runs');
|
|
941
|
+
const previousReceipts = live && fs.existsSync(runsDir) ? new Set(fs.readdirSync(runsDir)) : new Set();
|
|
942
|
+
const result = spawnSync(process.execPath, [cliPath, ...args], {
|
|
943
|
+
cwd,
|
|
944
|
+
encoding: 'utf8',
|
|
945
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
946
|
+
stdio: live ? 'inherit' : ['ignore', 'pipe', 'pipe'],
|
|
947
|
+
});
|
|
948
|
+
if (result.error) throw result.error;
|
|
949
|
+
if (live) {
|
|
950
|
+
const receiptName = fs.existsSync(runsDir)
|
|
951
|
+
? fs.readdirSync(runsDir).filter((name) => !previousReceipts.has(name) && name.startsWith(`mission-${missionId}-`) && name.endsWith('.json')).sort().at(-1)
|
|
952
|
+
: null;
|
|
953
|
+
const receipt = receiptName ? readJson(path.join(runsDir, receiptName), null) : null;
|
|
954
|
+
return { status: result.status, payload: receipt?.result?.kind === 'mission_run_summary'
|
|
955
|
+
? { ran_ticks: receipt.result.ran_ticks } : null, stderr: '', errorReported: result.status !== 0 };
|
|
956
|
+
}
|
|
957
|
+
let payload = null;
|
|
876
958
|
try {
|
|
877
|
-
|
|
878
|
-
cwd: process.cwd(),
|
|
879
|
-
stdio: 'inherit',
|
|
880
|
-
});
|
|
959
|
+
payload = JSON.parse(result.stdout);
|
|
881
960
|
} catch (error) {
|
|
882
|
-
|
|
961
|
+
if (result.status === 0) throw new Error(`member run: mission command returned invalid json: ${error.message}`);
|
|
962
|
+
}
|
|
963
|
+
return { status: result.status, payload, stderr: String(result.stderr || '').trim() };
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function memberRunConfiguredVerifier(paths) {
|
|
967
|
+
const frontmatter = parseFrontmatter(fs.readFileSync(paths.memberFile, 'utf8')) || {};
|
|
968
|
+
const check = frontmatter.verify || frontmatter.verifier;
|
|
969
|
+
return typeof check === 'string' ? check.trim() : '';
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
function printMemberRunResult(result, asJson) {
|
|
973
|
+
if (asJson) {
|
|
974
|
+
console.log(JSON.stringify(result));
|
|
975
|
+
} else if (result.started) {
|
|
976
|
+
console.log(`started ${result.mission_id} (${result.state})`);
|
|
977
|
+
}
|
|
978
|
+
if (result.ok === false || (!result.started && result.ok !== true)) {
|
|
979
|
+
if (!result.errorReported) console.error(result.error);
|
|
980
|
+
process.exitCode = 1;
|
|
883
981
|
}
|
|
884
982
|
}
|
|
885
983
|
|
|
@@ -967,48 +1065,96 @@ function memberPing(name, ...args) {
|
|
|
967
1065
|
|
|
968
1066
|
function memberRun(name, ...args) {
|
|
969
1067
|
if (!name || name === '--help' || name === '-h' || hasFlag(args, '--help') || hasFlag(args, '-h')) {
|
|
970
|
-
console.log('
|
|
971
|
-
console.log('
|
|
972
|
-
console.log('
|
|
973
|
-
console.log('
|
|
974
|
-
console.log('
|
|
975
|
-
console.log('
|
|
976
|
-
console.log('
|
|
1068
|
+
console.log('usage: atris member run <name> ["mission text"] [--verify "<cmd>"] [--minutes N|--hours N] [--json]');
|
|
1069
|
+
console.log('new mission: atris member run growth "improve onboarding proof" --verify "npm test" --minutes 30 --json');
|
|
1070
|
+
console.log('choose work: atris member run growth --verify "npm test" --industry logistics --minutes 30 --json');
|
|
1071
|
+
console.log('existing mission: atris member run growth --mission <mission-id> --max-ticks 1 --json');
|
|
1072
|
+
console.log('meaning: if mission text is omitted, the member chooses one useful bounded task from atris state.');
|
|
1073
|
+
console.log('truth: useful work must improve revenue, reliability, speed, security, clarity, or trust, then show plain proof.');
|
|
1074
|
+
console.log('isolation: new missions use --worktree by default; add --shared-checkout to stay here.');
|
|
1075
|
+
console.log('check: --verify or a verify field in the member file adds a mission check.');
|
|
977
1076
|
return;
|
|
978
1077
|
}
|
|
979
1078
|
|
|
1079
|
+
const asJson = hasFlag(args, '--json');
|
|
1080
|
+
const paths = requireMemberDir(name);
|
|
1081
|
+
const requestedVerifier = readFlag(args, '--verify', '') || memberRunConfiguredVerifier(paths);
|
|
980
1082
|
const missionText = memberRunMissionText(args);
|
|
981
1083
|
const hasMissionOverride = Boolean(readFlag(args, '--mission', '') || readFlag(args, '--mission-id', ''));
|
|
1084
|
+
let mission = null;
|
|
1085
|
+
let startedNewMission = false;
|
|
1086
|
+
let nodeModulesLinked = false;
|
|
1087
|
+
let nodeModulesSource = null;
|
|
982
1088
|
if (missionText && !hasMissionOverride) {
|
|
983
|
-
startMemberRunMission(name, missionText, args);
|
|
984
|
-
|
|
1089
|
+
const start = startMemberRunMission(name, missionText, requestedVerifier ? [...args, '--verify', requestedVerifier] : args);
|
|
1090
|
+
if (start.status !== 0 || !start.payload?.mission) {
|
|
1091
|
+
printMemberRunResult({ started: false, state: null, mission_id: start.payload?.mission?.id || null,
|
|
1092
|
+
error: start.payload?.detail || start.payload?.error || start.stderr || 'mission creation failed' }, asJson);
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
mission = start.payload.mission;
|
|
1096
|
+
startedNewMission = true;
|
|
1097
|
+
nodeModulesLinked = Boolean(start.payload.node_modules_linked);
|
|
1098
|
+
nodeModulesSource = start.payload.node_modules_source || null;
|
|
1099
|
+
} else {
|
|
1100
|
+
const missionId = resolveMemberRunMissionId(name, args);
|
|
1101
|
+
if (!missionId) {
|
|
1102
|
+
const start = startMemberRunMission(name, memberRunAutoMissionText(name, args), requestedVerifier ? [...args, '--verify', requestedVerifier] : args);
|
|
1103
|
+
if (start.status !== 0 || !start.payload?.mission) {
|
|
1104
|
+
printMemberRunResult({ started: false, state: null, mission_id: start.payload?.mission?.id || null,
|
|
1105
|
+
error: start.payload?.detail || start.payload?.error || start.stderr || 'mission creation failed' }, asJson);
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
mission = start.payload.mission;
|
|
1109
|
+
startedNewMission = true;
|
|
1110
|
+
nodeModulesLinked = Boolean(start.payload.node_modules_linked);
|
|
1111
|
+
nodeModulesSource = start.payload.node_modules_source || null;
|
|
1112
|
+
} else {
|
|
1113
|
+
mission = require('./mission').resolveMission(missionId);
|
|
1114
|
+
if (!mission) {
|
|
1115
|
+
printMemberRunResult({ started: false, state: null, mission_id: missionId, error: `mission ${missionId} was not found` }, asJson);
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
985
1119
|
}
|
|
986
1120
|
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1121
|
+
if (startedNewMission && !asJson) {
|
|
1122
|
+
if (mission.worktree?.path) console.log(`worktree: ${mission.worktree.path}`);
|
|
1123
|
+
if (nodeModulesLinked) console.log(`linked node_modules from ${nodeModulesSource}`);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
const cwd = mission.worktree?.path || process.cwd();
|
|
1127
|
+
const verifier = readFlag(args, '--verify', '') || mission.verifier || requestedVerifier;
|
|
1128
|
+
if (verifier && verifier !== mission.verifier) {
|
|
1129
|
+
const changed = memberRunCli(['mission', 'set-verifier', mission.id, verifier, '--json'], cwd);
|
|
1130
|
+
if (changed.status !== 0) {
|
|
1131
|
+
printMemberRunResult({ started: false, state: mission.status, mission_id: mission.id, mission,
|
|
1132
|
+
error: changed.payload?.detail || changed.payload?.error || changed.stderr || 'could not set mission check' }, asJson);
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
mission.verifier = verifier;
|
|
991
1136
|
}
|
|
992
1137
|
|
|
993
|
-
const
|
|
1138
|
+
const missionWordIndices = missionText && !hasMissionOverride ? new Set(memberRunMissionWordIndices(args)) : new Set();
|
|
1139
|
+
const executionArgs = args.filter((_, index) => !missionWordIndices.has(index));
|
|
1140
|
+
const runArgs = stripKnownFlags(executionArgs,
|
|
1141
|
+
['--mission', '--mission-id', '--minutes', '--hours', '--industry', '--domain', '--value', '--outcome', '--truth', '--proof', '--base'],
|
|
1142
|
+
['--worktree', '--shared-checkout', '--no-worktree', '--choose-work', '--auto']);
|
|
994
1143
|
const budgetSeconds = memberRunBudgetSeconds(args);
|
|
995
|
-
// A timed run is a loop contract, not one tick: keep picking the next useful
|
|
996
|
-
// move until the wall clock (--max-wall) spends the budget. Only untimed runs
|
|
997
|
-
// default to a single tick.
|
|
998
1144
|
if (!readFlag(runArgs, '--max-ticks', '')) {
|
|
999
1145
|
runArgs.push('--max-ticks', budgetSeconds ? String(Math.max(4, Math.ceil(budgetSeconds / 300))) : '1');
|
|
1000
1146
|
}
|
|
1001
1147
|
if (!readFlag(runArgs, '--max-wall', '')) runArgs.push('--max-wall', String(budgetSeconds || 900));
|
|
1002
|
-
|
|
1003
|
-
const
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1148
|
+
const run = memberRunCli(['mission', 'run', mission.id, ...runArgs], cwd, { live: !asJson, missionId: mission.id });
|
|
1149
|
+
const payload = run.payload || {};
|
|
1150
|
+
const finalMission = payload.mission || require('./mission').resolveMission(mission.id, cwd) || mission;
|
|
1151
|
+
const started = run.status === 0 && payload.ok !== false && Number(payload.ran_ticks) > 0;
|
|
1152
|
+
const noWorkStepExpected = hasFlag(runArgs, '--detach') || hasFlag(runArgs, '--dry-run');
|
|
1153
|
+
const ok = run.status === 0 && payload.ok !== false && (started || noWorkStepExpected);
|
|
1154
|
+
printMemberRunResult({ ...payload, ok, started, state: finalMission.status, mission_id: mission.id,
|
|
1155
|
+
mission: finalMission, node_modules_linked: nodeModulesLinked, node_modules_source: nodeModulesSource,
|
|
1156
|
+
errorReported: run.errorReported,
|
|
1157
|
+
...(!ok ? { error: payload.detail || payload.error || payload.reason || run.stderr || 'mission did not run a work step' } : {}) }, asJson);
|
|
1012
1158
|
}
|
|
1013
1159
|
|
|
1014
1160
|
function loadTeamScoreEvidence(scoreJsonPath) {
|
|
@@ -1831,8 +1977,8 @@ function problemSignalSources(root = process.cwd()) {
|
|
|
1831
1977
|
sources.push(source);
|
|
1832
1978
|
}
|
|
1833
1979
|
for (const source of problemSignalFilesForStateDir(path.join(root, '.atris', 'state'))) push(source);
|
|
1834
|
-
const siblingBackend =
|
|
1835
|
-
if (
|
|
1980
|
+
const siblingBackend = resolveBackendRoot(root);
|
|
1981
|
+
if (siblingBackend) {
|
|
1836
1982
|
for (const source of problemSignalFilesForStateDir(path.join(siblingBackend, '.atris', 'state'), 'backend')) push(source);
|
|
1837
1983
|
}
|
|
1838
1984
|
for (const source of configuredProblemSignalSources(root)) push(source);
|
|
@@ -4170,7 +4316,25 @@ function memberInstall(slug) {
|
|
|
4170
4316
|
const memberDir = path.join(process.cwd(), 'atris', 'team', slug);
|
|
4171
4317
|
const already = memberBundlePresent(memberDir);
|
|
4172
4318
|
fs.mkdirSync(path.join(memberDir, 'logs'), { recursive: true });
|
|
4173
|
-
|
|
4319
|
+
const templateDir = path.join(__dirname, '..', 'templates', 'members', slug);
|
|
4320
|
+
const copied = [];
|
|
4321
|
+
if (fs.existsSync(templateDir)) {
|
|
4322
|
+
const copyMissing = (source, relative = '') => {
|
|
4323
|
+
for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
|
|
4324
|
+
const rel = path.join(relative, entry.name);
|
|
4325
|
+
const target = path.join(memberDir, rel);
|
|
4326
|
+
if (entry.isDirectory()) {
|
|
4327
|
+
fs.mkdirSync(target, { recursive: true });
|
|
4328
|
+
copyMissing(path.join(source, entry.name), rel);
|
|
4329
|
+
} else if (entry.isFile() && !fs.existsSync(target)) {
|
|
4330
|
+
fs.writeFileSync(target, fs.readFileSync(path.join(source, entry.name)), { flag: 'wx' });
|
|
4331
|
+
copied.push(rel);
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
};
|
|
4335
|
+
copyMissing(templateDir);
|
|
4336
|
+
}
|
|
4337
|
+
if (already && copied.length === 0) {
|
|
4174
4338
|
console.log(`MEMBER already installed for ${slug}`);
|
|
4175
4339
|
return;
|
|
4176
4340
|
}
|
|
@@ -4179,7 +4343,7 @@ function memberInstall(slug) {
|
|
|
4179
4343
|
name: slug,
|
|
4180
4344
|
source: 'install',
|
|
4181
4345
|
});
|
|
4182
|
-
for (const rel of created) {
|
|
4346
|
+
for (const rel of [...copied, ...created]) {
|
|
4183
4347
|
console.log(`atris/team/${slug}/${rel.split(path.sep).join('/')}`);
|
|
4184
4348
|
}
|
|
4185
4349
|
console.log(`MEMBER installed for ${slug}.`);
|
|
@@ -4594,12 +4758,6 @@ function printJsonOrText(payload, lines, asJson) {
|
|
|
4594
4758
|
for (const line of lines) console.log(line);
|
|
4595
4759
|
}
|
|
4596
4760
|
|
|
4597
|
-
function sleepSync(ms) {
|
|
4598
|
-
const duration = Math.max(0, Number(ms) || 0);
|
|
4599
|
-
if (duration <= 0) return;
|
|
4600
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, duration);
|
|
4601
|
-
}
|
|
4602
|
-
|
|
4603
4761
|
function memberGoal(name, ...args) {
|
|
4604
4762
|
const paths = requireMemberDir(name);
|
|
4605
4763
|
const asJson = hasFlag(args, '--json');
|
|
@@ -7660,6 +7818,24 @@ function wakeDecision(name, paths, { force = false, runtimeKind = memberRuntimeK
|
|
|
7660
7818
|
return null;
|
|
7661
7819
|
}
|
|
7662
7820
|
|
|
7821
|
+
// The engine this member's work runs on, from the roster: its own team line,
|
|
7822
|
+
// else its job's pick, else the router. Never throws.
|
|
7823
|
+
function wakeMemberEngine(name, root = process.cwd()) {
|
|
7824
|
+
try {
|
|
7825
|
+
const { resolveEngineForMember } = require('../lib/member-engine');
|
|
7826
|
+
const picked = resolveEngineForMember(name, root);
|
|
7827
|
+
return {
|
|
7828
|
+
id: picked.engine ? picked.engine.id : null,
|
|
7829
|
+
model: picked.model || null,
|
|
7830
|
+
job: picked.job,
|
|
7831
|
+
source: picked.source,
|
|
7832
|
+
reason: picked.reason,
|
|
7833
|
+
};
|
|
7834
|
+
} catch {
|
|
7835
|
+
return null;
|
|
7836
|
+
}
|
|
7837
|
+
}
|
|
7838
|
+
|
|
7663
7839
|
async function runMemberWake(name, { execute = false, confirmed = false, force = false, domainInput = {} } = {}) {
|
|
7664
7840
|
const paths = requireMemberDir(name);
|
|
7665
7841
|
const runtimeKind = paths.runtimeKind || memberRuntimeKind(name);
|
|
@@ -7824,6 +8000,7 @@ async function runMemberWake(name, { execute = false, confirmed = false, force =
|
|
|
7824
8000
|
ok: true,
|
|
7825
8001
|
action: 'wake',
|
|
7826
8002
|
member: name,
|
|
8003
|
+
engine: wakeMemberEngine(name),
|
|
7827
8004
|
mode,
|
|
7828
8005
|
decision,
|
|
7829
8006
|
reason,
|
|
@@ -7946,6 +8123,7 @@ function wakeBootLines(name, result) {
|
|
|
7946
8123
|
` goal ${goal ? clipText(goal, 70) : s.dim('none yet')}`,
|
|
7947
8124
|
...(experiment ? [` working ${clipText(experiment, 70)}`] : []),
|
|
7948
8125
|
...(laneCandidates !== null ? [` lane ${laneCandidates} task${laneCandidates === 1 ? '' : 's'} waiting in ${name}'s lane`] : []),
|
|
8126
|
+
...(result.engine && result.engine.id ? [` engine ${clipText(String(result.engine.reason || '').replace(`${name} does `, ''), 70)}`] : []),
|
|
7949
8127
|
'',
|
|
7950
8128
|
` ${s.bold(name)} looked around and ${s.bold(decisionText)}.`,
|
|
7951
8129
|
` ${s.dim(`Why: ${wakeReasonText(result.reason)}.`)}`,
|
|
@@ -9261,7 +9439,7 @@ async function memberCommand(subcommand, ...args) {
|
|
|
9261
9439
|
console.log(' atris member goal-from-mission growth --json');
|
|
9262
9440
|
console.log(' atris member goal-from-score growth --score-json team-score.json --json');
|
|
9263
9441
|
console.log(' atris member wake growth --json');
|
|
9264
|
-
console.log(' atris member run growth "
|
|
9442
|
+
console.log(' atris member run growth "improve onboarding proof" --verify "npm test" --minutes 30 --json');
|
|
9265
9443
|
console.log(' atris member run growth --mission <mission-id> --max-ticks 1 --json');
|
|
9266
9444
|
console.log(' atris member wake growth --execute --confirm-autonomy-policy');
|
|
9267
9445
|
console.log(' atris member supervisor recommendations --json');
|