Skip to content

[codex] Expand merge smoke and conflict audit coverage#251

Merged
adamziel merged 107 commits into
trunkfrom
codex/navigation-block-merge-smoke
May 17, 2026
Merged

[codex] Expand merge smoke and conflict audit coverage#251
adamziel merged 107 commits into
trunkfrom
codex/navigation-block-merge-smoke

Conversation

@adamziel
Copy link
Copy Markdown
Contributor

@adamziel adamziel commented May 17, 2026

What changed

  • Adds fast COW smoke coverage for clean branch/main wp_navigation block creation where pages reference branch-local navigation blocks through core/navigation comments.
  • Adds edit/delete smoke coverage where a source-edited wp_navigation row conflicts with a target deletion and target page cleanup.
  • Adds clean media-reference smoke coverage for core/audio, core/cover, and core/video pages with attachment rows, _wp_attached_file metadata, and upload files on both branches.
  • Adds parent/child page, page revision, threaded comment, and authored-page smoke coverage for branch-specific post_parent, comment_parent, and post_author graphs.
  • Adds front/posts page, sticky_posts, site_icon, theme_mods_* custom_logo, widget_media_image, and widget_nav_menu disagreement coverage: object graphs survive, while singleton/serialized option values stay reviewable with target kept before resolution.
  • Adds explicit-ID coverage for serialized menu-location and nav-menu-widget option refs behind held out-of-band wp_terms imports, so embedded menu term IDs remain review-held instead of silently applying orphaned serialized data.
  • Adds merge-audit --revalidation-class <class> and --group-by revalidation-class for conflicts, backed by the latest recorded revalidation result, so reviewers can queue conflicts by classes like compatible-target-drift, missing, incompatible, or replacement-evidence without client-side JSON scanning.
  • Exposes latest revalidation status, reason, and timestamp in audit JSON/text, so callers can tell whether a recorded after-revalidate guard is still current or whether source/target drifted again before resolution.
  • Adds merge-audit --latest-revalidation-status <status> and --group-by latest-revalidation-status, so callers can queue conflicts whose last after-revalidate guard is still current, has source/target drift, or has no latest revalidation record without client-side filtering.
  • Adds merge-audit --stale-status <status> and --group-by stale-status, so callers can query live fresh/stale/error/unknown conflict queues without client-side filtering.
  • Adds merge-audit --conflict-id <id> support for conflicts, conflict events, and resolutions, so UI/API callers can fetch one first-class conflict and its history by the same numeric id used by review/resolve commands.
  • Makes forkpress branch revalidate-reviews --conflict-id <id> and forkpress branch merge-audit --revalidate --conflict-id <id> carry one reviewed conflict back to needs-action without revalidating the whole run.
  • Extends targeted stale revalidation to --conflict-key <key> with the same unambiguous logical-conflict guard used by review and resolve, so UI/API callers can revalidate by stable conflict identity.
  • Adds merge-audit --conflict-key <key> support for conflicts, conflict-events, and resolutions, including conflict lineage on resolution rows so UI/API callers can focus one logical conflict group across repeated runs.
  • Makes merge-resolve conflict-key <key> [--run <id>] validate or apply conflict choices by first-class logical conflict key when the key selects exactly one unresolved conflict, with ambiguity errors that direct callers back to --run or exact conflict ids.
  • Makes merge-review conflict-key <key> [--run <id>] attach review status by first-class logical conflict key with the same ambiguity guard, so UI/API callers can mark a logical conflict without scraping numeric row ids.
  • Reports candidate conflict ids and run ids when conflict-key review/resolution is ambiguous, giving UI/API callers deterministic disambiguation data in the error path.
  • Adds merge-audit --lifecycle-state <state> support for conflict queues and conflict-event history, covering unreviewed, deferred, needs-action, reviewed, validated, and resolved states without client-side lifecycle inference.
  • Adds merge-audit --records conflicts --group-by lifecycle and --group-by conflict-key, and --scope plugin --group-by plugin, --group-by plugin-object, --group-by plugin-severity, or --group-by plugin-logical-identity so callers can summarize current conflict queues by lifecycle state, logical conflict key, validator plugin, validator object, plugin severity, or plugin logical identity without client-side aggregation, defaulting those queue groupings to conflict records, and exposes conflict-key, plugin scope, lifecycle filter/group, and plugin logical-identity filtering plus conflict and event grouping through the Rust CLI wrapper, help text, and parser tests.
  • Links plugin validator replacement findings into the same conflict lineage via shared conflict_key and same-run previous_conflict_id, so --conflict-key can show original and replacement plugin evidence together.
  • Preserves and validates first-class plugin validator severity and review guidance fields (severity, resolution_policy, suggested_action, and manual_review_reason) in conflict payloads, and adds media coverage that missing original, metadata-original, generated, original_image, and backup upload files are explicitly review-only, and that non-image upload MIME drift such as PDF attachments is caught rather than auto-regenerated.
  • Tightens plugin validator finding validation so malformed or empty validator identities are rejected before audit rows are recorded.
  • Exposes plugin validator audit fields directly in merge-audit records (plugin, plugin_object, plugin_tables, plugin_files, plugin_validator, plugin_severity, plugin_logical_identity, and review guidance fields), adds first-class plugin, plugin-object, plugin-severity, and plugin-logical-identity filters, queue groupings, conflict-event metadata, and resolution metadata, resolution filters, resolution-status shortcuts, and resolution queue grouping by plugin fields across all plugin identity dimensions, including resolution row text metadata and text output for resolution groupings, and normalizes validator paths aliases into structured plugin_files so UIs do not scrape previews.
  • Adds guarded schema revalidation paths for source-added index, view, and trigger target drift: if revalidation proves the source object still matches review and dry-run replacement validates over current target state, merge-resolve --after-revalidate can source-apply that object while cyclic or unproven schema drift stays review-only.
  • Makes forkpress branch merge-audit accept --flag=value forms for valued audit filters, including conflict-key, lifecycle, grouping, path, review, decision, and resolution filters.
  • Makes forkpress branch merge-audit --revalidate and direct php scripts/cow/merge.php audit --revalidate reject normal audit filters they would ignore, so stale-audit revalidation cannot appear narrower than it actually is.
  • Adds actionable stale-audit revalidation summaries: text/JSON results now include needs_action_conflicts, carried_conflicts, and already_needs_action_conflicts with conflict ids, classifiers, drift reasons, revalidation records, and replacement conflict ids.
  • Aligns Rust and PHP revalidation entry points around --quiet, including forkpress branch revalidate-reviews --quiet and forkpress branch merge-audit --revalidate --quiet.
  • Tightens first-class conflict contracts so payload-specific schema blockers, such as cyclic source view/trigger resolution, are exposed as blocked_resolution_choices in JSON and text audit output instead of being advertised as executable source choices.
  • Extends schema blocked-choice contracts to source-dropped table/view conflicts whose current target still has dependent views, triggers, schema objects, or foreign-key child tables; audit output advertises source again after those dependency conflicts are resolved.
  • Extends row blocked-choice contracts to row-target-constraint conflicts whose audited source row or source row deletion would fail against the current target foreign-key state; audit output hides source until the missing parent or blocking child dependency is resolved.
  • Extends that blocked-choice contract to unsafe filesystem source payloads: unsafe symlinks, unsupported source entries, target-descendant directory deletions, and directory replacement subtrees with unsafe children now expose source as blocked in audit output and are rejected before resolver mutation starts.
  • Makes merge-resolve enforce blocked choices through that same conflict contract before entering schema mutation/validation paths, so audit and resolver behavior share one source of truth.
  • Adds merge-audit --resolution-choice source|target and --blocked-resolution-choice source|target, backed by the live conflict contract and direct PHP CLI regression coverage, so UI/API callers can query currently executable source choices separately from source-blocked review items.
  • Adds merge-audit --next-action <action> and --group-by next-action, backed by the live conflict lifecycle contract, so UI/API callers can query actionable queues like resolve, wait, and revalidate directly.
  • Hardens Git-created branch rollback cleanup so failed branch publication removes identity-capture decision/run metadata as well as ID bands, row identities, and merge-base artifacts.
  • Holds core/navigation-submenu post-type and taxonomy object refs behind the same review boundary as core/navigation-link, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Covers core/template-part theme/slug refs in discovered WordPress semantic validators, so block-theme templates left pointing at deleted template parts become plugin-scoped review conflicts.
  • Holds core/query taxQuery taxonomy refs behind the same review boundary as legacy category and tag query filters, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Holds core/latest-posts author and category filters behind the same review boundary, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Holds serialized nav_menu_options auto-add menu refs behind the same review boundary as theme mod and nav widget menu refs, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Holds serialized widget_block block content refs behind the same review boundary as post content block refs, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Holds serialized media widget refs across image, audio, video, and gallery widgets behind the same attachment review boundary, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Holds serialized widget_pages page exclusions behind the same page review boundary, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Holds serialized widget_text and widget_custom_html block-content refs behind the same attachment review boundary as post content block refs, covering both explicit-ID merge gating and discovered WordPress semantic validators.
  • Broadens discovered WordPress block-reference validators to scan content-bearing custom post types, with coverage for a CPT core/image block left pointing at a deleted attachment.
  • Retries transient static-php-cli PHP/source downloads during release dist builds, with validation for the retry-count knobs.
  • Documents the expanded smoke-gate, conflict-audit coverage, explicit-ID coverage, plugin replacement lineage, stale-audit summaries, media review guidance, filesystem blocked-choice behavior, and branch-birth cleanup coverage.
  • Documents latest revalidation and stale-status queues in the stale-audit workflow, merge guide, commands list, and merge reliability ledger.

