Jelajahi Sumber

fix: project rejected chapter commits to state

lingfengQAQ 3 minggu lalu
induk
melakukan
a656fd1f62

+ 1 - 2
webnovel-writer/scripts/chapter_commit.py

@@ -35,8 +35,7 @@ def main() -> None:
         extraction_result=_read_json(args.extraction_result),
     )
     service.persist_commit(payload)
-    if payload["meta"]["status"] == "accepted":
-        payload = service.apply_projections(payload)
+    payload = service.apply_projections(payload)
     print(json.dumps(payload, ensure_ascii=False))
 
 

+ 16 - 14
webnovel-writer/scripts/data_modules/chapter_commit_service.py

@@ -100,23 +100,25 @@ class ChapterCommitService:
         return path
 
     def apply_projections(self, payload: Dict[str, Any]) -> Dict[str, Any]:
-        if payload["meta"]["status"] != "accepted":
+        status = str((payload.get("meta") or {}).get("status") or "")
+        if status not in {"accepted", "rejected"}:
             return payload
 
-        chapter = int((payload.get("meta") or {}).get("chapter") or 0)
-        event_store = EventLogStore(self.project_root)
-        payload["accepted_events"] = event_store.normalize_events(
-            chapter, payload.get("accepted_events", [])
-        )
-        event_store.write_events(chapter, payload["accepted_events"])
+        if status == "accepted":
+            chapter = int((payload.get("meta") or {}).get("chapter") or 0)
+            event_store = EventLogStore(self.project_root)
+            payload["accepted_events"] = event_store.normalize_events(
+                chapter, payload.get("accepted_events", [])
+            )
+            event_store.write_events(chapter, payload["accepted_events"])
 
-        proposals = AmendProposalTrigger().check(chapter, payload.get("accepted_events", []))
-        if proposals:
-            manager = IndexManager(DataModulesConfig.from_project_root(self.project_root))
-            with manager._get_conn() as conn:
-                ensure_override_ledger_columns(conn)
-                persist_amend_proposals(conn, chapter, proposals)
-                conn.commit()
+            proposals = AmendProposalTrigger().check(chapter, payload.get("accepted_events", []))
+            if proposals:
+                manager = IndexManager(DataModulesConfig.from_project_root(self.project_root))
+                with manager._get_conn() as conn:
+                    ensure_override_ledger_columns(conn)
+                    persist_amend_proposals(conn, chapter, proposals)
+                    conn.commit()
 
         from .index_projection_writer import IndexProjectionWriter
         from .memory_projection_writer import MemoryProjectionWriter

+ 5 - 1
webnovel-writer/scripts/data_modules/event_projection_router.py

@@ -24,7 +24,11 @@ class EventProjectionRouter:
 
     def required_writers(self, commit_payload: Dict) -> List[str]:
         writers: Set[str] = set()
-        if str((commit_payload.get("meta") or {}).get("status") or "") == "accepted":
+        status = str((commit_payload.get("meta") or {}).get("status") or "")
+        if status == "rejected":
+            writers.add("state")
+            return sorted(writers)
+        if status == "accepted":
             writers.add("state")
             writers.add("index")
         if commit_payload.get("entity_deltas"):

+ 27 - 0
webnovel-writer/scripts/data_modules/tests/test_chapter_commit_service.py

@@ -289,6 +289,33 @@ def test_apply_projections_normalizes_events_before_router_inspection(
     assert payload["accepted_events"] == captured["events"]
 
 
+def test_apply_projections_updates_state_for_rejected_commit(tmp_path):
+    import json
+
+    (tmp_path / ".webnovel").mkdir(parents=True, exist_ok=True)
+    (tmp_path / ".webnovel" / "state.json").write_text("{}", encoding="utf-8")
+
+    service = ChapterCommitService(tmp_path)
+    payload = service.build_commit(
+        chapter=7,
+        review_result={"blocking_count": 1},
+        fulfillment_result={
+            "planned_nodes": ["进入坊市"],
+            "covered_nodes": ["进入坊市"],
+            "missed_nodes": [],
+            "extra_nodes": [],
+        },
+        disambiguation_result={"pending": []},
+        extraction_result={"state_deltas": [], "entity_deltas": [], "accepted_events": []},
+    )
+
+    projected = service.apply_projections(payload)
+
+    state = json.loads((tmp_path / ".webnovel" / "state.json").read_text(encoding="utf-8"))
+    assert projected["projection_status"]["state"] == "done"
+    assert state["progress"]["chapter_status"]["7"] == "chapter_rejected"
+
+
 def test_chapter_commit_cli_builds_and_persists_commit(tmp_path, monkeypatch):
     review_path = tmp_path / "review.json"
     fulfillment_path = tmp_path / "fulfillment.json"