Merge remote-tracking branch 'prgs/master' into feat/issue-436-ci-coverage

# Conflicts:
#	docs/webui-local-dev.md
This commit is contained in:
2026-07-09 09:38:24 -04:00
44 changed files with 2933 additions and 61 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.
+60
View File
@@ -33,6 +33,8 @@ audit logging). See [Related documents](#related-documents).
> to discover the available project workflows and `mcp_get_skill_guide(<name>)`
> for step-by-step instructions. This replaces long pasted operator prompts for
> 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.
Jenkins and GlitchTip workflows use separate MCP servers, not this Gitea MCP
@@ -413,6 +415,24 @@ The guard blocks when the **control checkout** (repository root) is:
`branches/...` directories are disposable role worktrees; the root checkout is
the stable orchestration surface only.
## Canonical workflow skill names (#551)
Controller prompts and sessions must load the **same** workflow skill wall
regardless of runtime (Claude, Codex, Gemini):
| Name | Role |
|------|------|
| `gitea-workflow` | Primary controller / Codex skill name |
| `llm-project-workflow` | Portable in-repo package |
| `git-pr-workflows` | Legacy alias |
- Inventory: `mcp_list_project_skills` lists all three.
- Preflight: `mcp_check_workflow_skill_preflight` before mutations.
- Codex install: `scripts/install-codex-workflow-skill.sh`
- Full doc: [`docs/workflow-skill-mount.md`](workflow-skill-mount.md)
If the skill is missing, stop with BLOCKED + DIAGNOSE — do not mutate.
## No direct-import mutation path (#558)
Never `import gitea_mcp_server` or call `gitea_auth.get_auth_header` /
@@ -899,6 +919,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)
+27 -3
View File
@@ -45,13 +45,26 @@ Optional environment variables:
| `/api/prompts` | JSON prompt export with workflow hashes |
| `/runtime` | MCP runtime health and stale detection (#430) |
| `/api/runtime` | JSON runtime health export |
| `/audit` | Stub — report audit paste (#431) |
| `/audit` | Report audit paste + validator preview (#431) |
| `/api/audit` | JSON validator preview (POST `report_text`, optional `task_kind`) |
| `/worktrees` | Worktree hygiene dashboard (#432) |
| `/api/worktrees` | JSON worktree scan with classifications and anomalies |
| `/leases` | Stub — lease visibility (#433) |
| `/worktrees` | Stub — hygiene dashboard (#432) |
| `/leases` | Lease and collision visibility (#433) |
| `/api/leases` | JSON lease/collision export |
All routes are GET-only. POST/PUT/PATCH/DELETE return `405` with
`read-only-mvp`.
Most routes are GET-only. POST/PUT/PATCH/DELETE return `405` with
`read-only-mvp`, except `/audit` and `/api/audit` which accept POST for
local validator preview only (no Gitea mutations, no server-side storage).
## Report audit (#431)
Paste an LLM final report at `/audit` or POST JSON to `/api/audit`. The UI
reuses `final_report_validator` and review schema checks to surface missing
proof fields, wrong validation vocabulary, mutation contradictions, and a
suggested next prompt or issue-comment draft. Task kind can be auto-detected
or selected explicitly.
## Project registry (#427)
@@ -84,6 +97,16 @@ credentials. The UI surfaces pagination proof (returned count, pages fetched,
If credentials are missing or the fetch fails, the page shows an explicit error
instead of an empty queue (fail closed).
## Worktree hygiene (#432)
`/worktrees` scans local `branches/` directories and registered git worktrees.
Each entry is classified (`active-pr`, `active-issue`, `dirty`, `stale-clean`,
`detached-review`, `unsafe-unknown`, `orphan`). Missing preserved worktrees
referenced by the issue lock file are flagged as anomalies (#404). The page
includes a copy/paste canonical cleanup prompt only — no deletion actions.
Override scan root with `WEBUI_REPO_ROOT` (defaults to repository root).
## Tests (#436)
Run the full hermetic web UI suite (all `test_webui_*.py` modules):
@@ -124,5 +147,6 @@ 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_audit.py tests/test_webui_worktree_hygiene.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
```
+68
View File
@@ -0,0 +1,68 @@
# Workflow skill mount across runtimes (#551)
## Problem
Controller prompts require **`gitea-workflow`**, but:
- Claude may load `~/.claude/skills/gitea-workflow`
- Codex often has **no** `~/.codex/skills/gitea-workflow`
- The portable package in-repo is `skills/llm-project-workflow`
- `mcp_list_project_skills` historically listed operational guides only, not
the workflow router
Sessions then either **block** incorrectly or **proceed without** the workflow
wall.
## Canonical names (must resolve to the same skill)
| Name | Use |
|------|-----|
| `gitea-workflow` | **Primary** controller / Codex skill name |
| `llm-project-workflow` | Portable in-repo package name |
| `git-pr-workflows` | Legacy alias |
Source of truth: `skills/llm-project-workflow/SKILL.md`
In-repo alias stub: `skills/gitea-workflow/SKILL.md`
## Codex install
From a `branches/` worktree (or any clone of the repo):
```bash
./scripts/install-codex-workflow-skill.sh
# optional:
./scripts/install-codex-workflow-skill.sh --dry-run
./scripts/install-codex-workflow-skill.sh --skills-dir "$HOME/.codex/skills"
```
This symlinks the portable package under all three names. **Restart Codex**
after install.
## MCP discovery
- `mcp_list_project_skills` includes `gitea-workflow`, `llm-project-workflow`,
and `git-pr-workflows`.
- `mcp_get_skill_guide("<name>")` returns the same router steps for each.
- `mcp_check_workflow_skill_preflight` proves the in-repo skill file exists and
reports Codex mount status.
## Preflight rule
Before any git or Gitea mutation:
1. Call `mcp_check_workflow_skill_preflight`.
2. If `blocked` / `workflow_skill_ready` is false → **BLOCKED + DIAGNOSE**; do
not mutate.
3. Load the skill by **any** canonical name and follow the router.
Missing Codex mount alone does not block if the in-repo skill is present and
loaded via MCP/docs; operators should still install the Codex symlink so
prompt names resolve natively.
## Controller prompts
Prefer:
> Invoke skill `gitea-workflow` (alias of `llm-project-workflow`).
Do not require a name that is only available on one runtime.