Why

The cheap local gate now covers more WordPress object graph cases before slower runtime E2E jobs run, including branch-local IDs embedded in block JSON, PHP serialization, media metadata, menus, authors, comments, and global options/widgets. The explicit-ID addition covers the unsafe case where serialized menu option payloads point at an out-of-band imported term: those references must remain review-held because ForkPress deliberately does not rewrite embedded IDs.

The conflict-key, lifecycle filters, lifecycle grouping, next-action filters and grouping, resolution-choice filters, conflict-key resolution, and plugin audit scope continue the first-class conflict model: callers no longer need to scan every conflict row, infer grouping from raw payloads, recompute conflict queue state, reconstruct event timelines, aggregate queue summaries, or guess how to request plugin-scoped conflicts in a UI. Conflict-key review/resolution stays deliberately bounded: ambiguous keys must be disambiguated by run or exact id, so repeated conflicts and identical payloads across branch pairs cannot be resolved accidentally. Plugin replacement findings now share that same lineage model, so changed validator evidence is not detached from the reviewed conflict it supersedes.

Plugin validator findings can now carry explicit review guidance without hiding it inside candidate-specific blobs. That matters for media uploads: missing generated derivatives should remain auditable review-only findings unless a future media repair driver can prove exact, deterministic regeneration.

Plugin audit records now expose the validator's plugin/object identity, owned tables/files, logical identity, and review guidance as structured fields, with first-class filters and queue groupings for plugin, plugin object, severity, and logical identity. That keeps the UI/API side aligned with the first-class conflict model instead of forcing clients to parse human previews or decode raw payload JSON.

The stale-audit guard makes revalidation intent explicit in both entry points: --revalidate is a mutation/checking flow over reviewed conflicts, not a filtered read-only audit report. The new result summaries make that flow operationally useful by showing the exact conflicts that were carried or were already open in needs-action, without requiring a second audit query just to find the next review ids.

Blocked choices keep audit and resolver behavior aligned: callers should not offer resolution actions that the merge layer already knows are blocked for a specific payload, or discover blocked schema choices only by attempting the mutation. The resolution-choice filters make that contract queryable without forcing clients to fetch and classify every conflict row themselves.

The Git-created branch cleanup change keeps branch birth atomic from the metadata side: failed publication should not leave orphaned birth audit rows that make later retries or audits look like a branch partly existed.

The release-build retry is a narrow guard for the transient upstream/network failure seen in the release workflow while downloading static-php-cli sources. It does not retry the whole release job or hide deterministic build failures.

  • Adds merge-audit --event-type so conflict event history can be filtered directly by recorded/review/revalidation/resolution lifecycle events.

  • Adds conflict-event grouping so audit consumers can summarize recorded/review/revalidation/resolution event history without client-side aggregation.

  • Adds resolver-contract grouping for conflicts by resolution strategy, generic resolver support, and after-revalidate support.

  • Adds resolver-contract filters so audit consumers can focus conflicts and conflict events by resolution strategy, generic resolver support, and after-revalidate support.

  • Documents the resolver-contract audit filters in the merging guide so UI/API clients can build queues from first-class conflict fields.

  • Records blocked conflict resolution attempts as first-class resolution-blocked conflict events, including audit filtering and docs.

  • Aligns Rust CLI help and parser tests with the resolution-blocked conflict-event type.

  • Adds a PHP CLI regression for auditing resolution-blocked conflict events through JSON output.

  • Adds legacy metadata migration coverage proving existing conflict-event tables accept resolution-blocked after schema migration.

  • Queues blocked resolver attempts as first-class needs-action conflicts so lifecycle/next-action filters and groups stop advertising stale validated applies.

  • Adds CLI regression coverage for blocked-resolution queues with --lifecycle-state=needs-action plus --next-action=manual-review.

  • Adds schema-conflict coverage proving blocked source schema choices enter the same needs-action/manual-review queues as row conflicts.

  • Extends first-class blocked source-choice contracts to target-side row CHECK constraints and target trigger rewrites, preserving FK cases that become executable after dependencies are reviewed.

  • Adds focused media-validator coverage for URL-like and Windows drive-letter upload metadata, keeping those as unsafe upload-path conflicts instead of treating them as missing files.

  • Adds focused plugin-validator coverage for URL-like and Windows drive-letter plugin-owned file references, preserving them as unsafe plugin graph findings with structured file evidence.

  • Adds focused ID-band audit coverage for plugin tables that use plain INTEGER PRIMARY KEY, proving skipped-band decisions name the table and explain why no durable sqlite_sequence reservation exists.

