Imported GitHub issues keep their real dates, closure reasons and release, and link to items another provider already tracks

Merged
UN
5d ago
+1742-97

Historical GitHub imports replaced source lifetimes with import-time dates, lost closure evidence and release context, and created mirrors of items already owned by another provider. Imports now preserve GitHub creation, closure and completion dates, retain exact source timestamps, map not-planned and duplicate closures to canceled, and assign the first locally available calendar release at or after closure.

Ownership comes from provenance tags and explicit GitHub/provenance/link metadata. Incidental description or body URLs cannot adopt an unrelated item. A URL-only GitHub owner receives native lifecycle and release updates; declared Linear/Jira/ADO owners retain their content, native status, dates and release. Explicit provider back-links and the persisted github_link_only marker remain supported.

Closure evidence selects the latest REST or GraphQL closure within a bounded forward skew of zero to five seconds. Earlier closure generations cannot suppress GraphQL fallback or provide an older closer when the latest event has none. Associated PRs remain labeled as linked evidence rather than proof of a fix.

Atomic finalization uses public SDK locks, serialization and append-only history before commit, with compensation on failure and stable reconciliation across external edits and lifecycle cycles. Native updated_at remains the SDK mutation clock; github_updated_at retains the exact source value.

The README scopes the ambiguity no-write guarantee to gated and atomic imports. Real tracker tests confirm that plain multi-issue imports can retain earlier writes, and empty filtered gated selections omit plan for preview and apply. A test-only marker probe separates finite module startup from the unchanged ten-second parser deadline and verifies forced termination of an intentional spin.

Validation: npm run release:check and bun run release:check both passed with isolated HOME, GIT_CONFIG_GLOBAL=/dev/null and GIT_CONFIG_NOSYSTEM=1 on Node 26. Each ran 797/797 tests with zero failures, skips, cancellations or TODOs, and exact 100/100/100/100 coverage across all 14 authored modules: 10438/10438 lines and statements, 273/273 functions, 3157/3157 branches. Docstrings, lint, zero duplication, privacy, production audit, package dry-run, changelog and publish attestation passed. Package locks, SDK pins and gate thresholds are unchanged.

Four function-only behavioral controls fail on the old ownership matcher, URL-only owner classification, closure reason selection and REST/GraphQL fallback. The fixed code passes real temporary-tracker regressions without SDK mocks. The original acceptance-watchdog startup follow-up remains open.

PM feature: https://github.com/unbraind/pm-github/blob/main/.agents/pm/features/pm-github-c093.toon

Watchdog follow-up: https://github.com/unbraind/pm-github/blob/main/.agents/pm/issues/pm-github-sah1.toon

Release adoption: https://github.com/unbraind/pm-github/blob/main/.agents/pm/tasks/pm-github-aiok.toon


Summary by cubic

Preserves GitHub import fidelity so scheduled imports keep real source lifecycle, and links issues another provider already tracks instead of duplicating them.

  • Imported issues retain GitHub creation, closure, and completion dates, keep closure reasons and closing PR/commit evidence, and get release attribution from actual calendar tag dates. not_planned and duplicate closures map to canceled.
  • Issues already owned by Linear, Jira, ADO, or another provider link to the existing item through explicit ownership and generic link-field back-links; empty provider fields or body/label examples never transfer ownership. The provider keeps its content, identity, native lifecycle, and release.
  • Finalization uses public SDK item locks, serialization, and append-only history, and transaction identity covers external edits and repeated lifecycle cycles so completed journals cannot hide a local reopen.
  • The SDK's native updated_at stays the mutation clock; the exact GitHub value is kept as github_updated_at.

Rollout

  • Imports now reconcile cancel-to-complete transitions instead of failing, without reusing stale completed journals.
  • The gate plan reports source dates, closure reason, release, and state conflicts.
  • All six consumer callers pin the workflow SHA and pm-github package to 2026.10.16; after they adopt the fixed release, the next scheduled sync regenerates existing PRs.

Summary by Sourcery

Preserve GitHub import fidelity and reconcile existing cross-provider records without duplicating or overwriting their ownership.

New Features:

  • Preserve GitHub issue lifecycle dates, closure reasons and evidence, and release attribution during imports.
  • Link issues already owned by Linear, Jira, ADO or other providers without replacing their provider-managed content or lifecycle.
  • Expose source fidelity, identity matches and lifecycle conflict decisions in gated import plans.

Bug Fixes:

  • Prevent duplicate records when imported GitHub issues are already tracked elsewhere.
  • Correct canceled-state mapping for not-planned and duplicate GitHub closures.
  • Make atomic import retries and reconciliation safe across local edits, repeated lifecycle transitions and interrupted transactions.

Enhancements:

  • Finalize imported source metadata through the public SDK while retaining the native mutation clock and exact GitHub update timestamp separately.
  • Use complete tracker provenance and provider metadata to distinguish ownership from incidental links or body references.

Documentation:

  • Document imported issue lifecycle, closure evidence, release-window attribution, cross-provider ownership and timestamp behavior.

Tests:

  • Add real SDK and GitHub fixture coverage for import fidelity, release assignment, closure evidence, provider linking, rollback, interruption recovery and idempotent retries.

Chores:

  • Record the feature and rollout work in project management metadata and the changelog.