Release 2.2.0 — unified onboard strategy + safety hardening
Folds `josh-sync adopt` into `josh-sync onboard <target>` as the adopt strategy alongside the original reset flow. Strategy resolves by precedence: --mode flag > targets[].history_lock config (preserve|rewrite) > auto-detect via `git ls-remote --heads`. `josh-sync adopt` is kept as a thin alias. Adds the new `targets[].history_lock` config field (validated at parse time) and folds `<target>/adopt.json` state into `<target>/onboard.json` with a `.strategy` field; legacy state files are read with a backward-compat fallback. Safety hardening (from a multi-angle review of the unification): - auto-detect distinguishes auth/network failure from empty repo - resume validates --mode against the strategy saved in state - `josh-sync adopt` rejects a conflicting --mode in the forwarded args - missing import-PR lookup dies in both strategies (was WARN+continue for reset, which could create duplicate import PRs on resume) - --restart durably removes the legacy adopt.json from the state branch - adopt_branch is now a subshell function (EXIT trap can't clobber callers) - strategy value validated after resolve/load (reset|adopt) - --mode with missing/empty value dies with a usage hint - migrate-pr against an adopt-strategy target dies with a specific hint - reset importing asserts archived_url is present (no "null" → git clone) End-to-end + CLI bats coverage added (tests/unit/adopt_e2e.bats, tests/unit/cli.bats). 72 tests, shellcheck clean. Makefile dist bundle header now correctly interpolates VERSION and line count. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
28
CHANGELOG.md
28
CHANGELOG.md
@@ -1,5 +1,33 @@
|
||||
# Changelog
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Changes
|
||||
|
||||
- **Unified onboarding via `josh-sync onboard <target>`.** The previously separate `adopt` workflow is now an onboarding strategy alongside the original `reset` flow. Strategy is resolved by precedence: `--mode={reset,adopt}` flag → `targets[].history_lock` config (`preserve` → adopt, `rewrite` → reset) → auto-detect via `git ls-remote --heads` on the subrepo (heads → adopt, empty → reset). The chosen strategy is logged at preflight (and re-announced on every resume).
|
||||
- **`josh-sync adopt` kept as a back-compat CLI alias** for `josh-sync onboard --mode=adopt`. Existing in-flight adoptions (state at `<target>/adopt.json` on the `josh-sync-state` branch) continue to resume — `read_onboard_state` falls back to that legacy file with an implicit `strategy: adopt` and strips the legacy `.mode` field. Pre-unification `onboard.json` files (no `.strategy`) are read as `strategy: reset`.
|
||||
- **New `targets[].history_lock` config field** (`preserve` | `rewrite`) — pins the onboarding strategy independently of the subrepo's current emptiness. Validated at config parse time. See [Config Reference](docs/config-reference.md#targets-section).
|
||||
- **End-to-end bats coverage** — tree-mismatch surfacing, idempotency, merge shape (ADR-005 trailer, ADR-008 first-parent ordering), fast-forward push semantics, reverse-sync loop guard, linearize-fallback selection, resume from every checkpoint, strategy resolution precedence, legacy-state migration, and the CLI surface (flag parsing, alias forwarding, error messages).
|
||||
|
||||
### Safety
|
||||
|
||||
- **Auto-detect now distinguishes auth/network failures from genuinely empty repos.** A failing `git ls-remote` previously fell through to `reset` (destructive force-push); it now dies with a clear "pass --mode explicitly" message.
|
||||
- **Resume validates `--mode` against the strategy already saved in state.** Conflicting flags die with a `--restart` hint instead of being silently ignored.
|
||||
- **`josh-sync adopt` rejects a conflicting `--mode`.** Previously the user-supplied flag silently won.
|
||||
- **Missing import-PR lookup now `die`s in both strategies.** The reset path used to `WARN` and continue without recording the PR number, leading to duplicate import PRs on resume.
|
||||
- **`--restart` durably removes the legacy `<target>/adopt.json`** from the state branch so it can't silently resurrect via the read fallback.
|
||||
- **`adopt_branch` is now a subshell function** — its EXIT trap can no longer clobber callers' traps (test reporting, etc.).
|
||||
- **Strategy value is validated** after resolve/load (`reset|adopt`); unknown/corrupt values die with a `--restart` hint.
|
||||
- **`--mode` with a missing/empty value** dies with a usage hint instead of crashing under `set -u`.
|
||||
- **`migrate-pr` against an adopt-strategy target** dies with a specific message rather than the misleading "Run onboard first" loop.
|
||||
- **Reset import step asserts `archived_url` is present** instead of silently flowing the literal string `"null"` into `git clone`.
|
||||
|
||||
ADR-013 updated with a status note pointing at the unified command.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Makefile `dist/josh-sync` bundle header now correctly interpolates VERSION and line count (was emitting empty values due to make's `$(...)` swallowing the shell command substitution).
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
Reference in New Issue
Block a user