1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages

Make project MCP workflows self-synchronizing

This commit is contained in:
Andraxion 2026-07-26 09:32:25 -04:00
parent a30f021a52
commit 73165c9f51
17 changed files with 1124 additions and 56 deletions

View file

@ -244,6 +244,8 @@ class DocForgeChangesetTests(unittest.TestCase):
node_ids = {node.node_id for node in snapshot.nodes}
workflow = next(node for node in snapshot.nodes if node.node_id == "guide.workflow")
self.assertTrue(result["applied"])
self.assertEqual("applied", result["lifecycle"]["status"])
self.assertEqual("ok", result["derived_refresh"]["status"])
self.assertEqual(
[
"docs/content/applied.md",
@ -265,8 +267,95 @@ class DocForgeChangesetTests(unittest.TestCase):
self.assertTrue((root / ".docforge/cache/index.sqlite3").is_file())
self.assertTrue((root / ".docforge/rendered/manual.html").is_file())
with self.assertRaisesRegex(DocForgeError, "Canonical project changed"):
with self.assertRaisesRegex(DocForgeError, "cannot be modified") as closed:
service.apply("apply-all", str(final["changeset_hash"]))
self.assertEqual("changeset_closed", closed.exception.code)
def test_abandoned_proposal_releases_overlap_and_stale_work_remains_active(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = self.copy_fixture(Path(directory))
project = Project.open(root)
store = ChangesetStore(project, "alpha-editor")
first = store.register(
"first",
[
{
"operation": "update",
"node_id": "guide.foundation",
"metadata": {"summary": "Abandoned proposal."},
"rationale": "Reserve then release this node.",
}
],
)
store.abandon(
"first",
str(first["changeset_hash"]),
"The proposal is no longer wanted.",
)
second = store.register(
"second",
[
{
"operation": "update",
"node_id": "guide.foundation",
"metadata": {"summary": "Replacement proposal."},
"rationale": "Verify terminal proposals release conflicts.",
}
],
)
workflow = root / "docs/content/workflow.md"
workflow.write_text(
workflow.read_text(encoding="utf-8") + "\nUnrelated current fact.\n",
encoding="utf-8",
)
active = store.list_changesets(include_history=False)
stale = store.list_changesets(include_history=False, status="stale")
self.assertEqual(0, active["count"])
self.assertEqual(["second"], [item["changeset_id"] for item in stale["changesets"]])
self.assertEqual("stale", stale["changesets"][0]["lifecycle"]["status"])
self.assertEqual("ready", second["lifecycle"])
def test_applied_receipt_survives_a_derived_refresh_failure(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = self.copy_fixture(Path(directory))
project = Project.open(root)
registered = ChangesetStore(project, "alpha-editor").register(
"degraded-refresh",
[
{
"operation": "update",
"node_id": "guide.workflow",
"metadata": {"summary": "Canonical even if refresh fails."},
"rationale": "Separate canonical success from disposable refresh.",
}
],
)
service = CanonicalApplicationService(
project,
applier_id="alpha-editor",
applier=GenericCanonicalApplier(project),
)
with mock.patch.object(
service.index,
"build",
side_effect=DocForgeError("index_failure", "Synthetic derived failure"),
):
result = service.apply(
"degraded-refresh",
str(registered["changeset_hash"]),
)
self.assertTrue(result["applied"])
self.assertEqual("applied", result["lifecycle"]["status"])
self.assertEqual("degraded", result["derived_refresh"]["status"])
self.assertEqual("index", result["derived_refresh"]["errors"][0]["component"])
with self.assertRaisesRegex(DocForgeError, "cannot be modified"):
service.apply(
"degraded-refresh",
str(registered["changeset_hash"]),
)
def test_relationship_only_update_is_hash_bound_and_does_not_rewrite_node(self) -> None:
with tempfile.TemporaryDirectory() as directory: