feat: extract canonical work-issue workflow from monolithic skill (Closes #333)
Add workflows/work-issue.md with full author/coder gates (§0–§30), work-issue final-report schema, task-mode router entry, start-issue template link, and doc-contract tests. Part of #333 workflow split (#334 review-merge extraction remains in PR #335).
This commit is contained in:
@@ -17,6 +17,26 @@ The core promise: **an LLM never does unsafe or untracked work.** Every change
|
|||||||
is tracked by an issue, isolated in its own worktree, reviewed by a different
|
is tracked by an issue, isolated in its own worktree, reviewed by a different
|
||||||
identity, and cleaned up only after a real merge.
|
identity, and cleaned up only after a real merge.
|
||||||
|
|
||||||
|
## Task mode router (#333)
|
||||||
|
|
||||||
|
**Identify task mode before any mutation.** Load the matching workflow file and
|
||||||
|
final-report schema; do not apply rules from other modes.
|
||||||
|
|
||||||
|
| Task mode | Workflow | Final report schema |
|
||||||
|
|-----------|----------|---------------------|
|
||||||
|
| `work-issue` | [`workflows/work-issue.md`](workflows/work-issue.md) (canonical; §0–§30) | [`schemas/work-issue-final-report.md`](schemas/work-issue-final-report.md) |
|
||||||
|
| `review-merge-pr` | `workflows/review-merge-pr.md` (planned — #334) | `schemas/review-merge-final-report.md` (planned) |
|
||||||
|
| `create-issue` | `workflows/create-issue.md` (planned — #333) | `schemas/create-issue-final-report.md` (planned) |
|
||||||
|
|
||||||
|
Mode isolation:
|
||||||
|
|
||||||
|
- **work-issue** — author namespace; implement, validate, commit, PR; no approve/merge
|
||||||
|
- **review-merge-pr** — reviewer namespace only; no issue creation, no code edits
|
||||||
|
- **create-issue** — author namespace; duplicate search + `create_issue` capability; no PR review/merge
|
||||||
|
|
||||||
|
For a full work-issue run, load [`workflows/work-issue.md`](workflows/work-issue.md)
|
||||||
|
instead of relying on the §E summary below.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
@@ -225,6 +245,10 @@ Worktree folder = branch with `/` replaced by `-`
|
|||||||
|
|
||||||
## E. Start-work workflow
|
## E. Start-work workflow
|
||||||
|
|
||||||
|
**Canonical author workflow:** [`workflows/work-issue.md`](workflows/work-issue.md)
|
||||||
|
(§0–§30). The steps below are a compact summary; load the workflow file for
|
||||||
|
gates, proof wording, mutation ledger, and controller handoff schema.
|
||||||
|
|
||||||
0. Acquire or verify a work lease (Work Selection Rule) — complete all seven
|
0. Acquire or verify a work lease (Work Selection Rule) — complete all seven
|
||||||
checks before any claim, branch, or PR work.
|
checks before any claim, branch, or PR work.
|
||||||
0b. Global LLM Worktree Rule — prove project root, `cwd`, branch, main-checkout
|
0b. Global LLM Worktree Rule — prove project root, `cwd`, branch, main-checkout
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Work-issue controller handoff schema
|
||||||
|
|
||||||
|
**Task mode:** `work-issue`
|
||||||
|
|
||||||
|
End every work-issue run with a section titled exactly `Controller Handoff`.
|
||||||
|
Use this canonical field set. Do not omit fields — use `none` or
|
||||||
|
`not verified in this session` where appropriate.
|
||||||
|
|
||||||
|
Do not use legacy fields: `Workspace mutations`, `Mutations: None` (when
|
||||||
|
mutations occurred).
|
||||||
|
|
||||||
|
```md
|
||||||
|
## Controller Handoff
|
||||||
|
|
||||||
|
- Task:
|
||||||
|
- Repo:
|
||||||
|
- Role:
|
||||||
|
- Identity:
|
||||||
|
- Active profile:
|
||||||
|
- Runtime context:
|
||||||
|
- Selected issue:
|
||||||
|
- Eligibility class:
|
||||||
|
- Issue ordering policy:
|
||||||
|
- Issue inventory pagination proof:
|
||||||
|
- Earlier issues skipped:
|
||||||
|
- Duplicate active work proof:
|
||||||
|
- Claim/lock state:
|
||||||
|
- Stable branch:
|
||||||
|
- Stable branch SHA:
|
||||||
|
- Branch name:
|
||||||
|
- Worktree path:
|
||||||
|
- Worktree inside branches:
|
||||||
|
- Worktree branch/HEAD state:
|
||||||
|
- Worktree dirty before implementation:
|
||||||
|
- Files changed:
|
||||||
|
- Validation:
|
||||||
|
- Baseline comparison:
|
||||||
|
- Commit SHA:
|
||||||
|
- Push result:
|
||||||
|
- PR number:
|
||||||
|
- PR URL:
|
||||||
|
- PR verification:
|
||||||
|
- Main checkout branch:
|
||||||
|
- Main checkout dirty state:
|
||||||
|
- Main checkout used for task work:
|
||||||
|
- File edits by author:
|
||||||
|
- Worktree/index mutations:
|
||||||
|
- Git ref mutations:
|
||||||
|
- MCP/Gitea mutations:
|
||||||
|
- Issue mutations:
|
||||||
|
- Branch mutations:
|
||||||
|
- Commit mutations:
|
||||||
|
- Push mutations:
|
||||||
|
- PR mutations:
|
||||||
|
- Cleanup mutations:
|
||||||
|
- External-state mutations:
|
||||||
|
- Read-only diagnostics:
|
||||||
|
- Blockers:
|
||||||
|
- Current status:
|
||||||
|
- Safe next action:
|
||||||
|
- Safety statement:
|
||||||
|
```
|
||||||
|
|
||||||
|
Identity format: `username / profile` (not personal email unless required — #305).
|
||||||
|
|
||||||
|
Narrative final report and controller handoff must agree on eligibility class,
|
||||||
|
selected issue, and mutation ledger categories (#319, #320).
|
||||||
|
|
||||||
|
`git fetch` and ref-updating commands belong under `Git ref mutations`, not
|
||||||
|
`Read-only diagnostics` (#297).
|
||||||
|
|
||||||
|
Forbidden claims without proof (#330): `next eligible issue`, `issue claimed`,
|
||||||
|
`validation passed`, `PR created`, `worktree clean`, `all gates passed`, etc.
|
||||||
@@ -5,6 +5,9 @@ Copy, fill the `<...>` fields, and paste as the task prompt.
|
|||||||
```text
|
```text
|
||||||
Task: implement <issue title / one-line goal>.
|
Task: implement <issue title / one-line goal>.
|
||||||
|
|
||||||
|
Canonical workflow: skills/llm-project-workflow/workflows/work-issue.md
|
||||||
|
Final report schema: skills/llm-project-workflow/schemas/work-issue-final-report.md
|
||||||
|
|
||||||
Rules (llm-project-workflow):
|
Rules (llm-project-workflow):
|
||||||
- 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.
|
||||||
|
|||||||
@@ -0,0 +1,888 @@
|
|||||||
|
---
|
||||||
|
task_mode: work-issue
|
||||||
|
canonical: true
|
||||||
|
final_report_schema: ../schemas/work-issue-final-report.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Work issue workflow (canonical)
|
||||||
|
|
||||||
|
**Task mode:** `work-issue`
|
||||||
|
|
||||||
|
This file is the canonical author/coder workflow for Gitea-Tools. Load it
|
||||||
|
before any issue implementation mutation. Final report schema:
|
||||||
|
[`schemas/work-issue-final-report.md`](../schemas/work-issue-final-report.md).
|
||||||
|
|
||||||
|
**Default task prompt:**
|
||||||
|
|
||||||
|
> Find the next eligible issue in this project, work on it only if all gates
|
||||||
|
> pass, and create a PR when complete.
|
||||||
|
|
||||||
|
Do not improvise around the gates. Follow project skills, MCP gates, and
|
||||||
|
workflow rules exactly.
|
||||||
|
|
||||||
|
This is an author/coder workflow. It is not a reviewer workflow.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Load the canonical workflow first
|
||||||
|
|
||||||
|
Before starting issue work, check whether the project provides a canonical work-on-issue workflow through a project skill, runbook, or MCP helper.
|
||||||
|
|
||||||
|
If available, load it first and report:
|
||||||
|
|
||||||
|
* workflow source
|
||||||
|
* workflow version, commit, or hash
|
||||||
|
* whether this prompt conflicts with the loaded workflow
|
||||||
|
|
||||||
|
If the canonical workflow cannot be loaded and the project requires it, stop and produce a recovery handoff only.
|
||||||
|
|
||||||
|
## 1. Mode isolation
|
||||||
|
|
||||||
|
This run is `work-issue` mode only.
|
||||||
|
|
||||||
|
Do not:
|
||||||
|
|
||||||
|
* review PRs
|
||||||
|
* approve PRs
|
||||||
|
* request changes
|
||||||
|
* merge PRs
|
||||||
|
* close PRs unless the PR creation workflow explicitly does so through Gitea automation
|
||||||
|
* close unrelated issues
|
||||||
|
* mutate reviewer state
|
||||||
|
* perform reviewer-only actions
|
||||||
|
* create process-hardening issues unless explicitly authorized and the workflow switches to issue-creation mode
|
||||||
|
|
||||||
|
If the task requires review, merge, issue creation, or MCP repair mode, stop and produce a handoff for the correct workflow.
|
||||||
|
|
||||||
|
Do not mix modes in one run.
|
||||||
|
|
||||||
|
## 2. Start with live identity, profile, runtime, and capability checks
|
||||||
|
|
||||||
|
Prove:
|
||||||
|
|
||||||
|
* authenticated identity
|
||||||
|
* active author/coder profile
|
||||||
|
* repo/project
|
||||||
|
* runtime context
|
||||||
|
* exact capability for reading issues
|
||||||
|
* exact capability for claiming/locking issues, if available
|
||||||
|
* exact capability for branch creation, if handled through MCP
|
||||||
|
* exact capability for pushing branches, if applicable
|
||||||
|
* exact capability for creating PRs
|
||||||
|
* exact capability for commenting on issues or PRs, if needed
|
||||||
|
|
||||||
|
A nearby capability does not count.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* `create_issue` does not authorize `issue_comment`
|
||||||
|
* `review_pr` does not authorize `merge_pr`
|
||||||
|
* `create_pr` does not authorize `merge_pr`
|
||||||
|
* `issue_comment` does not authorize `create_issue`
|
||||||
|
* `gitea.read` does not authorize issue claim, PR creation, or branch mutation
|
||||||
|
|
||||||
|
If capability cannot be proven, stop and produce a recovery handoff only.
|
||||||
|
|
||||||
|
## 3. Stop immediately on blocked infrastructure
|
||||||
|
|
||||||
|
If any of the following appears, stop immediately:
|
||||||
|
|
||||||
|
* `infra_stop`
|
||||||
|
* MCP reconnect failure
|
||||||
|
* stale capability state
|
||||||
|
* dirty control checkout
|
||||||
|
* dirty task worktree
|
||||||
|
* missing capability
|
||||||
|
* workspace mismatch
|
||||||
|
* stale target branch state
|
||||||
|
* broken canonical workflow loading
|
||||||
|
* failed required preflight
|
||||||
|
* capability resolver warning that says the current state may be unsafe
|
||||||
|
* stale or inconsistent runtime context
|
||||||
|
|
||||||
|
Do not continue issue selection, claiming, implementation, validation, commit, push, PR creation, cleanup, or handoff mutation.
|
||||||
|
|
||||||
|
Produce an executable recovery handoff only.
|
||||||
|
|
||||||
|
Blocked recovery handoffs must not include direct commit, push, or PR replay commands.
|
||||||
|
|
||||||
|
Blocked handoffs must say to rerun the full workflow after the blocker clears.
|
||||||
|
|
||||||
|
## 4. Main checkout rule
|
||||||
|
|
||||||
|
The main project checkout must stay on `master`, `main`, or `dev`.
|
||||||
|
|
||||||
|
Do not do task work in the main checkout.
|
||||||
|
|
||||||
|
Do not edit files in the main checkout.
|
||||||
|
|
||||||
|
Do not run tests in the main checkout.
|
||||||
|
|
||||||
|
Do not commit from the main checkout.
|
||||||
|
|
||||||
|
Do not create PRs from the main checkout.
|
||||||
|
|
||||||
|
All task work must happen under the project’s `branches/` directory.
|
||||||
|
|
||||||
|
No exceptions for small fixes, docs, tests, cleanup, conflict resolution, emergencies, or “just one file.”
|
||||||
|
|
||||||
|
If the main checkout is dirty before selection, stop and produce a recovery handoff.
|
||||||
|
|
||||||
|
If the main checkout becomes dirty during the run, stop and produce a recovery handoff unless the change is explicitly allowed by the canonical workflow.
|
||||||
|
|
||||||
|
## 5. No raw MCP repair during normal issue work
|
||||||
|
|
||||||
|
Do not run `pkill`, kill MCP processes, edit MCP config, restart servers, or perform control-checkout repair during normal issue work.
|
||||||
|
|
||||||
|
If MCP repair is required, stop issue work and produce a separate `CONTROL-CHECKOUT REPAIR MODE` handoff.
|
||||||
|
|
||||||
|
Do not mix MCP repair mode with work-on-issue mode.
|
||||||
|
|
||||||
|
Do not use successful repair as permission to resume the same issue workflow. After repair, rerun the full workflow from the beginning.
|
||||||
|
|
||||||
|
## 6. No background task tools
|
||||||
|
|
||||||
|
Do not use `schedule`, `manage_task`, background jobs, async waits, delayed task tools, or monitoring tasks during issue work.
|
||||||
|
|
||||||
|
Use direct commands and MCP tools only.
|
||||||
|
|
||||||
|
If a required action cannot complete synchronously, stop and produce a recovery handoff.
|
||||||
|
|
||||||
|
Long synchronous commands, such as a test suite, are allowed only if they are run directly and reported with exact command, working directory, and result.
|
||||||
|
|
||||||
|
Do not say “I will check later,” “I will monitor,” or “I will continue in the background.”
|
||||||
|
|
||||||
|
## 7. No local Gitea fallback during normal issue work
|
||||||
|
|
||||||
|
During normal author/coder workflows, do not read Gitea profile secret files.
|
||||||
|
|
||||||
|
Do not inspect or open files such as:
|
||||||
|
|
||||||
|
* `profiles.json`
|
||||||
|
* local token stores
|
||||||
|
* credential files
|
||||||
|
* local Gitea auth/profile config files
|
||||||
|
* `.env` files containing Gitea credentials
|
||||||
|
* keychain dumps
|
||||||
|
* token helper outputs
|
||||||
|
|
||||||
|
Do not run local Gitea helper scripts when MCP tools are available.
|
||||||
|
|
||||||
|
Use MCP tools for Gitea operations.
|
||||||
|
|
||||||
|
Local fallback is allowed only in explicit recovery mode when MCP is unavailable and identity/profile/capability can be independently proven.
|
||||||
|
|
||||||
|
If local fallback is used, report:
|
||||||
|
|
||||||
|
* why MCP was unavailable
|
||||||
|
* exact identity proof
|
||||||
|
* exact profile proof
|
||||||
|
* exact repo proof
|
||||||
|
* exact capability proof
|
||||||
|
* exact local command used
|
||||||
|
|
||||||
|
Do not use local fallback to bypass MCP gates.
|
||||||
|
|
||||||
|
## 8. Build a complete live issue inventory
|
||||||
|
|
||||||
|
List open issues according to the project’s issue selection policy.
|
||||||
|
|
||||||
|
Follow pagination until the tool proves there are no more pages.
|
||||||
|
|
||||||
|
Do not assume inventory is complete.
|
||||||
|
|
||||||
|
Do not claim `next eligible issue`, `oldest eligible issue`, or complete issue inventory unless pagination is proven.
|
||||||
|
|
||||||
|
Pagination proof must not rely on assumed default API page size.
|
||||||
|
|
||||||
|
Inventory is complete only if one of the following is proven:
|
||||||
|
|
||||||
|
* the MCP response explicitly says there is no next page / `has_more=false` / final page
|
||||||
|
* the workflow traversed pages until an empty page or explicit final page was returned
|
||||||
|
* the tool response includes total-count or pagination metadata proving all relevant issues were returned
|
||||||
|
* the request explicitly set `page` / `limit` / `per_page`, and the response explicitly proves the server honored that page size and did not truncate results
|
||||||
|
|
||||||
|
Do not say “inventory complete” merely because the result count is less than an assumed default page size.
|
||||||
|
|
||||||
|
For each candidate issue, identify:
|
||||||
|
|
||||||
|
* issue number
|
||||||
|
* title
|
||||||
|
* labels
|
||||||
|
* status
|
||||||
|
* author/requester, if relevant
|
||||||
|
* assignee/owner, if any
|
||||||
|
* linked PRs, if any
|
||||||
|
* dependency/blocker labels, if any
|
||||||
|
* whether it appears already claimed
|
||||||
|
* whether it appears already implemented or superseded
|
||||||
|
* whether it is eligible under project rules
|
||||||
|
|
||||||
|
Final report must include pagination/final-page proof.
|
||||||
|
|
||||||
|
## 9. Issue selection rules
|
||||||
|
|
||||||
|
State the issue ordering policy before selecting an issue.
|
||||||
|
|
||||||
|
If the project uses oldest-first, explicitly sort or reason by issue number or created date.
|
||||||
|
|
||||||
|
Do not rely on API response order unless the tool proves that order matches the project policy.
|
||||||
|
|
||||||
|
Do not pick:
|
||||||
|
|
||||||
|
* already-claimed issues
|
||||||
|
* issues assigned to another active worker
|
||||||
|
* issues with an open PR already covering the work
|
||||||
|
* duplicate issues
|
||||||
|
* blocked issues
|
||||||
|
* dependency-blocked issues
|
||||||
|
* already implemented issues
|
||||||
|
* issues outside the current requested scope
|
||||||
|
* process-hardening issues unless this run was explicitly started for process-hardening work
|
||||||
|
* reviewer-only issues if this is author/coder mode
|
||||||
|
|
||||||
|
For every earlier issue skipped, report:
|
||||||
|
|
||||||
|
* issue number
|
||||||
|
* current status
|
||||||
|
* blocking category
|
||||||
|
* proof used
|
||||||
|
* whether there is an open PR
|
||||||
|
* whether there is an active claim
|
||||||
|
* reason it is not eligible
|
||||||
|
|
||||||
|
If eligibility cannot be proven, classify it as:
|
||||||
|
|
||||||
|
`ISSUE_ELIGIBILITY_UNVERIFIED`
|
||||||
|
|
||||||
|
Then stop or produce a recovery handoff according to project policy.
|
||||||
|
|
||||||
|
Do not select an issue based only on memory from a previous session.
|
||||||
|
|
||||||
|
## 10. Linked PR / duplicate active work proof
|
||||||
|
|
||||||
|
Before claiming or working on an issue, check whether there is already an open PR, branch, or active claim for that issue.
|
||||||
|
|
||||||
|
If an open PR already exists for the issue, do not implement duplicate work.
|
||||||
|
|
||||||
|
Classify the issue as:
|
||||||
|
|
||||||
|
`OPEN_PR_EXISTS`
|
||||||
|
|
||||||
|
and skip it only if project policy allows skipping.
|
||||||
|
|
||||||
|
If branch naming or PR title convention links issues to branches, search for matching branches or PRs.
|
||||||
|
|
||||||
|
Report:
|
||||||
|
|
||||||
|
* issue number
|
||||||
|
* linked/open PRs found
|
||||||
|
* matching branches found, if checked
|
||||||
|
* active claims found
|
||||||
|
* duplicate work status
|
||||||
|
|
||||||
|
Do not create another branch/PR for the same issue unless the project explicitly allows taking over or updating existing work and exact capability is proven.
|
||||||
|
|
||||||
|
## 11. Claim or lock the issue before implementation
|
||||||
|
|
||||||
|
Claim/lock the issue before implementation if the project provides a claim/lock mechanism.
|
||||||
|
|
||||||
|
If claim/lock requires a Gitea mutation, prove exact capability first.
|
||||||
|
|
||||||
|
If claim/lock fails, stop.
|
||||||
|
|
||||||
|
Do not implement unclaimed work.
|
||||||
|
|
||||||
|
If the claim/lock gates are broken, produce a recovery handoff.
|
||||||
|
|
||||||
|
Create a tooling issue only if this run is explicitly authorized to switch to issue-creation mode and exact `create_issue` capability is proven.
|
||||||
|
|
||||||
|
Report:
|
||||||
|
|
||||||
|
* claim mechanism used
|
||||||
|
* claim result
|
||||||
|
* claim timestamp, if available
|
||||||
|
* issue owner/assignee after claim, if available
|
||||||
|
|
||||||
|
## 12. Refresh stable branch before branch/worktree creation
|
||||||
|
|
||||||
|
Fetch the stable target branch from the remote before creating a task branch or worktree.
|
||||||
|
|
||||||
|
Do not rely on stale local `master`, `main`, or `dev`.
|
||||||
|
|
||||||
|
Record the fetched stable branch SHA.
|
||||||
|
|
||||||
|
If the stable branch cannot be fetched or verified, stop and produce a recovery handoff.
|
||||||
|
|
||||||
|
`git fetch`, `git remote update`, and any command that updates refs must be reported under `Git ref mutations`, not read-only diagnostics.
|
||||||
|
|
||||||
|
## 13. Branch and worktree ownership rule
|
||||||
|
|
||||||
|
Create a fresh session-owned worktree under `branches/`.
|
||||||
|
|
||||||
|
Prefer a branch name that includes the issue number, for example:
|
||||||
|
|
||||||
|
`feat/issue-<ISSUE_NUMBER>-short-description`
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
`fix/issue-<ISSUE_NUMBER>-short-description`
|
||||||
|
|
||||||
|
Prefer a worktree path like:
|
||||||
|
|
||||||
|
`branches/issue-<ISSUE_NUMBER>-short-description`
|
||||||
|
|
||||||
|
Before any file edits, prove:
|
||||||
|
|
||||||
|
* project root
|
||||||
|
* current working directory
|
||||||
|
* main checkout branch
|
||||||
|
* stable branch
|
||||||
|
* stable branch SHA
|
||||||
|
* task branch name
|
||||||
|
* session-owned worktree path
|
||||||
|
* worktree path is inside `branches/`
|
||||||
|
* worktree is not the main checkout
|
||||||
|
* clean tracked state
|
||||||
|
* clean untracked state
|
||||||
|
* worktree HEAD/branch state
|
||||||
|
|
||||||
|
Do not reuse an existing worktree unless safe-reuse proof passes.
|
||||||
|
|
||||||
|
Safe-reuse proof must include:
|
||||||
|
|
||||||
|
* exact worktree path
|
||||||
|
* worktree is inside `branches/`
|
||||||
|
* worktree is not the main checkout
|
||||||
|
* worktree is not owned by another active task/session
|
||||||
|
* clean tracked state
|
||||||
|
* clean untracked state
|
||||||
|
* current branch/head before reset
|
||||||
|
* reset target SHA
|
||||||
|
* explicit project policy allowing reuse/reset
|
||||||
|
|
||||||
|
Do not run `git reset --hard`, `git clean`, checkout, or other destructive commands unless the worktree is session-owned or safe-reuse proof passes.
|
||||||
|
|
||||||
|
If safe-reuse proof cannot be produced, create a fresh session-owned worktree.
|
||||||
|
|
||||||
|
## 14. Implementation scope rule
|
||||||
|
|
||||||
|
Implement only what is required for the selected issue.
|
||||||
|
|
||||||
|
Do not perform opportunistic refactors.
|
||||||
|
|
||||||
|
Do not fix unrelated tests unless they are required for the selected issue and clearly documented.
|
||||||
|
|
||||||
|
Do not modify reviewer workflow files unless the selected issue explicitly requires workflow changes.
|
||||||
|
|
||||||
|
Do not modify Gitea profiles, MCP authorization, tokens, secrets, deployment config, production config, or credentials unless the selected issue explicitly requires it and exact capability/proof gates pass.
|
||||||
|
|
||||||
|
Do not introduce provenance markers, agent signatures, temporary files, debug dumps, or generated artifacts unless required.
|
||||||
|
|
||||||
|
If implementation uncovers a separate issue, note it in the final report or create a follow-up issue only if exact capability is proven and project policy allows it.
|
||||||
|
|
||||||
|
## 15. File edit rule
|
||||||
|
|
||||||
|
All edits must happen only inside the session-owned issue worktree.
|
||||||
|
|
||||||
|
Do not edit files in the main checkout.
|
||||||
|
|
||||||
|
Do not edit files in reviewer worktrees.
|
||||||
|
|
||||||
|
Do not edit unrelated worktrees.
|
||||||
|
|
||||||
|
Track every edited, created, deleted, or generated file.
|
||||||
|
|
||||||
|
If any file is edited, created, generated, or written, report it under `File edits by author`.
|
||||||
|
|
||||||
|
For each file write, report:
|
||||||
|
|
||||||
|
* exact path
|
||||||
|
* whether it was inside the repo
|
||||||
|
* whether it was tracked or untracked
|
||||||
|
* why it was created
|
||||||
|
* whether final `git status` was run after the write
|
||||||
|
|
||||||
|
Do not say `File edits by author: none` if any file write occurred.
|
||||||
|
|
||||||
|
Do not write files after the final clean-status check unless you rerun and report a new final clean-status check.
|
||||||
|
|
||||||
|
## 16. Validation rule
|
||||||
|
|
||||||
|
Run appropriate validation for the selected issue.
|
||||||
|
|
||||||
|
Validation may include:
|
||||||
|
|
||||||
|
* targeted tests
|
||||||
|
* full test suite
|
||||||
|
* compile checks
|
||||||
|
* lint checks
|
||||||
|
* type checks
|
||||||
|
* diff checks
|
||||||
|
* secret/provenance checks
|
||||||
|
* dangerous artifact checks
|
||||||
|
* project-specific validation
|
||||||
|
|
||||||
|
If validation cannot run, explain why and include the exact failure.
|
||||||
|
|
||||||
|
Do not hide failures.
|
||||||
|
|
||||||
|
Do not claim success if tests failed.
|
||||||
|
|
||||||
|
Do not skip required validation silently.
|
||||||
|
|
||||||
|
Do not bypass MCP gates.
|
||||||
|
|
||||||
|
Report every validation command with:
|
||||||
|
|
||||||
|
* exact command
|
||||||
|
* working directory
|
||||||
|
* exit code or pass/fail result
|
||||||
|
* summary count if available
|
||||||
|
* whether it was targeted, full-suite, compile, lint, diff, secret/provenance, or diagnostic validation
|
||||||
|
|
||||||
|
If using bare `pytest`, also report:
|
||||||
|
|
||||||
|
* `which pytest`
|
||||||
|
* `pytest --version`
|
||||||
|
* whether it resolves to the project venv
|
||||||
|
|
||||||
|
Prefer the project venv executable when available.
|
||||||
|
|
||||||
|
## 17. Baseline comparison rule
|
||||||
|
|
||||||
|
Do not run tests in the main checkout.
|
||||||
|
|
||||||
|
If the full suite fails and you need to prove failures are pre-existing, create a clean baseline worktree under `branches/`, such as:
|
||||||
|
|
||||||
|
`branches/baseline-master-issue-<ISSUE_NUMBER>`
|
||||||
|
|
||||||
|
Baseline comparison must include:
|
||||||
|
|
||||||
|
* baseline worktree path
|
||||||
|
* baseline target SHA
|
||||||
|
* task branch SHA
|
||||||
|
* exact command run on both worktrees
|
||||||
|
* baseline failures
|
||||||
|
* task branch failures
|
||||||
|
* proof the failure signatures match
|
||||||
|
* proof the baseline worktree was clean before and after validation
|
||||||
|
* proof the issue worktree was clean before and after validation
|
||||||
|
|
||||||
|
Do not claim “same as master” unless the clean baseline worktree proof is included.
|
||||||
|
|
||||||
|
Do not claim “full-suite failures are pre-existing” unless baseline proof is complete and the failure signatures match.
|
||||||
|
|
||||||
|
If full-suite failures differ or proof is incomplete, do not create a PR unless project policy explicitly allows PR creation with documented validation failures.
|
||||||
|
|
||||||
|
## 18. Pre-commit review
|
||||||
|
|
||||||
|
Before committing, review the actual diff.
|
||||||
|
|
||||||
|
Check:
|
||||||
|
|
||||||
|
* correctness
|
||||||
|
* tests
|
||||||
|
* scope
|
||||||
|
* security boundaries
|
||||||
|
* workflow rule compliance
|
||||||
|
* whether the implementation really satisfies the selected issue
|
||||||
|
* unrelated changes
|
||||||
|
* dangerous generated artifacts
|
||||||
|
* secrets
|
||||||
|
* provenance markers
|
||||||
|
* temporary agent files
|
||||||
|
* debug output
|
||||||
|
* formatting-only churn
|
||||||
|
* docs/tests consistency
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
* `git status`
|
||||||
|
* `git diff --stat`
|
||||||
|
* `git diff`
|
||||||
|
* project-required diff checks
|
||||||
|
|
||||||
|
Do not commit if unrelated or unsafe changes are present.
|
||||||
|
|
||||||
|
## 19. Commit rules
|
||||||
|
|
||||||
|
Commit only from the session-owned issue worktree.
|
||||||
|
|
||||||
|
Do not commit from the main checkout.
|
||||||
|
|
||||||
|
Commit only after implementation and required validation pass, unless project policy explicitly allows draft PRs with failing validation.
|
||||||
|
|
||||||
|
Commit message must reference the issue number.
|
||||||
|
|
||||||
|
Preferred format:
|
||||||
|
|
||||||
|
`fix: short summary (Closes #<ISSUE_NUMBER>)`
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
`feat: short summary (Closes #<ISSUE_NUMBER>)`
|
||||||
|
|
||||||
|
Before commit, prove:
|
||||||
|
|
||||||
|
* worktree path
|
||||||
|
* branch name
|
||||||
|
* selected issue number
|
||||||
|
* staged files
|
||||||
|
* diff summary
|
||||||
|
* validation status
|
||||||
|
|
||||||
|
After commit, record:
|
||||||
|
|
||||||
|
* commit SHA
|
||||||
|
* commit message
|
||||||
|
* changed files
|
||||||
|
|
||||||
|
Do not amend, reset, rebase, squash, or force-push unless the project workflow explicitly allows it and the worktree is session-owned.
|
||||||
|
|
||||||
|
## 20. Push rules
|
||||||
|
|
||||||
|
Push only the session-owned task branch.
|
||||||
|
|
||||||
|
Do not push `master`, `main`, `dev`, tags, or unrelated branches.
|
||||||
|
|
||||||
|
Before push, prove:
|
||||||
|
|
||||||
|
* current branch
|
||||||
|
* upstream/remote target
|
||||||
|
* commit SHA being pushed
|
||||||
|
* selected issue number
|
||||||
|
* branch name matches the issue
|
||||||
|
|
||||||
|
After push, report:
|
||||||
|
|
||||||
|
* remote
|
||||||
|
* branch
|
||||||
|
* pushed commit SHA
|
||||||
|
* push result
|
||||||
|
|
||||||
|
If push fails, stop and produce a recovery handoff.
|
||||||
|
|
||||||
|
## 21. PR creation rules
|
||||||
|
|
||||||
|
Create a PR only if implementation and validation pass, unless project policy explicitly allows draft PRs with documented validation failures.
|
||||||
|
|
||||||
|
Do not create a PR if:
|
||||||
|
|
||||||
|
* issue was not claimed/locked
|
||||||
|
* issue eligibility was unproven
|
||||||
|
* duplicate open PR exists
|
||||||
|
* task branch does not reference the issue
|
||||||
|
* implementation is incomplete
|
||||||
|
* validation failed without allowed exception
|
||||||
|
* worktree is dirty
|
||||||
|
* secrets/provenance/dangerous artifacts are present
|
||||||
|
* capability for PR creation is missing
|
||||||
|
* runtime context is blocked
|
||||||
|
* authenticated identity/profile changed unexpectedly
|
||||||
|
|
||||||
|
PR must reference or close the issue.
|
||||||
|
|
||||||
|
PR body must include:
|
||||||
|
|
||||||
|
* summary
|
||||||
|
* linked issue
|
||||||
|
* files changed
|
||||||
|
* validation commands and results
|
||||||
|
* risk
|
||||||
|
* exact worktree path
|
||||||
|
* branch name
|
||||||
|
* commit SHA
|
||||||
|
* known limitations, if any
|
||||||
|
|
||||||
|
Do not merge your own PR.
|
||||||
|
|
||||||
|
Do not approve your own PR.
|
||||||
|
|
||||||
|
Do not request changes on your own PR.
|
||||||
|
|
||||||
|
After PR creation, fetch or view the PR to verify:
|
||||||
|
|
||||||
|
* PR number
|
||||||
|
* PR URL
|
||||||
|
* PR title
|
||||||
|
* base branch
|
||||||
|
* head branch
|
||||||
|
* linked issue
|
||||||
|
* head SHA
|
||||||
|
* open status
|
||||||
|
|
||||||
|
## 22. Cleanup rules
|
||||||
|
|
||||||
|
Clean only session-owned temporary/baseline worktrees if the project workflow explicitly allows cleanup.
|
||||||
|
|
||||||
|
Do not delete unrelated branches/worktrees.
|
||||||
|
|
||||||
|
Do not delete the task worktree if the project expects it to remain for handoff unless policy says cleanup is allowed after PR creation.
|
||||||
|
|
||||||
|
Do not update the main checkout unless the canonical workflow explicitly allows it.
|
||||||
|
|
||||||
|
Any cleanup is a mutation and must be reported.
|
||||||
|
|
||||||
|
## 23. Recovery handoff rules
|
||||||
|
|
||||||
|
If blocked, produce a recovery handoff with:
|
||||||
|
|
||||||
|
* exact blocker
|
||||||
|
* failed tool/function, if any
|
||||||
|
* repo/project
|
||||||
|
* selected issue, if one was safely selected
|
||||||
|
* eligibility class
|
||||||
|
* claim/lock state
|
||||||
|
* branch name, if created
|
||||||
|
* worktree path, if created
|
||||||
|
* stable branch and stable branch SHA, if known
|
||||||
|
* files changed, if any
|
||||||
|
* validation state
|
||||||
|
* commit SHA, if committed
|
||||||
|
* PR number/URL, if created
|
||||||
|
* exact state reached before stopping
|
||||||
|
* safe next action
|
||||||
|
* statement that no unsafe mutation was attempted
|
||||||
|
|
||||||
|
Blocked handoffs must not include direct commit, push, or PR replay commands.
|
||||||
|
|
||||||
|
Blocked handoffs must say to rerun the full workflow after the blocker clears.
|
||||||
|
|
||||||
|
## 24. Final report must be precise
|
||||||
|
|
||||||
|
Include:
|
||||||
|
|
||||||
|
* canonical workflow source/version/hash, if available
|
||||||
|
* authenticated identity/profile
|
||||||
|
* repo/project
|
||||||
|
* capability proof summary
|
||||||
|
* issue inventory proof, including pagination/final-page proof
|
||||||
|
* issue ordering policy used
|
||||||
|
* selected issue number/title
|
||||||
|
* eligibility class
|
||||||
|
* skipped earlier issues and proof, if any
|
||||||
|
* duplicate active work proof
|
||||||
|
* claim/lock result
|
||||||
|
* stable branch and stable branch SHA
|
||||||
|
* branch name
|
||||||
|
* worktree path
|
||||||
|
* worktree inside `branches/`: true/false
|
||||||
|
* worktree branch/HEAD state
|
||||||
|
* worktree dirty before implementation: true/false
|
||||||
|
* files changed
|
||||||
|
* validation commands and results
|
||||||
|
* baseline comparison result, if used
|
||||||
|
* pre-commit diff review result
|
||||||
|
* commit SHA and commit message, if committed
|
||||||
|
* push result, if pushed
|
||||||
|
* PR number and URL, if created
|
||||||
|
* PR verification result, if created
|
||||||
|
* cleanup result
|
||||||
|
* blockers, if stopped
|
||||||
|
* confirmation that the main checkout was not used for task work
|
||||||
|
|
||||||
|
If the report and actual tool/command log disagree, fix the report before final output.
|
||||||
|
|
||||||
|
## 25. Final report must distinguish mutation types
|
||||||
|
|
||||||
|
Do not use the legacy field `Workspace mutations`.
|
||||||
|
|
||||||
|
Use only precise categories:
|
||||||
|
|
||||||
|
* File edits by author:
|
||||||
|
* Worktree/index mutations:
|
||||||
|
* Git ref mutations:
|
||||||
|
* MCP/Gitea mutations:
|
||||||
|
* Issue mutations:
|
||||||
|
* Branch mutations:
|
||||||
|
* Commit mutations:
|
||||||
|
* Push mutations:
|
||||||
|
* PR mutations:
|
||||||
|
* Cleanup mutations:
|
||||||
|
* External-state mutations:
|
||||||
|
* Read-only diagnostics:
|
||||||
|
|
||||||
|
`git fetch`, `git remote update`, and any command that updates refs must be listed under `Git ref mutations`, not read-only diagnostics.
|
||||||
|
|
||||||
|
If `git reset --hard`, checkout, clean, worktree add/remove, merge simulation, merge abort, or similar commands occurred, report them under `Worktree/index mutations`.
|
||||||
|
|
||||||
|
Use precise wording:
|
||||||
|
|
||||||
|
* `File edits by author: none`
|
||||||
|
* `Worktree/index mutations: ...`
|
||||||
|
* `Git ref mutations: ...`
|
||||||
|
* `MCP/Gitea mutations: ...`
|
||||||
|
|
||||||
|
Do not collapse issue, branch, commit, push, PR, cleanup, or external-state mutations into vague wording.
|
||||||
|
|
||||||
|
## 26. Forbidden final-report claims unless proven
|
||||||
|
|
||||||
|
Do not claim:
|
||||||
|
|
||||||
|
* `next eligible issue`
|
||||||
|
* `oldest eligible issue`
|
||||||
|
* `issue claimed`
|
||||||
|
* `no duplicate work`
|
||||||
|
* `no open PR`
|
||||||
|
* `worktree clean`
|
||||||
|
* `validation passed`
|
||||||
|
* `same as master`
|
||||||
|
* `full-suite failures are pre-existing`
|
||||||
|
* `committed`
|
||||||
|
* `pushed`
|
||||||
|
* `PR created`
|
||||||
|
* `issue closed`
|
||||||
|
* `main checkout untouched`
|
||||||
|
* `no file edits`
|
||||||
|
* `no unsafe mutation`
|
||||||
|
* `all gates passed`
|
||||||
|
* `target branch up to date`
|
||||||
|
|
||||||
|
unless the corresponding proof is included.
|
||||||
|
|
||||||
|
If anything blocks safe work or PR creation, stop immediately and produce an executable recovery handoff.
|
||||||
|
|
||||||
|
Do not improvise around the gates.
|
||||||
|
|
||||||
|
## 27. Proof wording enforcement
|
||||||
|
|
||||||
|
The following phrases are forbidden unless directly supported by current-session evidence:
|
||||||
|
|
||||||
|
* next eligible issue
|
||||||
|
* oldest eligible issue
|
||||||
|
* inventory complete
|
||||||
|
* no duplicate work
|
||||||
|
* issue claimed
|
||||||
|
* worktree clean
|
||||||
|
* validation passed
|
||||||
|
* same as master
|
||||||
|
* full-suite failures are pre-existing
|
||||||
|
* committed
|
||||||
|
* pushed
|
||||||
|
* PR created
|
||||||
|
* issue closed
|
||||||
|
* target branch up to date
|
||||||
|
* all gates passed
|
||||||
|
* no unsafe mutation
|
||||||
|
* no file edits
|
||||||
|
|
||||||
|
If the proof comes from prior state rather than a command/tool run in the current session, label it as prior proof, not live proof.
|
||||||
|
|
||||||
|
If a tool call was rejected, confirmation-gated, dry-run-only, or no-op, report it separately from performed mutations.
|
||||||
|
|
||||||
|
## 28. Final self-check before output
|
||||||
|
|
||||||
|
Before final output, check the report for contradictions.
|
||||||
|
|
||||||
|
Verify:
|
||||||
|
|
||||||
|
* if any file was edited, `File edits by author` is not `none`
|
||||||
|
* if any worktree was added/removed, `Worktree/index mutations` lists it
|
||||||
|
* if any fetch happened, `Git ref mutations` lists it
|
||||||
|
* if any issue was claimed/commented/updated, `Issue mutations` lists it
|
||||||
|
* if any branch was created, `Branch mutations` lists it
|
||||||
|
* if any commit was created, `Commit mutations` lists it
|
||||||
|
* if any push occurred, `Push mutations` lists it
|
||||||
|
* if any PR was created, `PR mutations` lists it
|
||||||
|
* if any cleanup happened, `Cleanup mutations` lists it
|
||||||
|
* if any issue/PR external state changed, `External-state mutations` lists it
|
||||||
|
* if pagination is claimed complete, final-page proof is present
|
||||||
|
* if same-as-master is claimed, baseline proof is complete
|
||||||
|
* if selected issue is claimed next eligible, every earlier issue has proof-backed skip reasoning
|
||||||
|
* if PR created is claimed, PR verification proof is present
|
||||||
|
* if main checkout untouched is claimed, main checkout status proof is present
|
||||||
|
|
||||||
|
If any contradiction exists, fix the final report before output.
|
||||||
|
|
||||||
|
## 29. Controller handoff schema
|
||||||
|
|
||||||
|
End every run with a controller handoff using this schema.
|
||||||
|
|
||||||
|
Do not omit fields. Use `none` or `not verified in this session` where appropriate.
|
||||||
|
|
||||||
|
Controller Handoff:
|
||||||
|
|
||||||
|
* Task:
|
||||||
|
* Repo:
|
||||||
|
* Role:
|
||||||
|
* Identity:
|
||||||
|
* Active profile:
|
||||||
|
* Runtime context:
|
||||||
|
* Selected issue:
|
||||||
|
* Eligibility class:
|
||||||
|
* Issue ordering policy:
|
||||||
|
* Issue inventory pagination proof:
|
||||||
|
* Earlier issues skipped:
|
||||||
|
* Duplicate active work proof:
|
||||||
|
* Claim/lock state:
|
||||||
|
* Stable branch:
|
||||||
|
* Stable branch SHA:
|
||||||
|
* Branch name:
|
||||||
|
* Worktree path:
|
||||||
|
* Worktree inside branches:
|
||||||
|
* Worktree branch/HEAD state:
|
||||||
|
* Worktree dirty before implementation:
|
||||||
|
* Files changed:
|
||||||
|
* Validation:
|
||||||
|
* Baseline comparison:
|
||||||
|
* Commit SHA:
|
||||||
|
* Push result:
|
||||||
|
* PR number:
|
||||||
|
* PR URL:
|
||||||
|
* PR verification:
|
||||||
|
* Main checkout branch:
|
||||||
|
* Main checkout dirty state:
|
||||||
|
* Main checkout used for task work:
|
||||||
|
* File edits by author:
|
||||||
|
* Worktree/index mutations:
|
||||||
|
* Git ref mutations:
|
||||||
|
* MCP/Gitea mutations:
|
||||||
|
* Issue mutations:
|
||||||
|
* Branch mutations:
|
||||||
|
* Commit mutations:
|
||||||
|
* Push mutations:
|
||||||
|
* PR mutations:
|
||||||
|
* Cleanup mutations:
|
||||||
|
* External-state mutations:
|
||||||
|
* Read-only diagnostics:
|
||||||
|
* Blockers:
|
||||||
|
* Current status:
|
||||||
|
* Safe next action:
|
||||||
|
* Safety statement:
|
||||||
|
|
||||||
|
## 30. Stop conditions summary
|
||||||
|
|
||||||
|
Stop immediately and produce a recovery handoff if:
|
||||||
|
|
||||||
|
* canonical workflow is required but cannot be loaded
|
||||||
|
* identity/profile/capability cannot be proven
|
||||||
|
* runtime context is blocked
|
||||||
|
* infra stop appears
|
||||||
|
* MCP reconnect fails
|
||||||
|
* capability state is stale
|
||||||
|
* issue inventory pagination cannot be proven
|
||||||
|
* issue ordering cannot be proven
|
||||||
|
* issue eligibility cannot be proven
|
||||||
|
* duplicate active work cannot be checked
|
||||||
|
* selected issue is already claimed by another worker
|
||||||
|
* selected issue already has an open PR
|
||||||
|
* claim/lock fails
|
||||||
|
* stable branch cannot be fetched
|
||||||
|
* task worktree cannot be created safely
|
||||||
|
* task worktree is dirty before implementation
|
||||||
|
* validation cannot run
|
||||||
|
* validation fails without allowed exception
|
||||||
|
* baseline comparison is required but incomplete
|
||||||
|
* diff review finds unrelated or unsafe changes
|
||||||
|
* commit fails
|
||||||
|
* push fails
|
||||||
|
* PR creation fails
|
||||||
|
* PR verification fails
|
||||||
|
* any report contradiction cannot be resolved
|
||||||
|
|
||||||
|
Blocked handoffs must not include direct commit, push, or PR replay commands.
|
||||||
|
|
||||||
|
Blocked handoffs must say to rerun the full workflow after the blocker clears.
|
||||||
|
|
||||||
|
Do not improvise around the gates.
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
"""Doc-contract checks for task-specific LLM workflow split (#333)."""
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
SKILL_DIR = REPO_ROOT / "skills" / "llm-project-workflow"
|
||||||
|
|
||||||
|
|
||||||
|
def test_work_issue_workflow_file_exists():
|
||||||
|
path = SKILL_DIR / "workflows" / "work-issue.md"
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
assert "canonical: true" in text
|
||||||
|
assert "work-issue" in text
|
||||||
|
assert "## 0. Load the canonical workflow first" in text
|
||||||
|
assert "## 29. Controller handoff schema" in text
|
||||||
|
assert "## 30. Stop conditions summary" in text
|
||||||
|
assert "ISSUE_ELIGIBILITY_UNVERIFIED" in text
|
||||||
|
assert "OPEN_PR_EXISTS" in text
|
||||||
|
assert "author/coder workflow" in text.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def test_work_issue_final_report_schema_exists():
|
||||||
|
path = SKILL_DIR / "schemas" / "work-issue-final-report.md"
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
assert "Controller Handoff" in text
|
||||||
|
assert "Issue inventory pagination proof:" in text
|
||||||
|
assert "File edits by author:" in text
|
||||||
|
assert "Workspace mutations" in text # documented as rejected
|
||||||
|
|
||||||
|
|
||||||
|
def test_skill_router_points_to_work_issue_workflow():
|
||||||
|
skill = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8")
|
||||||
|
assert "## Task mode router" in skill
|
||||||
|
assert "workflows/work-issue.md" in skill
|
||||||
|
assert "schemas/work-issue-final-report.md" in skill
|
||||||
|
assert "Identify task mode before any mutation" in skill
|
||||||
|
|
||||||
|
|
||||||
|
def test_skill_still_declares_controller_handoff_contract():
|
||||||
|
skill = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8")
|
||||||
|
assert "## Controller Handoff" in skill
|
||||||
|
assert "assess_controller_handoff" in skill
|
||||||
|
assert "## Global LLM Worktree Rule" in skill
|
||||||
|
|
||||||
|
|
||||||
|
def test_start_issue_template_references_work_issue_workflow():
|
||||||
|
text = (SKILL_DIR / "templates" / "start-issue.md").read_text(encoding="utf-8")
|
||||||
|
assert "workflows/work-issue.md" in text
|
||||||
Reference in New Issue
Block a user