atris 3.30.3 → 3.30.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/commands/mission.js +170 -9
- package/package.json +1 -1
package/commands/mission.js
CHANGED
|
@@ -851,6 +851,149 @@ function inferRunObjectiveVerifier(objective, root = process.cwd()) {
|
|
|
851
851
|
return missionRunSmokeVerifier();
|
|
852
852
|
}
|
|
853
853
|
|
|
854
|
+
function markMissionRunContinuation(mission) {
|
|
855
|
+
return {
|
|
856
|
+
...mission,
|
|
857
|
+
started_from: 'mission_run_objective',
|
|
858
|
+
continue_on_complete: true,
|
|
859
|
+
continuation_policy: 'decide_and_start_next_useful_mission',
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
function continuationObjective(parent) {
|
|
864
|
+
return `Decide and start the next useful mission after: ${parent.objective}`;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
function findActiveContinuationMission(parent, root = process.cwd()) {
|
|
868
|
+
return listMissions(root).find((mission) => (
|
|
869
|
+
mission.parent_mission_id === parent.id
|
|
870
|
+
&& mission.started_from === 'mission_run_continuation'
|
|
871
|
+
&& !TERMINAL_STATUSES.has(mission.status)
|
|
872
|
+
)) || null;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
function findActiveMissionRunContinuation(root = process.cwd(), excludeId = '') {
|
|
876
|
+
const excluded = String(excludeId || '');
|
|
877
|
+
const candidates = listMissions(root)
|
|
878
|
+
.filter((mission) => (
|
|
879
|
+
mission.id !== excluded
|
|
880
|
+
&& mission.started_from === 'mission_run_continuation'
|
|
881
|
+
&& mission.continuation_policy === 'choose_next_mission'
|
|
882
|
+
&& !TERMINAL_STATUSES.has(mission.status)
|
|
883
|
+
));
|
|
884
|
+
candidates.sort((a, b) => missionSortTime(b) - missionSortTime(a));
|
|
885
|
+
return candidates[0] || null;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
function completeActiveContinuationForStartedMission(nextMission, root = process.cwd()) {
|
|
889
|
+
const continuation = findActiveMissionRunContinuation(root, nextMission?.id);
|
|
890
|
+
if (!continuation || !nextMission) return null;
|
|
891
|
+
if (continuation.objective === nextMission.objective) return null;
|
|
892
|
+
|
|
893
|
+
const proof = `Started next mission ${nextMission.id}: ${nextMission.objective}`;
|
|
894
|
+
const completionGate = { ok: true, source: 'mission_run_continuation', forced: false };
|
|
895
|
+
const baseNext = {
|
|
896
|
+
...continuation,
|
|
897
|
+
status: 'complete',
|
|
898
|
+
completed_at: stampIso(),
|
|
899
|
+
proof,
|
|
900
|
+
completion_gate: completionGate,
|
|
901
|
+
continued_by_mission_id: nextMission.id,
|
|
902
|
+
continued_by_objective: nextMission.objective,
|
|
903
|
+
next_action: 'mission complete',
|
|
904
|
+
};
|
|
905
|
+
const completion = missionCompletionReceipt(baseNext, proof);
|
|
906
|
+
const { mission: saved } = saveMission({
|
|
907
|
+
...baseNext,
|
|
908
|
+
landing: completion.landing,
|
|
909
|
+
result: completion.result,
|
|
910
|
+
}, root, 'mission_continuation_completed', {
|
|
911
|
+
proof,
|
|
912
|
+
continued_by_mission_id: nextMission.id,
|
|
913
|
+
continued_by_objective: nextMission.objective,
|
|
914
|
+
});
|
|
915
|
+
appendMemberLog(saved.owner, 'Mission continuation completed', {
|
|
916
|
+
mission: saved.objective,
|
|
917
|
+
continued_by: nextMission.id,
|
|
918
|
+
proof,
|
|
919
|
+
}, root);
|
|
920
|
+
return {
|
|
921
|
+
completed: true,
|
|
922
|
+
mission: saved,
|
|
923
|
+
continued_by: {
|
|
924
|
+
mission_id: nextMission.id,
|
|
925
|
+
objective: nextMission.objective,
|
|
926
|
+
},
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
function seedMissionRunContinuation(parent, root = process.cwd(), proof = '') {
|
|
931
|
+
if (!parent || parent.status !== 'complete') return null;
|
|
932
|
+
if (parent.continue_on_complete !== true) return null;
|
|
933
|
+
if (parent.continuation_seeded_mission_id) return {
|
|
934
|
+
inserted: false,
|
|
935
|
+
reason: 'already_seeded',
|
|
936
|
+
mission_id: parent.continuation_seeded_mission_id,
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
const existing = findActiveContinuationMission(parent, root);
|
|
940
|
+
if (existing) return { inserted: false, reason: 'active_continuation_exists', mission: existing };
|
|
941
|
+
|
|
942
|
+
const owner = parent.owner || process.env.ATRIS_AGENT_ID || 'mission-lead';
|
|
943
|
+
const objective = continuationObjective(parent);
|
|
944
|
+
const mission = missionFromArgs([
|
|
945
|
+
objective,
|
|
946
|
+
'--owner',
|
|
947
|
+
owner,
|
|
948
|
+
'--runner',
|
|
949
|
+
'codex_goal',
|
|
950
|
+
'--lane',
|
|
951
|
+
parent.lane || 'workspace',
|
|
952
|
+
'--cadence',
|
|
953
|
+
'manual',
|
|
954
|
+
'--stop',
|
|
955
|
+
'next useful mission is started, or no useful next mission remains',
|
|
956
|
+
]);
|
|
957
|
+
const nextMission = {
|
|
958
|
+
...mission,
|
|
959
|
+
started_from: 'mission_run_continuation',
|
|
960
|
+
parent_mission_id: parent.id,
|
|
961
|
+
parent_objective: parent.objective,
|
|
962
|
+
continue_on_complete: false,
|
|
963
|
+
continuation_policy: 'choose_next_mission',
|
|
964
|
+
parent_proof: proof || parent.receipt_path || null,
|
|
965
|
+
next_action: `decide next mission, then run: atris mission run "<next useful mission>" --owner ${owner}`,
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
ensureMemberMissionFile(nextMission.owner, root, nextMission.objective);
|
|
969
|
+
const { mission: saved } = saveMission(nextMission, root, 'mission_continuation_started', {
|
|
970
|
+
parent_mission_id: parent.id,
|
|
971
|
+
parent_objective: parent.objective,
|
|
972
|
+
proof: proof || null,
|
|
973
|
+
});
|
|
974
|
+
const worktreeBaseline = captureMissionWorktreeBaseline(saved, root);
|
|
975
|
+
const seededAt = stampIso();
|
|
976
|
+
const { mission: updatedParent } = saveMission({
|
|
977
|
+
...parent,
|
|
978
|
+
continuation_seeded_mission_id: saved.id,
|
|
979
|
+
continuation_seeded_at: seededAt,
|
|
980
|
+
continuation_seeded_objective: saved.objective,
|
|
981
|
+
}, root, 'mission_continuation_seeded', {
|
|
982
|
+
continuation_mission_id: saved.id,
|
|
983
|
+
continuation_objective: saved.objective,
|
|
984
|
+
});
|
|
985
|
+
return {
|
|
986
|
+
inserted: true,
|
|
987
|
+
mission: saved,
|
|
988
|
+
parent: updatedParent,
|
|
989
|
+
worktree_baseline: worktreeBaseline ? {
|
|
990
|
+
path: path.relative(root, missionBaselinePath(saved.id, root)),
|
|
991
|
+
dirty_count: worktreeBaseline.dirty_count,
|
|
992
|
+
dirty_hash: worktreeBaseline.dirty_hash,
|
|
993
|
+
} : null,
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
|
|
854
997
|
function startMission(args) {
|
|
855
998
|
const asJson = wantsJson(args);
|
|
856
999
|
const mission = missionFromArgs(args);
|
|
@@ -931,7 +1074,7 @@ function startMissionFromRunObjective(objective, args) {
|
|
|
931
1074
|
if (hasFlag(args, '--always-on')) startArgs.push('--always-on');
|
|
932
1075
|
if (hasFlag(args, '--xp-task') || hasFlag(args, '--agent-xp')) startArgs.push('--xp-task');
|
|
933
1076
|
|
|
934
|
-
const mission = missionFromArgs(startArgs);
|
|
1077
|
+
const mission = markMissionRunContinuation(missionFromArgs(startArgs));
|
|
935
1078
|
const warnings = [missingVerifierWarning(mission)].filter(Boolean);
|
|
936
1079
|
ensureMemberMissionFile(mission.owner, process.cwd(), mission.objective);
|
|
937
1080
|
const { mission: saved } = saveMission(mission, process.cwd(), 'mission_started', { objective: mission.objective, source: 'mission_run_objective' });
|
|
@@ -944,6 +1087,7 @@ function startMissionFromRunObjective(objective, args) {
|
|
|
944
1087
|
verifier: saved.verifier,
|
|
945
1088
|
});
|
|
946
1089
|
const worktreeBaseline = captureMissionWorktreeBaseline(saved, process.cwd());
|
|
1090
|
+
const completedContinuationGoal = completeActiveContinuationForStartedMission(saved, process.cwd());
|
|
947
1091
|
const codexGoalState = refreshCodexGoalController(process.cwd());
|
|
948
1092
|
printJsonOrText(
|
|
949
1093
|
{
|
|
@@ -959,6 +1103,7 @@ function startMissionFromRunObjective(objective, args) {
|
|
|
959
1103
|
dirty_count: worktreeBaseline.dirty_count,
|
|
960
1104
|
dirty_hash: worktreeBaseline.dirty_hash,
|
|
961
1105
|
} : null,
|
|
1106
|
+
completed_continuation_goal: completedContinuationGoal,
|
|
962
1107
|
codex_goal_state: codexGoalState,
|
|
963
1108
|
next_command: codexGoalState.goal?.next_command || `atris mission tick ${saved.id} --verify`,
|
|
964
1109
|
},
|
|
@@ -2345,6 +2490,7 @@ async function runMission(args) {
|
|
|
2345
2490
|
const startedAt = Date.now();
|
|
2346
2491
|
let backoffAttempt = 0;
|
|
2347
2492
|
let lastRateLimit = null;
|
|
2493
|
+
let continuationGoal = null;
|
|
2348
2494
|
|
|
2349
2495
|
const sessionLabel = skipWorker
|
|
2350
2496
|
? 'caller-session'
|
|
@@ -2557,6 +2703,10 @@ async function runMission(args) {
|
|
|
2557
2703
|
verifier: verifierResult ? (verifierResult.passed ? 'passed' : 'failed') : 'not_run',
|
|
2558
2704
|
receipt: receiptPath,
|
|
2559
2705
|
});
|
|
2706
|
+
if (newStatus === 'complete') {
|
|
2707
|
+
continuationGoal = seedMissionRunContinuation(mission, cwd, receiptPath);
|
|
2708
|
+
if (continuationGoal?.parent) mission = continuationGoal.parent;
|
|
2709
|
+
}
|
|
2560
2710
|
refreshCodexGoalController(cwd);
|
|
2561
2711
|
|
|
2562
2712
|
console.error(`[tick ${tickIdx}] status=${result.status} reason=${result.reason} verifier=${verifierResult ? (verifierResult.passed ? 'pass' : 'fail') : 'skip'} -> ${receiptPath || '-'}`);
|
|
@@ -2634,7 +2784,7 @@ async function runMission(args) {
|
|
|
2634
2784
|
const codexGoalState = refreshCodexGoalController(cwd);
|
|
2635
2785
|
|
|
2636
2786
|
printJsonOrText(
|
|
2637
|
-
{ ok: true, action: 'mission_run', mission, ran_ticks: ranTicks, tick_count: ticks.length, ticks, pause_reason: pauseReason, session_id: sessionId, summary_receipt: finalReceipt, worktree: summaryWorktree, codex_goal_state: codexGoalState },
|
|
2787
|
+
{ ok: true, action: 'mission_run', mission, ran_ticks: ranTicks, tick_count: ticks.length, ticks, pause_reason: pauseReason, session_id: sessionId, summary_receipt: finalReceipt, worktree: summaryWorktree, codex_goal_state: codexGoalState, continuation_goal: continuationGoal },
|
|
2638
2788
|
[
|
|
2639
2789
|
`Ran mission ${mission.id}`,
|
|
2640
2790
|
` objective: ${mission.objective}`,
|
|
@@ -2643,6 +2793,7 @@ async function runMission(args) {
|
|
|
2643
2793
|
pauseReason ? ` pause: ${pauseReason}` : null,
|
|
2644
2794
|
` session: ${sessionId || '(none)'}`,
|
|
2645
2795
|
` summary receipt: ${finalReceipt}`,
|
|
2796
|
+
continuationGoal?.mission ? ` next goal: ${continuationGoal.mission.objective}` : null,
|
|
2646
2797
|
].filter(Boolean),
|
|
2647
2798
|
asJson,
|
|
2648
2799
|
);
|
|
@@ -2771,15 +2922,20 @@ function tickMission(args) {
|
|
|
2771
2922
|
receipt: receiptPath,
|
|
2772
2923
|
summary: summary || undefined,
|
|
2773
2924
|
});
|
|
2925
|
+
const continuationGoal = saved.status === 'complete'
|
|
2926
|
+
? seedMissionRunContinuation(saved, cwd, receiptPath)
|
|
2927
|
+
: null;
|
|
2928
|
+
const outputMission = continuationGoal?.parent || saved;
|
|
2774
2929
|
const codexGoalState = refreshCodexGoalController(process.cwd());
|
|
2775
2930
|
printJsonOrText(
|
|
2776
|
-
{ ok: true, action: 'mission_tick', mission:
|
|
2931
|
+
{ ok: true, action: 'mission_tick', mission: outputMission, tick: tickRecord, verifier_result: verifierResult, receipt_path: receiptPath, log_path: logPath, codex_goal_state: codexGoalState, continuation_goal: continuationGoal },
|
|
2777
2932
|
[
|
|
2778
|
-
`Ticked mission: ${
|
|
2779
|
-
`State: ${
|
|
2933
|
+
`Ticked mission: ${outputMission.objective}`,
|
|
2934
|
+
`State: ${outputMission.status}`,
|
|
2780
2935
|
`Tick: ${tickIdx}`,
|
|
2781
|
-
`Next: ${
|
|
2936
|
+
`Next: ${outputMission.next_action}`,
|
|
2782
2937
|
...(receiptPath ? [`Receipt: ${receiptPath}`] : []),
|
|
2938
|
+
...(continuationGoal?.mission ? [`Next goal: ${continuationGoal.mission.objective}`] : []),
|
|
2783
2939
|
],
|
|
2784
2940
|
asJson,
|
|
2785
2941
|
);
|
|
@@ -2861,24 +3017,28 @@ function completeMission(args) {
|
|
|
2861
3017
|
result: completion.result,
|
|
2862
3018
|
};
|
|
2863
3019
|
const { mission: saved } = saveMission(next, process.cwd(), 'mission_completed', { proof, completion_gate: next.completion_gate });
|
|
2864
|
-
const
|
|
3020
|
+
const continuationGoal = seedMissionRunContinuation(saved, process.cwd(), proof);
|
|
3021
|
+
const outputMission = continuationGoal?.parent || saved;
|
|
3022
|
+
const logPath = appendMemberLog(outputMission.owner, 'Mission completed', { mission: outputMission.objective, proof });
|
|
2865
3023
|
const codexGoalState = refreshCodexGoalController(process.cwd());
|
|
2866
3024
|
printJsonOrText(
|
|
2867
3025
|
{
|
|
2868
3026
|
ok: true,
|
|
2869
3027
|
action: 'mission_completed',
|
|
2870
|
-
mission:
|
|
3028
|
+
mission: outputMission,
|
|
2871
3029
|
landing: completion.landing,
|
|
2872
3030
|
result: completion.result,
|
|
2873
3031
|
log_path: logPath,
|
|
2874
3032
|
codex_goal_state: codexGoalState,
|
|
2875
3033
|
xp_next_command: xpNextCommand,
|
|
3034
|
+
continuation_goal: continuationGoal,
|
|
2876
3035
|
},
|
|
2877
3036
|
[
|
|
2878
|
-
`Completed mission: ${
|
|
3037
|
+
`Completed mission: ${outputMission.objective}`,
|
|
2879
3038
|
...missionResultLines(completion),
|
|
2880
3039
|
`Proof: ${proof}`,
|
|
2881
3040
|
...(xpNextCommand ? [`AgentXP: ${xpNextCommand}`] : []),
|
|
3041
|
+
...(continuationGoal?.mission ? [`Next goal: ${continuationGoal.mission.objective}`] : []),
|
|
2882
3042
|
],
|
|
2883
3043
|
asJson,
|
|
2884
3044
|
);
|
|
@@ -3059,6 +3219,7 @@ atris mission - durable goal + loop + owner + proof state
|
|
|
3059
3219
|
atris mission run ["objective"|id|--due] [--owner <member>] [--max-ticks 4] [--max-wall 3600] [--cadence "15m"]
|
|
3060
3220
|
[--no-claude] [--no-verify] [--complete-on-pass] [--no-drain] [--json]
|
|
3061
3221
|
(bare run prompts for mission + owner; --due runs the saved queue)
|
|
3222
|
+
(mission-run completions seed the next visible goal: decide and start the next useful mission)
|
|
3062
3223
|
atris mission complete <id> --proof "..."
|
|
3063
3224
|
atris mission stop <id> [--pause] [--reason "..."]
|
|
3064
3225
|
|