Merge pull request 'feat: require Controller Handoff plus Thread State Ledger (Closes #507)' (#511) from feat/issue-507-controller-thread-ledger into master

This commit was merged in pull request #511.
This commit is contained in:
2026-07-09 08:27:44 -05:00
10 changed files with 1207 additions and 0 deletions
@@ -0,0 +1,43 @@
# Two-comment workflow examples (#507)
Paired `[CONTROLLER HANDOFF]` + `[THREAD STATE LEDGER]` comments for Gitea threads.
See `thread_state_ledger_examples.py` for machine-checked fixtures.
## Approved review posted
**Handoff** (detailed): identity, worktree, validation commands, mutation ledger with
`gitea_submit_pr_review → APPROVED review posted to Gitea`.
**Ledger** (concise):
```markdown
[THREAD STATE LEDGER] PR #487 — APPROVED review posted to Gitea
What is true now:
- PR state: open
- Server-side decision state: APPROVED review posted to Gitea
- Local verdict/state: APPROVE verdict prepared locally
What is blocked:
- Blocker classification: no blocker
Who/what acts next:
- Next actor: merger
- Required action: merge on explicit operator command
- Do not do: re-post APPROVE
```
## Approve validated locally but blocked before posting
Ledger must show `no server-side state changed` under server-side decision state and
`APPROVE verdict prepared locally` under local verdict/state.
## Environment / tooling blocker
Ledger blocker classification: `environment/tooling blocker`. Mutation ledger:
`none — no server-side state changed`.
## Stale head blocker
Ledger: `approval_at_current_head is false`; classification `stale head`.
Do not do: merge with stale approval.
+40
View File
@@ -917,6 +917,46 @@ touched release state names the exact tag/commit and why. Design debates
belong in **discussion/RFC issues** (e.g. #100 `profiles.json v2`) — comment
on the issue, create no branches/PRs, and end the comment with this handoff.
## Two-comment workflow reporting (#507)
After meaningful controller/workflow work, post **two separate Gitea comments**
(not one combined blob):
1. **`[CONTROLLER HANDOFF]`** — detailed operational continuation for the
next LLM/controller (proof-heavy; may be long).
2. **`[THREAD STATE LEDGER]`** — short canonical truth readable in ~30 seconds.
The ledger must answer: what is true now, what changed, what is blocked,
who/what acts next — and must **separate**:
- local verdict/state
- server-side Gitea state
- attempted-but-blocked mutations
- completed mutations
Use precise state phrases (`APPROVED review posted to Gitea`,
`APPROVE verdict prepared locally`, `merge performed`, `merge not performed`,
`no server-side state changed`, `lease attempt blocked`) instead of ambiguous
standalone words (`approved`, `merged`, `ready`, `blocked`, `done`).
The ledger must include a **blocker classification** from:
`code blocker`, `test blocker`, `merge conflict`, `stale head`,
`permission/capability blocker`, `environment/tooling blocker`,
`process/rule blocker`, `queue/lease blocker`,
`duplicate/canonicalization blocker`, `no blocker`.
Templates: [`two-comment-workflow.md`](two-comment-workflow.md).
Worked examples: [`examples/two-comment-workflow-examples.md`](examples/two-comment-workflow-examples.md).
Validation: `thread_state_ledger_validator.py` checks tagged comments at post
time (`gitea_create_issue_comment`) and tagged final reports via
`assess_final_report_validator`. Legacy `## Controller Handoff` final reports
remain valid during transition; the tagged pair is required for new workflow
comments.
Related (do not duplicate): #494/#495 lifecycle state, #501 mutation-ledger
consistency, #505 CTH umbrella, #496 workflow comment gate when merged.
## Canonical comment validation (#496)
Workflow-changing issue/PR/review comments must carry durable next-action
+123
View File
@@ -0,0 +1,123 @@
# Two-comment workflow: Controller Handoff + Thread State Ledger
After meaningful controller/workflow work, post **two separate Gitea comments**:
1. **`[CONTROLLER HANDOFF]`** — detailed operational handoff for the next
LLM/controller session (proof-heavy; may be long).
2. **`[THREAD STATE LEDGER]`** — short canonical truth readable in ~30 seconds.
The ledger is the concise source of truth. The handoff is the detailed
continuation artifact. This complements CTH (#505) and lifecycle state
comments (#494/#495) without replacing them.
## Controller Handoff template
```markdown
[CONTROLLER HANDOFF] PR #___ / Issue #___ — <short title>
Purpose:
This comment is the operational handoff for the next controller/LLM session.
Identity/profile:
- Active profile:
- Authenticated identity:
- Role:
- Self-review / role-conflict proof:
Target:
- Repo:
- Issue:
- PR:
- Branch:
- Pinned head SHA:
- Worktree:
Work performed:
- <step 1>
- <step 2>
Files touched or reviewed:
- `<file>` — <why it matters>
Validation:
- `<command>` → <result>
- Full suite: <result or not run + reason>
Server-side mutation ledger:
- <mutation 1, including tool/action/comment id if available>
- Or: none — no server-side state changed
Local-only changes:
- <worktree created, files edited locally, etc.>
- Or: none
Blockers:
- <none>
- Or: <exact blocker, exact gate, exact reason>
Controller prompt for next session:
```markdown
<ready-to-paste prompt>
```
```
## Thread State Ledger template
```markdown
[THREAD STATE LEDGER] PR #___ / Issue #___ — <current state in one line>
What is true now:
- PR state:
- Issue state:
- Current head SHA:
- Server-side decision state:
- Local verdict/state:
- Latest known validation:
What changed:
- <short summary since prior ledger>
What is blocked:
- Blocker classification: <see list below>
Who/what acts next:
- Next actor:
- Required action:
- Do not do:
- Resume from:
```
### Blocker classifications
- code blocker
- test blocker
- merge conflict
- stale head
- permission/capability blocker
- environment/tooling blocker
- process/rule blocker
- queue/lease blocker
- duplicate/canonicalization blocker
- no blocker
### Precise state language
Prefer:
- `APPROVE verdict prepared locally`
- `APPROVED review posted to Gitea`
- `REQUEST_CHANGES posted to Gitea`
- `merge performed` / `merge not performed`
- `lease acquired` / `lease attempt blocked`
- `server-side state changed` / `no server-side state changed`
Avoid ambiguous standalone claims (`approved`, `ready`, `merged`, `blocked`,
`done`) without proof and server-side state separation.
## Validation
- `thread_state_ledger_validator.py` — comment and final-report checks
- `gitea_create_issue_comment` — fail-closed gate on tagged comments
- `assess_final_report_validator``shared.two_comment_workflow` rule
Examples: [`examples/two-comment-workflow-examples.md`](examples/two-comment-workflow-examples.md)