diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a52336e..e309c9fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: cow-changed-preflight: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -49,7 +49,7 @@ jobs: needs: cow-changed-preflight runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install toolchain run: | @@ -80,7 +80,7 @@ jobs: run: make test-cow-fast - name: Cache runtime build - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .build key: >- @@ -132,7 +132,7 @@ jobs: target: x86_64-apple-darwin runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: @@ -159,7 +159,7 @@ jobs: run: make test-cow-fast - name: Cache runtime build - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .build key: >- @@ -187,7 +187,7 @@ jobs: needs: cow-changed-preflight runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/release-prepare.yml b/.github/workflows/release-prepare.yml index 55510b13..ff335b49 100644 --- a/.github/workflows/release-prepare.yml +++ b/.github/workflows/release-prepare.yml @@ -25,7 +25,7 @@ jobs: if: env.RELEASE_PREPARE_TOKEN_PRESENT == 'true' run: gh api "repos/${GITHUB_REPOSITORY}" --jq .full_name >/dev/null - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: trunk fetch-depth: 0 diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 4c7fa312..2be2cb74 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -64,7 +64,7 @@ jobs: printf 'ref=%s\n' "$MERGE_COMMIT_SHA" >> "$GITHUB_OUTPUT" fi - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ steps.requested_ref.outputs.ref }} fetch-depth: 0 @@ -135,7 +135,7 @@ jobs: WINDOWS_CODESIGN_CERT_BASE64: ${{ secrets.WINDOWS_CODESIGN_CERT_BASE64 }} WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.preflight.outputs.checkout_ref }} @@ -166,7 +166,7 @@ jobs: # and the PHP/lib compilation when inputs haven't changed. Cache key # includes every input that affects the produced binaries. - name: Cache .build - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .build key: >- @@ -312,7 +312,7 @@ jobs: Dismount-DiskImage -ImagePath $vhdPath -ErrorAction SilentlyContinue | Out-Null } - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: forkpress-${{ matrix.target }} path: | @@ -333,7 +333,7 @@ jobs: env: HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.preflight.outputs.checkout_ref }} fetch-depth: 0 @@ -346,7 +346,7 @@ jobs: exit 1 fi - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v8 with: pattern: forkpress-* merge-multiple: true @@ -382,7 +382,7 @@ jobs: exit 1 fi - - uses: softprops/action-gh-release@v2 + - uses: softprops/action-gh-release@v3 with: tag_name: ${{ needs.preflight.outputs.tag }} target_commitish: ${{ needs.preflight.outputs.checkout_ref }} @@ -394,7 +394,7 @@ jobs: generate_release_notes: true prerelease: ${{ needs.preflight.outputs.is_prerelease }} - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 if: needs.preflight.outputs.is_prerelease != 'true' with: repository: Automattic/homebrew-tap diff --git a/.github/workflows/release-verify.yml b/.github/workflows/release-verify.yml index 49f43eb5..b82ca892 100644 --- a/.github/workflows/release-verify.yml +++ b/.github/workflows/release-verify.yml @@ -58,7 +58,7 @@ jobs: env: RELEASE_BRANCH: ${{ github.event.pull_request.head.ref }} - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ steps.ref.outputs.checkout_ref }} fetch-depth: 0 @@ -112,7 +112,7 @@ jobs: WINDOWS_CODESIGN_CERT_BASE64: ${{ secrets.WINDOWS_CODESIGN_CERT_BASE64 }} WINDOWS_CODESIGN_PASSWORD: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.preflight.outputs.checkout_ref }} @@ -143,7 +143,7 @@ jobs: # and the PHP/lib compilation when inputs haven't changed. Cache key # includes every input that affects the produced binaries. - name: Cache .build - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .build key: >- @@ -285,7 +285,7 @@ jobs: Dismount-DiskImage -ImagePath $vhdPath -ErrorAction SilentlyContinue | Out-Null } - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: forkpress-${{ matrix.target }} path: | diff --git a/docs/merge-reliability.md b/docs/merge-reliability.md index ca7db6d9..29bcc0b2 100644 --- a/docs/merge-reliability.md +++ b/docs/merge-reliability.md @@ -262,7 +262,7 @@ Recent focused coverage also tightens three roadmap edges: | Branch birth | CLI, Git-created, and remote-cache branches allocate ID bands and capture merge base metadata. Branch-birth validation rejects missing ID bands and keyless row identities, filesystem base capture records user content/uploads while excluding managed DB/config/Git files, and rollback cleanup removes only the failed branch metadata and preserves unrelated branch birth metadata. Git-created branches finalize birth metadata before publishing the branch tree, so a pre-metadata crash cannot expose a branch without ID bands or row identities. Existing branches reused by automation or updated through Git publication must still have a database, DB merge base, filesystem merge base, and required birth metadata before reuse/update. The WordPress admin branch create/merge UI is covered as a thin wrapper over the same CLI paths, including validation, CLI failure surfacing, and real runtime E2E create/merge requests. Remote-cache branch E2E coverage registers a materialized `main` cache, creates `remote-cache-branch`, verifies branch storage, inserts into the runtime AUTOINCREMENT probe inside the branch band, then merges branch DB and filesystem changes back to `main`. | Keep branch create, Git ref create, remote-cache branch, reset, UI creation, and Git-updated existing branches on one invariant: DB base, file base, ID bands, and metadata must exist before user writes. | | ID bands | AUTOINCREMENT bands protect common WordPress and plugin tables. Normal branch reuse inside the reserved band refreshes existing metadata instead of allocating fresh IDs; reaching the previous band end allocates a fresh band before the next implicit insert while preserving prior reserved ranges as valid for merge; reset below old bands gets fresh bands. Existing non-main Git branch updates with a WordPress SQLite database now validate DB merge base, filesystem merge base, and branch-birth metadata before replacing branch storage, so pushes cannot write into an ID-bearing branch that is missing its band reservation. Explicit source IDs outside the reserved branch band are review-held instead of applied automatically for core WordPress and plugin AUTOINCREMENT tables, paired source deletes in the same AUTOINCREMENT table are also held when an out-of-band explicit insert or primary-key rewrite is held, and source child `wp_posts`, owner/reference `wp_postmeta` including inserted and updated type-aware nav menu object refs, inserted or updated scalar/serialized/theme/widget `wp_options` references, inserted or updated `wp_comments`, `wp_commentmeta`, inserted or updated `wp_termmeta`, hierarchical and updated `wp_term_taxonomy`, inserted or primary-key-rewritten `wp_term_relationships`, inserted or updated `wp_usermeta`, inserted or updated post authors, inserted or updated reusable/media/avatar/latest-posts/navigation/query block `post_content` refs including `taxQuery`, inserted or updated classic attachment refs in `post_content`, inserted or updated taxonomy menu-item object refs, or inserted or updated comment user refs pointing at held explicit post/term/user IDs are review-held instead of leaving orphan WordPress child rows. Focused explicit-ID coverage now includes inserted or updated `wp_posts` rows with `post_author`, `core/avatar`, and `core/query` author references plus `wp_usermeta` and `wp_comments` rows behind held out-of-band explicit `wp_users` imports, inserted or updated `wp_commentmeta` and threaded comments behind held explicit `wp_comments` imports, inserted or updated featured-image postmeta, image-block content, classic `wp-image-*` and `[gallery ids="..."]` content, `site_icon`, theme-mod `custom_logo`, and media/block/text/custom HTML widget options behind held explicit attachment imports, pages-widget options and inserted or updated `core/navigation-link`, `core/navigation-submenu`, and `core/navigation` post_content refs behind held explicit page/term/`wp_navigation` imports, and inserted or updated `wp_termmeta`, `wp_term_taxonomy`, `wp_term_relationships`, serialized theme-mod menu locations, nav-menu widgets, and `nav_menu_options` options behind held explicit `wp_terms` imports. Non-AUTOINCREMENT `INTEGER PRIMARY KEY` plugin tables are marked non-bandable; non-colliding rows merge, while collisions are review-held and auditable. Dependent source child rows are also held when their foreign key points at a source parent row whose plain integer key collides with a different target parent. | Expand explicit-ID/import handling beyond covered AUTOINCREMENT row-insert cases and reject/review unsafe reuse for more plugin/custom logical identities that are not safely bandable. | | Stale audits | Resolution fails if target no longer matches the audited payload. `forkpress branch revalidate-reviews` and `forkpress branch merge-audit --revalidate` carry stale reviewed conflicts back into `needs-action` while preserving prior reviewer intent, avoiding duplicate carried notes, recording revalidated payloads, linking plugin replacement validator conflicts, emitting actionable text/JSON summaries of carried and already-open conflict ids, and storing a conservative revalidation classifier such as `compatible-target-drift`, `compatible-source-drift`, `missing`, no-primary-key rowid-reuse `incompatible`, supported WordPress post/postmeta/option/term/term-taxonomy/termmeta/user/usermeta/comment/commentmeta primary-key semantic `incompatible`, custom/plugin non-PK `UNIQUE` logical-key `incompatible`, plugin `replacement-evidence`, schema `compatible-schema-index-target-drift`, `compatible-schema-view-target-drift`, `compatible-schema-trigger-target-drift`, `compatible-schema-table-target-drift`, or schema index/view/trigger/table-restore/table-rebuild `unclassified` drift. A latest `revalidation-required` event now overrides older unapplied validated choices, and bulk `apply-reviewed-resolutions` preflights live staleness, revalidates stale validated choices, reports them as skipped, and leaves the target unchanged instead of surfacing a raw resolver error or silently applying a stale reviewed choice. If a later revalidation shows the source and target payloads are fresh again, the prior `pending` or `reviewed` intent is restored and validated choices re-enter the `apply-reviewed` queue. New database cell conflicts also retain source/target row-context payloads, so custom/plugin logical-key replacement can be detected even when the reviewed scalar cell value is unchanged. `forkpress branch merge-audit --resolution-choice source` and `--blocked-resolution-choice source` expose the current executable/blocking contract for conflict queues. `forkpress branch merge-audit --event-type recorded|review-pending|review-needs-action|review-reviewed|resolution-validated|resolution-applied|resolution-blocked|revalidation-required` exposes the first-class conflict event history without scraping review notes, including failed resolver attempts that leave conflicts open, and `forkpress branch merge-audit --records conflict-events --group-by event-type|lifecycle|conflict-key` summarizes that history for UI queues. `forkpress branch merge-audit --latest-revalidation-status current|source-drifted|target-drifted|source-and-target-drifted|unknown|none` and `--group-by latest-revalidation-status` expose whether the latest recorded after-revalidate guard still matches live source/target state before the reviewer attempts a guarded resolution. `forkpress branch merge-resolve conflict --after-revalidate` can apply reviewed stale database row/cell and filesystem conflicts only when the current source/target payloads still match the latest revalidation record, the latest classifier is not `incompatible`, and the original logical row still exists; source-added view/trigger compatible source drift, source-added schema index/view/trigger compatible target drift, compatible table-rebuild source drift, and compatible table-rebuild target drift can also source-apply after revalidation only when the planner recorded its matching compatible schema class. The fast stale-audit gate now covers deleted target rows, no-primary-key rowid reuse, supported WordPress semantic replacement classifiers, custom/plugin logical-key replacements inferred from non-PK `UNIQUE` indexes, row-context-backed cell conflict identity drift, stale validated choices being excluded or preflight-revalidated by batch apply, fresh-again restoration into the batch apply queue, live source-applicable/source-blocked audit filters, event-type output/filtering/grouping, latest revalidation status output/filtering/grouping, and the direct revalidation output shape. Plugin validator conflicts now return to `needs-action` when a validator rerun records changed evidence for the same plugin object, including explicit changed plugin `source` payload evidence or changed first-class `logical_identity` evidence. Generic source/target resolution remains blocked for plugin conflicts, but a plugin driver can resolve the current replacement conflict when the previous reviewed conflict has a latest current `replacement-evidence` revalidation pointing at that replacement; stale originals, unrevalidated replacements, incompatible revalidations, and drifted replacement evidence are rejected. Ordinary cross-run plugin conflict lineage remains outside that replacement-evidence guard. Reviewed schema index/view/trigger/table-restore/table-rebuild conflicts now return to `needs-action` with current SQL and, for table rebuilds, dependency-plan evidence when schema SQL or dependent object SQL drifts. Other schema conflicts still need planner-backed guarded resolution before they can be applied after revalidation. `docs/stale-audit-workflow.md` maps the current flow and the remaining richer classifier model. | Add more guarded revalidation resolution for plugin and schema conflicts where a plugin or schema planner can prove compatibility. | -| Release gates | Linux, Windows, x86_64 macOS, and aarch64 macOS production bundle artifacts built in the last checked release. macOS and Linux release workflows install static PHP build prerequisites up front, `scripts/build-dist.sh` now fails before cloning/building PHP if those tools are missing instead of letting `static-php-cli` mutate package-manager state during the release bundle step, avoids macOS bash empty-array expansion under `set -u` while wrapping Apple Silicon `spc` commands in `arch -arm64`, and the default `static-php-cli` checkout is pinned to a known upstream commit with an explicit override for deliberate upgrades. Release-verification PRs now run the same production bundle matrix even when the source branch is not `release/v*`, while keeping tag-state validation scoped to actual release branches. Release `v0.1.41` workflow run `26051644782` passed release packaging, artifact smoke checks, tag creation, GitHub release publication, and Homebrew formula update for all release targets, including `aarch64-apple-darwin`. The published release is tagged at commit `8ae3a784a284dc2e9e7475318709c1edb58b6f96` and includes the Apple Silicon artifact `forkpress-aarch64-apple-darwin.tar.gz`. Trunk and release CI also run APFS sparsebundle E2E on both macOS targets with a bounded product retry and e2e-only tolerance for the known transient `hdiutil compact` unavailable condition. | Keep aarch64 macOS release and APFS sparsebundle E2E green on trunk for future releases. Add a separate product check if compact-success itself becomes release-critical. | +| Release gates | Linux, Windows, x86_64 macOS, and aarch64 macOS production bundle artifacts built in the last checked release. macOS and Linux release workflows install static PHP build prerequisites up front, `scripts/build-dist.sh` now fails before cloning/building PHP if those tools are missing instead of letting `static-php-cli` mutate package-manager state during the release bundle step, avoids macOS bash empty-array expansion under `set -u` while wrapping Apple Silicon `spc` commands in `arch -arm64`, and the default `static-php-cli` checkout is pinned to a known upstream commit with an explicit override for deliberate upgrades. Release-verification PRs now run the same production bundle matrix even when the source branch is not `release/v*`, while keeping tag-state validation scoped to actual release branches. Release `v0.1.48` workflow run `26067459265` passed release packaging, artifact smoke checks, tag creation, GitHub release publication, and Homebrew formula update for all release targets, including `aarch64-apple-darwin`. The published release is tagged at commit `eb3fe1d390870d3118221221bd4316fe1247fd4a` and includes the Apple Silicon artifact `forkpress-aarch64-apple-darwin.tar.gz`. Trunk and release CI also run APFS sparsebundle E2E on both macOS targets with a bounded product retry and e2e-only tolerance for the known transient `hdiutil compact` unavailable condition. | Keep aarch64 macOS release and APFS sparsebundle E2E green on trunk for future releases. Add a separate product check if compact-success itself becomes release-critical. | ## Test Direction @@ -589,6 +589,6 @@ should stay focused on these areas: - Improve deterministic schema dependency planning for safe view/trigger reorderings while keeping cyclic or semantic ambiguity review-only. - Keep aarch64 macOS release artifacts and APFS sparsebundle E2E runs green for - each release. `v0.1.41` is the current published release after all five + each release. `v0.1.48` is the current published release after all five production-bundle targets stayed green and the release commit - `8ae3a784a284dc2e9e7475318709c1edb58b6f96` was published. + `eb3fe1d390870d3118221221bd4316fe1247fd4a` was published.