fix: preserve source task sections and explicit empty notes

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
tegwick 2026-09-10 15:11:03 +02:00
parent ccb285fc40
commit f767a1a245
4 changed files with 231 additions and 17 deletions

View file

@ -17,6 +17,81 @@ from api.services import forge_credential as fc
from api.services import forge_projection as fp
def test_task_description_retains_nested_sections_and_matches_consistency(monkeypatch):
monkeypatch.syspath_prepend(str(Path(__file__).parents[1] / "scripts"))
from scripts.consistency_check import parse_task_blocks
body = '''## Factory admission
```task
id: HFACT-WP-0001-T01
status: progress
description: Earlier inline summary.
intervention_note: ""
blocking_reason: ""
```
---
Current native admission requirements.
### Local proof
Retain the source evidence and limitations.
#### Remaining return
Exact operator binding remains open.
---
## Next task
```task
id: HFACT-WP-0001-T02
status: wait
```
Separate next-task description.
'''
derived = fp._parse_tasks(body, "HFACT-WP-0001")
authoritative = parse_task_blocks(body)
assert derived[0].description == authoritative[0]["description"]
assert "### Local proof" in derived[0].description
assert "#### Remaining return" in derived[0].description
assert "Next task" not in derived[0].description
assert not derived[0].description.startswith("---")
assert derived[0].intervention_note == ""
assert derived[0].blocking_reason == ""
assert derived[1].description == authoritative[1]["description"]
assert derived[1].intervention_note is None
@pytest.mark.parametrize("heading", ["", "# Workplan\n", "## Task\n", "### Task\n"])
def test_task_description_stops_before_next_task_block(heading, monkeypatch):
monkeypatch.syspath_prepend(str(Path(__file__).parents[1] / "scripts"))
from scripts.consistency_check import parse_task_blocks
body = heading + '''```task
id: DEMO-WP-0001-T01
status: todo
```
First description.
```task
id: DEMO-WP-0001-T02
status: wait
description: Inline fallback.
intervention_note: null
blocking_reason: null
```
'''
derived = fp._parse_tasks(body, "DEMO-WP-0001")
authoritative = parse_task_blocks(body)
assert derived[0].description == authoritative[0]["description"] == "First description."
assert derived[1].description == authoritative[1]["description"] == "Inline fallback."
assert derived[1].intervention_note is derived[1].blocking_reason is None
def test_identity_matches_the_fleet_derivation():
"""Same namespace as ADR-007, so overlay and forge agree on identity."""
assert fp.derived_record_uuid("CUST-WP-0067") == "16249302-2767-55df-aec0-d92c2751c225"

View file

@ -146,3 +146,61 @@ async def test_reconcile_rejects_commit_mismatch_without_db_changes(
)
assert rows.status_code == 200
assert rows.json() == []
async def test_real_source_projection_converges_without_followup_task_patches(client, monkeypatch, tmp_path):
"""Derive source through the real parser and persist it through the real API/DB."""
await create_test_domain(client)
await create_test_repo(client, slug="projection-test")
from api.config import settings
from api.routers import work_record_projection as route
monkeypatch.setattr(settings, "state_hub_instance_role", "primary")
monkeypatch.setattr(settings, "state_hub_instance_label", "railiance01")
root = tmp_path / "projection-test"
(root / "workplans").mkdir(parents=True)
path = root / "workplans/TEST-WP-0001.md"
path.write_text('''---
id: TEST-WP-0001
type: workplan
title: Factory test
status: active
---
## Native admission
```task
id: TEST-WP-0001-T01
status: wait
intervention_note: Review needed.
blocking_reason: Waiting.
needs_human: true
```
Admission context.
### Proof
Retain full proof.
''')
commit = "a" * 40
monkeypatch.setattr(route, "derive_from_forge", lambda slug: fp.derive_from_checkout(root, slug, commit))
endpoint = "/repos/projection-test/work-record-projection/reconcile"
first = await client.post(endpoint, json={"expected_commit": commit}, headers={"Idempotency-Key": "source:first"})
assert first.status_code == 200, first.text
task_id = fp.derived_record_uuid("TEST-WP-0001-T01")
created = (await client.get(f"/tasks/{task_id}")).json()
assert created["description"] == "Admission context.\n\n### Proof\n\nRetain full proof."
assert created["needs_human"] is True
path.write_text(path.read_text().replace("Review needed.", '""').replace("Waiting.", '""').replace("needs_human: true", "needs_human: false"))
commit = "b" * 40
for key in ["source:updated", "source:independent-rederivation"]:
result = await client.post(endpoint, json={"expected_commit": commit}, headers={"Idempotency-Key": key})
assert result.status_code == 200, result.text
assert result.json()["outcome"]["status"] in {"applied", "noop"}
actual = (await client.get(f"/tasks/{task_id}")).json()
assert actual["description"] == created["description"]
assert actual["intervention_note"] == actual["blocking_reason"] == ""
assert actual["needs_human"] is False
if key == "source:independent-rederivation":
assert result.json()["outcome"]["counts"]["updated_tasks"] == 0