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.
Files changed (2) hide show
  1. package/commands/mission.js +113 -9
  2. package/package.json +1 -1
@@ -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: saved, tick: tickRecord, verifier_result: verifierResult, receipt_path: receiptPath, log_path: logPath, codex_goal_state: codexGoalState },
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: ${saved.objective}`,
2779
- `State: ${saved.status}`,
2876
+ `Ticked mission: ${outputMission.objective}`,
2877
+ `State: ${outputMission.status}`,
2780
2878
  `Tick: ${tickIdx}`,
2781
- `Next: ${saved.next_action}`,
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 logPath = appendMemberLog(saved.owner, 'Mission completed', { mission: saved.objective, proof });
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: saved,
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: ${saved.objective}`,
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "3.30.3",
3
+ "version": "3.30.4",
4
4
  "main": "bin/atris.js",
5
5
  "bin": {
6
6
  "atris": "bin/atris.js",