03. AI-Assisted Development Workflow
Scope: AI agents and human collaborators working on PI-Desktop Status: Accepted Cross-references: 00-baseline · decisions-log · acceptance-criteria · e2e-test-plan · change-checklist · ADR index
1. Core Immutable Rules
The rules below govern every change to the PI-Desktop codebase and documentation. R1–R4 restate the five numbered Immutable Rules in AGENTS.md (R4 covers both the merge-back and worktree clean-up rules); R5 and R6 restate its GitHub issue and pull request handling sections. They cannot be relaxed by an agent without explicit human override.
R1 — Spec-first / Spec-sync
No behavior change without updating the corresponding spec.
- Every code, config, or UX change that alters observable behavior must update the relevant
docs/spec/document before or alongside the change. - Architectural boundary changes (process model, IPC contract, storage ownership, security boundary) also require an ADR — see
docs/adr/README.md. - Pure refactor that preserves behavior and API contracts does not require spec updates, but must still be committed (R2).
R2 — Commit-per-change
Every completed logical change must be git committed.
- No large uncommitted piles of work. Each logical unit of work — a feature, a fix, a spec update, a chore — gets its own commit.
- Uncommitted work at session end is a violation of this rule.
- If a change is incomplete, either commit it as a draft with a
WIP:prefix or roll it back.
R3 — E2E coverage doc
Every feature/fix that affects user-visible or protocol-visible behavior must update e2e test documentation.
- "User-visible": anything the end-user sees or interacts with (UI, CLI output, dialogs, notifications).
- "Protocol-visible": IPC messages, RPC methods, plugin API surfaces, event payloads.
- Document the scenario in
06-delivery/04-e2e-test-plan.md— even before the automated test exists. - Internal-only changes (logging format, internal variable rename) do not require e2e doc updates.
R4 — Request branch + worktree + merge gate
Every development request starts from current
origin/mainin a dedicated branch and worktree. Opening or updating a pull request requires that head to contain the latestorigin/main.
- Before editing, preserve any existing uncommitted work, fetch
origin/main, fast-forward localmainwhen its worktree is clean, and create a new request branch and worktree from that up-to-date commit. Existing work in the primary checkout must never be moved, stashed, or overwritten merely to start a new request. - Use one short-lived branch per request. Name it
<type>/<short-description>, wheretypematches the conventional change type when practical, for examplefeat/provider-importordocs/request-branch-workflow. - Use one dedicated worktree per request. Do not implement a new request in the primary checkout or reuse another request's worktree.
- Reuse the primary checkout's development environment where safe: installed toolchains, package-manager stores, build caches, and ignored local environment configuration remain the canonical environment. Reference or link those resources into the request worktree when required; do not copy environment state into tracked files. Generate other worktree-local state only when isolation or version compatibility requires it.
- Task-candidate E2E runs from the request worktree but must reuse the host dependency/runtime environment already provisioned in the primary checkout. Do not run
pnpm install,npm install, or create a second environment solely for E2E. Keep temporary profiles, data directories, sockets, ports, logs, and artifacts isolated; install or rebuild only when host dependencies are missing or incompatible, and record the reason. - Development commits and direct pushes on
mainare forbidden. - A commit request does not itself authorize remote publishing. If remote delivery has not been authorized, stop after the request-branch commit in the worktree. Do not merge the task into local
mainto create an E2E candidate. - Before opening or updating a PR/MR, fetch
origin/mainand make it an ancestor of the request head (git merge-base --is-ancestor origin/main HEAD, orpnpm check:pr-base). Refresh in the task worktree (git rebase origin/mainon a private branch; a non-destructive merge when rewriting history would be unsafe). Do not open or update a PR that is behindorigin/main. - When a push or other remote delivery is authorized, the fixed delivery order in
AGENTS.mdapplies: refresh against latestorigin/main, run task-candidate E2E in the worktree, push the request branch, open a PR/MR targetingmain, pass the required remote checks (including the PR-base gate) and reviews, and merge using a permitted strategy. Then fetch and safely synchronize localmainwith the landed change. Do not infer permission to push directly tomain, force-push, or discard unrelated local work. - Both routes retain the required validation, security, and conflict gates. Relevant E2E runs on a candidate that already contains latest
origin/main(R7). If a gate, authentication, permissions, or required review prevents integration, report the actual blocker and remaining work; the requested integration is not Done. - Worktree cleanup is mandatory and immediate. As soon as the request branch is integrated into remote
main(or the user-authorized local-only delivery is complete), remove the worktree and delete the merged branch. A merged request must not leave a worktree on disk. Remove only your own worktree and branch, and only after verifying the merge commits are present inmain. - If the user requests a launch after delivery, build and start the app from the integrated
maincheckout and its development environment.
R5 — Verify linked GitHub issues before work, then reply and close
A linked GitHub issue is not a task until the reported problem is shown to exist. After the outcome is conclusive, reply on that issue and close it.
This rule applies when the user prompt includes a GitHub issue URL or an unambiguous issue number for this repository.
- Fetch the issue (title, body, labels, comments, and state) before creating a worktree or changing files for the claimed problem.
- Independently verify the claim against the current codebase. For a bug, reproduce it or cite concrete code/spec evidence. For a feature or improvement, confirm the requested behavior is actually missing or incomplete and in scope.
- Do not start implementation until verification confirms the problem exists.
- If the problem does not exist (already fixed, invalid, or a misunderstanding): comment with the verification evidence and close the issue when that conclusion is clear. If verification is inconclusive, comment with what was tried and leave the issue open.
- If the problem exists: follow R4, implement the smallest coherent change, and after the request is merged into local
main, comment with the resolution and close the issue. - Write the GitHub comment in the language of the original issue title and body. Code, commits, specs, and other repository documentation stay English.
- An issue link authorizes commenting on and closing that issue only. It does not authorize a git push. Remote publishing remains opt-in per R4 and
AGENTS.md. - Do not comment on or close unrelated issues. Do not reopen a closed issue unless the user explicitly asks.
R6 — Land a linked pull request only when it fixes the root cause with a minimal diff
A linked GitHub pull request lands only when it actually removes the reported failure mode at the root, with the smallest coherent change. A sound direction is not enough. Completeness nits may follow after merge; an incomplete fix may not.
This rule applies when the user prompt includes a GitHub pull request URL or an unambiguous pull request number for this repository.
- Fetch the pull request (title, body, files, commits, comments, checks, draft state, base/head, and linked issues) before creating a replacement implementation or requesting a rewrite.
- Independently verify all of:
- The reported problem is real and in scope (same bar as R5).
- The change must fix the reported root cause with the smallest coherent change — not a nearby symptom, a docs-only restatement, a config contract test, or a partial workaround that leaves the original path intact.
- Extra files, refactors, and spec theater do not compensate for an incomplete fix. The approach must still be compatible with the baseline, security boundaries, and architecture (or be a justified spec-backed amendment).
- Do not reimplement the pull request as a replacement, close it for nits, or ask the contributor to start over when (1)–(3) hold.
- If (1)–(3) hold:
- Merge that pull request first, preserving the contributor's commits. Use a repository-permitted merge strategy that keeps the contributor as author of the landed work.
- Missing additional test coverage, documentation, naming cleanup, formatting, and other non-blocking polish are follow-up work only when they are not required to prove the root-cause fix. Build, typecheck, relevant existing test, required E2E, security, data-safety, protocol-compatibility, and merge-conflict failures remain landing blockers.
- Landing blockers that would break
main(the change does not compile, fails existing tests for the changed area, or has merge conflicts) may receive the smallest commits on top of the author's work so the pull request can land. Do not squash away the author. Do not rewrite the design. Do not expand the diff beyond the root-cause fix. - After the pull request is in
main, follow R4 for any follow-up improvements from the updatedmain. - Comment on the pull request in its language: acknowledge the contribution, state what was merged, and list follow-up if any.
- If (1)–(3) fail, or a harm blocker exists (secrets, sandbox or privilege bypass, malicious or clearly destructive changes, out-of-scope reversal of a frozen decision, unrelated drive-by payload): do not merge, do not approve as "direction is fine, follow up later", and comment with the evidence in the pull request's language. Prefer a minimal completion of the author's approach when that approach can actually reach the root cause. Do not silently reimplement the same idea as if the pull request never existed unless the user asks to take the work over.
- Do not merge a draft pull request the author has not marked ready, unless the user explicitly asks to merge the draft. Comment with the review and wait until it is ready.
- A pull request link authorizes reviewing, commenting on, and merging that pull request when this rule applies. It does not authorize force-pushing the contributor's branch or publishing unrelated branches. Follow-up still follows R4's opt-in remote publishing rule.
- Do not comment on or merge unrelated pull requests. An already-merged pull request is not reopened; remaining gaps become ordinary follow-up.
- When both an issue and a pull request are linked, R6 applies to the pull request and R5 still applies to the issue after the merged outcome.
R7 — Code-bearing changes require relevant E2E after main integration
Every code-bearing change must pass relevant E2E on a candidate that already contains the latest
origin/main, before its request branch is pushed or a PR/MR is opened.
This rule applies to changes that modify executable or runtime-affecting content, including apps/, packages/, crates/, runtime scripts, build or CI configuration, packaging behavior, protocol behavior, and persisted data. Documentation-only changes are exempt when they do not alter executable behavior.
E2E execution is mandatory for code-bearing changes. Task-candidate E2E runs in the request worktree after incorporating origin/main. Do not merge the task into local main to satisfy this gate. An E2E run on a branch that is behind origin/main does not satisfy R7. Select suites using the regression-surface guidance in 04-e2e-test-plan.md; build, typecheck, lint, unit tests, integration tests, manual review, and source inspection do not replace relevant E2E.
Required validation is part of the authorized integration workflow and does not require a separate user request to run tests.
If a required suite cannot run in the current environment, record the suite, reason, alternative validation, and remaining risk as NOT RUN. The branch push and PR/MR may still proceed with that record so the change can be validated in a capable environment, but the gate is not satisfied and delivery remains incomplete until the suite passes against a candidate that contains latest origin/main. A failed required suite blocks the push, the PR/MR, and declaring the change delivered until the failure is classified and fixed.
After the PR/MR merges into remote main, rerun the affected suites when the landed executable content differs from the commit the gate ran on (landing fixes, conflict resolution, or commits added during review). Otherwise the recorded result stands. Always state the commit the recorded E2E evidence applies to.
GitHub issue templates
.github/ISSUE_TEMPLATE is the only public intake path (blank_issues_enabled: false). English is the source label language; Chinese remains on the same fields.
- Bug report requires: description, reproduction steps, expected behavior, actual behavior, app version, and OS. Logs, extra environment, and screenshots are optional. Settings → Info prefills version, OS, and environment when opened from the app (D313).
- Feature request requires: problem and proposed change. Alternatives and extra context are optional.
Do not weaken these required fields. Blank issues stay disabled.
2. Development Loop
Every change follows this sequence. Steps may be iterated if the implementation reveals new requirements. If the prompt includes a GitHub issue, complete R5 verification before step 1. If the prompt includes a GitHub pull request, complete the R6 root-cause review (and merge only when the change actually fixes the problem with a minimal diff) before starting a replacement or follow-up implementation.
0. If a GitHub issue is linked: verify the claim (R5) before any implementation
0b. If a GitHub pull request is linked: review root cause and minimality (R6); merge only when it actually fixes the problem; start follow-up only after it is in `main`
1. Sync main + create a request branch and worktree
2. Read baseline + relevant specs
3. Plan change + list impacted specs and necessary validation
4. Implement
5. Update specs / ADR / decisions-log if needed
6. Update or add e2e scenarios when R3 applies
7. Run targeted local checks necessary for the change's risk
8. Commit with conventional message
9. Update BOARD if milestone-related
10. Refresh against latest `origin/main` (`pnpm check:pr-base`) and run
task-candidate E2E in the worktree (R7); when remote delivery is authorized,
push branch + open PR/MR to main only after that gate
11. Merge the PR/MR into remote `main` through the remote gates when remote
delivery is authorized, synchronize local `main`, verify, and clean up
12. If launch was requested: build and start from integrated mainStep-by-step
| Step | Action | Output |
|---|---|---|
| 0. Issue verify | When a GitHub issue is linked, fetch it and independently verify that the reported problem exists. Stop here (comment, and close only if conclusive) when it does not. | Verified issue, or a comment and close/leave-open decision. |
| 0b. PR review | When a GitHub pull request is linked, fetch it and independently verify that it fixes the reported root cause with the smallest coherent change. Merge only when it does; start follow-up only after it is in main. Stop (comment, do not rewrite) when it does not. | Merged contributor PR plus follow-up plan, or a comment and no merge. |
| 1. Branch + worktree | Preserve existing work, update from origin/main, and create a dedicated request branch in a dedicated worktree. Reuse the primary checkout's environment where safe. | Isolated task files on current main with a consistent development environment. |
| 2. Read | Read 00-baseline.md and any specs relevant to the change area. | Mental model of constraints. |
| 3. Plan | Describe the intended change. List every spec, ADR, and e2e scenario that will need updates, and assess whether local validation is necessary. | Change plan + impact and validation list. |
| 4. Implement | Write code, config, or assets. | Changed files. |
| 5. Spec-sync | Update specs per the impact list. Add ADR if architectural. Update decisions-log.md if an implementation default changes. | Updated docs/spec/* and/or docs/adr/*. |
| 6. E2E doc | When R3 applies, add or update scenario entries in 04-e2e-test-plan.md and link to acceptance criteria IDs (A–H). Otherwise, confirm no scenario update is needed. | Updated e2e test plan, or confirmed not applicable. |
| 7. Validate | Use change risk and regression scope to select the smallest useful local checks. The relevant E2E gate for a code-bearing change runs in the request worktree after origin/main is incorporated (pnpm check:pr-base) and before any branch push or PR/MR; a suite that cannot run is recorded as NOT RUN and keeps delivery incomplete. | Targeted check and E2E results, or an explicit environment limitation. |
| 8. Commit | Git commit with conventional message (see §4). | One or more commits. |
| 9. BOARD | If the change completes a milestone deliverable, update docs/project/BOARD.md. | Updated board. |
| 10. Refresh + gate | Refresh against latest origin/main, confirm it is an ancestor of HEAD (pnpm check:pr-base), then run task-candidate E2E in the worktree. When remote publishing is authorized, push the request branch and open a PR/MR targeting main only after that gate. | Verified candidate with the E2E gate result, or a recorded NOT RUN limitation; reviewable remote change or a local-only delivery route. |
| 11. Remote merge + cleanup | For authorized remote delivery, merge the PR/MR into remote main through the required gates (including the PR-base check) and synchronize local main; rerun the affected suites when the landed executable content differs from the commit the gate ran on. Verify the expected commits and remove the merged worktree and branch. | Requested integration complete, or an explicit blocker / narrower user-requested handoff. |
| 12. Launch | When requested, build and start from the integrated main checkout and its development environment. | Running app includes the delivered change. |
Local Validation and E2E Execution Policy
- Local validation is risk-based rather than an automatic prerequisite for delivery. Documentation-only changes and low-risk mechanical edits normally require no local tests or checks and proceed to the authorized delivery route under R4. No separate approval or waiver is needed to skip unnecessary checks; the required E2E gate on a candidate that already contains latest
origin/mainstill applies to code-bearing changes. - Changes with material regression risk, including security boundaries, protocol contracts, data migrations, build configuration, or widely shared behavior, normally require the smallest targeted non-E2E validation that can address that risk. A full local suite is not the default.
- E2E scenario documentation and E2E execution are separate concerns. R3 still requires scenario updates for user-visible or protocol-visible behavior.
- Every code-bearing change must run at least one relevant E2E suite on a candidate that contains latest
origin/mainbefore its branch is pushed or a PR/MR is opened, and must run the union of suites required by the affected regression surfaces. The available commands are defined by the rootpackage.jsonand the selection matrix in04-e2e-test-plan.md. - Task-candidate E2E may use the request worktree's source, but it must use the host dependency/runtime environment described in R4. Do not reinstall the repository environment for each run; only missing or incompatible host dependencies justify installation or rebuild, and that reason must be recorded. Temporary profiles, data, sockets, ports, logs, and artifacts remain isolated from the host's mutable runtime state.
- Development-time iteration remains risk-based: an E2E run on a stale request branch may be used for debugging, but only a run after incorporating
origin/mainsatisfies this policy. - If the environment cannot run a required suite, record the suite, reason, alternative validation, and remaining risk as
NOT RUN. The branch push and PR/MR may proceed with that record, but the gate is not satisfied and delivery remains incomplete until the suite passes against a candidate that contains latestorigin/main. - Required E2E jobs that the hosting platform starts before a remote merge do not replace the task-candidate gate. Observe and report their result; after the remote merge, rerun the affected suites when the landed executable content differs from the commit the gate ran on. Otherwise the recorded result stands.
Marketplace/update diagnosis gate
Plugin update incidents require an evidence-first prompt flow before code changes:
- Capture the exact plugin ID, installed version, displayed version, expected release, catalog URL, and observation time.
- Fetch the live catalog and inspect the exact entry, then inspect the local catalog cache and installed registry independently.
- Classify the failure boundary: publisher/catalog data, fetch/cache fallback, host version comparison, IPC propagation, or renderer presentation.
- Run
pnpm check:marketplace -- --url <catalog-url> --plugin <id>. Missingshasum,url, positivesizeBytes, orpermissions, or a catalogauthorthat is not a string (for example{ name, url }copied from a plugin manifest), is a release-data failure, not evidence of a stale renderer. Incomplete releases remain non-installable. - Reproduce with a fixture containing unsorted versions and incomplete metadata before changing host or renderer code.
The agent must state which boundary failed and what evidence rules out the other boundaries. A client-side fallback may preserve safe discovery, but it must not be used to conceal an invalid marketplace release.
3. Spec Update Matrix
Which change types require which doc updates.
| Change type | Spec update | ADR | Decisions-log | E2E doc | BOARD |
|---|---|---|---|---|---|
| New feature (user-visible) | Related domain spec | If architectural boundary | — | New scenario | If milestone deliverable |
| Bug fix (user-visible) | Related spec if behavior clarified | — | — | New or updated scenario | — |
| Bug fix (internal) | — | — | — | — | — |
| Refactor (behavior preserved) | — | — | — | — | — |
| Architectural change | Related specs + baseline | New ADR | Update entry if default changes | Update affected scenarios | — |
| New IPC/RPC method | 03-runtime/01-ipc-protocol.md or 06-host-rpc-protocol.md | If contract boundary | — | New protocol scenario | — |
| Plugin API addition | 07-plugins/03-plugin-api.md | If boundary change | — | New plugin scenario | If M4 deliverable |
| Security change | 05-security/01-security.md | If boundary change | Update if D001–D010 touched | New security scenario | — |
| UX change | Related 04-ux/ spec | — | — | New UI scenario | — |
| Spec-only update | The spec itself | — | — | — | — |
| Chore (deps, tooling) | — | — | If tooling decision | — | — |
| App version release / stable tag | 06-delivery/06-release-runbook.md (mandatory version-surface gate before tag: shipped-locale packages/shared/src/changelog.ts, its test list, all workspace/Cargo/APP_VERSION versions, and the release line in README.md + README.zh-CN.md) | — | If release policy changes | Confirm E2E-067B still accurate | If milestone ship |
4. Git Commit Rules
4.1 Conventional Commits
Format: type(scope): description
| Type | Use for |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation-only change |
test | Adding or updating tests |
chore | Build, deps, tooling, CI |
refactor | Code restructuring, no behavior change |
perf | Performance improvement |
build | Build system or external dependency change |
ci | CI/CD configuration change |
Scope is optional but encouraged — e.g. feat(host-core):, fix(ui):, docs(spec):.
4.2 Language
- Commit messages: English only (matches baseline language policy).
- Body: optional; use for non-obvious context.
4.3 One logical change per commit
- Prefer small, focused commits.
- Spec updates that are tightly coupled to the code change should be in the same commit.
- Pure doc changes (spec rewrite, ADR) may be a separate adjacent
docs:commit.
4.4 Never commit
- Secrets, API keys, tokens, passwords
- Local-only data (user configs, session data, logs)
node_modules/, build artifacts, release packages- Generated files that should be rebuilt per CI
4.5 Pre-commit checklist
Before committing, verify:
- Change is one logical unit (or clearly split).
- No secrets or local data in the diff.
- Specs updated per §3 matrix.
- E2E doc updated if behavior changed.
git diff --statreview — nothing unexpected.- Commit message follows conventional format.
5. Branching Model
The repository uses a mandatory request-branch and worktree workflow:
mainis always deployable and is the protected integration target. Do not develop or create development commits on it, or push it directly.- Request branches and worktrees are mandatory for every development request, including docs, chores, and small fixes. Create each branch and worktree from an up-to-date
main, then remove both immediately after the branch is merged intomain. - Branch names use
<type>/<short-description>with a lowercase, kebab-case description. Allowed type prefixes mirror §4.1. - No long-lived development branch exists. Each request gets a new branch; an old request branch must not be reused for unrelated work.
- The primary checkout owns the default development environment. Request worktrees reuse its toolchains, package-manager stores, caches, and ignored local configuration where safe. A request may create isolated local state when sharing would be unsafe or incompatible, but that state stays ignored and must not leak into commits.
- Delivery follows R4's authorization boundary and its fixed order. Commit-only delivery stops at the request-branch commit in the worktree. Authorized push/remote delivery first refreshes against latest
origin/main(pnpm check:pr-base), runs task-candidate E2E in the worktree (R7), then pushes the request branch and opens the PR/MR, merges it into remotemainthrough the PR/MR gates (including the PR-base check), and synchronizes localmain. Explicit branch-only or draft-only requests retain their narrower scope. Do not open or update a PR that is behindorigin/main.
Typical request start (run from the primary checkout; choose a path outside it):
git status --short
git fetch origin main
git worktree add -b <type>/<short-description> <worktree-path> origin/mainIf main is checked out in a clean primary worktree, git switch main plus git fetch origin main and git pull --ff-only origin main should be run before git worktree add. If local main has diverged, synchronize with git merge origin/main and resolve the divergence before starting new work without discarding commits. If the primary worktree is not clean or is on another branch, leave it untouched and create the request worktree directly from the fetched origin/main. Never discard, stash, move, or overwrite unrelated work merely to satisfy this sequence.
Environment reuse is resource-specific. Package-manager stores and language toolchains are normally shared automatically. A compatible dependency tree and Electron/Rust build targets should be referenced or linked from the primary checkout when a task needs them; do not run pnpm install or npm install merely because the request uses a separate worktree. Build outputs that can race, mutable runtime data, temporary E2E profiles, and incompatible dependency trees must remain worktree-local. Clean CI and release runners are the exception and may install from lockfiles.
Typical authorized GitHub delivery (use the hosting platform's equivalent when needed; synchronize and clean up from the clean primary checkout after merge):
# from the request worktree
git fetch origin main
git rebase origin/main # private branch; do not force-push a shared branch
pnpm check:pr-base
# run the required task-candidate E2E suites for this change (R7)
git push -u origin <type>/<short-description>
gh pr create --base main --head <type>/<short-description>
gh pr checks --watch
gh pr merge --merge
git fetch origin main
# from a clean primary checkout
git switch main
git merge --ff-only origin/main
git worktree remove <worktree-path>
git branch -d <type>/<short-description>
git worktree prune
git push origin --delete <type>/<short-description>After the remote merge, synchronize local main with a fast-forward when possible. Reset local main to origin/main only after the request commits are verified present in remote main and no local-only commits remain.
If the primary checkout cannot take that synchronization, use a short-lived worktree for main instead of disturbing unrelated work.
Do not merge the request branch into local main to create an E2E candidate or to open a PR. Local-only delivery (no remote PR/MR) stays on the request branch until the user explicitly asks to integrate it.
The worktree must be clean before removal; commit or discard the request's own leftover changes first. Use git branch -d rather than -D so an unmerged branch refuses to delete. If git worktree remove reports the worktree as dirty or locked, resolve that state instead of forcing removal, and never remove another request's worktree.
6. Definition of Done
A change is Done when all applicable conditions are true, respecting an explicit branch-only or draft-only delivery scope:
- A dedicated request branch and worktree were created from an up-to-date
main. - Code (or doc) implements the planned change.
- All impacted specs are updated.
- E2E scenarios are documented (or confirmed not needed per §3).
- Necessary targeted local validation passes; for a code-bearing change the relevant E2E gate has run on a candidate that contains latest
origin/mainbefore the branch push, the PR/MR, or a commit-only completion, or the environment limitation is recorded asNOT RUNand delivery remains incomplete until that suite passes; automatically triggered remote gates also pass, including the PR-base ancestry check. - Change is committed with a conventional message.
- BOARD is updated if a milestone deliverable completed.
- No secrets or local data are present in the commit.
- Before a PR/MR is opened or updated,
origin/mainis an ancestor of the request head (pnpm check:pr-base). When remote delivery was authorized, the PR/MR was reviewed and merged into remotemain, localmainincludes the landed change, and the affected suites were rerun when the landed executable content differs from the commit the gate ran on. - After integration, the expected commits were verified in
main, the request worktree was removed, and the merged request branch was deleted. - If a GitHub issue was linked: the claim was verified before implementation; the issue received a comment in its language; and the issue was closed when the outcome was conclusive.
- If a GitHub pull request was linked: the root-cause bar was reviewed; the pull request was merged only when it actually fixed the problem with a minimal diff; follow-up landed after merge; the contributor's work was not discarded.
- If launch was requested after delivery: the app was built and started from the integrated
maincheckout and its development environment.
Release / version-tag gate
When the change is a stable app version release (version bump + tag), Definition of Done also requires, before the tag, that every version-bearing surface describes the new version: the shipped-locale in-app changelog entries in packages/shared/src/changelog.ts (English and every shipped product locale, with aligned highlight counts) with its changelog.test.ts list, every workspace package.json (including docs/package.json), the Cargo workspace version and host-core lockfile entry, APP_VERSION, and the release line stated in README.md + README.zh-CN.md. node scripts/check-release-docs.mjs must pass; scripts/release.mjs runs it and refuses to tag otherwise. See 06-release-runbook.md §4.1, D164, and D260. GitHub release notes are not a substitute.
7. Forbidden Practices
| Practice | Why |
|---|---|
| Committing secrets | Security violation |
| Large uncommitted diffs | Violates R2; loss of granularity |
| Changing behavior without spec update | Violates R1; specs become unreliable |
| Skipping e2e doc for user-visible changes | Violates R3; traceability gap |
Declaring a code-bearing change complete without successful relevant E2E after incorporating latest origin/main | Violates R7 and leaves cross-process behavior unverified |
| Treating the full local test/check suite as an automatic pre-push requirement | Ignores risk-based validation and delays delivery without evidence of need |
Developing or creating development commits on main, or pushing it directly | Violates R4; bypasses isolation and review gates |
| Developing a new request in the primary checkout or another request's worktree | Violates R4; mixes task files and local state |
| Reusing a request branch for unrelated work | Mixes request scope and weakens traceability |
Opening or updating a PR/MR whose head is behind origin/main | Violates R4; review starts on a stale base |
| Stopping at a task-branch commit or push when the user requested remote delivery | Violates R4 unless the user explicitly limited delivery to a branch or draft |
| Leaving a merged request worktree on disk | Violates R4; stale worktrees accumulate and invite cross-request contamination |
| Modifying baseline frozen decisions without ADR + version bump | Baseline is frozen; changes need formal process |
| Committing generated artifacts that CI should rebuild | Repo bloat, merge conflicts |
| Mixing multiple logical changes in one commit without clear message | Loss of history granularity |
| Implementing a linked GitHub issue without verifying the problem exists | Violates R5; wastes work on invalid or already-fixed claims |
| Closing a linked GitHub issue without a comment in the issue language | Violates R5; leaves no public record of the outcome |
| Closing, rewriting, or requesting a restart of a linked pull request that already fixes the root cause with a minimal diff, solely for nits | Violates R6; discards the contributor's work |
| Blocking merge of a root-cause-complete linked pull request solely for missing specs, extra tests, style, or agent-workflow completeness | Violates R6; those are follow-up after merge |
| Merging a linked pull request that only has a sound direction, leaves the original failure mode, or is larger than the smallest coherent fix without a stated reason | Violates R6; direction is not enough |
| Merging a linked pull request that introduces a harm blocker | Violates R6 |
| Force-pushing a contributor's branch to land a linked pull request | Violates R6; landing fixes go on top of the author's commits |
Tagging a stable app release without updating packages/shared/src/changelog.ts for every shipped locale | Violates D164 / D345 / release runbook; in-app What's new is empty for that locale and version |
Tagging a stable app release while README.md / README.zh-CN.md still state an older release line, or bypassing scripts/check-release-docs.mjs with --skip-docs-check | Violates D260 / release runbook; published documentation advertises a version the release no longer matches |
Pushing a request branch or opening a PR/MR before the required E2E has run against a candidate that contains latest origin/main, or declaring a code-bearing change delivered without that result (except a recorded NOT RUN limitation) | Violates R7's fixed order; review would start on an unvalidated commit |
8. Acceptance Criteria for This Workflow
This workflow spec itself is accepted when:
- [ ] R1/R2/R3/R4/R5/R6/R7 are stated clearly and cross-linked to relevant specs.
- [ ] Development loop is documented and referenced by
AGENTS.md. - [ ] Spec update matrix covers all change types in the baseline.
- [ ] Git commit rules match existing repo commit style (
docs:,chore:). - [ ] Every development request is required to use a dedicated branch and worktree created from current
main. - [ ] Request worktrees reuse the primary checkout's environment where safe without committing local environment state.
- [ ] Opening or updating a PR/MR requires
origin/mainto be an ancestor of the request head (pnpm check:pr-base); a PR behindorigin/mainis rejected. - [ ] Remote publishing requires authorization and uses PR/MR gates before remote
mainintegration and local synchronization. - [ ] Refreshing against latest
origin/mainand the relevant E2E gate precede the request branch push and the pull request. Do not merge the task into localmainto create that candidate. - [ ] Worktree removal and branch deletion are required immediately after the request branch is merged into
main. - [ ] Relevant E2E execution is mandatory for code-bearing changes on a candidate that contains latest
origin/mainbefore the PR/MR is opened, without a separate test request; E2E documentation remains mandatory under R3. - [ ] Local validation is risk-based; unnecessary checks may be skipped without blocking commit, push, or PR/MR creation.
- [ ] Definition of Done is complete and actionable.
- [ ] Forbidden practices list covers known risk areas.
- [ ]
AGENTS.mdpoints to this doc,04-e2e-test-plan.md, and05-change-checklist.md. - [ ] Linked GitHub issues are verified before implementation, then commented on in the issue language and closed when conclusive.
- [ ] Linked GitHub pull requests land only when they fix the reported root cause with a minimal diff; contributor work is not discarded for nits.
- [ ] All indexes updated (NAV, delivery README, spec README, docs README, BOARD).