git:20260919.cd7d625 to git:20260919.e265ee2

58 added, 38 removed. Audit A to A.

---
name: geode-gitflow
description: Prepare GEODE worktrees, Korean PRs, CI-gated merges, and guarded cleanup. Use for repository branch, commit, PR, merge, or release work; apply only the stages the user authorized.
---
# GEODE Git & PR Workflow
Apply only the stages authorized by the current request. Review or local edits
do not authorize commit, push, merge, cleanup, reinstall, or runtime restart.
The [workflow](../../../docs/workflow.md) owns development phases;
this skill owns the GitFlow procedure. Read `AGENTS.md` for repository guardrails.
## Merge Flow
| Transaction | Base and head | Merge method |
|---|---|---|
| Feature, fix, or release preparation | fetched `origin/develop` → topic branch → `develop` | merge |
- | Canonical pre-sync | current `main` → `develop`, or the trusted sync head below | merge |
+ | Main drift | current `main` → the existing topic branch, before its PR merges | local merge commit, then fresh PR CI |
| Promotion | `develop` → `main` | merge |
Never push directly to `main` or `develop`. Promotion can batch verified
features; it does not itself authorize a tag, package publication, installation,
or service restart. `[Unreleased]` may remain on main.
+ ### Don't cases
+
+ - **Don't squash or rebase a PR.** Both discard the reviewed head's ancestry.
+ Use a merge commit for feature integration, synchronization, and promotion.
+ - **Don't open a separate `main -> develop` or `sync/*` PR.** Include missing
+ main commits in the existing feature branch before integration. CI and the
+ merge guard reject those standalone sync heads.
+ - **Don't run an old checkout's merge guard after fetching.** Fetch refreshes
+ remote refs, not local instructions or scripts. Inspect the guard in the
+ owned, current worktree; a stale `main` checkout is not the policy authority.
+ - **Don't confuse `--merge` with a method guarantee.** Older guards used that
+ flag only to authorize the write and still sent `merge_method=squash`.
+ - **Don't treat green CI or a merged PR as proof of preserved history.** Check
+ the result's ordered parents against the admitted base and head. An uncertain
+ write/readback requires inspection, not retry, cleanup, or a success claim.
+
## Worktree Allocation
Inspect `git status --short --branch`, `git worktree list`, and any `.owner`
before editing. Continue in the correct existing worktree when available;
read-only inspection does not require allocating another checkout.
For a new implementation worktree:
```bash
git fetch origin
git worktree add .claude/worktrees/<task-name> \
-b feature/<branch-name> origin/develop
```
Use the host's branch prefix when specified. Record the current session and
`task_id=<task-name>` in the gitignored `.owner` file using the available file
editor. Do not overwrite another session's ownership record, change branches
inside a worktree, or move a checkout held by another session. Fetching does
not update a checked-out local `develop`; allocate from the remote-tracking tip.
### Architecture Ledger
Ordinary tracking documents are maintained from `main`. Architecture-program
exceptions and status transitions belong to
[`extensibility-roadmap.md` §0.3](../../../docs/architecture/extensibility-roadmap.md).
Read that section only when the task participates in the program.
Implementation starts from `origin/develop` after its package-atomic claim is
merged there. It preserves `IN_PROGRESS`; no prospective `IN_DEVELOP` or `DONE`.
The roadmap-only readiness, claim, registration, reconciliation, and full-ledger
audit paths use the roadmap's own prerequisites, not an extra implementation
claim. Tracking-only `DONE` work starts from `origin/main`, targets `main`,
- carries no implementation, and is followed by a CI-gated main-to-develop sync.
+ carries no implementation; the next owned feature branch incorporates that
+ main history before integration.
Do not turn an ordinary bug or documentation fix into a new architecture program.
## Pre-PR Quality Gate
Use [verification-gates.md](../geode-workflow/references/verification-gates.md)
to select local checks by changed behavior and risk. `scripts/preflight.sh` is
the existing broad local gate runner; `--fast` skips tests and site generation.
Report skipped checks explicitly. Neither a targeted pass nor `--fast` proves
the full suite passed, and local checks never replace required remote CI.
Reuse passing evidence while the relevant code, configuration, dependencies,
and environment are unchanged. Rerun or broaden for a new change, failed check,
or unresolved concern—not merely because another workflow stage was reached.
Never hide exit codes with `gate | tail`, `gate | grep -c`, or `check; merge`.
Functional commits include their `CHANGELOG.md` entry and necessary user-facing
documentation. Documentation-only corrections need no artificial code commit
or version bump. Regenerate affected derived artifacts through their existing
generators; do not hand-edit generated snapshots. Stage only in-scope paths.
## PR Body Template
Use the single [repository PR template](../../../.github/PULL_REQUEST_TEMPLATE.md).
Write the title and body in Korean, keep titles under 70 characters, and assign
`mangowhoiscloud`. Keep `Summary`, `Why`, `Changes`, and `Verification`; fill them
from the actual diff against the fetched target branch and executed checks.
Group related files when that is clearer than repeating one sentence per file.
Add a GAP Audit table for audit-driven work. Include design choices, compatibility,
migrations, external sources, or live-test limitations only when relevant.
- Promotion PRs identify included PRs, the pre-sync result, and head-specific CI;
+ Promotion PRs identify included PRs, the main-ancestry result, and head-specific CI;
they link feature evidence instead of copying its whole report. Do not pre-check
unrun gates, fabricate counts, or attribute work to a tool/model that did not do it.
Prepare a Markdown body file with the editor and pass `--body-file <path>` to
`gh pr create`; a safely quoted heredoc is also valid. The transport is not a
quality rule—preserve the rendered body and inspect it after creation.
```bash
gh pr create --base develop --head <topic-branch> \
--assignee mangowhoiscloud --title "<type>: <한국어 설명>" \
--body-file <pr-body.md>
```
## Post-PR CI Ratchet
Before every merge, confirm the current PR head, base, mergeability, and actual
required check results. Zero attached checks, an unknown result, pending work,
or a failed/cancelled/timed-out/skipped/neutral required check is not green.
An inapplicable inner step may skip only when explicit change detection permits
it and the enclosing required check completes successfully.
```bash
gh pr checks <PR#> --watch --repo mangowhoiscloud/geode
gh pr view <PR#> --repo mangowhoiscloud/geode \
--json headRefOid,baseRefName,mergeable,statusCheckRollup
uv run python scripts/merge_pr.py --pr <PR#>
```
Run these as inspected steps, not as an unconditional command chain followed
by merge. Preserve command failures. Use a bounded watcher when waiting;
report meaningful state changes rather than polling an unchanged failure.
On failure, inspect `gh run view <run-id> --log-failed`, fix the actual cause,
verify affected behavior, push the scoped fix, and wait for the new head's CI.
Do not delete tests or suppress a security finding merely to get green.
- The read-only merge guard checks the current head and base, current PR-linked
+ The read-only merge guard requires the live repository settings
+ `allow_merge_commit=true`, `allow_squash_merge=false`, and
+ `allow_rebase_merge=false`. These [GitHub repository settings](https://docs.github.com/en/rest/repos/repos#update-a-repository)
+ also reject obsolete squash requests from other checkouts or the UI. Only an
+ authorized operator changes them; the guard never repairs server policy itself.
+
+ The guard checks the current head and base, current PR-linked
required GitHub Actions evidence (app 15368), and server protection: strict
up-to-date checks, administrator enforcement and no force-push/deletion bypass. It rejects
missing or ambiguous evidence rather than interpreting an empty list as green.
Pages Render lint and Build are required alongside CI and both install-smoke
platforms; Deploy is intentionally not a PR check. A green CI Gate alone is
insufficient when Pages fails.
Once authorized, use the same guard's explicit merge mode. It rereads the
snapshot immediately before the head-pinned REST request and verifies the
- merged PR afterward:
+ merged PR afterward, including exactly two ordered commit parents: the verified
+ base SHA, then the PR head SHA. Its receipt retains the returned merge SHA even
+ when that readback is unavailable or mismatched; do not retry an uncertain write.
```bash
uv run python scripts/merge_pr.py --pr <PR#> --merge
```
- The guard chooses merge for ordinary feature-to-develop PRs and for
- canonical main/develop synchronization, including trusted sync branches.
- For those branches, it enforces the graph-trust proof below against live remote
- tips. A refusal never permits an unguarded merge. Record its merge SHA and receipt.
+ The guard chooses merge for feature-to-develop PRs and develop-to-main promotion.
+ It requires the current main SHA to be an ancestor of the admitted PR head and
+ rechecks that SHA before the write. A refusal never permits an unguarded merge.
+ Record its merge SHA and receipt.
A changed head or base requires fresh verification. Never use
`--admin` to bypass gates or `gh pr merge --delete-branch` inside a linked
worktree: GitHub CLI may switch that checkout while deleting the local branch.
The guarded cleanup below owns branch/worktree deletion.
The server settings are a live prerequisite, not a promise made by this file.
- If protection is removed, weakened or unavailable, stop; do not downgrade the
+ If protection or merge-method policy is weakened or unavailable, stop; do not downgrade the
guard to proceed. An administrator can still change repository policy itself;
the guard rejects observed policy drift but does not claim tamper-proof hosting.
### Concurrent-session drift & CI-trigger recovery
Serialize develop merges. After another merge, fetch and inspect the actual
content, ancestry, mergeability, and CI before deciding an update is needed.
Commit-count asymmetry alone does not require rebasing every waiting worktree.
For a conflicting feature PR, merge current `origin/develop` in its owned
worktree, preserve concurrent changes, stage only resolved in-scope paths, and
rerun affected checks plus required CI on the new head. Do not rewrite another
session's branch. Only an authorized release changes version stamps; verify the
version remains available and regenerate affected metadata after resolving it.
Ordinary fixes stay under `[Unreleased]`.
If a new PR has no checks, inspect Actions availability, applicable workflow
events/path filters, and the current head's check-runs API before treating it as
a missed event. An outage is not a code failure. After confirming a missed
`pull_request` event and authorized PR operation, close/reopen once to regenerate
the event, then verify new runs attached. If checks remain absent, report the
specific blocker instead of repeating mutations or treating absence as success.
- ### Deliberate main-to-develop pre-sync
-
- Before every `develop -> main` promotion, fetch both protected branches and
- compare content and ancestry. If main has commits not in develop, use a CI-gated
- PR from the current `main` head to `develop` when mergeable under strict
- up-to-date protection. Do not put a copied or fast-forwarded main head behind
- a trusted sync prefix.
+ ### Integrate main before feature merge
- If conflicts or strict ancestry block that canonical head, create
- `sync/main-into-develop-<task>` from current `origin/develop` and explicitly merge
- current `origin/main` in an owned worktree. Its head must have exactly two
- parents, in this order: current `origin/develop`, current `origin/main`.
- Immediately before merge, fetch and rerun the trust resolver from that sync worktree:
+ Fetch before integrating a feature. Check main ancestry in its owned worktree:
```bash
- git fetch origin
- uv run python scripts/resolve_architecture_roadmap_trust.py \
- --event-mode pull_request --target-branch develop \
- --head-ref "sync/main-into-develop-<task>" \
- --head-repo mangowhoiscloud/geode --repository mangowhoiscloud/geode \
- --head-sha "$(git rev-parse HEAD)" --require-trust main
+ git merge-base --is-ancestor origin/main HEAD
```
- For a direct-main sync, use `--head-ref main` and the current canonical main SHA.
- The resolver must pass for that exact head. For a prefixed sync, the merge guard
- rechecks the same parent proof against live remote tips before its head-pinned request.
- If either tip invalidates the trust proof, reconstruct from the new tips and
- rerun CI; an earlier green is stale. Strict protection, administrator enforcement,
- and required CI success remain mandatory. After sync, promote current develop
- through a separate CI-gated merge PR.
+ Compare actual content too. If main is missing, merge `origin/main` there before
+ the feature PR is admitted; resolve conflicts without rewriting history, push
+ the synchronization commit, and wait for required CI on that new head. Also
+ incorporate current `origin/develop` when strict protection or concurrent
+ feature changes require it.
+ Do not create a separate `main -> develop` or `sync/*` PR. An ancestor-preserving
+ feature merge carries both the feature and prior main history into develop.
+ The roadmap resolver trusts only canonical main evidence already in that head;
+ the ledger validator still checks exact closure rows rather than trusting new
+ claims merely because main is an ancestor.
+
+ Before `develop -> main`, fetch and confirm main is an ancestor of develop.
+ If main moved after feature integration, return to the owned feature/update
+ branch, integrate the new tip, and pass fresh CI before promotion. Do not bypass
+ that proof or create a standalone synchronization transaction.
+
Serialize protected-branch integrations: GitHub pins the PR head, not the
- non-target main tip. A fresh parent proof does not make that final window atomic.
+ non-target main tip. Rechecking ancestry does not make the last window atomic.
## Release Flow
Only when a release is requested, create its worktree from `origin/develop`,
prepare version stamps and promote the changelog under
[`geode-changelog`](../geode-changelog/SKILL.md), then merge into develop.
- Leave a fresh `[Unreleased]` heading. Perform the canonical pre-sync above and
+ Leave a fresh `[Unreleased]` heading. Incorporate main in the release branch
+ before its feature merge, then
promote develop to main with a merge commit. Release preparation does not bypass
CI or add an automatic post-release backmerge; main-owned tracking may still
- require its own sync transaction.
+ require incorporation into the next owned feature branch.
Tags, GitHub Release, PyPI publication, and installed-version verification follow
[`geode-distribution`](../geode-distribution/SKILL.md) only when authorized.
Inspect the affected workflow's actual trigger before promising deployment;
do not infer publication from a merge SHA or static workflow description.
## Post-Merge Cleanup
After an owned feature PR merges and the checkout is no longer needed, run the
guarded command from outside the target worktree:
```bash
uv run python scripts/check_repo_hygiene.py free-merged-worktree \
--pr <feature-pr> --worktree .claude/worktrees/<task-name>
```
It verifies the merged PR and final head, replays that head onto the merge's
base to compare the resulting tree, checks local ancestry and remote head,
requires a clean checkout, and validates `.owner.task_id`. It then removes the
remote branch, worktree, and local topic branch and prunes. The owner
record's task-name check is not proof that another active session has released
the checkout; confirm current session ownership first. Use `--dry-run` when
inspection is needed. A refusal requires investigation, never manual force.
After promotion, verify fetched branch content and the actual requested CI or
deployment result. Reuse unchanged docs/test evidence; investigate drift if the
merged result differs. Update tracking only when in scope, through its owning
workflow. Report PRs, merge SHAs, verification, skipped work, and cleanup results.
## Rebuild & Restart
A merge does not authorize changing global installations or running services.
When deployment or restart is explicitly in scope:
1. Resolve the intended installation, checkout, process identity, and owner.
Inspect `core/cli/commands/lifecycle.py` before selecting the operation;
a process-name match alone does not establish ownership.
2. Stop only the confirmed in-scope process. Do not use broad `pkill -f`, stop
another session, or hide a failed stop with `|| true`.
3. Install the requested channel and extras under the distribution contract.
Editable global installation and `[audit]` are not ordinary runtime defaults.
4. Verify version, process identity, and the requested smoke result. If ownership
or restart authority is unclear, preserve the artifact and ask for direction.