Skip to content

Add an opt-in exact-sync mode for existing target projects #70

Description

@SIkebe

Background

Importing into an existing target Project is currently additive. Target-only fields, items, status updates, views, saved workflows, collaborators, linked repositories, and linked teams are reported by verify but are not removed. The default behavior must remain non-destructive.

This is an umbrella issue for an explicit exact-sync mode. Implementation should be staged across multiple reviewable PRs, not delivered as one monolithic change.

Confirmed API capability (2026-08-19)

The required destructive primitives are primarily GraphQL mutations:

Target-only state Confirmed mutation
Project field deleteProjectV2Field
Project item deleteProjectV2Item
Status update deleteProjectV2StatusUpdate
Saved view deleteProjectV2View
Saved workflow deleteProjectV2Workflow
Explicit collaborator updateProjectV2Collaborators with role NONE
Repository link unlinkProjectV2FromRepository
Team link unlinkProjectV2FromTeam

GitHub.com live introspection confirms all mutation names and ProjectV2Roles.NONE. REST supports deleting Project items but does not provide equivalent field/view/workflow/collaborator/link management, so exact sync should use GraphQL consistently.

Iteration definitions are different: there is no dedicated delete-iteration mutation. updateProjectV2Field accepts a complete iteration configuration, but removal semantics must be proven against the real API before exact mode modifies existing iterations. Until then, target-only iterations must be reported as not safely prunable.

Unsaved default workflow sidebar entries are not GraphQL resources and are out of scope.

Implementation scope

  • Add an explicit option such as --sync-mode exact; additive import remains the default.
  • Add --dry-run or an equivalent guaranteed non-mutating preview mode that emits the complete machine-readable prune plan and never calls BeforeWriteAsync or a mutation.
  • Build and print a deterministic prune plan before BeforeWriteAsync and before any mutation.
  • Resolve every target-only object to a stable target ID and persist pending/completed destructive operations in the durable import log.
  • Order operations to avoid invalid dependencies and template-write restrictions.
  • Never retry an ambiguous delete as if it were idempotently confirmed; reconcile target state first.
  • Support rerun/idempotency after interruption.
  • Report unsupported/non-prunable state separately from successful exact synchronization.
  • Phase delivery by resource category while keeping this issue as the contract/tracking issue.

Test strategy

  • Add deterministic plan, ordering, safety-gate, resume, reconciliation, and serialization tests.
  • Add real Ghpmv.Integration.Tests lifecycle coverage for each mutation listed above: create target-only state, run exact sync, re-read, rerun, and verify no unrelated source-matched state was deleted.
  • Add a dedicated live experiment for iteration removal semantics before enabling iteration pruning.
  • Use browser-assisted verification only to confirm UI-visible results; the prune mutations themselves do not require Playwright.
  • Live tests must use cancellation tokens and delete disposable Projects in finally.

ghpmv-e2e-validation skill integration

Do not add a separate user-facing scenario selector for this issue. Extend the existing browser-e2e validation run with an isolated exact-sync checkpoint that creates an additional disposable target only after explicit resource-creation consent.

Extend the existing ghpmv-e2e-validation browser-e2e flow with an isolated destructive exact-sync checkpoint; do not reuse or mutate the shared standard fixture.

  • Add a feature-specific CLI target-seeding helper that the existing flow invokes conditionally that creates a uniquely named disposable existing target with target-only state in each supported category and outputs a machine-readable inventory of logical names plus node IDs.
  • Add --dry-run (or an equivalent guaranteed non-mutating preview mode) to exact sync. The skill must run preview first, parse the planned operations, and stop for explicit destructive-operation confirmation before sending the mutating command.
  • Compare the preview against the fixture command's machine-readable inventory; do not require users to discover node IDs in the UI.
  • Keep the same token execution terminal and observe durable log/progress during exact sync and rerun.
  • Require final API and browser-assisted verification, including explicit reporting for non-prunable iterations.
  • Add an optional controlled-interruption branch only when it can be triggered deterministically; otherwise rely on Integration failure injection and mark the manual branch NotApplicable, not passed.
  • Inventory every disposable Project/Team/repository and require separate cleanup consent after results are recorded.
  • Update CLI fixture tests, Integration mutation tests, skill instructions/state, settings validation, destructive warnings, and cleanup handling together.

Existing manual E2E flow additions

E2E runtime consolidation: Do not add a standalone feature scenario or repeat the full fixture/export/import/verify/cleanup sequence. Fold fixture setup into the existing fixture step, snapshot assertions into the existing export result, target assertions into the existing import/verify and visual checklist, deliberate drift into the existing negative-test phase, and repair into the single idempotence re-import. Reuse the same snapshot, mappings, and target Project. Add another disposable target or native command only when a distinct code path cannot be proven otherwise; document why and include every added resource in the existing inventory and cleanup.

Extend the existing browser-assisted migration flow in docs/MANUAL_TEST_PLAN.md with an isolated destructive phase that uses a uniquely named disposable existing target Project created by the feature-specific target-seeding helper:

  1. Import the source snapshot once, then add target-only fixtures for every enabled exact-sync category: field, item, status update, saved view, saved workflow, explicit collaborator, repository link, and Team link. Also add a target-only iteration to exercise the non-prunable report until removal semantics are proven.
  2. Run normal additive import first and confirm none of the extras are deleted and verify reports them.
  3. Run exact sync in non-mutating preview mode and compare the complete proposed deletion list with the fixture command's machine-readable target-only inventory. Compare UI-visible names/titles and use emitted IDs from the fixture inventory; do not ask the tester to discover node IDs manually. Source-matched resources must never appear.
  4. Execute exact sync, re-export the target, and confirm every supported target-only resource/link was removed while source-matched state remains.
  5. Confirm the target-only iteration is either removed under proven semantics or reported explicitly as not safely prunable.
  6. Rerun exact sync and confirm a no-op/idempotent result.
  7. Where the environment permits deterministic cancellation after at least one recorded deletion, stop the command, inspect the durable log, resume, and confirm completion without unrelated deletion. The manual plan must mark this step optional only when the Integration failure-injection test is the authoritative interruption check.
  8. Run API-only and browser-assisted verify as applicable and record the final category results.
  9. Record the prune plan, confirmation, progress, operation-log evidence, rerun output, and resource inventory before/after.
  10. Delete the disposable Project and any disposable Team/repository fixtures in the standard cleanup section.

The plan must include prominent destructive-operation warnings and must never target a shared fixture Project.

Acceptance criteria

  • ghpmv-e2e-validation can seed an isolated exact-sync target, run and validate a non-mutating preview, obtain explicit destructive consent, execute/retry/verify safely, and inventory cleanup resources.

  • docs/MANUAL_TEST_PLAN.md contains an isolated destructive phase for additive safety, exact plan review, supported deletion categories, iteration reporting, rerun/resume, final verification, and cleanup.

  • Additive behavior remains the default.

  • Exact mode presents a complete deterministic plan before writes.

  • Every supported destructive mutation has real Integration coverage.

  • Interrupted runs resume without duplicate or unrelated deletion.

  • Saved target-only resources and links are removed.

  • Target-only iterations are either safely removed after proven API semantics or explicitly reported as not prunable.

  • Unsaved default workflows are explicitly out of scope.

  • Verify reports Match only when all selected exact-sync categories are reconciled.

  • CLI documentation clearly describes destructive behavior and recovery.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions