@@ -105,6 +105,163 @@ def _collect_policy_action(
105105 return ""
106106
107107
108+ def _extract_thread_id (
109+ * ,
110+ contract : dict [str , Any ],
111+ task_result : dict [str , Any ] | None ,
112+ run_dir : Path ,
113+ ) -> str :
114+ if isinstance (task_result , dict ):
115+ evidence_refs = task_result .get ("evidence_refs" )
116+ if isinstance (evidence_refs , dict ):
117+ thread_id = str (evidence_refs .get ("thread_id" ) or evidence_refs .get ("codex_thread_id" ) or "" ).strip ()
118+ if thread_id :
119+ return thread_id
120+ assigned_agent = contract .get ("assigned_agent" )
121+ if isinstance (assigned_agent , dict ):
122+ thread_id = str (assigned_agent .get ("codex_thread_id" ) or "" ).strip ()
123+ if thread_id :
124+ return thread_id
125+ return run_dir .name
126+
127+
128+ def _detect_context_pack_trigger (
129+ * ,
130+ failure_reason : str ,
131+ reply_auditor : dict [str , Any ],
132+ ) -> str :
133+ normalized_reason = failure_reason .lower ()
134+ trigger_pairs = [
135+ ("context_pressure" , ["context pressure" , "context limit" , "token limit" ]),
136+ ("contamination" , ["contamination" , "context contamination" , "poisoned context" ]),
137+ ("role_switch" , ["role switch" , "handoff to another role" ]),
138+ ("phase_switch" , ["phase switch" , "stage switch" , "next phase" ]),
139+ ("repetition" , ["repetition" , "repeat" , "looping reply" ]),
140+ ("distortion" , ["distortion" , "garbled" , "misread" ]),
141+ ]
142+ for trigger , phrases in trigger_pairs :
143+ if any (phrase in normalized_reason for phrase in phrases ):
144+ return trigger
145+ signals = reply_auditor .get ("signals" )
146+ if isinstance (signals , list ):
147+ normalized_signals = [str (item ).strip ().lower () for item in signals if str (item ).strip ()]
148+ if any ("repetition" in item for item in normalized_signals ):
149+ return "repetition"
150+ if any ("contamination" in item for item in normalized_signals ):
151+ return "contamination"
152+ return ""
153+
154+
155+ def _build_context_pack_artifact (
156+ * ,
157+ contract : dict [str , Any ],
158+ run_dir : Path ,
159+ failure_reason : str ,
160+ continuation_summary : str ,
161+ reply_auditor : dict [str , Any ],
162+ ) -> dict [str , Any ] | None :
163+ trigger_reason = _detect_context_pack_trigger (
164+ failure_reason = failure_reason ,
165+ reply_auditor = reply_auditor ,
166+ )
167+ if not trigger_reason :
168+ return None
169+ assigned_agent = contract .get ("assigned_agent" ) if isinstance (contract .get ("assigned_agent" ), dict ) else {}
170+ objective = str (contract .get ("objective" ) or "" ).strip () or "Continue the current scope safely."
171+ source_role = str (assigned_agent .get ("role" ) or "WORKER" ).strip () or "WORKER"
172+ thread_id = _extract_thread_id (contract = contract , task_result = None , run_dir = run_dir )
173+ return {
174+ "version" : "v1" ,
175+ "pack_id" : f"ctx-pack-{ run_dir .name } " ,
176+ "role_scope" : "L1" ,
177+ "source_session_id" : thread_id ,
178+ "source_role" : source_role ,
179+ "trigger_reason" : trigger_reason ,
180+ "global_state_summary" : (
181+ f"The current run for '{ objective } ' hit a { trigger_reason } fallback condition and needs an explicit handoff."
182+ ),
183+ "actor_handoff_summary" : continuation_summary ,
184+ "required_reads" : [
185+ "contract.json" ,
186+ "reports/task_result.json" ,
187+ "reports/completion_governance_report.json" ,
188+ ],
189+ "optional_reads" : [
190+ "reports/review_report.json" ,
191+ "reports/test_report.json" ,
192+ "events.jsonl" ,
193+ ],
194+ "conversation_exports" : ["events.jsonl" ],
195+ "artifact_refs" : [
196+ "reports/task_result.json" ,
197+ "reports/completion_governance_report.json" ,
198+ ],
199+ }
200+
201+
202+ def _derive_harness_request_artifact (
203+ * ,
204+ contract : dict [str , Any ],
205+ task_result : dict [str , Any ] | None ,
206+ run_dir : Path ,
207+ ) -> tuple [dict [str , Any ] | None , str ]:
208+ if not isinstance (task_result , dict ):
209+ return None , "not_requested"
210+ gates = task_result .get ("gates" )
211+ if not isinstance (gates , dict ):
212+ return None , "not_requested"
213+ policy_gate = gates .get ("policy_gate" )
214+ if not isinstance (policy_gate , dict ):
215+ return None , "not_requested"
216+ violations = policy_gate .get ("violations" )
217+ if not isinstance (violations , list ) or not violations :
218+ return None , "not_requested"
219+ normalized_violations = [str (item ).strip () for item in violations if str (item ).strip ()]
220+ if not normalized_violations :
221+ return None , "not_requested"
222+
223+ project_level_signals = {"network_gate" , "mcp_gate" , "human_approval_required" }
224+ scope = "project-local" if any (item in project_level_signals for item in normalized_violations ) else "session-local"
225+ approval_state = "approval_required" if scope == "project-local" else "auto_approved"
226+ assigned_agent = contract .get ("assigned_agent" ) if isinstance (contract .get ("assigned_agent" ), dict ) else {}
227+ runtime_options = contract .get ("runtime_options" ) if isinstance (contract .get ("runtime_options" ), dict ) else {}
228+
229+ requested_capabilities = {
230+ "skills" : ["continuation-hardening" ],
231+ "mcp_servers" : ["runtime-governance" ] if "mcp_gate" in normalized_violations else [],
232+ "permission_changes" : [],
233+ "runtime_bindings" : [str (runtime_options .get ("provider" ) or runtime_options .get ("runner" ) or "codex" )],
234+ }
235+ if "network_gate" in normalized_violations :
236+ requested_capabilities ["permission_changes" ].append ("network.allow" )
237+ if "tool_gate" in normalized_violations :
238+ requested_capabilities ["permission_changes" ].append ("tool.allow" )
239+ if "sampling_gate" in normalized_violations :
240+ requested_capabilities ["permission_changes" ].append ("sampling.allow" )
241+ if "human_approval_required" in normalized_violations :
242+ requested_capabilities ["permission_changes" ].append ("approval.resume" )
243+
244+ request = {
245+ "version" : "v1" ,
246+ "request_id" : f"harness-{ run_dir .name } " ,
247+ "scope" : scope ,
248+ "requested_by" : {
249+ "role" : str (assigned_agent .get ("role" ) or "WORKER" ).strip () or "WORKER" ,
250+ "agent_id" : str (assigned_agent .get ("agent_id" ) or "agent-1" ).strip () or "agent-1" ,
251+ },
252+ "reason" : (
253+ "Runtime completion governance detected policy-gate blockers and generated a harness evolution request "
254+ f"for { ', ' .join (normalized_violations )} ."
255+ ),
256+ "requested_capabilities" : requested_capabilities ,
257+ "risk_level" : "medium" if scope == "project-local" else "low" ,
258+ "approval_required" : scope != "session-local" ,
259+ "rollback_plan" : "Remove the temporary capability request and restore the current runtime/tool permission posture." ,
260+ "validation_plan" : "Rerun repo hygiene, targeted runtime tests, and the affected operator read-back after apply." ,
261+ }
262+ return request , approval_state
263+
264+
108265def _build_dod_checker (
109266 * ,
110267 required_checks : list [str ],
@@ -252,6 +409,19 @@ def evaluate_completion_governance(
252409 overall_verdict = "manual_triage"
253410 continuation_summary = "Completion governance could not select a safe automatic continuation path."
254411
412+ context_pack_artifact = _build_context_pack_artifact (
413+ contract = contract ,
414+ run_dir = run_dir ,
415+ failure_reason = failure_reason ,
416+ continuation_summary = continuation_summary ,
417+ reply_auditor = reply_auditor ,
418+ )
419+ harness_request_artifact , harness_policy_state = _derive_harness_request_artifact (
420+ contract = contract ,
421+ task_result = task_result ,
422+ run_dir = run_dir ,
423+ )
424+
255425 report = {
256426 "report_type" : "completion_governance_report" ,
257427 "generated_at" : generated_at ,
@@ -269,12 +439,20 @@ def evaluate_completion_governance(
269439 "summary" : continuation_summary ,
270440 },
271441 "context_pack" : {
272- "status" : "not_wired" ,
273- "summary" : "Context Pack remains fallback-only, but no runtime producer/consumer is wired into finalize_run yet." ,
442+ "status" : "generated" if context_pack_artifact else "not_requested" ,
443+ "summary" : (
444+ f"Generated { context_pack_artifact ['pack_id' ]} for fallback handoff."
445+ if context_pack_artifact
446+ else "No fallback Context Pack was requested for this run."
447+ ),
274448 },
275449 "harness_request" : {
276- "status" : "not_wired" ,
277- "summary" : "Harness Request has a schema home, but no request/apply lifecycle is wired into this run finalizer yet." ,
450+ "status" : harness_policy_state ,
451+ "summary" : (
452+ f"Generated { harness_request_artifact ['request_id' ]} with { harness_policy_state } policy verdict."
453+ if harness_request_artifact
454+ else "No harness evolution request was needed for this run."
455+ ),
278456 },
279457 }
280- return report , updated_unblock_tasks
458+ return report , updated_unblock_tasks , context_pack_artifact , harness_request_artifact
0 commit comments