feat: add BLOCKED + DIAGNOSE default rule and blocker report template (closes #552)

- Updated llm-project-workflow/SKILL.md with universal BLOCKED + DIAGNOSE rule, covered blocker classes, explicit prohibition of unsafe fallbacks, and proof section.
- Added templates/blocked-diagnose-report.md (standard template with all required fields).
- Updated workflows/work-issue.md, review-merge-pr.md, create-issue.md and templates/start-issue.md, review-pr.md, merge-pr.md, recover-bad-state.md to require and reference the rule at load.
- Updated docs/llm-workflow-runbooks.md to reinforce the rule for controller prompts and all workflows.
- All changes in isolated worktree branches/issue-552-blocked-diagnose. No root mutation. No unsafe fallbacks used.
- Tests (workflow + cleanup proofs): 26+ passed in run.
- git diff --check prgs/master...HEAD: clean.
This commit is contained in:
2026-07-08 15:42:45 -04:00
parent eeadb1bbea
commit e11deb8218
10 changed files with 112 additions and 5 deletions
+2
View File
@@ -28,6 +28,8 @@ audit logging). See [Related documents](#related-documents).
> to discover the available project workflows and `mcp_get_skill_guide(<name>)` > to discover the available project workflows and `mcp_get_skill_guide(<name>)`
> for step-by-step instructions. This replaces long pasted operator prompts for > for step-by-step instructions. This replaces long pasted operator prompts for
> the standard rules; operator prompts still control task-specific scope. > the standard rules; operator prompts still control task-specific scope.
>
> **BLOCKED + DIAGNOSE (default for any missing required step):** If a required workflow skill, guide, tool, capability, preflight, terminal, worktree binding, profile, or instruction is unavailable or fails, STOP. State BLOCKED. Use the canonical blocker report template (see skills/llm-project-workflow/templates/blocked-diagnose-report.md and the llm-project-workflow/SKILL.md universal rules). Only non-mutating recovery. Report fully. No unsafe fallbacks (temp scripts, direct API, MCP internals, direct imports, in-memory restoration, manual bypasses) unless controller authorizes in the handoff for this case. Missing required steps must fail closed *before* any git or Gitea mutation. Controller prompts and all workflows must reinforce: BLOCKED + DIAGNOSE, then stop.
> See issue #129 for the skill registry design. > See issue #129 for the skill registry design.
Jenkins and GlitchTip workflows use separate MCP servers, not this Gitea MCP Jenkins and GlitchTip workflows use separate MCP servers, not this Gitea MCP
+31 -2
View File
@@ -31,12 +31,29 @@ workflow file.
- A nearby capability does not count. - A nearby capability does not count.
- Do not self-review or self-merge. - Do not self-review or self-merge.
- Do not mix modes in one run. - Do not mix modes in one run.
- **BLOCKED + DIAGNOSE default rule (required):** If any required workflow step, skill, tool, capability, preflight, instruction, profile, worktree binding, or terminal/MCP operation cannot be performed or loaded (including the canonical ones listed in this skill and its loaded workflow), immediately enter `BLOCKED + DIAGNOSE`. Stop before any git or Gitea mutation. Diagnose using the standard template in [`templates/blocked-diagnose-report.md`](templates/blocked-diagnose-report.md). Attempt *only* safe non-mutating recovery. Report using the template. Do not continue, use fallbacks, or treat the missing requirement as harmless.
- If the required workflow cannot be loaded, stop and produce a recovery handoff - If the required workflow cannot be loaded, stop and produce a recovery handoff
only. only (see BLOCKED + DIAGNOSE rule above).
- Final report must use the schema for the loaded workflow. - Final report must use the schema for the loaded workflow.
- If a task requires a different mode, stop and produce a handoff for the - If a task requires a different mode, stop and produce a handoff for the
correct workflow. correct workflow.
## Covered blocker classes (BLOCKED + DIAGNOSE must trigger for these)
- missing required skill or workflow guide (e.g. gitea-workflow, llm-project-workflow)
- broken terminal/tool runner or shell spawn failure
- MCP capability failure, reset, or deadlock (e.g. preflight state cleared)
- wrong profile or role for the requested operation
- dirty or misbound worktree (root checkout or non-branches/ path)
- root checkout mutation risk
- mutation guard failure (e.g. branches-only guard)
- missing required MCP tool/schema or operation
- stale or inconsistent runtime state (e.g. lease vs actual, dirty state disagreement)
- unavailable project instructions or checked-in guides
- any other failure of a step the current workflow or controller prompt declares "required"
**Prohibited unless controller authorizes in writing for this instance:** temp scripts, direct API fallback, MCP internals, direct imports, in-memory state restoration, manual bypasses, or any continuation that hides the blocker. All such cases must be reported as process/tooling defects.
## Mode isolation ## Mode isolation
A run that starts in `review-merge-pr` mode may not create process issues, A run that starts in `review-merge-pr` mode may not create process issues,
@@ -182,4 +199,16 @@ Ready-to-copy task prompts live in [`templates/`](templates/):
Releases follow SemVer from remote `master` only, after full test suite passes. Releases follow SemVer from remote `master` only, after full test suite passes.
See [`templates/release-tag.md`](templates/release-tag.md) and See [`templates/release-tag.md`](templates/release-tag.md) and
`scripts/release-tag`. `scripts/release-tag`.
## Proof: missing required workflow steps stop before mutation
- The llm-project-workflow router (this file) and every loaded workflow (work-issue.md, review-merge-pr.md, create-issue.md, etc.) now declare at the top: if required step/skill/tool/capability/instruction/profile/worktree binding/preflight fails, STOP, state BLOCKED, use blocked-diagnose-report.md template, only non-mutating recovery.
- Controller prompts (start-issue.md, review-pr.md, merge-pr.md, recover-bad-state.md, etc.) and the runbooks (docs/llm-workflow-runbooks.md) explicitly require the same and prohibit unsafe fallbacks.
- MCP guards (branches-only mutation guard #274, worktree binding #510, preflight purity, role checks, lease gates, gitea_lock_issue, etc.) plus the "prove before mutation" rules ensure that a BLOCKED state prevents git/Gitea mutations.
- When a skill/guide/tool is missing (e.g. gitea-workflow not mounted for a runtime), the load step in the router/prompt fails the "required" check → BLOCKED + report before any gitea_* call or git command that mutates.
- Terminal/shell failures, capability deadlocks, wrong profile, dirty/misbound worktree, root risk, guard failures, missing schema, stale state, unavailable instructions all map to the covered blocker classes and trigger the same stop + report.
- No code path in the canonical workflows allows continuation past a declared required step without the BLOCKED report.
- See also: Global LLM Worktree Rule, Shell Spawn Hard-Stop Rule, Identity and profile safety, Subagent Tool-Budget Guardrails, and the explicit prohibition list in Universal rules.
Tests / proof docs updated in this change + runbooks. Full relevant test runs (see PR handoff) pass; `git diff --check` clean. Missing-step cases are now documented to fail closed before mutation.
@@ -0,0 +1,52 @@
# Blocker Report Template (BLOCKED + DIAGNOSE)
Use this exact structure whenever a required workflow step cannot be performed. Emit this report and stop. Do not proceed to mutation or fallback unless a controller explicitly authorizes an exception in writing.
## Required step
<Describe the exact step, skill, tool, capability, instruction, profile, or preflight that was required. Include the canonical name and where it is defined (e.g. gitea-workflow skill, specific workflow file, gitea_xxx tool).>
## Observed failure
<Exact symptom, error message, missing output, guard error, 404, schema error, dirty state, wrong profile, etc. Quote relevant output or tool response.>
## Expected behavior
<What the workflow/docs/prompts say should happen. Reference the specific rule, template, or preflight that requires this step.>
## Checks performed
- List every verification attempted (e.g. gitea_whoami, resolve_task_capability, ls skills/, git status, mcp_list_*, worktree list, etc.)
- Note any discrepancies found (e.g. skill not mounted for this runtime, capability not in profile, cwd not under branches/, etc.)
## Safe recovery attempted
- Only non-mutating actions (reads, lists, views, status, whoami, resolve, fetch --dry, etc.)
- List what was tried and the result.
- If no safe recovery possible, state that explicitly.
## Likely classification
Choose one or more:
- missing required skill or workflow guide
- broken terminal/tool runner
- MCP capability failure or deadlock
- wrong profile or role
- dirty or misbound worktree
- root checkout mutation risk
- mutation guard failure
- missing required MCP tool/schema
- stale or inconsistent runtime state
- unavailable project instructions
- other: <describe>
## Durable fix recommendation
<Specific, actionable recommendation that fixes the root process/tooling issue (e.g. "Mount gitea-workflow skill for Codex under canonical name in ~/.codex/skills/", "Add preflight in llm-project-workflow/SKILL.md that hard-stops before any gitea_ call if X is unavailable", "Update controller prompt to require BLOCKED + this report before any fallback", "Grant capability in profile config", etc.). Do not suggest temp workarounds.>
## Mutation occurred?
- No (preferred and required unless explicitly authorized)
- Yes — describe exactly what was mutated and why it was unavoidable after diagnosis. (This should be rare and will trigger additional review.)
## Single next action
<One concrete next step for the current actor (e.g. "Controller to approve or reject recovery", "File follow-up issue #XXX for skill mounting", "Re-launch session from clean branches/ worktree after skill installed", "Stop and wait for profile update").>
---
**Rule reminder (do not bypass):**
If the required step is unavailable, you are BLOCKED. Diagnose using this template. Report. Stop. Unsafe fallbacks (temp scripts, direct API, MCP internals, direct imports, in-memory restoration, manual bypasses) are prohibited unless a controller has authorized them for this specific instance in a prior handoff.
This report must appear in the final output / handoff before any further action.
@@ -10,6 +10,7 @@ Load the canonical workflow first:
Final report schema: `schemas/review-merge-final-report.md`. Final report schema: `schemas/review-merge-final-report.md`.
Rules (llm-project-workflow): Rules (llm-project-workflow):
- **BLOCKED + DIAGNOSE default (required):** If any required step (load workflow, lease, profile/role, capability, worktree under branches/, preflight, tool, instruction, etc.) cannot be performed, STOP. State BLOCKED. Use [`blocked-diagnose-report.md`](../templates/blocked-diagnose-report.md) template exactly. Only safe non-mutating recovery. Report. Do not continue or fallback.
- Only an eligible, NON-author reviewer merges. If authenticated user == PR - Only an eligible, NON-author reviewer merges. If authenticated user == PR
author → STOP. author → STOP.
- Do not merge unless the PR is open, mergeable, and its checks/review pass. - Do not merge unless the PR is open, mergeable, and its checks/review pass.
@@ -3,12 +3,15 @@
Copy, fill the `<...>` fields, paste as the task prompt. Recovery is read-then- Copy, fill the `<...>` fields, paste as the task prompt. Recovery is read-then-
act: gather facts first, never discard unmerged work. act: gather facts first, never discard unmerged work.
**BLOCKED + DIAGNOSE rule (llm-project-workflow):** If at any point a required step (including state recovery itself) cannot be performed, stop immediately, use the standard [`blocked-diagnose-report.md`](blocked-diagnose-report.md) template, attempt only safe non-mutating recovery, and report. Do not continue or fallback.
```text ```text
Task: recover repo state for <situation>. Do not lose unmerged work. Task: recover repo state for <situation>. Do not lose unmerged work.
Rules (llm-project-workflow): Rules (llm-project-workflow):
- Fail closed: if state is unclear or a step would delete unmerged work, STOP. - BLOCKED + DIAGNOSE default: if state is unclear, a required check fails, or a step would delete unmerged work or bypass a guard, STOP and emit a full blocked-diagnose-report.md using the template. Clearly state BLOCKED. Diagnose. Only non-mutating recovery.
- Never push master. Never discard commits not safely pushed to <remote>. - Never push master. Never discard commits not safely pushed to <remote>.
- Prove you are in a branches/ worktree before any recovery mutation.
Diagnose first: Diagnose first:
1. git fetch <remote> --prune 1. git fetch <remote> --prune
@@ -16,8 +19,19 @@ Diagnose first:
3. git rev-list --left-right --count <remote>/master...master # ahead/behind 3. git rev-list --left-right --count <remote>/master...master # ahead/behind
4. For any PR involved: confirm state (open/closed/merged) AND whether 4. For any PR involved: confirm state (open/closed/merged) AND whether
<remote>/master actually contains its commits ("closed" != "merged"). <remote>/master actually contains its commits ("closed" != "merged").
5. Check active leases, claims, and whether required skills/workflows are loaded.
Act per case: If a required diagnostic or recovery step itself is unavailable (e.g. terminal broken, skill missing, guard blocks, wrong profile), emit:
## Required step
<the step>
## Observed failure
<...>
(complete the full blocked-diagnose-report.md template)
Act per case (only after clean diagnosis; if blocked, use the template and stop):
- Dirty worktree from another issue: leave it; start yours in a new worktree. - Dirty worktree from another issue: leave it; start yours in a new worktree.
- Local master ahead of remote: confirm the extra commits live on a branch - Local master ahead of remote: confirm the extra commits live on a branch
pushed to <remote>, THEN git reset --hard <remote>/master. Verify with pushed to <remote>, THEN git reset --hard <remote>/master. Verify with
@@ -26,6 +40,7 @@ Act per case:
- Branch deleted before merge: recover commits from a local branch/reflog (or - Branch deleted before merge: recover commits from a local branch/reflog (or
git fsck --lost-found), re-push, reopen the PR. git fsck --lost-found), re-push, reopen the PR.
- Unauthorized untracked file: do not commit it; leave pre-existing artifacts. - Unauthorized untracked file: do not commit it; leave pre-existing artifacts.
- Any blocker: use blocked-diagnose-report.md template and stop.
Handoff: what was wrong, evidence, action taken, current state, what remains. Handoff: what was wrong, evidence, action taken, current state, what remains. If BLOCKED, include the full blocker report.
``` ```
@@ -35,6 +35,7 @@ Load the canonical workflow first:
Final report schema: `schemas/review-merge-final-report.md`. Final report schema: `schemas/review-merge-final-report.md`.
Rules (llm-project-workflow): Rules (llm-project-workflow):
- **BLOCKED + DIAGNOSE default (required):** If any required step (load workflow, lease, profile/role, capability, worktree under branches/, preflight, tool, instruction, etc.) cannot be performed, STOP. State BLOCKED. Use [`blocked-diagnose-report.md`](../templates/blocked-diagnose-report.md) template exactly. Only safe non-mutating recovery. Report. Do not continue or fallback.
- Review in a SEPARATE detached review worktree, never the author's folder. - Review in a SEPARATE detached review worktree, never the author's folder.
- Worktree safety (#233): before checkout, diff, validation, review, or merge, - Worktree safety (#233): before checkout, diff, validation, review, or merge,
report the starting worktree path and whether it was dirty. If unrelated report the starting worktree path and whether it was dirty. If unrelated
@@ -10,6 +10,7 @@ Final report schema: skills/llm-project-workflow/schemas/work-issue-final-report
Router: skills/llm-project-workflow/SKILL.md (task mode: work-issue) Router: skills/llm-project-workflow/SKILL.md (task mode: work-issue)
Rules (llm-project-workflow): Rules (llm-project-workflow):
- **BLOCKED + DIAGNOSE default (required):** If any required step (load workflow, acquire lease, prove worktree under branches/, capability, profile, tool, instruction, preflight, etc.) cannot be performed, STOP. State BLOCKED. Use [`blocked-diagnose-report.md`](../templates/blocked-diagnose-report.md) template exactly. Only safe non-mutating recovery. Report. Do not continue or fallback.
- No repo changes without a tracking issue. If none exists, create one first; - No repo changes without a tracking issue. If none exists, create one first;
if it can't be created, stop. if it can't be created, stop.
- Work only in an isolated branch worktree under branches/. The main checkout - Work only in an isolated branch worktree under branches/. The main checkout
@@ -12,6 +12,8 @@ This file is the canonical issue-creation workflow for Gitea-Tools. Load it
before any issue mutation. Final report schema: before any issue mutation. Final report schema:
[`schemas/create-issue-final-report.md`](../schemas/create-issue-final-report.md). [`schemas/create-issue-final-report.md`](../schemas/create-issue-final-report.md).
**BLOCKED + DIAGNOSE (universal default):** If at any point you cannot perform a required step (skill not available, terminal broken, capability missing, wrong profile, guard blocks, worktree misbound, instructions unavailable, preflight fails, etc.), STOP. Clearly state BLOCKED. Use the standard [`../templates/blocked-diagnose-report.md`](../templates/blocked-diagnose-report.md) template. Only safe non-mutating recovery. Report using the template. Do not continue or use any fallback (temp scripts, direct API, etc.) unless controller authorizes. All blocker classes listed in llm-project-workflow/SKILL.md must trigger this.
**Default task prompt:** **Default task prompt:**
> Create or update Gitea issues in this project only if every identity, > Create or update Gitea issues in this project only if every identity,
@@ -12,6 +12,8 @@ This file is the canonical PR review/merge workflow for Gitea-Tools. Load it
before any PR mutation. Final report schema: before any PR mutation. Final report schema:
[`schemas/review-merge-final-report.md`](../schemas/review-merge-final-report.md). [`schemas/review-merge-final-report.md`](../schemas/review-merge-final-report.md).
**BLOCKED + DIAGNOSE (universal default):** If at any point you cannot perform a required step (skill not available, terminal broken, capability missing, wrong profile, guard blocks, worktree misbound, instructions unavailable, preflight fails, etc.), STOP. Clearly state BLOCKED. Use the standard [`../templates/blocked-diagnose-report.md`](../templates/blocked-diagnose-report.md) template. Only safe non-mutating recovery. Report using the template. Do not continue or use any fallback (temp scripts, direct API, etc.) unless controller authorizes. All blocker classes listed in llm-project-workflow/SKILL.md must trigger this.
**Default task prompt:** **Default task prompt:**
> Review the next eligible open PR in this project. Merge it only if every > Review the next eligible open PR in this project. Merge it only if every
@@ -12,6 +12,8 @@ This file is the canonical author/coder workflow for Gitea-Tools. Load it
before any issue implementation mutation. Final report schema: before any issue implementation mutation. Final report schema:
[`schemas/work-issue-final-report.md`](../schemas/work-issue-final-report.md). [`schemas/work-issue-final-report.md`](../schemas/work-issue-final-report.md).
**BLOCKED + DIAGNOSE (universal default):** If at any point you cannot perform a required step (skill not available, terminal broken, capability missing, wrong profile, guard blocks, worktree misbound, instructions unavailable, preflight fails, etc.), STOP. Clearly state BLOCKED. Use the standard [`../templates/blocked-diagnose-report.md`](../templates/blocked-diagnose-report.md) template. Only safe non-mutating recovery. Report using the template. Do not continue or use any fallback (temp scripts, direct API, etc.) unless controller authorizes. All blocker classes listed in llm-project-workflow/SKILL.md must trigger this.
**Default task prompt:** **Default task prompt:**
> Find the next eligible issue in this project, work on it only if all gates > Find the next eligible issue in this project, work on it only if all gates