From 3f21ca9aaa897544a447ef27220252ce53ed572b Mon Sep 17 00:00:00 2001 From: Tom Softreck Date: Sun, 18 Oct 2026 13:55:34 +0200 Subject: [PATCH] fix(governance): ignore released and missing-worktree leases in governed_clone_evidence (ticket-188) --- goal/governance/delivery.py | 13 ++++- project/TICKETS.md | 2 + project/ticket-188/README.md | 23 +++++++++ project/ticket-188/intent.json | 82 +++++++++++++++++++++++++++++++ tests/test_governance_delivery.py | 14 ++++++ 5 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 project/ticket-188/README.md create mode 100644 project/ticket-188/intent.json diff --git a/goal/governance/delivery.py b/goal/governance/delivery.py index 7cb2c47..9632918 100644 --- a/goal/governance/delivery.py +++ b/goal/governance/delivery.py @@ -723,8 +723,17 @@ def governed_clone_evidence(cwd: Path | None = None) -> list[Path]: for lease_file in sorted(lease_root.glob("*.json")): try: payload = json.loads(lease_file.read_text(encoding="utf-8")) - if isinstance(payload, dict) and payload.get("status") == "released": - continue + if isinstance(payload, dict): + if any( + payload.get(k) == "released" + for k in ("status", "phase", "state") + ) or payload.get("released_at"): + continue + wt_raw = payload.get("worktreePath") or payload.get("worktree") + if not wt_raw and payload.get("worktreeId"): + wt_raw = str(checkouts[0] / ".worktrees" / str(payload["worktreeId"])) + if wt_raw and not Path(str(wt_raw)).exists(): + continue except (OSError, UnicodeDecodeError, json.JSONDecodeError): pass evidence.append(lease_file) diff --git a/project/TICKETS.md b/project/TICKETS.md index 9a7fcf8..3ce460a 100644 --- a/project/TICKETS.md +++ b/project/TICKETS.md @@ -128,5 +128,7 @@ This file indexes governance tickets without taking ownership of | **ticket-182** | [`README.md`](./ticket-182/README.md) | - | - | - | - | - | | **ticket-183** | [`README.md`](./ticket-183/README.md) | - | - | - | - | - | | **ticket-184** | [`README.md`](./ticket-184/README.md) | - | - | - | - | - | +| **ticket-185** | [`README.md`](./ticket-185/README.md) | - | - | - | - | - | +| **ticket-186** | [`README.md`](./ticket-186/README.md) | - | - | - | - | - | | **ticket-187** | [`README.md`](./ticket-187/README.md) | - | - | - | - | - | diff --git a/project/ticket-188/README.md b/project/ticket-188/README.md new file mode 100644 index 0000000..5dfb83f --- /dev/null +++ b/project/ticket-188/README.md @@ -0,0 +1,23 @@ +# Ticket 188: Ignore released and missing-worktree leases in governed_clone_evidence + +- **ID**: ticket-188 +- **Owner**: agent:antigravity +- **Status**: IN_PROGRESS +- **Workflow state**: VALIDATION +- **Created**: 2026-10-18 + +## Goal and scope + +Ignore released (`status="released"`, `phase="released"`, `state="released"`, or `released_at` set) and stale `.subactor/leases/*.json` files whose target worktree directory no longer exists when `governed_clone_evidence` checks whether a non-governed checkout belongs to a governed clone. + +SESSION_EXECUTION_AUTHORIZATION: user requested fixing publication issues across semcod/* via ticket creation and Willman execution. + +## Acceptance criteria + +- [x] AC-01: `governed_clone_evidence` in `goal/governance/delivery.py` skips lease records with `phase="released"`, `state="released"`, `released_at`, or a non-existent `worktreePath`/`worktree`/`worktreeId` directory. +- [x] AC-02: Unit tests in `tests/test_governance_delivery.py` and `./project/governance-check.sh` pass (`GOV-PASS`). + +## Tracking boundary + +This directory contains the minimal reviewed intent. Optional participant prose +and raw command logs are not required delivery output. diff --git a/project/ticket-188/intent.json b/project/ticket-188/intent.json new file mode 100644 index 0000000..85ad012 --- /dev/null +++ b/project/ticket-188/intent.json @@ -0,0 +1,82 @@ +{ + "schema": "new-project.intent/v3", + "ticket": "ticket-188", + "summary": "Ignore released and missing-worktree leases in governed_clone_evidence", + "workstream": "application", + "classification": { + "kind": "BUG", + "priority": "P1", + "origin": "health" + }, + "allowedPaths": [ + "project/ticket-188/**", + "TODO.md", + "project/TICKETS.md", + "goal/governance/delivery.py", + "tests/test_governance_delivery.py" + ], + "forbiddenPaths": [ + "project/ticket-*/user-*.md" + ], + "stacks": [ + "python" + ], + "dependsOn": [], + "conflictsWith": [], + "integrationTicket": null, + "delivery": { + "acceptedBaseSha": "b6501606c29523c878065a9eeb2cb110b8bd8df0", + "targetBranch": "main", + "outcome": "Ignore released and stale missing-worktree .subactor/leases/*.json records in governed_clone_evidence so non-governed repositories with historical lease artifacts are not blocked by GOV-DELIVERY-CLONE-001 during goal -a.", + "nonGoals": [ + "No change to active governed ticket worktree enforcement." + ], + "complexity": "S", + "estimatedMinutes": 15, + "budgets": { + "maxImplementationFiles": 3, + "maxAffectedComponents": 1, + "maxPublicInterfaceChanges": 0, + "maxRuntimeDependencies": 0 + }, + "architecture": { + "status": "accepted", + "decision": "Extend lease filtering in governed_clone_evidence to skip lease payloads where status/phase/state is released, released_at is present, or an explicit worktreePath/worktree/worktreeId directory no longer exists on disk.", + "components": [ + { + "name": "governance_delivery", + "paths": [ + "goal/governance/delivery.py", + "tests/test_governance_delivery.py" + ] + } + ], + "responsibilityChanges": false, + "interfaceChanges": [], + "dataChanges": [], + "ui": { + "impact": "none", + "states": [], + "evidence": [] + }, + "rollback": "Revert the commit." + }, + "runtimeDependencies": [], + "validation": [ + { + "criterion": "AC-01", + "commands": [ + "pytest -q tests/test_governance_delivery.py -k lease" + ], + "evidence": "project/ticket-188/README.md" + }, + { + "criterion": "AC-02", + "commands": [ + "./project/governance-check.sh" + ], + "evidence": "project/ticket-188/README.md" + } + ] + } +} diff --git a/tests/test_governance_delivery.py b/tests/test_governance_delivery.py index d1306fa..ff66a26 100644 --- a/tests/test_governance_delivery.py +++ b/tests/test_governance_delivery.py @@ -957,6 +957,20 @@ def test_primary_worktree_lease_marks_clone_governed(tmp_path): delivery.validate_legacy_governance(cwd=root) +def test_released_or_missing_worktree_leases_do_not_mark_clone_governed(tmp_path): + root = _publish_repository(tmp_path) + lease_dir = root / ".subactor" / "leases" + lease_dir.mkdir(parents=True) + (lease_dir / "ticket-001--phase.json").write_text('{"phase": "released"}\n', encoding="utf-8") + (lease_dir / "ticket-002--state.json").write_text('{"state": "released"}\n', encoding="utf-8") + (lease_dir / "ticket-003--missing.json").write_text( + f'{{"worktreePath": "{root / ".worktrees" / "ticket-003--gone"}"}}\n', + encoding="utf-8", + ) + assert delivery.governed_clone_evidence(root) == [] + assert delivery.validate_legacy_governance(cwd=root) is False + + def test_linked_worktree_without_governance_keeps_legacy_flow(tmp_path): root = _publish_repository(tmp_path) _git(root, "worktree", "add", "--quiet", "-b", "feature", str(tmp_path / "feature"))