feat(control-plane): durable MCP session checkpoint schema (Closes #660) #881

Merged
sysadmin merged 5 commits from feat/issue-660-session-checkpoint-schema into master 2026-07-24 15:52:52 -05:00
Owner

Summary

Implements issue #660: a versioned, redacted, reconcile-on-boot session checkpoint store in control_plane_db so restarts can recover session identity, stage, lease ownership, and next valid action instead of forcing human reconstruction (parent #655; vision #652 / roadmap #653; supports #628 autonomous handoff goals).

What this adds

  • session_checkpoints table — current-state row per (remote, org, repo, session_id, work_kind, work_number); session-level sentinel is work_kind='' / work_number=0. Additive CREATE TABLE IF NOT EXISTS (same pattern as dependency edges / usage events). SCHEMA_VERSION remains 5 (already shipped by #651); rows carry checkpoint_schema_version.
  • Writer / readerswrite_session_checkpoint (upsert + stage-change audit to events), get_session_checkpoint, list_session_checkpoints.
  • Redaction at write — free-text and JSON fields pass through gitea_audit.redact before storage (AC4).
  • reconcile_session_checkpoint — pure diagnosis only (never blind-restores). Flags stale head / dead or reassigned lease; unknown live inputs do not false-positive (AC3).
  • Drain fail-closedrequire_complete=True refuses incomplete records (session_id, role, workflow_stage, next_valid_action, recovery_instructions).
  • Docsdocs/architecture/control-plane-db-substrate.md documents schema, API, and hard rules (AC1).

Acceptance criteria

AC Coverage
1. Schema documented and versioned substrate doc + checkpoint_schema_version
2. Multi-role session fixtures SessionCheckpointTest.test_multi_role_fixtures_each_get_a_row
3. Reconcile detects stale head/lease head / dead-lease / reassigned-lease cases
4. No secrets in stored records redaction test plants Bearer token + password URL
5. Links #652 #653 #655 this body + commits

Non-goals honored

  • No conversation transcript storage
  • No secrets in checkpoints
  • Write-only substrate first; full post-start boot wiring stays with callers / follow-on work

Files

File Change
control_plane_db.py table, indexes, write/get/list/reconcile/completeness
tests/test_control_plane_db.py 13 new cases; suite 33/33
docs/architecture/control-plane-db-substrate.md session_checkpoints section

Validation

From worktree /Users/jasonwalker/Development/Gitea-Tools/branches/issue-660-session-checkpoint-schema:

../../venv/bin/python -m pytest tests/test_control_plane_db.py -q
# 33 passed

Branch tip is merged with current master (includes #838 inventory); no conflicts on the three files in this PR.

Risk

Low. Additive schema + pure APIs; no MCP tool surface or drain/boot integration in this PR. Residual risk is callers forgetting to reconcile before resume — the API returns reconcile_action and never restores by itself.

Canonical PR state

STATE: awaiting-review
WHO_IS_NEXT: reviewer
NEXT_ACTION: Review against #660 AC1-5; confirm redaction, reconcile purity, drain fail-closed; submit verdict; stop

Closes #660.

## Summary Implements issue **#660**: a versioned, redacted, reconcile-on-boot session checkpoint store in `control_plane_db` so restarts can recover session identity, stage, lease ownership, and next valid action instead of forcing human reconstruction (parent **#655**; vision **#652** / roadmap **#653**; supports **#628** autonomous handoff goals). ## What this adds - **`session_checkpoints` table** — current-state row per `(remote, org, repo, session_id, work_kind, work_number)`; session-level sentinel is `work_kind=''` / `work_number=0`. Additive `CREATE TABLE IF NOT EXISTS` (same pattern as dependency edges / usage events). `SCHEMA_VERSION` remains **5** (already shipped by #651); rows carry `checkpoint_schema_version`. - **Writer / readers** — `write_session_checkpoint` (upsert + stage-change audit to `events`), `get_session_checkpoint`, `list_session_checkpoints`. - **Redaction at write** — free-text and JSON fields pass through `gitea_audit.redact` before storage (AC4). - **`reconcile_session_checkpoint`** — pure diagnosis only (never blind-restores). Flags stale head / dead or reassigned lease; unknown live inputs do not false-positive (AC3). - **Drain fail-closed** — `require_complete=True` refuses incomplete records (`session_id`, `role`, `workflow_stage`, `next_valid_action`, `recovery_instructions`). - **Docs** — `docs/architecture/control-plane-db-substrate.md` documents schema, API, and hard rules (AC1). ## Acceptance criteria | AC | Coverage | |---|---| | 1. Schema documented and versioned | substrate doc + `checkpoint_schema_version` | | 2. Multi-role session fixtures | `SessionCheckpointTest.test_multi_role_fixtures_each_get_a_row` | | 3. Reconcile detects stale head/lease | head / dead-lease / reassigned-lease cases | | 4. No secrets in stored records | redaction test plants Bearer token + password URL | | 5. Links #652 #653 #655 | this body + commits | ## Non-goals honored - No conversation transcript storage - No secrets in checkpoints - Write-only substrate first; full post-start boot wiring stays with callers / follow-on work ## Files | File | Change | |---|---| | `control_plane_db.py` | table, indexes, write/get/list/reconcile/completeness | | `tests/test_control_plane_db.py` | 13 new cases; suite 33/33 | | `docs/architecture/control-plane-db-substrate.md` | session_checkpoints section | ## Validation From worktree `/Users/jasonwalker/Development/Gitea-Tools/branches/issue-660-session-checkpoint-schema`: ```text ../../venv/bin/python -m pytest tests/test_control_plane_db.py -q # 33 passed ``` Branch tip is merged with current `master` (includes #838 inventory); no conflicts on the three files in this PR. ## Risk Low. Additive schema + pure APIs; no MCP tool surface or drain/boot integration in this PR. Residual risk is callers forgetting to reconcile before resume — the API returns `reconcile_action` and never restores by itself. ## Canonical PR state ```text STATE: awaiting-review WHO_IS_NEXT: reviewer NEXT_ACTION: Review against #660 AC1-5; confirm redaction, reconcile purity, drain fail-closed; submit verdict; stop ``` Closes #660.
jcwalker3 added 4 commits 2026-07-24 15:05:12 -05:00
Add a versioned, redacted, reconcile-on-boot session checkpoint store to
control_plane_db so a restart can recover session identity, stage, lease
ownership, and next valid action instead of forcing human reconstruction
(umbrella #655; #628 autonomous-handoff goal).

- Bump SCHEMA_VERSION 4->5. New `session_checkpoints` table + two indexes,
  added via `CREATE TABLE IF NOT EXISTS` so table creation is itself the
  additive, idempotent v4->v5 migration (dependency_edges precedent).
- Writer `write_session_checkpoint` upserts the current recoverable state
  per (remote, org, repo, session_id, work_kind, work_number); stage
  transitions audit to `events`. Readers `get_session_checkpoint` /
  `list_session_checkpoints`.
- Every free-text and JSON field is passed through `gitea_audit.redact`
  before storage — no tokens/credential URLs can land in a checkpoint (AC4).
- `reconcile_session_checkpoint` is pure and never restores: it diagnoses a
  stored checkpoint against live head/lease state and flags staleness (AC3).
- Drain gate: `require_complete=True` fails closed (writes nothing) when a
  checkpoint is missing a drain-required field, so drain cannot complete on
  an unrecoverable record.
- `lease_id`/`assignment_id` are soft references (no enforced FK) so a
  checkpoint survives deletion of the lease it names; `work_number=0` is the
  NULL-safe session-level sentinel.

Tests: 13 new cases (schema/version, multi-role fixtures, upsert+audit,
JSON round-trip, secret redaction, reconcile stale-head/dead-lease/
reassigned-lease/clean/unknown, drain fail-closed, sentinel key). Existing
schema_version assertion updated 4->5. Full tests/test_control_plane_db.py
suite: 33/33 pass.

Links #652 #653 #655.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Base-sync of the #660 durable session checkpoint schema branch onto current
master. The only conflicting file was control_plane_db.py, where master added
the #651 usage_events table, migration, and indexes while this branch added the

Resolution keeps both sides in full. Verified against both merge parents: the
resolved file contains every line of master's control_plane_db.py with zero
removals, plus exactly the #660 additions (session_checkpoints table, its two
indexes, _session_checkpoint_row, write_session_checkpoint,
get_session_checkpoint, list_session_checkpoints, reconcile_session_checkpoint,
and checkpoint_completeness).

Conflicts:
	control_plane_db.py

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Adds the session_checkpoints section to the control-plane DB substrate
architecture doc: schema version and row identity, the column groups, the
public API surface, and the hard rules (redaction at write, reconcile
rather than blind restore, unknown live state is not a mismatch, drain
fails closed on an incomplete checkpoint, no transcript storage).

Satisfies acceptance criterion 1 of #660 ("Schema documented and
versioned") for the implementation added in 7e18dcc.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
jcwalker3 added 1 commit 2026-07-24 15:25:41 -05:00
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #881
issue: #660
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 99619-0e7139e466e6
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/baseline-master-9b52899
phase: claimed
candidate_head: 6862049ef6
target_branch: master
target_branch_sha: 9b5289940c
last_activity: 2026-07-24T20:47:26Z
expires_at: 2026-07-24T20:57:26Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #881 issue: #660 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 99619-0e7139e466e6 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/baseline-master-9b52899 phase: claimed candidate_head: 6862049ef6c60a55026e6aeb1c10b374554fdae1 target_branch: master target_branch_sha: 9b5289940c898d75e90b8d05612d942f36008fb8 last_activity: 2026-07-24T20:47:26Z expires_at: 2026-07-24T20:57:26Z blocker: none
sysadmin approved these changes 2026-07-24 15:49:41 -05:00
sysadmin left a comment
Owner

APPROVE — reviewed at head 6862049ef6c60a55026e6aeb1c10b374554fdae1 against base master@9b5289940c898d75e90b8d05612d942f36008fb8.

NATIVE_REVIEW_PROOF: native reviewer namespace prgs-reviewer (sysadmin), workflow skills/llm-project-workflow/workflows/review-merge-pr.md hash 263d0a6cb8a6, reviewer lease comment 16097, head-scoped final decision at 6862049ef6.

Scope

3 files, +692/-1: control_plane_db.py, tests/test_control_plane_db.py, docs/architecture/control-plane-db-substrate.md. Purely additive — no MCP tool surface, no capability gate, no drain/boot wiring touched. Scope matches #660; no unrelated files.

Verified against acceptance criteria

  • AC1 (schema documented + versioned)session_checkpoints is created via CREATE TABLE IF NOT EXISTS inside _SCHEMA_SQL, which _init_schema runs unconditionally on every open (not gated on a stored schema_version). Confirmed the table therefore lands on databases already stamped version 5 by #651 — no silent "no such table" on existing deployments. Rows carry checkpoint_schema_version; substrate doc updated with schema, API table, and hard rules.
  • AC2 (multi-role fixtures)test_multi_role_fixtures_each_get_a_row writes author/reviewer/merger/controller rows; UNIQUE key (remote, org, repo, session_id, work_kind, work_number) with the ('', 0) session-level sentinel keeps the constraint NULL-safe.
  • AC3 (reconcile detects stale head/lease)reconcile_session_checkpoint is a @staticmethod with no DB handle: it cannot restore, only diagnose. None live inputs are treated as "not checked" and never flag a mismatch on their own; dead lease and reassigned lease are separate paths.
  • AC4 (no secrets stored) — traced gitea_audit.redact end to end: recursive over dicts/lists, key-hint redaction (token/password/secret/authorization/auth), Bearer /Basic /token value-prefix redaction, and URL/credential redaction with real hosts replaced. None of the checkpoint column names collide with a secret key hint, so no column is blanket-wiped. Redaction is applied to the assembled record before any SQL runs.
  • AC5 (links) — body and code comments reference #652 / #653 / #655 / #628.

Drain fail-closed also verified structurally: require_complete=True raises ControlPlaneError before _tx() is entered, so an incomplete record writes nothing — and the test asserts the table is still empty afterward.

Test evidence

Run in the PR worktree at the exact head:

../../venv/bin/python -m pytest tests/test_control_plane_db.py -q
33 passed in 0.95s

Regression scope — every test module importing control_plane_db (23 files), run at PR head and at master@9b52899:

PR head 6862049e : 7 failed, 559 passed
master  9b52899  : 7 failed, 559 passed
diff of FAILED sets: identical

The 7 failures are pre-existing on master (test_issue_784_dependency_edges.py asserts SCHEMA_VERSION == 4, stale since #651 bumped it to 5; test_branch_cleanup_guard.py unrelated). Failure reasons were compared line by line and are identical on both sides. 0 new failures introduced by this PR.

Advisories (LOW — none blocking, no remediation required for merge)

  1. checkpoint_schema_version DDL default is the literal 5 while inserts write the SCHEMA_VERSION constant. When SCHEMA_VERSION next moves, the column default silently drifts from the written value. Prefer dropping the literal default (the writer always supplies it) on the next touch.
  2. Invalid work_kind raises dependency_graph.InvalidEdgeEndpointError, not ControlPlaneError. It still fails closed, but the message talks about "dependency edge endpoint" in a checkpoint context, and a caller catching this module's ControlPlaneError will not catch it.
  3. JSON columns are serialized before the transaction with no type validation. A non-JSON-serializable evidence/pending_mutation surfaces a raw TypeError, and capabilities="read" (a bare string) round-trips as a string rather than a list.
  4. Stage-change audit rows are invisible in the operator timeline. They are written with work_item_id = NULL, and the only consumer, webui/timeline.py::_CP_EVENTS_QUERY, does an inner JOIN work_items ON e.work_item_id = w.work_item_id, so session_checkpoint_stage_change events never surface there. The durable row itself is unaffected; worth wiring when checkpoints get a UI.
  5. Redaction rewrites non-synthetic URLs inside recovery_instructions / next_valid_action to [REDACTED_URL]. Security-correct, but it means recovery text should cite issue/PR numbers rather than links, or the pointer is lost on resume. Worth stating in the substrate doc's hard rules.

Canonical PR State

STATE: approved
WHO_IS_NEXT: merger
NEXT_ACTION: Merge PR 881 at head 6862049ef6 through the gated merger path; the approval is head-scoped and void if the head advances.
NEXT_PROMPT:

Load the canonical gitea-workflow skill first. Act as merger in the prgs-merger MCP namespace on prgs/Scaled-Tech-Consulting/Gitea-Tools. Merge PR 881 at the exact head 6862049ef6c60a55026e6aeb1c10b374554fdae1 (base master 9b5289940c898d75e90b8d05612d942f36008fb8). Preflight: gitea_whoami(remote=prgs) -> gitea_assess_master_parity -> gitea_assess_pr_sync_status(pr_number=881) -> gitea_load_review_workflow -> gitea_resolve_task_capability(task=merge_pr) immediately before each mutation -> gitea_acquire_merger_pr_lease(head_sha + candidate_head + worktree under branches/) -> gitea_merge_pr. Stop and report if the head has advanced past 6862049e, if parity reports restart_required, or if a foreign lease holds PR 881. Do not re-review and do not push to the branch.

WHAT_HAPPENED: Reviewer read the full three-file diff at head 6862049e, traced the redaction path through gitea_audit.redact, confirmed the schema is created by unconditional executescript rather than a version-gated migration, ran the focused suite (33 passed) and the 23-module control_plane_db regression scope at both PR head and master, and compared failure sets.
WHY: All five #660 acceptance criteria are satisfied at this head, the change is additive with no gate or tool-surface impact, and the regression scope shows zero new failures against the master baseline.
ISSUE: 660
HEAD_SHA: 6862049ef6
REVIEW_STATUS: approved
MERGE_READY: yes
BLOCKERS: none
VALIDATION: tests/test_control_plane_db.py 33 passed at 6862049e; control_plane_db import scope 559 passed / 7 failed at PR head, identical 559 passed / 7 failed at master 9b52899 with identical FAILED sets and identical assertion messages (pre-existing SCHEMA_VERSION==4 debt from #651 plus unrelated branch-cleanup failures); merge state mergeable with 0 commits behind and no conflicts.
LAST_UPDATED_BY: prgs-reviewer (sysadmin)

APPROVE — reviewed at head `6862049ef6c60a55026e6aeb1c10b374554fdae1` against base `master@9b5289940c898d75e90b8d05612d942f36008fb8`. NATIVE_REVIEW_PROOF: native reviewer namespace prgs-reviewer (sysadmin), workflow skills/llm-project-workflow/workflows/review-merge-pr.md hash 263d0a6cb8a6, reviewer lease comment 16097, head-scoped final decision at 6862049ef6c60a55026e6aeb1c10b374554fdae1. ## Scope 3 files, +692/-1: `control_plane_db.py`, `tests/test_control_plane_db.py`, `docs/architecture/control-plane-db-substrate.md`. Purely additive — no MCP tool surface, no capability gate, no drain/boot wiring touched. Scope matches #660; no unrelated files. ## Verified against acceptance criteria - **AC1 (schema documented + versioned)** — `session_checkpoints` is created via `CREATE TABLE IF NOT EXISTS` inside `_SCHEMA_SQL`, which `_init_schema` runs unconditionally on every open (not gated on a stored `schema_version`). Confirmed the table therefore lands on databases already stamped version 5 by #651 — no silent "no such table" on existing deployments. Rows carry `checkpoint_schema_version`; substrate doc updated with schema, API table, and hard rules. - **AC2 (multi-role fixtures)** — `test_multi_role_fixtures_each_get_a_row` writes author/reviewer/merger/controller rows; UNIQUE key `(remote, org, repo, session_id, work_kind, work_number)` with the `('', 0)` session-level sentinel keeps the constraint NULL-safe. - **AC3 (reconcile detects stale head/lease)** — `reconcile_session_checkpoint` is a `@staticmethod` with no DB handle: it cannot restore, only diagnose. `None` live inputs are treated as "not checked" and never flag a mismatch on their own; dead lease and reassigned lease are separate paths. - **AC4 (no secrets stored)** — traced `gitea_audit.redact` end to end: recursive over dicts/lists, key-hint redaction (`token`/`password`/`secret`/`authorization`/`auth`), `Bearer `/`Basic `/`token ` value-prefix redaction, and URL/credential redaction with real hosts replaced. None of the checkpoint column names collide with a secret key hint, so no column is blanket-wiped. Redaction is applied to the assembled record before any SQL runs. - **AC5 (links)** — body and code comments reference #652 / #653 / #655 / #628. Drain fail-closed also verified structurally: `require_complete=True` raises `ControlPlaneError` **before** `_tx()` is entered, so an incomplete record writes nothing — and the test asserts the table is still empty afterward. ## Test evidence Run in the PR worktree at the exact head: ```text ../../venv/bin/python -m pytest tests/test_control_plane_db.py -q 33 passed in 0.95s ``` Regression scope — every test module importing `control_plane_db` (23 files), run at PR head and at `master@9b52899`: ```text PR head 6862049e : 7 failed, 559 passed master 9b52899 : 7 failed, 559 passed diff of FAILED sets: identical ``` The 7 failures are pre-existing on master (`test_issue_784_dependency_edges.py` asserts `SCHEMA_VERSION == 4`, stale since #651 bumped it to 5; `test_branch_cleanup_guard.py` unrelated). Failure reasons were compared line by line and are identical on both sides. 0 new failures introduced by this PR. ## Advisories (LOW — none blocking, no remediation required for merge) 1. `checkpoint_schema_version` DDL default is the literal `5` while inserts write the `SCHEMA_VERSION` constant. When `SCHEMA_VERSION` next moves, the column default silently drifts from the written value. Prefer dropping the literal default (the writer always supplies it) on the next touch. 2. Invalid `work_kind` raises `dependency_graph.InvalidEdgeEndpointError`, not `ControlPlaneError`. It still fails closed, but the message talks about "dependency edge endpoint" in a checkpoint context, and a caller catching this module's `ControlPlaneError` will not catch it. 3. JSON columns are serialized before the transaction with no type validation. A non-JSON-serializable `evidence`/`pending_mutation` surfaces a raw `TypeError`, and `capabilities="read"` (a bare string) round-trips as a string rather than a list. 4. Stage-change audit rows are invisible in the operator timeline. They are written with `work_item_id = NULL`, and the only consumer, `webui/timeline.py::_CP_EVENTS_QUERY`, does an inner `JOIN work_items ON e.work_item_id = w.work_item_id`, so `session_checkpoint_stage_change` events never surface there. The durable row itself is unaffected; worth wiring when checkpoints get a UI. 5. Redaction rewrites non-synthetic URLs inside `recovery_instructions` / `next_valid_action` to `[REDACTED_URL]`. Security-correct, but it means recovery text should cite issue/PR numbers rather than links, or the pointer is lost on resume. Worth stating in the substrate doc's hard rules. ## Canonical PR State STATE: approved WHO_IS_NEXT: merger NEXT_ACTION: Merge PR 881 at head 6862049ef6c60a55026e6aeb1c10b374554fdae1 through the gated merger path; the approval is head-scoped and void if the head advances. NEXT_PROMPT: ```text Load the canonical gitea-workflow skill first. Act as merger in the prgs-merger MCP namespace on prgs/Scaled-Tech-Consulting/Gitea-Tools. Merge PR 881 at the exact head 6862049ef6c60a55026e6aeb1c10b374554fdae1 (base master 9b5289940c898d75e90b8d05612d942f36008fb8). Preflight: gitea_whoami(remote=prgs) -> gitea_assess_master_parity -> gitea_assess_pr_sync_status(pr_number=881) -> gitea_load_review_workflow -> gitea_resolve_task_capability(task=merge_pr) immediately before each mutation -> gitea_acquire_merger_pr_lease(head_sha + candidate_head + worktree under branches/) -> gitea_merge_pr. Stop and report if the head has advanced past 6862049e, if parity reports restart_required, or if a foreign lease holds PR 881. Do not re-review and do not push to the branch. ``` WHAT_HAPPENED: Reviewer read the full three-file diff at head 6862049e, traced the redaction path through gitea_audit.redact, confirmed the schema is created by unconditional executescript rather than a version-gated migration, ran the focused suite (33 passed) and the 23-module control_plane_db regression scope at both PR head and master, and compared failure sets. WHY: All five #660 acceptance criteria are satisfied at this head, the change is additive with no gate or tool-surface impact, and the regression scope shows zero new failures against the master baseline. ISSUE: 660 HEAD_SHA: 6862049ef6c60a55026e6aeb1c10b374554fdae1 REVIEW_STATUS: approved MERGE_READY: yes BLOCKERS: none VALIDATION: tests/test_control_plane_db.py 33 passed at 6862049e; control_plane_db import scope 559 passed / 7 failed at PR head, identical 559 passed / 7 failed at master 9b52899 with identical FAILED sets and identical assertion messages (pre-existing SCHEMA_VERSION==4 debt from #651 plus unrelated branch-cleanup failures); merge state mergeable with 0 commits behind and no conflicts. LAST_UPDATED_BY: prgs-reviewer (sysadmin)
Owner

adopted_at: 2026-07-24T20:52:33Z
adopted_by_identity: sysadmin
adopted_by_profile: prgs-merger
adopted_from_session_id: 99619-0e7139e466e6
adopted_from_profile: prgs-reviewer
adopted_from_reviewer_identity: sysadmin
adopted_from_comment_id: 16097
adoption_reason: merger-handoff-approved-head

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #881
issue: #660
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 29320-808c11ff9ef8
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/baseline-master-9b52899
phase: adopted
candidate_head: 6862049ef6
target_branch: master
target_branch_sha: 9b5289940c
last_activity: 2026-07-24T20:52:33Z
expires_at: 2026-07-24T21:02:33Z
blocker: none

<!-- mcp-review-lease-adoption:v1 --> adopted_at: 2026-07-24T20:52:33Z adopted_by_identity: sysadmin adopted_by_profile: prgs-merger adopted_from_session_id: 99619-0e7139e466e6 adopted_from_profile: prgs-reviewer adopted_from_reviewer_identity: sysadmin adopted_from_comment_id: 16097 adoption_reason: merger-handoff-approved-head <!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #881 issue: #660 reviewer_identity: sysadmin profile: prgs-merger session_id: 29320-808c11ff9ef8 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/baseline-master-9b52899 phase: adopted candidate_head: 6862049ef6c60a55026e6aeb1c10b374554fdae1 target_branch: master target_branch_sha: 9b5289940c898d75e90b8d05612d942f36008fb8 last_activity: 2026-07-24T20:52:33Z expires_at: 2026-07-24T21:02:33Z blocker: none
sysadmin merged commit 870843f999 into master 2026-07-24 15:52:52 -05:00
Owner

Stale #332 review-decision lock cleanup (#594)

Status: APPLIED

Manual deletion of session-state files is not the workflow.
This path only clears a lock when the referenced PR is merged/closed.

## Stale #332 review-decision lock cleanup (#594) Status: **APPLIED** - actor: `sysadmin` - profile: `prgs-merger` - timestamp: `2026-07-24T20:52:54.683757+00:00` - last terminal: `approve` on PR #881 - PR state: `closed` (merged=True) - merge_commit_sha: `870843f999fb4bb8fc8c15ff7ede730448cdb3d4` - prior live_mutations_count: `2` - prior profile_identity: `prgs-reviewer` Manual deletion of session-state files is **not** the workflow. This path only clears a lock when the referenced PR is merged/closed.
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#881