Validation

  • php -l tests/cow/merge_smoke.php
  • make test-cow-merge-smoke (593 assertions)
  • php -l scripts/cow/merge.php
  • FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress-cli branch_merge_audit
  • php -l tests/cow/merge.php
  • php -l tests/cow/filesystem.php
  • php tests/cow/filesystem.php (78 assertions)
  • make test-cow-branch-birth (32 assertions)
  • make test-cow-branch-ui (branch UI/router/lock focused tests)
  • php -l tests/cow/schema_review.php
  • php tests/cow/schema_review.php (179 assertions)
  • php tests/cow/merge.php (3182 assertions)
  • php -l tests/cow/wp_semantic_validator.php
  • php tests/cow/wp_semantic_validator.php (328 assertions)
  • php -l tests/cow/media_validator.php
  • php tests/cow/media_validator.php (123 assertions)
  • php -l tests/cow/plugin_validator.php
  • php tests/cow/plugin_validator.php (193 assertions)
  • FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress-cli parses_branch_merge_audit_plugin_resolution_grouping
  • FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress-cli parses_cow_branch_merge_audit_resolution_plugin_grouping
  • FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress-cli parses_cow_branch_merge_audit_resolution_plugin_filters
  • FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress-cli parses_cow_branch_merge_audit_id_band_skip_shortcut
  • php -l tests/cow/stale_audit.php
  • php tests/cow/stale_audit.php (240 assertions)
  • php -l tests/cow/explicit_ids.php
  • make test-cow-explicit-ids (76 assertions)
  • php -l tests/cow/id_bands.php
  • php tests/cow/id_bands.php (34 assertions)
  • php -l scripts/cow/git_server.php
  • php -l tests/cow/git_server.php
  • php tests/cow/git_server.php (257 assertions)
  • bash -n scripts/build-dist.sh
  • bash -n tests/release/build-dist-preflight.sh
  • make test-release
  • FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress-cli (91 tests)
  • FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress-cli branch_help_lists_review_revalidation_command
  • cargo fmt --check
  • cargo test -p forkpress-storage (16 tests)
  • git diff --check

@adamziel adamziel force-pushed the codex/navigation-block-merge-smoke branch 13 times, most recently from c65ee7c to 61d02cf Compare May 17, 2026 00:57
@adamziel adamziel changed the title [codex] Cover navigation block merge smoke [codex] Expand merge smoke and conflict audit coverage May 17, 2026
@adamziel adamziel force-pushed the codex/navigation-block-merge-smoke branch 4 times, most recently from ff01bda to bec8908 Compare May 17, 2026 01:17
@adamziel adamziel force-pushed the codex/navigation-block-merge-smoke branch from bec8908 to 89b5ffc Compare May 17, 2026 01:20
@adamziel adamziel force-pushed the codex/navigation-block-merge-smoke branch 9 times, most recently from e90235d to 15454d7 Compare May 17, 2026 01:50
@adamziel adamziel marked this pull request as ready for review May 17, 2026 09:54
@adamziel adamziel merged commit da117ac into trunk May 17, 2026
7 checks passed
@adamziel adamziel deleted the codex/navigation-block-merge-smoke branch May 17, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant