fix(space): make root-repo sync an explicit post-approval merge step - #2310
Conversation
Step 5 of PR_MERGE_POST_APPROVAL_INSTRUCTIONS claimed root-repo sync is 'handled outside the isolated worktree' — false, since the reviewer post-approval session is the only actor that runs it. The disclaim caused a reviewer to skip syncing the root repo after merging PR #2307. Replace it with an explicit 'git -C <mainRepoPath> pull --ff-only origin dev' (the banner names that path as 'Main repository' and permits writes under post-approval). Keep the worktree-safe 'git fetch origin dev'; mirror step 4's best-effort cleanup_warning handling if the ff-only fails.
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (Anthropic)
Model: glm-5.1 | Client: NeoKai | Provider: Anthropic
Recommendation: APPROVE — zero P0–P3 findings. (Own-PR: GitHub rejects APPROVE from the author, so posting as COMMENT; this is an explicit approve.)
Verdict
The fix is correct, minimal, and faithful to the task. The false claim ("Root repo synchronization is handled outside the isolated worktree") is removed and replaced with an explicit root-repo sync instruction. Step 4 (branch deletion) left untouched as required.
Verified
- Correctness of the new instruction.
git -C <mainRepoPath> pull --ff-only origin devis the right way to fast-forward the root checkout from inside the worktree.<mainRepoPath>is the path the worktree-isolation banner already surfaces (query-options-builder.ts:977→Main repository (read-only unless post-approval instructions say otherwise): ${wt.mainRepoPath}), and the banner's own clause is exactly what permits this write.mainRepoPathis typedstring(non-null) on the internal worktree type and resolves to the git root, so it is always present in the reviewer session. - Worktree-safe. Step 5a keeps
git fetch origin devand forbidsgit checkout devin the isolated worktree (a branch can't be checked out in two worktrees at once). Good. - Best-effort handling. ff-only failure → NON-result
cleanup_warningartifact + continue, mirroring step 4. Consistent. - Single source of truth. All three consumers (
built-in-workflows.ts:517Coding,:663Research,:1090Fullstack QA) reference the one constant — fixing it fixes all three. Confirmed. - Regression test is well-placed (next to the step-4 test), well-commented, asserts both the absence of the false claim and the presence of
git -C … pull --ff-only. Passes. - No test collisions. The QA-prompt
not.toContain('git pull --ff-only')atend-node-handoff.test.ts:241targets a different prompt (endNodePrompt(FULLSTACK_QA_LOOP_WORKFLOW)), and the "safe for isolated worktrees" test atbuilt-in-workflows.test.ts:6212(git fetch origin dev,do NOT \git checkout dev`, nogit checkout dev && git pull`) still holds. Both files: 348 pass / 0 fail.
Checks
./scripts/test-daemon.sh→ end-node-handoff + built-in-workflows: 348 pass, 0 fail.bun run check: lint ✅ typecheck ✅ knip ✅ session-guards ✅ db-schema-parity ✅. The one red ischeck:test-qualityflagging1-core/providers/provider-registry.test.ts:748— identical todevand untouched by this PR, so pre-existing baseline noise, out of scope here.- CI (PR matrix): 31 jobs pass; CLI/Build/E2E/Discover correctly
skipping(gated todev/workflow_dispatch); no failures. Zero review conversations to resolve.
Surgical, two-file change, no scope creep. Approving.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f7f2832be
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (Anthropic)
Model: glm-5.1 | Client: NeoKai | Provider: Anthropic
Recommendation: REQUEST_CHANGES — superseding my earlier APPROVE. Fresh round triggered by chatgpt-codex-connector's inline comments, which I verified against the code. One P1 blocks: the new step 5b cannot actually run as written, so the PR does not achieve its stated goal.
I previously approved based on the diff being faithful to the task spec and passing tests. That was incomplete — I did not verify the runtime assumption the new wording depends on (that the reviewer session receives the worktree-isolation banner). It does not. Reversing on the new evidence.
P1 — <mainRepoPath> is an unresolved literal; the worktree-isolation banner is never delivered to the post-approval session
Step 5b tells the reviewer to read mainRepoPath from "the worktree-isolation banner above." That banner is appended by QueryOptionsBuilder.getWorktreeIsolationText() only when session.worktree is set (query-options-builder.ts:932, 945). For the post-approval reviewer session it is not set:
- Space agent sessions are
type: "worker"(custom-agent.ts:690), built viaresolveAgentInit→createCustomAgentInit, which carry onlyworkspacePath, never aWorktreeMetadata. createSessionFromInit(agent-session.ts:675) returns a Session with noworktreefield;createSubSession's new-session path never sets it;task-agent-managerstores only the path string intaskWorktreePaths(line 491);createTaskWorktreereturns{ path }(line 749) without touching any session.query-lifecycle-manager.test.ts:1357+has to manually setmockContext.session.worktree = {…}to exercise the banner;archive-session.test.ts:151,226assertssession.worktreeisundefinedfor task sessions.
Net effect: the reviewer runs git -C <mainRepoPath> pull --ff-only origin dev with the literal string, the command fails, the new best-effort clause emits a cleanup_warning, and the root repo stays stale — the exact regression this PR claims to fix. The regression test only checks the string git -C .*pull --ff-only is present, so it passes while the behavior is still broken.
Fix (stays in this one file — no token/banner plumbing): derive the root path from git instead of referencing an absent banner:
ROOT=$(cd "$(git rev-parse --git-common-dir)/.." && pwd)
git -C "$ROOT" pull --ff-only origin dev
--git-common-dir inside a worktree resolves to the main repo's .git, so its parent is the root checkout. (Larger alternative: thread mainRepoPath as a real {{main_repo_path}} token through PostApprovalRouter + interpolatePostApprovalTemplate.) Detailed verification + fix posted as an inline reply on line 211.
P2 — guard the pull against a non-dev root branch (bot comment #2)
git -C "$ROOT" pull --ff-only origin dev merges origin/dev into whatever branch the root checkout is currently on, not necessarily dev. --ff-only only aborts on non-fast-forward; if the checked-out branch is an ancestor of origin/dev, it silently fast-forwards the wrong branch to the dev tip. Cheap mitigation while reworking 5b: confirm git -C "$ROOT" rev-parse --abbrev-ref HEAD is dev first; otherwise record a cleanup_warning and skip.
P2 — run the root sync on the "already merged" early-exit path (bot comment #3)
Step 1 exits early when state === MERGED ("record an audit artifact and exit — the work is done"). If the reviewer/daemon restarts after a successful merge, the resumed session starts at step 1, sees MERGED, and exits — never reaching step 5, so the root is left stale in precisely the restart window where post-approval is meant to be idempotent. The merged-exit branch should still perform the root sync (5b) before completing.
P2 — treat a root dev that is ahead of origin/dev as a warning, not success (bot comment #4)
If the root dev has unpushed local commits ahead of origin/dev, pull --ff-only reports "Already up to date" and leaves those commits at HEAD; step 5 reports success while the root tip differs from origin/dev. If later task worktrees branch from the root's HEAD, they inherit those commits. Cheap mitigation: after git fetch origin dev, compare git -C "$ROOT" rev-parse dev with origin/dev; on an ahead-only state, record a cleanup_warning rather than claiming sync.
The P1 is the blocker. P2s are cheap and touch the same step, so worth folding in while reworking 5b. The single-constant fix covering Coding/Research/QA and the worktree-safe git fetch origin dev in 5a remain correct and should be kept.
Round-1 step 5 referenced the worktree-isolation banner and a literal
<mainRepoPath> to name the root path — both broken for the post-approval
reviewer session, which has no session.worktree (worker sub-session via
createCustomAgentInit), so QueryOptionsBuilder never appends the banner and
<mainRepoPath> is not an interpolation token. The reviewer would run it
verbatim, fail, and leave the root stale — the exact regression intended.
Derive the root from git instead: ROOT from the worktree's shared common
dir parent. Add guards: refuse a root not on dev (pull --ff-only moves the
current branch), refuse to claim sync when local dev is ahead of origin/dev
('Already up to date' hides stray commits), keep best-effort cleanup_warning
on pull failure. Also run the sync on step 1's already-merged path so a
restart after merge still syncs the root.
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (Anthropic)
Model: glm-5.1 | Client: NeoKai | Provider: Anthropic
Recommendation: APPROVE — zero P0–P3 findings. (Own-PR: GitHub rejects APPROVE from the author, so posting as COMMENT; this is an explicit approve of commit 16c86e5.)
Round 2 (fresh): all four round-1 findings addressed correctly and verified.
P1 (was the blocker) — resolved & empirically verified
Step 5b no longer references the absent worktree-isolation banner or the literal <mainRepoPath>. The root path is derived from git: ROOT=$(cd "$(git rev-parse --git-common-dir)/.." && pwd). I ran this in the actual worktree — --git-common-dir resolves to /Users/lsm/focus/dev-neokai/.git, so the parent is the correct main repo /Users/lsm/focus/dev-neokai; it also resolves correctly when cwd is the main repo itself. The new wording even explains why the banner is absent ("the post-approval session receives NO worktree-isolation banner (it has no session.worktree)"), which will stop the assumption recurring. The strengthened regression test now asserts <mainRepoPath> is absent and git rev-parse --git-common-dir is present — round-1's test only checked the command string and gave false confidence; this one would catch a regression to that approach.
P2s — all folded into the same step, correct
- Non-dev root guard: checks
git -C "$ROOT" rev-parse --abbrev-ref HEAD == devbefore pulling; otherwise a NON-resultcleanup_warningand skip. Correct —pull --ff-only origin devfast-forwards the checked-out branch, notdevby name. - Already-merged path runs the sync: step 1 no longer exits immediately on
state === MERGED— it records an audit artifact, performs step 5 only, then exits (and skips the step-6 merge artifact since no merge happened this session). Closes the restart-after-merge idempotency gap. - Ahead-of-origin guard: after the ff-only pull, compares
rev-parse HEADvsrev-parse origin/dev; they differ only when localdevis ahead (the "Already up to date" case hiding stray commits) → NON-resultcleanup_warning. Logic is sound: a successful fast-forward makes HEAD == origin/dev, so the warning fires precisely in the intended case.
Checks
end-node-handoff+built-in-workflows: 348 pass, 0 fail (1541 expects); strengthened regression test passes (6 expects).bun run lint,typecheck,knip,check:session-guards,check:db-schema-parity: all clean. (The unrelated pre-existingcheck:test-qualitynoise in1-core/providers/provider-registry.test.tsis identical todevand out of scope.)- All 5 review conversations resolved; CI on 16c86e5 green (applicable jobs pass; CLI/Build/E2E/Discover correctly skipping on a PR).
Clean fix to a genuine integration defect. Approving.
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (Anthropic)
Model: glm-5.1 | Client: NeoKai | Provider: Anthropic
Recommendation: REQUEST_CHANGES — supersedes the round-2 APPROVE. New finding raised by the operator: the template hardcodes dev, which is HyperNeo-specific. As a product built-in that runs against arbitrary user repos, it must be branch-agnostic.
P1 — Template hardcodes dev throughout; derive the base branch from the PR
dev is this project'"'"'s convention (CLAUDE.md: "All PRs target dev"), but PR_MERGE_POST_APPROVAL_INSTRUCTIONS ships as a built-in for any repo. Every literal dev / origin/dev breaks on a main-based (or any non-dev) repo — step 3'"'"'s git fetch origin dev would fetch a non-existent branch, the merge-tree/rebase targets would be wrong, and step 5 would refuse to pull. The PR'"'"'s own base ref is the correct, repo-agnostic target.
Plan (operator-approved scope: whole template, derive from the PR):
-
Extract the base branch once, up front (fold into step 1'"'"'s existing
gh pr view, or a dedicated preamble line):BASE=$(gh pr view {{pr_url}} --json baseRefName --jq .baseRefName)Use
baseRefName(the branch the PR merges INTO), NOTdefaultBranchRef— you fast-forward the branch the PR was merged into, which can differ from the repo default (e.g. a PR targeting a release branch). -
Replace every literal
dev/origin/devin steps 3–5 with$BASE/origin/$BASE. Functional occurrences (current line numbers):- Step 3: L85
origin/dev(prose), L88git fetch origin dev, L89git merge-tree … origin/dev, L96 & L122base_branch: "dev"(conflict artifacts), L125origin/dev(rebase target). - Step 4: L206
Do NOT delete \dev`→Do NOT delete `$BASE``. - Step 5: L210
git checkout dev, L212git fetch origin dev, L218pull --ff-only origin dev, L219 rootnot on \dev`, L220local `dev` ahead of `origin/dev`, L223 guard!= "dev", L225root not on dev, L227fetch origin dev, L228pull --ff-only origin dev, L229rev-parse origin/dev, L230 & L232dev ahead of origin/dev`.
- Step 3: L85
-
Genericize the prose for consistency: file-header L38 ("conflict with the base branch (
dev)"), and step-5 intro L64 / L207 / L209 ("track the freshly-mergeddev", "inherits olddev") — refer to "the base branch ($BASE)" instead. -
Update the tests that pin
dev-specific strings (they will break):end-node-handoff.test.ts:518toContain('base_branch: "dev"'),:534toContain('origin/dev').built-in-workflows.test.ts:6213toContain('git fetch origin dev'),:6214toContain('do NOT \git checkout dev`')`.- The round-2 regression test'"'"'s
root dev ahead of origin/devassertion (end-node-handoff ~L401) → the$BASEform. - Add a branch-agnostic guard so it can'"'"'t regress:
expect(...).not.toMatch(/origin\/dev\b/)andexpect(...).toContain('--jq .baseRefName'). - Unaffected / leave as-is:
built-in-workflows.test.ts:968(assertsPLAN_AND_DECOMPOSE_WORKFLOW.description— a different workflow, not this template) and the QA-promptnot.toContain('git checkout dev')atend-node-handoff.test.ts:242(negative assertion on a different prompt).
Keep as-is: step 5b'"'"s git rev-parse --git-common-dir root derivation (already branch-independent), the non-dev / ahead-of-origin guards, the already-merged→step-5-only routing, and the best-effort cleanup_warning handling — all of those remain correct once dev→$BASE.
Net: one preamble line + a mechanical dev→$BASE sweep across steps 3–5 + test updates. The round-2 root-derivation fix is preserved.
These are product built-ins (Coding/Research/QA) that run against arbitrary
user repos, but the merge template hard-coded `dev` everywhere — breaking any
repo whose base branch is main/master or a release branch.
Derive the base up front from the PR's baseRefName (the branch it merges INTO,
which can differ from the repo default, e.g. a release branch):
BASE=$(gh pr view {{pr_url}} --json baseRefName --jq .baseRefName)
and sweep every literal dev/origin/dev in steps 3–5 to $BASE/origin/$BASE
(fetch, merge-tree, base_branch artifacts, rebase target, root sync, guards).
Round-2 work preserved: git-derived root path, non-base + ahead-of-origin
guards, already-merged→step-5 routing, best-effort cleanup_warning. Updated
the dev-pinning tests and added a branch-agnostic guard (baseRefName present,
no origin/dev).
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (Anthropic)
Model: glm-5.1 | Client: NeoKai | Provider: Anthropic
Recommendation: APPROVE — zero P0–P3 findings. (Own-PR: GitHub rejects APPROVE from the author, so posting as COMMENT; explicit approve of commit d402209.)
Round 4 (fresh): the branch-agnosticism concern is fully resolved and verified.
Verified
- Base branch derived from the PR, not hard-coded.
BASE=$(gh pr view {{pr_url}} --json baseRefName --jq .baseRefName)is extracted in step 1 (line 61), before its first use in step 3 (line 89), with clear prose notingbaseRefName(the branch the PR merges INTO) is used over the repo default — correct for release-branch PRs. Sweep is complete: zero functionalorigin/dev; the onlydevleft is line 64'"'"'s intentional example list (dev/main/master/...) explaining why the built-in must be repo-agnostic. $BASEsubstitutions are correct and quoted, including the step-5 guard!= "$BASE"and the ahead-checkrev-parse "origin/$BASE". Logic preserved end-to-end across steps 3 (fetch / merge-tree / bothbase_branchartifacts / rebase target), 4 (Do NOT delete \$BASE`), and 5. The non-base guard correctly refuses to fast-forward when the root sits on a different branch (e.g. a release-branch PR with a root onmain`) — defensive, not a bug.- Round-2 work intact: git-derived root path (
git rev-parse --git-common-dir), non-base + ahead-of-origin guards, already-merged→step-5-only routing, best-effortcleanup_warninghandling — all still correct under$BASE. - Regression lock present:
end-node-handoff.test.ts:412asserts--jq .baseRefName;:413assertsnot /origin\/dev\b/. So a future edit can'"'"'t silently re-introduce a hard-coded branch.
Checks
end-node-handoff+built-in-workflows: 349 pass, 0 fail (1544 expects).bun run lint,typecheck,knip,check:session-deletion-callers,check:db-schema-parity: all clean.- Review threads: 5/5 resolved, 0 unresolved.
- CI on d402209: 17 pass, 12 pending, 0 fail (in-flight — the slower integration shards). The merge template self-gates on CI at step 1 (
gh pr checksbefore merge), so the PR cannot merge until CI is green regardless of approval timing.
Optional polish (not a finding)
The PR description still narrates the round-2 wording ("guards for a root not on dev, a local dev ahead of origin/dev"). The code is correct; only the description text is stale. Feel free to refresh it to baseRefName/$BASE for accuracy — no blocker.
Clean, repo-agnostic built-in. Approving.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d402209c5d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Round 2 derived the sync path from `git rev-parse --git-common-dir`, but that
resolves to the shared main-repo .git — whose parent is a DIFFERENT checkout
when the Space workspace is itself a linked worktree. createTaskWorktree bases
future task worktrees on the workspace's HEAD (`git worktree add … HEAD` with
cwd=space.workspacePath), so inferring the main repo leaves the actual branching
base stale.
The configured workspace path is already threaded into the post-approval context
as {{workspace_path}} (= space.workspacePath). Use it directly:
SPACE_WS="{{workspace_path}}"
and fast-forward THAT checkout (with the existing $BASE / ahead-of-origin /
pull-failure guards). Renames $ROOT → $SPACE_WS to reflect that it is the
Space checkout, not the repo root. No new token plumbing needed.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 971625b532
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ayloads
Two round-5 P2s on the merge template:
1. Shell-quote the interpolated workspace path. The interpolator renders values
verbatim, so SPACE_WS="{{workspace_path}}" (double quotes) would expand $/backtick/
$() in a workspace path. Single-quote it: SPACE_WS='{{workspace_path}}'.
2. $BASE is a shell variable, but step 3's base_branch fields live inside send_message /
save_artifact (MCP/JSON, not shell), so "$BASE" there would be sent literally and
the coder would be told to rebase onto literal origin/$BASE. Use the resolved-value
placeholder <base branch> in those tool-call fields (and the coder message body), and
clarify in step 1 that tool-call payloads take the actual value, not the variable.
Added negative regression guards for both. Shell-command uses of $BASE (git fetch/pull,
the guard) are unchanged.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a81043548b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Each Bash tool call runs in a fresh shell, so the $BASE assigned in step 1 does not persist — step 3a's conflict inspection (git fetch origin "$BASE") and step 5's sync/guard would receive an empty value, breaking conflict inspection and leaving the Space checkout stale after a successful merge. Re-derive BASE at the top of each dependent command block (3a, 5a, 5b) — the gh pr view baseRefName call is idempotent — and note the statelessness next to the step-1 definition.
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (GLM)
Model: glm-5.1 | Client: NeoKai | Provider: GLM
Recommendation: APPROVE (posted as COMMENT — GitHub blocks self-APPROVE because the round-5 commits below were authored by this same reviewer account during the prior post-approval session.)
Round 5 re-review — APPROVE for merge. The branch advanced three commits (971625b5, a8104354, 3d65b631f) past the round-4 approval at d402209c5, so those needed a fresh sign-off before merge. Independently verified each against the codebase:
{{workspace_path}}is a real token —POST_APPROVAL_TEMPLATE_KEYSlists it (post-approval-template.ts:59), populated fromspace.workspacePathatspace-runtime.ts:4232. Renders verbatim via the interpolator.- Syncing the Space checkout (not the git-inferred root) is correct —
createTaskWorktreerunsgit worktree add … HEADwithcwd: space.workspacePath(space-worktree-manager.ts:144-146), so future task worktrees branch from the workspace's HEAD.git rev-parse --git-common-dirwould resolve to the main-repo.gitwhose parent is a different checkout when the workspace is a linked worktree — round-5a's switch to the supplied path is the right fix. - For this Space,
workspacePath == /Users/lsm/focus/dev-neokai(the main repo) — so step 5b syncs exactly the path the original "root repo stale" bug was about, and is product-correct for the linked-worktree case. - Shell correctness —
SPACE_WS='{{workspace_path}}'single-quoted (no re-expansion);$BASEre-derived per Bash block (fresh shell per call);<base branch>placeholder used in tool-call payloads where$BASEwould be sent literally.
Verification: end-node-handoff.test.ts 50/0 pass; lint + typecheck + knip + session-guards + db-schema-parity all clean; CI green on 3d65b631f (all PR checks pass). PR diff is correctly scoped to 3 files (+109/−20: template + two test files); step 4 untouched. The lone check:test-quality failure is pre-existing on dev (provider-registry.test.ts, untouched by this PR) — out of scope.
Non-blocking nit (P3): step 1's MERGED early-exit still glosses "fast-forward the root repository" while step 5 authoritatively syncs the "Space checkout." For this Space they're the same path and step 1 defers to "perform step 5 ONLY," so behavior is unaffected; the wording can be reconciled later.
Proceeding to squash-merge.
Step 5 of
PR_MERGE_POST_APPROVAL_INSTRUCTIONSclaimed root-repo sync was "handled outside the isolated worktree" — false, since the reviewer post-approval session is the only actor that runs it. The disclaim caused a reviewer to skip syncing after merging PR #2307, leaving the checkout stale.The final step 5 (after four review rounds):
baseRefName($BASE), not a hard-codeddev, so these product built-ins work against any base branch.{{workspace_path}}token (=space.workspacePath, whatcreateTaskWorktreebranches future task worktrees from viagit worktree add … HEAD). Earlier rounds tried the worktree-isolation banner (absent — nosession.worktree), a literal<mainRepoPath>(not an interpolation token), andgit rev-parse --git-common-dir(resolves to the shared main-repo.git, a different checkout when the workspace is a linked worktree); all incorrect.$BASE, refuses to claim sync when local$BASEis ahead oforigin/$BASE("Already up to date" hides stray commits), and best-effortcleanup_warningon pull failure.Fixes all three consumers (Coding / Research / QA) via the shared constant, plus strengthened regression tests.