tenseleyflow/loader / 383a8c1

Browse files

Track workflow ledger through clarify and recovery

Authored by espadonne
SHA
383a8c16f07487d25cb080c363aa5a8a152dab77
Parents
e84c07c
Tree
ae0d16b

3 changed files

StatusFile+-
M src/loader/runtime/workflow_lanes.py 18 0
M src/loader/runtime/workflow_recovery.py 9 0
M tests/test_workflow_runtime.py 8 0
src/loader/runtime/workflow_lanes.pymodified
@@ -38,6 +38,10 @@ from .workflow import (
3838
     enrich_clarify_brief_with_grounding,
3939
     sync_todos_to_definition_of_done,
4040
 )
41
+from .workflow_ledger import (
42
+    seed_workflow_ledger_from_acceptance_criteria,
43
+    seed_workflow_ledger_from_brief,
44
+)
4145
 
4246
 EventSink = Callable[[AgentEvent], Awaitable[None]]
4347
 UserQuestionHandler = Callable[[str, list[str] | None], Awaitable[str]] | None
@@ -132,6 +136,13 @@ class WorkflowLaneRunner:
132136
         dod.clarify_brief = str(brief_path)
133137
         dod.acceptance_criteria = list(dict.fromkeys(latest_brief.acceptance_criteria))
134138
         self.dod_store.save(dod)
139
+        self.agent.session.update_workflow_ledger(
140
+            seed_workflow_ledger_from_brief(
141
+                self.agent.session.workflow_ledger,
142
+                latest_brief,
143
+                phase="clarify",
144
+            )
145
+        )
135146
         append_timeline(
136147
             ModeDecision.transition(
137148
                 WorkflowMode.CLARIFY,
@@ -202,6 +213,13 @@ class WorkflowLaneRunner:
202213
         if artifacts.verification_commands:
203214
             dod.verification_commands = artifacts.verification_commands
204215
         self.dod_store.save(dod)
216
+        self.agent.session.update_workflow_ledger(
217
+            seed_workflow_ledger_from_acceptance_criteria(
218
+                self.agent.session.workflow_ledger,
219
+                list(dod.acceptance_criteria),
220
+                phase="plan",
221
+            )
222
+        )
205223
         await self._emit_artifact(
206224
             emit=emit,
207225
             kind="implementation_plan",
src/loader/runtime/workflow_recovery.pymodified
@@ -21,6 +21,7 @@ from .workflow import (
2121
     WorkflowSignalExtractor,
2222
 )
2323
 from .workflow_lanes import WorkflowLaneRunner
24
+from .workflow_ledger import apply_freshness_to_workflow_ledger
2425
 
2526
 EventSink = Callable[[AgentEvent], Awaitable[None]]
2627
 UserQuestionHandler = Callable[[str, list[str] | None], Awaitable[str]] | None
@@ -77,6 +78,14 @@ class WorkflowRecoveryController:
7778
         if not freshness.requires_refresh:
7879
             return False
7980
 
81
+        self.agent.session.update_workflow_ledger(
82
+            apply_freshness_to_workflow_ledger(
83
+                self.agent.session.workflow_ledger,
84
+                freshness,
85
+                phase="recovery",
86
+            )
87
+        )
88
+
8089
         strategy = WorkflowRecoveryStrategy(freshness.recovery_strategy)
8190
         if strategy == WorkflowRecoveryStrategy.PLAN_REFRESH:
8291
             return await self._run_plan_refresh_reentry(
tests/test_workflow_runtime.pymodified
@@ -1541,3 +1541,11 @@ async def test_full_replan_can_reenter_clarify_before_rebuilding_plan(
15411541
         entry.reason_code == "full_replan_required"
15421542
         for entry in run.agent.last_turn_summary.workflow_timeline
15431543
     )
1544
+    assert any(
1545
+        item.status == "contradicted"
1546
+        for item in run.agent.session.workflow_ledger.assumptions
1547
+    )
1548
+    assert any(
1549
+        item.status == "changed"
1550
+        for item in run.agent.session.workflow_ledger.acceptance_anchors
1551
+    )