Fix daily gated issue sync idempotency, privacy precision and alerts
Daily gated syncs fail when repeating unchanged issue imports, when source syntax is mistaken for private data, or when installation bookkeeping reaches the publication scope check. This change makes unchanged imports produce no item/history writes and adds a safe, deduplicated failure tracking issue.
- Compare normalized stored and desired fields for each item before plain writes or fresh atomic batches. Preserve complete pending transaction plans and synchronize native comments independently.
- Scan gated dry-run plans through the same rendered values and privacy rules as apply, including non-git scratch trackers. Admit stored bare-root regex expressions and SSH URLs using the
gitservice identity; retain host-path and contact-address refusals. - Restore workflow-owned setup bookkeeping when extension installation fails. Successful setup isolation continues to preserve caller bytes and reject caller edits outside the setup window.
- Reconcile one stable failure issue after failed/successful syncs. Its body contains only a fixed failing-step name, run URL and enumerated rule names. Failed lookups cannot create duplicates.
The SDK's forced identical closed-state update resets closure and mutation timestamps. Independent non-git reproductions confirmed this with pinned SDK 2026.10.25 and current 2026.10.28; tracked upstream in pm-cli #1628. This package skips no-ops independently of that upstream fix.
Validation: npm run release:check and bun run release:check both pass: 1,598/1,598 tests each, zero failed/skipped/cancelled; exact 100/100/100/100 coverage across all 28 authored modules (13,170 lines/statements, 421 functions, 5,040 branches), unchanged thresholds and no exemptions. All static, privacy, duplication, audit, package, changelog and attestation checks pass. Both repeat-import properties also pass with Git absent from PATH, and allowed/refused gated non-git previews make zero durable writes. The captured candidate package contains 75 byte-verified files; disposable generated-file mutation is detected while the captured artifact remains unchanged.
Behavioral reversions in disposable copies fail the import properties, privacy must-allow corpus, alert creation/recovery check, and registry restoration assertion. The fixed implementation passes again. Real-data gated previews made zero source writes for pm-gantt-chart (10 issues), pm-web (9), and pm-rl (1). Released second-import diffs were 18, 12 and 0 durable files; candidate diffs are 0, 0 and 0. See the audit and source-content triage.
Rollout requirements: preserve source refusals for the seven policy-hit issue bodies listed in the audit; the orchestrator owns redaction, including intentionally synthetic examples. pm-csv issue #197 separately requires duplicate-owner repair. Existing callers granting issues: read keep syncing but need a caller-owned issues: write change to enable alerts; a reusable workflow cannot elevate permissions. Caller templates document this. Fleet callers and source issues/comments were not edited.
PM: pm-github-3it2; follow-up pm-github-samq. Companion reference: pm-cli-website-c0jw.
Summary by cubic
Makes daily gated issue sync idempotent, tightens privacy scanning precision, and adds deduplicated failure alerts.
Unchanged imports now produce no item or history writes; repeat imports report zero updates. Gated dry-runs scan the rendered plan in memory, including non-git trackers. Privacy rules admit source syntax like regex literals and ssh://git@ URLs while still refusing host paths and contact addresses. Failed and successful syncs reconcile to one stable failure issue whose body contains only fixed data, and the workflow forwards only enumerated rule names (a regression test pins that allowlist to the gate's emitted names). The workflow no longer grants blanket permissions; the sync job narrows its token, and the alert job inherits the caller grant. Audit findings and the caller adoption handoff are recorded in docs/daily-sync-recovery.md.
-
Migration
- Callers granting
issues: readcan keep syncing but need caller-ownedissues: writeto enable alerts; a reusable workflow cannot elevate permissions. - The caller template documents the permission change.
- Callers granting
-
Bug Fixes
- Restores workflow-owned setup bookkeeping when extension installation fails; successful setup isolation still rejects caller edits outside the setup window.
- Skips no-op updates independently of the upstream
pm-clifix for forced identical closed-state updates.
Summary by Sourcery
Make daily gated issue synchronization idempotent, privacy-precise, and safely recoverable with deduplicated failure alerts.
New Features:
- Add a deduplicated sync failure tracking issue that records safe failure metadata and closes or reopens across recovery cycles.
- Support privacy-gated dry-run scanning of rendered import plans in non-git trackers.
Bug Fixes:
- Prevent unchanged imports from writing item or history changes while continuing independent comment synchronization.
- Align gated preview and apply privacy checks to admit source syntax such as regex literals and Git SSH URLs without weakening host-path or contact-address refusals.
- Restore workflow-owned setup bookkeeping when extension installation fails.
- Prevent duplicate failure alerts when issue lookups fail.
Enhancements:
- Preserve complete pending transaction plans while filtering normalized no-op mutations and report unchanged plan actions.
- Restrict failure-alert content and transported rule names to fixed, enumerated values.
CI:
- Update workflow permission handling so synchronization retains read access while failure alerts use caller-provided write access.
Documentation:
- Document gated dry-run behavior, caller permission requirements, recovery procedures, privacy triage, and validation results.
Tests:
- Add property and regression coverage for repeat-import idempotency, privacy precision, alert reconciliation, workflow restoration, and rule-name allowlists.
Chores:
- Record the upstream SDK identical closed-state timestamp issue and package-level mitigation in recovery documentation.