Merge master into issue-552-blocked-diagnose to resolve conflicts

This commit is contained in:
2026-07-09 09:06:59 -04:00
45 changed files with 4439 additions and 84 deletions
+183
View File
@@ -0,0 +1,183 @@
# Canonical State Comments
Gitea is the durable system of record for workflow continuation. When a
comment changes issue, PR, or discussion state, it should leave enough
information for the next role to continue without private chat history.
Canonical comments answer:
- what state the object is in
- who acts next
- what the next actor should do
- the exact prompt the next actor should run
- which proof, blocker, or dependency matters
Non-workflow discussion comments do not need this template.
## Issue State
Use this when an issue becomes ready, blocked, in progress, PR-open,
superseded, merged, or otherwise changes workflow direction.
```text
## Canonical Issue State
STATE:
<ready-for-author | in-progress | blocked | PR-open | needs-review | ready-to-merge | merged | closed | superseded>
WHO_IS_NEXT:
<controller | author | reviewer | merger | reconciler | user>
NEXT_ACTION:
<specific one-sentence action>
NEXT_PROMPT:
<paste-ready prompt for the next role>
WHAT_HAPPENED:
<latest meaningful event>
WHY:
<decision rationale>
RELATED_DISCUSSION:
<link/reference or none>
RELATED_PRS:
- #...
BRANCH:
<branch or none>
HEAD_SHA:
<40-character SHA or none>
VALIDATION:
<tests/proofs or none>
BLOCKERS:
<blocker and unblock condition, or none>
LAST_UPDATED_BY:
<identity/profile/date>
```
## PR State
Use this when a PR needs review, receives changes requested, is approved,
is stale, is superseded, or becomes ready for merge.
```text
## Canonical PR State
STATE:
<needs-review | changes-requested | approved | stale-approval | ready-to-merge | merged | blocked | superseded>
WHO_IS_NEXT:
<controller | author | reviewer | merger | reconciler | user>
NEXT_ACTION:
<specific one-sentence action>
NEXT_PROMPT:
<paste-ready prompt for the next role>
WHAT_HAPPENED:
<latest meaningful event>
WHY:
<decision rationale>
ISSUE:
#...
BASE:
<branch>
HEAD:
<branch>
HEAD_SHA:
<40-character SHA>
REVIEW_STATUS:
<none | approved | changes-requested | stale | contaminated>
VALIDATION:
<tests/proofs>
BLOCKERS:
<blockers or none>
SUPERSEDES:
<PRs or none>
SUPERSEDED_BY:
<PR or none>
MERGE_READY:
<yes/no and why>
LAST_UPDATED_BY:
<identity/profile/date>
```
## Discussion Summary
Discussions should normally have at least five substantive comments before
conversion into issues. A controller may waive that only for tiny mechanical,
urgent, or explicitly trivial work.
```text
## Canonical Discussion Summary
STATE:
<needs-more-discussion | ready-for-issues | issues-created | closed>
WHO_IS_NEXT:
<controller | author | reviewer | user>
DECISION:
<what was decided>
WHY:
<reasoning and tradeoffs>
SUBSTANTIVE_COMMENTS:
<count and summary>
ISSUES_TO_CREATE_OR_CREATED:
- #...
DEPENDENCY_ORDER:
<order or none>
NON_GOALS:
<non-goals>
OPEN_QUESTIONS:
<questions or none>
NEXT_ACTION:
<specific one-sentence action>
NEXT_PROMPT:
<paste-ready prompt for the next role>
LAST_UPDATED_BY:
<identity/profile/date>
```
## Validation Rules
The final-report validator rejects canonical state update claims when the
report omits the canonical block or when the block lacks:
- `STATE`
- `WHO_IS_NEXT`
- `NEXT_ACTION`
- `NEXT_PROMPT`
It also rejects vague next actions such as `continue`, ready-to-merge states
without approval/head-SHA proof, superseded states without canonical item
proof, and blocked states without an unblock condition.
+142
View File
@@ -0,0 +1,142 @@
# Canonical Thread Handoff (CTH)
**CTH** = **Canonical Thread Handoff**
A CTH comment is the authoritative workflow handoff in a Gitea issue or PR
thread. It records current state, decisions, blockers, proof, and the exact
next prompt/action for the next LLM or person.
CTH comments complement — but do not replace — formal Gitea review state.
A CTH may summarize an APPROVE or REQUEST_CHANGES decision, yet merge gates
still require the live Gitea review verdict.
## CTH comment types
- `CTH: State Handoff`
- `CTH: Controller Decision`
- `CTH: Author Handoff`
- `CTH: Reviewer Handoff`
- `CTH: Merger Handoff`
- `CTH: Supersession Notice`
- `CTH: Blocker`
## Required base template
```md
## CTH: <Type>
Status:
Next owner:
Current blocker:
Decision:
Proof:
Next action:
Ready-to-paste prompt:
```
Extended fields may map to canonical issue/PR state templates from #495 when
that layer is available. Until then, keep the base fields complete.
## Discovery and posting rules
Before acting in an issue or PR thread:
1. **Find the latest CTH comment** before doing work.
2. Treat the **latest valid CTH** as the current handoff state.
3. **Post a new CTH** when you finish, block, skip, supersede, request
changes, approve, or hand off.
4. Do **not** rely on stale non-CTH comments when a newer CTH exists.
5. Casual discussion comments do not need to be CTH comments.
## Examples
### PR approved and ready for merger
```md
## CTH: Reviewer Handoff
Status: approved_at_current_head
Next owner: merger
Current blocker: none
Decision: APPROVE recorded at head abc123...
Proof: gitea_submit_pr_review performed; visible verdict APPROVE
Next action: eligible merger merges PR #N with pinned expected_head_sha
Ready-to-paste prompt: Merge PR #N for issue #M if live head still abc123... and merge gates pass.
```
### PR request-changes back to author
```md
## CTH: Reviewer Handoff
Status: request_changes_at_current_head
Next owner: author
Current blocker: unresolved findings in validation report
Decision: REQUEST_CHANGES at head def456...
Proof: gitea_submit_pr_review performed; blocking review visible
Next action: author fixes findings and pushes; reviewer re-validates fresh head
Ready-to-paste prompt: Fix PR #N review findings, push to feat/issue-M-..., post Author Handoff CTH.
```
### Duplicate / superseded PR closure
```md
## CTH: Supersession Notice
Status: superseded
Next owner: controller
Current blocker: duplicate branch/PR work
Decision: close PR #N; continue on PR #M
Proof: duplicate gate linked open PR #M for issue #K
Next action: controller closes superseded PR and records canonical state
Ready-to-paste prompt: Close superseded PR #N; confirm PR #M remains canonical for issue #K.
```
### Blocked workflow due to dirty root/worktree
```md
## CTH: Blocker
Status: blocked_preflight
Next owner: operator
Current blocker: dirty control checkout / branches worktree mismatch
Decision: stop before mutation
Proof: verify_preflight_purity failed; workspace diagnostics attached
Next action: repair worktree or relaunch MCP from branches/ worktree
Ready-to-paste prompt: Repair dirty workspace, relaunch MCP from branches/review-prN, retry review.
```
### Stale head requiring fresh review
```md
## CTH: Reviewer Handoff
Status: stale_head
Next owner: reviewer
Current blocker: live head differs from pinned review head
Decision: prior approval not valid for current head
Proof: expected_head_sha mismatch at merge gate
Next action: re-run validation and post fresh review decision
Ready-to-paste prompt: Re-validate PR #N at live head, dry-run review gates, submit fresh verdict.
```
### Issue implementation handoff
```md
## CTH: Author Handoff
Status: implementation_complete_pending_review
Next owner: reviewer
Current blocker: none
Decision: PR #N ready for review at head fedcba...
Proof: tests passed in branches/issue-M-...; PR opened with Closes #M
Next action: reviewer acquires lease and validates PR #N
Ready-to-paste prompt: Review PR #N for issue #M; pin head fedcba... before mutations.
```
## Related
- [`llm-workflow-runbooks.md`](llm-workflow-runbooks.md)
- [`../skills/llm-project-workflow/templates/canonical-thread-handoff.md`](../skills/llm-project-workflow/templates/canonical-thread-handoff.md)
- #495 — canonical next-action comment fields
- #496 — fail-closed validation for workflow-changing comments
+88 -24
View File
@@ -1,34 +1,98 @@
# Label Taxonomy
This document catalogs the issue labels used for MCP workflows, including Jenkins and GlitchTip (observability).
This document defines the canonical issue labels used by MCP workflows.
> **Approval Required:** Do not create or apply new labels in `manage_labels.py` without explicit owner approval of this document.
Every issue should carry:
## Existing Labels
- one `type:*` label
- one `status:*` label
* **`jenkins`**
* Description: Jenkins integration
* Color: `d93f0b`
* Use: Used to mark issues, PRs, or tasks that involve the `jenkins-mcp` boundaries, CI/CD designs, or build failures.
Discussion-only issues must carry `type:discussion`.
* **`glitchtip`**
* Description: GlitchTip integration
* Color: `b60205`
* Use: Used to mark issues related to the `glitchtip-mcp` boundary and observability integration.
## Issue Type Labels
## Proposed / Missing Labels
| Label | Use |
| --- | --- |
| `type:bug` | Bug or defect |
| `type:feature` | Feature or enhancement |
| `type:process` | Process or policy work |
| `type:workflow` | Workflow automation or guidance |
| `type:guardrail` | Safety gate or guardrail |
| `type:docs` | Documentation work |
| `type:test` | Tests or test infrastructure |
| `type:discussion` | Discussion-only issue |
| `type:umbrella` | Umbrella or tracker issue |
| `type:cleanup` | Cleanup or hygiene work |
* **`observability`**
* Proposed Description: Observability, metrics, and monitoring tasks
* Proposed Color: `5319e7`
* Use: Broader than GlitchTip alone; covers logging, metrics, traces, and general observability pipeline improvements.
## Workflow Status Labels
* **`source:glitchtip`**
* Proposed Description: Issue filed automatically by GlitchTip orchestration
* Proposed Color: `b60205`
* Use: Applied automatically by the orchestrator when a GlitchTip error event is converted into a Gitea issue.
Only one `status:*` label should be active on an issue at a time. When an issue
moves forward, tooling must remove the old `status:*` label and apply the new
one.
* **`status:triage`**
* Proposed Description: Issue needs human or orchestrator triage
* Proposed Color: `fbca04`
* Use: Used for incoming issues (especially automated ones like `source:glitchtip`) that have not yet been evaluated for priority or resolution.
| Label | Use |
| --- | --- |
| `status:triage` | Issue needs triage |
| `status:ready` | Issue is ready for work |
| `status:claimed` | Issue is claimed |
| `status:in-progress` | Issue is being worked on |
| `status:blocked` | Issue is blocked |
| `status:needs-review` | Issue work needs review |
| `status:pr-open` | A linked PR is open |
| `status:approved` | Linked PR is approved |
| `status:merged` | Linked PR is merged |
| `status:reconcile` | Issue needs reconciliation |
| `status:done` | Issue workflow is complete |
| `status:duplicate` | Issue is a duplicate |
| `status:wontfix` | Issue will not be fixed |
## Transition Rules
Suggested lifecycle:
1. New issue created: `status:triage` or `status:ready`
2. Issue selected by an author: `status:claimed`
3. Author starts work: `status:in-progress`
4. Work is blocked: `status:blocked`
5. PR opened: `status:pr-open`
6. PR approved: `status:approved`
7. PR merged but issue still needs closure/reconciliation: `status:reconcile`
8. Issue fully complete: `status:done`
9. Duplicate issue: `status:duplicate`
10. Won't-fix issue: `status:wontfix`
The helper module `issue_workflow_labels.py` is the source of truth for the
canonical label specs and status transition replacement behavior.
## Discussion Issues
Discussion issues must be labeled `type:discussion`.
A discussion issue should not be treated as implementation-ready unless it also
has a clear implementation status and next action.
If a discussion produces implementation work, either:
1. convert the discussion issue into an implementation issue by changing labels
and adding acceptance criteria, or
2. create child implementation issues and leave the discussion issue as
`type:discussion`.
## Tooling
- `manage_labels.py --create-labels` creates the canonical `type:*` and
`status:*` labels.
- `gitea_create_issue` recommends `type:*` and `status:*` labels when missing
and can apply supplied label names.
- `gitea_mark_issue(..., action="start")` replaces old `status:*` labels with
`status:in-progress`.
- `gitea_create_pr` fails closed before PR creation if `status:pr-open` cannot
be applied to the locked issue, then applies it after the PR is created.
- `gitea_set_issue_labels` accepts an explicit `worktree_path` so author
sessions can satisfy the branches-only mutation guard while changing labels.
## Existing Non-Workflow Labels
Existing non-workflow labels such as `mcp`, `workflow`, `labels`, `tracker`,
`jenkins`, `glitchtip`, `documentation`, and `testing` remain valid topical
labels. They do not replace the required `type:*` and `status:*` labels.
+86 -5
View File
@@ -7,6 +7,11 @@ package of the MCP Control Plane: creating issues, implementing them, opening
and reviewing pull requests, merging, and closing out — safely and
reproducibly.
Canonical state comments for durable issue/PR/discussion continuation are
documented in [`canonical-state-comments.md`](canonical-state-comments.md).
Use them when a workflow-changing comment needs to leave the next actor, next
action, and paste-ready prompt in Gitea.
> For the **project-agnostic** version of these operating rules (issue-first,
> isolated worktrees, no self-review/merge, profile safety, cleanup, fail-closed)
> that can be copied into any repository, see the reusable skill
@@ -636,19 +641,24 @@ loop and do **not** substitute WebFetch/Playwright/manual base64.
- **Profile:** issue-manager or author (any profile allowed to create issues).
- **Steps:** create the parent/roadmap issue; create child issues; apply the
minimal label set; link children to the parent.
- **Labels:** new issues should carry one `type:*` label and one `status:*`
label. Discussion-only issues must carry `type:discussion`. See
[`label-taxonomy.md`](label-taxonomy.md).
- **Prompt:** `Using the issue-manager profile, create issue "<title>" with body
<body>, then create child issues for <list> and link them to the parent.`
### Implement an issue and open a PR
- **Profile:** author.
- **Steps:** claim the issue (`status:in-progress`); create an isolated branch
worktree from latest `master` under `branches/` (`feat/issue-<n>-...` /
- **Steps:** claim the issue (`status:in-progress`, replacing any old
`status:*` label); create an isolated branch worktree from latest `master`
under `branches/` (`feat/issue-<n>-...` /
`fix/...` / `docs/...`); `cd` into that worktree; implement narrowly; add or
update tests if behavior changes; run the full suite; commit with an
issue-linked message; open a PR to `master`. **Do not** review or merge your
own PR. Include an `LLM Handoff Metadata` block (with `LLM-Agent-SHA`) in
the PR body — see [`llm-agent-sha.md`](llm-agent-sha.md).
issue-linked message; open a PR to `master`; move the issue to
`status:pr-open`. **Do not** review or merge your own PR. Include an
`LLM Handoff Metadata` block (with `LLM-Agent-SHA`) in the PR body — see
[`llm-agent-sha.md`](llm-agent-sha.md).
- **Prompt:** `Use an author profile to implement issue #N and open a PR to
master. Do not self-review or self-merge.`
@@ -831,6 +841,27 @@ Never imply full-suite success unless the full-suite command itself passed
(`full_suite_passed: true`). A report that hides a failed or skipped check
is worse than a failing report.
## Canonical Thread Handoff (CTH)
**CTH** = **Canonical Thread Handoff** — the authoritative workflow handoff
comment in a Gitea issue or PR thread. See
[`canonical-thread-handoff.md`](canonical-thread-handoff.md) for types,
templates, and examples.
Before acting in an issue or PR thread:
1. **Find the latest CTH comment** before doing work.
2. Treat the **latest valid CTH** as the current handoff state.
3. **Post a new CTH** when you finish, block, skip, supersede, request
changes, approve, or hand off.
4. Do **not** rely on stale non-CTH comments when a newer CTH exists.
A CTH summarizes workflow state for the next session. Formal Gitea review
verdicts remain authoritative for merge gates — a CTH is not merge approval
by itself.
Template: [`../skills/llm-project-workflow/templates/canonical-thread-handoff.md`](../skills/llm-project-workflow/templates/canonical-thread-handoff.md)
## Controller Handoff (required, every task)
Every task — implementation, review, merge, triage, documentation,
@@ -863,6 +894,55 @@ 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.
## Canonical comment validation (#496)
Workflow-changing issue/PR/review comments must carry durable next-action
state. Casual discussion is still allowed.
The MCP server runs `canonical_comment_validator.assess_canonical_comment`
**before** posting through:
- `gitea_create_issue_comment`
- `gitea_submit_pr_review` / `gitea_dry_run_pr_review` (non-empty review bodies)
- `gitea_reconcile_already_landed_pr` when `post_comment=True`
- internal structured comment helpers (machine lease/heartbeat markers stay exempt)
Detection examples:
- **Allowed:** `Thanks, I will check this.`
- **Rejected:** `Blocked, author should fix.` (workflow trigger without canonical fields)
When validation fails, the tool returns `canonical_comment_validation` with
`allowed: false`, `missing_fields`, `vague_fields`, `correction_message`, and
`suggested_template`. **No Gitea API call is made.**
Minimum workflow comment fields:
```text
STATE:
WHO_IS_NEXT:
NEXT_ACTION:
NEXT_PROMPT:
WHY:
```
`WHO_IS_NEXT` must be one of: `controller`, `author`, `reviewer`, `merger`,
`reconciler`, `user`.
Issue comments also require `RELATED_PRS`, `BLOCKERS`, and `VALIDATION` when
they mention PR work. PR comments/reviews also require `ISSUE`, `HEAD_SHA`,
`REVIEW_STATUS`, `MERGE_READY`, `BLOCKERS`, and `VALIDATION`.
Special states:
- `STATE: blocked` — `BLOCKERS` must name an explicit unblock condition.
- `STATE: superseded` — requires `CANONICAL_ITEM` and `SUPERSEDED_ITEM`.
- `STATE: ready-to-merge` — requires approval proof and head SHA in
`HEAD_SHA`, `REVIEW_STATUS`, `MERGE_READY`, or `VALIDATION`.
Final reports must not claim a comment was posted when
`canonical_comment_validation.allowed` is false (#496 AC14).
## Fail-closed behavior
Before any mutating action the workflow verifies identity, active profile,
@@ -974,6 +1054,7 @@ When posting a Canonical Thread Handoff after a binding blocker:
## Related documents
- [`reviewer-handoff-consistency.md`](reviewer-handoff-consistency.md) — reject contradictory reviewer handoffs (#501).
- [`issue-acceptance-gate.md`](issue-acceptance-gate.md) — controller issue-acceptance audit after PR merge (#500).
- [`../skills/llm-project-workflow/SKILL.md`](../skills/llm-project-workflow/SKILL.md) — portable cross-project LLM workflow skill.
- [`gitea-execution-profiles.md`](gitea-execution-profiles.md) — the profile model.
+35
View File
@@ -0,0 +1,35 @@
# Reviewer Handoff Consistency
Reviewer and final-review controller handoffs must not contradict themselves.
A narrative that says a merge happened, a review was blocked, or a terminal
mutation budget was consumed must match the mutation ledger fields in the same
handoff.
## What gets validated
`reviewer_handoff_consistency.assess_reviewer_handoff_consistency()` checks:
- merge claims appear under `Merge mutations` or `MCP/Gitea mutations`
- terminal-mutation-budget claims name the exact prior mutation in the ledger
- blocked review submission is not paired with "final decision marked"
- reviewer lease acquisition includes a `Review decision`
- blocked/rejected mutations include proof fields:
- tool called
- mutation attempted
- mutation rejected
- no server-side state changed
`final_report_validator` applies this as `reviewer.handoff_consistency` on
`review_pr` reports and fails closed.
## Blocked review template
When `gitea_submit_pr_review` fails closed, use
`reviewer_handoff_consistency.render_blocked_review_handoff_template()` or the
copy in
[`skills/llm-project-workflow/templates/blocked-review-handoff.md`](../skills/llm-project-workflow/templates/blocked-review-handoff.md).
## Related
- #331 — file-mutation ledger alignment
- #501 — contradictory narrative vs ledger detection
+12 -2
View File
@@ -43,7 +43,8 @@ Optional environment variables:
| `/api/projects` | JSON registry export |
| `/prompts` | Prompt library with per-prompt copy buttons (#428) |
| `/api/prompts` | JSON prompt export with workflow hashes |
| `/runtime` | Stub — MCP runtime health (#430) |
| `/runtime` | MCP runtime health and stale detection (#430) |
| `/api/runtime` | JSON runtime health export |
| `/audit` | Stub — report audit paste (#431) |
| `/worktrees` | Stub — hygiene dashboard (#432) |
| `/leases` | Lease and collision visibility (#433) |
@@ -91,8 +92,17 @@ in-progress claim inventory (#268), reviewer PR lease comments when present
and duplicate local branches per issue. Links to collision-history backend
issues (#267, #268, #400, #407) are included. No lease acquire/release from UI.
## Runtime health (#430)
`/runtime` surfaces read-only MCP/runtime diagnostics for the default registry
project: active profile and role kind, authenticated identity (when credentials
are available), config model/mode, local vs remote `master` SHA sync, shell
health, workflow/schema SHA-256 hashes, and stale-runtime warnings when the
checkout is behind merged safety-gate changes. Restart guidance links to #420;
no tokens or MCP restart actions are exposed.
## Tests
```bash
pytest tests/test_webui_skeleton.py tests/test_webui_project_registry.py tests/test_webui_prompt_library.py tests/test_webui_queue_dashboard.py tests/test_webui_lease_visibility.py -q
pytest tests/test_webui_skeleton.py tests/test_webui_project_registry.py tests/test_webui_prompt_library.py tests/test_webui_queue_dashboard.py tests/test_webui_lease_visibility.py tests/test_webui_runtime_health.py -q
```