atris 3.30.3 → 3.30.4
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 +113 -9
- package/package.json +1 -1
package/commands/mission.js
CHANGED
|
@@ -851,6 +851,94 @@ 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 seedMissionRunContinuation(parent, root = process.cwd(), proof = '') {
|
|
876
|
+
if (!parent || parent.status !== 'complete') return null;
|
|
877
|
+
if (parent.continue_on_complete !== true) return null;
|
|
878
|
+
if (parent.continuation_seeded_mission_id) return {
|
|
879
|
+
inserted: false,
|
|
880
|
+
reason: 'already_seeded',
|
|
881
|
+
mission_id: parent.continuation_seeded_mission_id,
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
const existing = findActiveContinuationMission(parent, root);
|
|
885
|
+
if (existing) return { inserted: false, reason: 'active_continuation_exists', mission: existing };
|
|
886
|
+
|
|
887
|
+
const owner = parent.owner || process.env.ATRIS_AGENT_ID || 'mission-lead';
|
|
888
|
+
const objective = continuationObjective(parent);
|
|
889
|
+
const mission = missionFromArgs([
|
|
890
|
+
objective,
|
|
891
|
+
'--owner',
|
|
892
|
+
owner,
|
|
893
|
+
'--runner',
|
|
894
|
+
'codex_goal',
|
|
895
|
+
'--lane',
|
|
896
|
+
parent.lane || 'workspace',
|
|
897
|
+
'--cadence',
|
|
898
|
+
'manual',
|
|
899
|
+
'--stop',
|
|
900
|
+
'next useful mission is started, or no useful next mission remains',
|
|
901
|
+
]);
|
|
902
|
+
const nextMission = {
|
|
903
|
+
...mission,
|
|
904
|
+
started_from: 'mission_run_continuation',
|
|
905
|
+
parent_mission_id: parent.id,
|
|
906
|
+
parent_objective: parent.objective,
|
|
907
|
+
continue_on_complete: false,
|
|
908
|
+
continuation_policy: 'choose_next_mission',
|
|
909
|
+
parent_proof: proof || parent.receipt_path || null,
|
|
910
|
+
next_action: `decide next mission, then run: atris mission run "<next useful mission>" --owner ${owner}`,
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
ensureMemberMissionFile(nextMission.owner, root, nextMission.objective);
|
|
914
|
+
const { mission: saved } = saveMission(nextMission, root, 'mission_continuation_started', {
|
|
915
|
+
parent_mission_id: parent.id,
|
|
916
|
+
parent_objective: parent.objective,
|
|
917
|
+
proof: proof || null,
|
|
918
|
+
});
|
|
919
|
+
const worktreeBaseline = captureMissionWorktreeBaseline(saved, root);
|
|
920
|
+
const seededAt = stampIso();
|
|
921
|
+
const { mission: updatedParent } = saveMission({
|
|
922
|
+
...parent,
|
|
923
|
+
continuation_seeded_mission_id: saved.id,
|
|
924
|
+
continuation_seeded_at: seededAt,
|
|
925
|
+
continuation_seeded_objective: saved.objective,
|
|
926
|
+
}, root, 'mission_continuation_seeded', {
|
|
927
|
+
continuation_mission_id: saved.id,
|
|
928
|
+
continuation_objective: saved.objective,
|
|
929
|
+
});
|
|
930
|
+
return {
|
|
931
|
+
inserted: true,
|
|
932
|
+
mission: saved,
|
|
933
|
+
parent: updatedParent,
|
|
934
|
+
worktree_baseline: worktreeBaseline ? {
|
|
935
|
+
path: path.relative(root, missionBaselinePath(saved.id, root)),
|
|
936
|
+
dirty_count: worktreeBaseline.dirty_count,
|
|
937
|
+
dirty_hash: worktreeBaseline.dirty_hash,
|
|
938
|
+
} : null,
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
|
|
854
942
|
function startMission(args) {
|
|
855
943
|
const asJson = wantsJson(args);
|
|
856
944
|
const mission = missionFromArgs(args);
|
|
@@ -931,7 +1019,7 @@ function startMissionFromRunObjective(objective, args) {
|
|
|
931
1019
|
if (hasFlag(args, '--always-on')) startArgs.push('--always-on');
|
|
932
1020
|
if (hasFlag(args, '--xp-task') || hasFlag(args, '--agent-xp')) startArgs.push('--xp-task');
|
|
933
1021
|
|
|
934
|
-
const mission = missionFromArgs(startArgs);
|
|
1022
|
+
const mission = markMissionRunContinuation(missionFromArgs(startArgs));
|
|
935
1023
|
const warnings = [missingVerifierWarning(mission)].filter(Boolean);
|
|
936
1024
|
ensureMemberMissionFile(mission.owner, process.cwd(), mission.objective);
|
|
937
1025
|
const { mission: saved } = saveMission(mission, process.cwd(), 'mission_started', { objective: mission.objective, source: 'mission_run_objective' });
|
|
@@ -2345,6 +2433,7 @@ async function runMission(args) {
|
|
|
2345
2433
|
const startedAt = Date.now();
|
|
2346
2434
|
let backoffAttempt = 0;
|
|
2347
2435
|
let lastRateLimit = null;
|
|
2436
|
+
let continuationGoal = null;
|
|
2348
2437
|
|
|
2349
2438
|
const sessionLabel = skipWorker
|
|
2350
2439
|
? 'caller-session'
|
|
@@ -2557,6 +2646,10 @@ async function runMission(args) {
|
|
|
2557
2646
|
verifier: verifierResult ? (verifierResult.passed ? 'passed' : 'failed') : 'not_run',
|
|
2558
2647
|
receipt: receiptPath,
|
|
2559
2648
|
});
|
|
2649
|
+
if (newStatus === 'complete') {
|
|
2650
|
+
continuationGoal = seedMissionRunContinuation(mission, cwd, receiptPath);
|
|
2651
|
+
if (continuationGoal?.parent) mission = continuationGoal.parent;
|
|
2652
|
+
}
|
|
2560
2653
|
refreshCodexGoalController(cwd);
|
|
2561
2654
|
|
|
2562
2655
|
console.error(`[tick ${tickIdx}] status=${result.status} reason=${result.reason} verifier=${verifierResult ? (verifierResult.passed ? 'pass' : 'fail') : 'skip'} -> ${receiptPath || '-'}`);
|
|
@@ -2634,7 +2727,7 @@ async function runMission(args) {
|
|
|
2634
2727
|
const codexGoalState = refreshCodexGoalController(cwd);
|
|
2635
2728
|
|
|
2636
2729
|
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 },
|
|
2730
|
+
{ 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
2731
|
[
|
|
2639
2732
|
`Ran mission ${mission.id}`,
|
|
2640
2733
|
` objective: ${mission.objective}`,
|
|
@@ -2643,6 +2736,7 @@ async function runMission(args) {
|
|
|
2643
2736
|
pauseReason ? ` pause: ${pauseReason}` : null,
|
|
2644
2737
|
` session: ${sessionId || '(none)'}`,
|
|
2645
2738
|
` summary receipt: ${finalReceipt}`,
|
|
2739
|
+
continuationGoal?.mission ? ` next goal: ${continuationGoal.mission.objective}` : null,
|
|
2646
2740
|
].filter(Boolean),
|
|
2647
2741
|
asJson,
|
|
2648
2742
|
);
|
|
@@ -2771,15 +2865,20 @@ function tickMission(args) {
|
|
|
2771
2865
|
receipt: receiptPath,
|
|
2772
2866
|
summary: summary || undefined,
|
|
2773
2867
|
});
|
|
2868
|
+
const continuationGoal = saved.status === 'complete'
|
|
2869
|
+
? seedMissionRunContinuation(saved, cwd, receiptPath)
|
|
2870
|
+
: null;
|
|
2871
|
+
const outputMission = continuationGoal?.parent || saved;
|
|
2774
2872
|
const codexGoalState = refreshCodexGoalController(process.cwd());
|
|
2775
2873
|
printJsonOrText(
|
|
2776
|
-
{ ok: true, action: 'mission_tick', mission:
|
|
2874
|
+
{ 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
2875
|
[
|
|
2778
|
-
`Ticked mission: ${
|
|
2779
|
-
`State: ${
|
|
2876
|
+
`Ticked mission: ${outputMission.objective}`,
|
|
2877
|
+
`State: ${outputMission.status}`,
|
|
2780
2878
|
`Tick: ${tickIdx}`,
|
|
2781
|
-
`Next: ${
|
|
2879
|
+
`Next: ${outputMission.next_action}`,
|
|
2782
2880
|
...(receiptPath ? [`Receipt: ${receiptPath}`] : []),
|
|
2881
|
+
...(continuationGoal?.mission ? [`Next goal: ${continuationGoal.mission.objective}`] : []),
|
|
2783
2882
|
],
|
|
2784
2883
|
asJson,
|
|
2785
2884
|
);
|
|
@@ -2861,24 +2960,28 @@ function completeMission(args) {
|
|
|
2861
2960
|
result: completion.result,
|
|
2862
2961
|
};
|
|
2863
2962
|
const { mission: saved } = saveMission(next, process.cwd(), 'mission_completed', { proof, completion_gate: next.completion_gate });
|
|
2864
|
-
const
|
|
2963
|
+
const continuationGoal = seedMissionRunContinuation(saved, process.cwd(), proof);
|
|
2964
|
+
const outputMission = continuationGoal?.parent || saved;
|
|
2965
|
+
const logPath = appendMemberLog(outputMission.owner, 'Mission completed', { mission: outputMission.objective, proof });
|
|
2865
2966
|
const codexGoalState = refreshCodexGoalController(process.cwd());
|
|
2866
2967
|
printJsonOrText(
|
|
2867
2968
|
{
|
|
2868
2969
|
ok: true,
|
|
2869
2970
|
action: 'mission_completed',
|
|
2870
|
-
mission:
|
|
2971
|
+
mission: outputMission,
|
|
2871
2972
|
landing: completion.landing,
|
|
2872
2973
|
result: completion.result,
|
|
2873
2974
|
log_path: logPath,
|
|
2874
2975
|
codex_goal_state: codexGoalState,
|
|
2875
2976
|
xp_next_command: xpNextCommand,
|
|
2977
|
+
continuation_goal: continuationGoal,
|
|
2876
2978
|
},
|
|
2877
2979
|
[
|
|
2878
|
-
`Completed mission: ${
|
|
2980
|
+
`Completed mission: ${outputMission.objective}`,
|
|
2879
2981
|
...missionResultLines(completion),
|
|
2880
2982
|
`Proof: ${proof}`,
|
|
2881
2983
|
...(xpNextCommand ? [`AgentXP: ${xpNextCommand}`] : []),
|
|
2984
|
+
...(continuationGoal?.mission ? [`Next goal: ${continuationGoal.mission.objective}`] : []),
|
|
2882
2985
|
],
|
|
2883
2986
|
asJson,
|
|
2884
2987
|
);
|
|
@@ -3059,6 +3162,7 @@ atris mission - durable goal + loop + owner + proof state
|
|
|
3059
3162
|
atris mission run ["objective"|id|--due] [--owner <member>] [--max-ticks 4] [--max-wall 3600] [--cadence "15m"]
|
|
3060
3163
|
[--no-claude] [--no-verify] [--complete-on-pass] [--no-drain] [--json]
|
|
3061
3164
|
(bare run prompts for mission + owner; --due runs the saved queue)
|
|
3165
|
+
(mission-run completions seed the next visible goal: decide and start the next useful mission)
|
|
3062
3166
|
atris mission complete <id> --proof "..."
|
|
3063
3167
|
atris mission stop <id> [--pause] [--reason "..."]
|
|
3064
3168
|
|