From acc47601278e92cdca573e06d074cdf1ec52dc71 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 3 Jul 2026 10:20:10 -0700 Subject: [PATCH 1/2] Sharpen the develop-staleness check to a direction-aware content diff (#236) Refines the develop-staleness guidance added in #233. Driving that promotion (#235) exposed that the `git log origin/develop..origin/main` form is noisy in this repo's bots-target-both model. ## Why Running `git log origin/develop..origin/main` on a clean, current `develop` returned ~50 commits - all routine promotion merges and `main`-direct dependabot/codegen commits whose content `develop` already carries via its own parallel bot PRs (even `--no-merges --cherry-pick --right-only` still lists them, since parallel bumps have different patch-ids). It cannot cheaply distinguish "develop is missing a main-only fix" from that expected topology noise. ## What changed Use a **content** diff that reflects final tree state, read directionally: - `git diff origin/main origin/develop` - hunks it would *remove* are content on `main` that `develop` lacks (real staleness); hunks it *adds* are `develop`'s normal unpromoted work. This also resolves the original Copilot objection to a plain `git diff` (that non-empty != stale): the fix is to read the diff's *direction*, not its emptiness. Verified on #235: for a clean `develop`, this diff was exactly the doc files `develop` adds - no `main`-only content - which is the correct "not stale" reading. Issue-closing keywords omitted (targets `develop`); no issue to close. Co-authored-by: Claude Opus 4.8 (1M context) --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index e6bd451..152a599 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ This is the developer-facing git policy. The branch rulesets that enforce it (me - **`develop` is forward-only**: no `main -> develop` back-merges. Historical back-merge commits in `git log` predate this rule and must not be repeated. - All commits on both branches are cryptographically signed (see Git and Commit Rules). Squash and merge commits created in the GitHub UI are signed by GitHub's web-flow key. - **Bots target both `main` and `develop` directly.** Dependabot and codegen open PRs against each branch independently. This is deliberate: running a bot on one branch and merging its changes across to the other causes endless conflicts as the feature -> develop -> main flow moves underneath it, whereas landing the same dependency or data update directly in each branch keeps bot changes conflict-free regardless of what else is in flight, and keeps the `main` package fresh without waiting on a promotion. Dependabot security PRs open against `main`. The mechanics (Dependabot's per-target-branch config, codegen's per-branch matrix) are in [`WORKFLOW.md`](./WORKFLOW.md) D8. -- **Mirror to `develop` any change that lands on `main` outside the feature -> develop -> main flow.** A reconciliation-branch fix made to resolve a `develop -> main` promotion conflict, or a security PR that merges only to `main`, leaves `develop` behind on that content - and forward-only `develop` never back-merges to catch up (the same parallel-target principle as the bots). Before basing new work on `develop`, or diagnosing a defect from it, check `git log origin/develop..origin/main`: any commits it lists are on `main` but not yet mirrored to `develop`, so `develop` is stale on that content and the defect may already be fixed on `main`. (A plain `git diff origin/develop origin/main` is not a staleness signal - it is normally non-empty because `develop` runs ahead of `main` between promotions.) +- **Mirror to `develop` any change that lands on `main` outside the feature -> develop -> main flow.** A reconciliation-branch fix made to resolve a `develop -> main` promotion conflict, or a security PR that merges only to `main`, leaves `develop` behind on that content - and forward-only `develop` never back-merges to catch up (the same parallel-target principle as the bots). Before basing new work on `develop`, or diagnosing a defect from it, compare content and not commit history: run `git diff origin/main origin/develop` and read the line prefixes: `-` lines are content that lives on `main` but not `develop` (real staleness; the defect may already be fixed on `main`), while `+` lines are just `develop`'s normal unpromoted work. Prefer this over a commit-log check like `git log origin/develop..origin/main`, which is noisy here because it also lists routine promotion merges and the `main`-direct bot commits whose content `develop` already carries via its own parallel bot PRs. - **Put issue-closing keywords (`Closes #N`) where they fire on merge to the default branch (`main`).** GitHub closes an issue from a *PR description* only when that PR merges to `main`, so a `Closes #N` in a PR that targets `develop` never fires - put it in the `develop -> main` promotion PR instead. A closing keyword in a *commit message* does close the issue once that commit reaches `main` via promotion, but that is fragile across squash-merges, so prefer the promotion PR's description or close the issue manually once the fix lands on `main`. ## Release Model From ba5bdf59cefa93ce02735bbdfe8fb49acf6954da Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 3 Jul 2026 10:31:28 -0700 Subject: [PATCH 2/2] Frame the staleness-diff -/+ lines more precisely (#238) Follow-up to #236, addressing a Copilot point raised on promotion PR #237: describing `-` lines as "real staleness" and `+` lines as "just" unpromoted work overstates what `git diff origin/main origin/develop` proves. ## Why A hunk where `develop` merely *modified* the same code shows both a `-` (main's old form) and a `+` (develop's new form) - that is normal unpromoted work, not staleness. Calling every `-` line "real staleness" is inaccurate. ## What changed Reframe `-` lines as **main-only differences to inspect** for staleness, and note that a `-`/`+` pair in one hunk is usually just `develop`'s own modification; a `-` line with **no** corresponding `develop`-side replacement is the stronger staleness signal. Targets `develop`; promotion PR #237 will carry it to `main`. Co-authored-by: Claude Opus 4.8 (1M context) --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 152a599..cd03779 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ This is the developer-facing git policy. The branch rulesets that enforce it (me - **`develop` is forward-only**: no `main -> develop` back-merges. Historical back-merge commits in `git log` predate this rule and must not be repeated. - All commits on both branches are cryptographically signed (see Git and Commit Rules). Squash and merge commits created in the GitHub UI are signed by GitHub's web-flow key. - **Bots target both `main` and `develop` directly.** Dependabot and codegen open PRs against each branch independently. This is deliberate: running a bot on one branch and merging its changes across to the other causes endless conflicts as the feature -> develop -> main flow moves underneath it, whereas landing the same dependency or data update directly in each branch keeps bot changes conflict-free regardless of what else is in flight, and keeps the `main` package fresh without waiting on a promotion. Dependabot security PRs open against `main`. The mechanics (Dependabot's per-target-branch config, codegen's per-branch matrix) are in [`WORKFLOW.md`](./WORKFLOW.md) D8. -- **Mirror to `develop` any change that lands on `main` outside the feature -> develop -> main flow.** A reconciliation-branch fix made to resolve a `develop -> main` promotion conflict, or a security PR that merges only to `main`, leaves `develop` behind on that content - and forward-only `develop` never back-merges to catch up (the same parallel-target principle as the bots). Before basing new work on `develop`, or diagnosing a defect from it, compare content and not commit history: run `git diff origin/main origin/develop` and read the line prefixes: `-` lines are content that lives on `main` but not `develop` (real staleness; the defect may already be fixed on `main`), while `+` lines are just `develop`'s normal unpromoted work. Prefer this over a commit-log check like `git log origin/develop..origin/main`, which is noisy here because it also lists routine promotion merges and the `main`-direct bot commits whose content `develop` already carries via its own parallel bot PRs. +- **Mirror to `develop` any change that lands on `main` outside the feature -> develop -> main flow.** A reconciliation-branch fix made to resolve a `develop -> main` promotion conflict, or a security PR that merges only to `main`, leaves `develop` behind on that content - and forward-only `develop` never back-merges to catch up (the same parallel-target principle as the bots). Before basing new work on `develop`, or diagnosing a defect from it, compare content and not commit history: run `git diff origin/main origin/develop` and inspect its `-` lines - the `main`-side of each difference, to check for staleness. A `-`/`+` pair within one hunk is usually just `develop` modifying that code as normal unpromoted work (occasionally `develop` reworking a `main`-side fix differently - worth a glance). The stronger staleness signal is a deletion-only hunk (`-` lines, no `+` lines): content on `main` that `develop` lacks entirely, i.e. a `main`-only fix `develop` never received, so the defect may already be fixed on `main`. Prefer this over a commit-log check like `git log origin/develop..origin/main`, which is noisy here because it also lists routine promotion merges and the `main`-direct bot commits whose content `develop` already carries via its own parallel bot PRs. - **Put issue-closing keywords (`Closes #N`) where they fire on merge to the default branch (`main`).** GitHub closes an issue from a *PR description* only when that PR merges to `main`, so a `Closes #N` in a PR that targets `develop` never fires - put it in the `develop -> main` promotion PR instead. A closing keyword in a *commit message* does close the issue once that commit reaches `main` via promotion, but that is fragile across squash-merges, so prefer the promotion PR's description or close the issue manually once the fix lands on `main`. ## Release Model