|
| 1 | +--- |
| 2 | +title: Hard-correct next-tag-only surfaces before stable release |
| 3 | +date: 2026-06-25 |
| 4 | +category: conventions |
| 5 | +module: Release compatibility |
| 6 | +problem_type: convention |
| 7 | +component: development_workflow |
| 8 | +severity: medium |
| 9 | +applies_when: |
| 10 | + - Removing or renaming a config value, wire field, CLI flag, or public API surface |
| 11 | + - Deciding whether a shipped-looking surface needs backward compatibility |
| 12 | +tags: [release-channel, compatibility, deprecation, config-schema] |
| 13 | +--- |
| 14 | + |
| 15 | +# Hard-correct next-tag-only surfaces before stable release |
| 16 | + |
| 17 | +## Context |
| 18 | + |
| 19 | +AgentV briefly exposed `results.sync.push_conflict_policy: backup_and_force_push` |
| 20 | +on the npm `next` tag while replacing force-push results sync with a no-force |
| 21 | +merge loop. Treating that as a stable shipped surface would have kept a |
| 22 | +misleading compatibility alias around even though the value contradicted the new |
| 23 | +product invariant: AgentV never force-pushes result branches. |
| 24 | + |
| 25 | +## Guidance |
| 26 | + |
| 27 | +When checking whether a config value or public surface has shipped, distinguish |
| 28 | +release channels: |
| 29 | + |
| 30 | +- Stable npm releases require normal compatibility handling: preserve behavior, |
| 31 | + soft-deprecate, or provide an explicit migration path. |
| 32 | +- `next`-only releases can be hard-corrected before the surface reaches stable, |
| 33 | + especially when preserving the surface would encode a dangerous or misleading |
| 34 | + contract. |
| 35 | + |
| 36 | +For removed config values, make the correction explicit: |
| 37 | + |
| 38 | +```yaml |
| 39 | +results: |
| 40 | + sync: |
| 41 | + # Remove unsupported aliases and use the stable default. |
| 42 | + push_conflict_policy: block |
| 43 | +``` |
| 44 | +
|
| 45 | +If existing local registries or generated config may contain the removed value, |
| 46 | +either reject it with migration guidance or drop it during a registry migration |
| 47 | +that rewrites the supported shape on the next save. |
| 48 | +
|
| 49 | +## Why This Matters |
| 50 | +
|
| 51 | +Pre-release tags are useful for discovering wrong API names and unsafe contracts. |
| 52 | +If every `next` exposure becomes permanent compatibility debt, the project loses |
| 53 | +the ability to correct those mistakes before stable release. The compatibility |
| 54 | +bar should protect stable users without forcing unsafe pre-release names into |
| 55 | +the long-term schema. |
| 56 | + |
| 57 | +## When to Apply |
| 58 | + |
| 59 | +- A value, flag, or field appeared only on npm `next` or another prerelease |
| 60 | + channel. |
| 61 | +- The replacement behavior is already stable and safer. |
| 62 | +- Keeping the old surface would confuse users about current behavior or |
| 63 | + preserve a hazardous name. |
| 64 | + |
| 65 | +## Examples |
| 66 | + |
| 67 | +`backup_and_force_push` should not remain a supported |
| 68 | +`results.sync.push_conflict_policy` value after the force-push implementation is |
| 69 | +removed. Even though it appeared on a published `next` tarball, the stable |
| 70 | +migration is to remove the field or set it to `block`; AgentV's actual behavior |
| 71 | +is a no-force-push merge loop. |
| 72 | + |
| 73 | +## Related |
| 74 | + |
| 75 | +- docs/adr/2026-06-24-no-force-push-results-sync.md |
0 commit comments