Multi-Branch Tracker Merge Safety

Tracked by pm-wc1r, with the integrity and concurrency fixes pm-9q2t, pm-cxyv, pm-gpo7, pm-m3nl, pm-wwfd, and pm-xdn6. Fresh-init fence ownership is tracked by pm-1w3ljt; runtime-cache index governance by pm-hous; local allocation safety by pm-khdq; fence-coverage completeness and drift detection by pm-i4fx; package-defined item coverage by pm-5rexki; non-item JSON coverage by pm-gjicmx; portable driver identity by pm-w91mvg; pending receipt validation by pm-ysqb6n; receipt classification by pm-jtwsct; direction-independent item conflict selection by pm-dlx7v7; corrected reconciliation guidance by pm-lwmstb; cross-branch id collision safety by pm-pibw; auditable merge history by pm-9j2r3b; durable conflict decisions by pm-rh98vo; continuous conformance by pm-76dnfg; workspace-wide CI enforcement by pm-pdr8t1; post-merge reconciliation by pm-mfkv92; linked-command execution trust by pm-ed28wi; this repository's own adoption by pm-iwsj.

Lossless receipt health gating is tracked by pm-baksix, and executable remediation that performs settlement is tracked by pm-r0p3at. Immutable record sealing and retained re-anchor evidence are tracked by pm-javbsq and pm-aka8m7; preferred-era receipt-summary compatibility is tracked by pm-wn3ee5. Lossless concurrent acceptance-criteria composition is tracked by pm-inn5y5. Recency-aware scalar convergence, bounded fresh-clone decision evidence, and audited pre-durable receipt dispositions are tracked by pm-7wzb6d, pm-mg13iz, and pm-cf4t42.

pm stores project context as reviewable repository files. Concurrent agents can therefore use ordinary branches and worktrees, but tracker artifacts need semantic merge behavior: raw line merging cannot preserve TOON collection counts, JSON object structure, or append-only history hash chains.

Install the repository merge contract

Fresh pm init runs this automatically when the tracker is inside a Git worktree. It writes the shared fence and configures the current clone before returning success. Use pm init --no-merge-fence only when another system deliberately owns Git merge configuration.

Existing trackers and fresh clones can install or repair the contract directly:

pm merge install
git add .gitattributes
git commit -m "chore(pm): install tracker merge drivers"

pm merge install writes an idempotent, fenced .gitattributes block and repository-local git config entries. The attributes are committed; the driver commands are clone-local, so every collaborator and fresh CI clone that performs merges must run the install command.

The clone-local driver values record the absolute runtime launcher and bundled dist/cli.js path resolved by the installing SDK. The installer preserves an absolute PATH symlink when it resolves to the executing runtime, so a runtime manager can retarget that launcher during upgrades without breaking every clone. Relative PATH entries, inaccessible launchers, and different runtimes are ignored; without a matching launcher, the installer retains the executing binary path. Git therefore does not depend on a bare pm command or the caller's later PATH when it merges tracker data. The item-path placeholder is stored as bare %P: Git performs the required shell quoting when it expands the placeholder. Receipt ingestion also removes one legacy matching quote pair so receipts written by older clone-local drivers remain reconcilable. pm validate --check-storage-integrity and pm health also compare every clone-local driver definition with the installed SDK. Exact commands remain the fast path. A command installed by another valid @unbrained/pm-cli package is also accepted when its Node and dist/cli.js paths exist, its manifest owns the pm bin, and the driver arguments are semantically identical. This keeps copied worktrees and upgraded global installs healthy without accepting an arbitrary executable. A missing, malformed, or semantically stale definition is reported even when the committed attribute fence is correct. Health and validation name pm merge install as the repair command for missing or drifted drivers. This upgrade behavior is tracked by pm-rcjyft.

The installer publishes the shared .gitattributes fence only after the clone-local driver commands are configured. If the repository Git config is read-only or another Git process holds its lock, the command returns the stable merge_git_config_unwritable error with recovery guidance and leaves an absent fence absent. Use pm merge install --dry-run --json to inspect the contract in intentionally read-only workspaces.

Fence coverage contract

The fenced block is generated by one shared coverage contract (buildMergeAttributePatterns) covering every mergeable artifact class: tracker-wide **/*.toon and **/*.md item patterns, explicit per-type diagnostic patterns, all tracker **/*.jsonl paths under the relationship-event driver with the more-specific history/*.jsonl rule overriding history streams, root settings.json, and every nested **/*.json document. The tracker-wide item rules protect extension-defined type folders even when a receiving branch has not installed the package that registered them; explicit type rows still make active-registry drift diagnosable. The broad JSON rules automatically cover schema, managed-extension, evaluation-corpus, and future package-owned authoritative JSON without another hand-maintained allowlist. The broad JSONL rule is required because RelationshipEventStore supports package-owned custom relative paths anywhere below the tracker root. Two mechanisms keep the committed fence from drifting out of that contract:

  • pm schema add-type / pm schema remove-type refresh the fence automatically when it is installed (warning merge_fence_refreshed); repos inside git that never installed it get the actionable merge_fence_not_installed hint instead.
  • pm validate (the storage_integrity check) audits the committed fence against the active schema's type folders and reports validate_merge_fence_drift with the exact missing/stale attribute lines when they diverge — for example after editing type folders out-of-band. Rerun pm merge install and commit .gitattributes to clear it.

Preview without mutation:

pm merge install --dry-run --json

Artifact semantics

Artifact Driver Merge behavior
Item .toon / .md pm-item-toon / pm-item-markdown Three-way field merge; append-like collections use set union, updated_at uses the latest timestamp, scalar conflicts select the value from the later document update with stable value order as an equal-timestamp tie-break, and canonical serialization recomputes TOON counts.
history/*.jsonl pm-history Preserves the common prefix and both divergent suffixes, orders deterministically, then re-anchors the resulting hash chain.
tracker **/*.jsonl except the later history/*.jsonl override pm-relationship Covers default and package-owned custom relationship event paths, unions divergent suffixes by eventId (timestamp-ordered, ours-first on ties), and renumbers sequence consecutively so the strict-sequence store loader accepts the merged stream.
root settings.json and nested **/*.json pm-json Recursively merges objects per key. Arrays compose when both branches preserve the base and add distinct entries, so independent extension installs and evaluation additions merge without weakening edit/removal conflict detection.

The tests collection has an additional execution-safety rule. Its semantic identity excludes provenance so the same command/context does not duplicate when branches record different authorship metadata. A test definition newly contributed by the other merge side is persisted with provenance.source_kind=merge_union while retaining its author, creation time, and source ref. pm test --run and pm test-all refuse that command before spawning a process until the receiving clone acknowledges its fingerprint or uses the two-part project-policy plus per-run override documented in Testing. pm validate --check-command-references reports outstanding entries. This is the threat boundary for append-like data that becomes executable after a merge; ordinary notes, files, and other non-executable collections retain normal set-union behavior.

Although acceptance_criteria is serialized as a semicolon-delimited scalar for backward compatibility, the item driver treats its parsed criteria as a collection. Independent additions compose in branch order, removals made by either side remain removed, the field is reported in union_fields, and a lossless merge does not create a scalar conflict decision. This gives repeated pm update --add-ac mutations the same multi-branch preservation guarantee as native append-like metadata without a storage migration.

When both sides change the same item scalar differently, the driver retains the value from the document with the later metadata.updated_at timestamp. Equal timestamps fall back to stable value ordering, so reversing Git's ours/theirs labels still converges to the same result. Item results, driver results, and receipts expose conflict_resolution: latest_document_update and requested_preference_applied: false; each conflict decision adds retained_side and resolution_basis so review automation can distinguish a recency decision from the stable tie-break. The caller's requested_preference remains observable but does not override item scalar convergence. Readers continue to accept legacy preferred_side and stable_value_order receipts and normalize the legacy preferred key. JSON leaf conflicts retain their explicit preferred-side policy. Git keeps the item path conflicted so a human or coordinating agent must review the discarded value and explicitly git add the resolution.

The exact object { "pm_item_scalar_missing": true } is reserved for JSON-stable missing-value evidence. Item merge inputs reject that object as a present metadata value, while the hashing primitive independently separates present and missing domains. This prevents extension data from impersonating a deletion without wrapping every ordinary scalar in receipt output.

The driver result's guidance always points unresolved conflicts to pm merge report. When a clone-local receipt exists, guidance includes its privacy-safe receipt and item ids for exact correlation; discarded values remain confined to the local receipt and never appear in generic logs or tracker history. Tracked by pm-fbrz7p.

For item conflicts, the driver writes a clone-local receipt below the Git directory and a durable privacy-safe sidecar below merge-receipts/ in the tracker. The local receipt contains retained and discarded values so recovery does not depend on a reflog. The tracked sidecar applies the versioned bounded_non_sensitive_scalars_v1 policy. Built-in lifecycle statuses, priority integers from 0 through 4, bounded risk/confidence/severity ordinals, and null are stored with both their value and matching hash. All other values remain hash-only. value_availability distinguishes bounded_inline, mixed, and hash_only, while the clone-local receipt remains clone_local. This lets a fresh-clone reviewer recover ordinary control-plane decisions without publishing titles, descriptions, custom statuses, or other potentially private content. When both copies exist the SDK deduplicates them and prefers the locally recoverable copy:

pm merge report
pm merge report --include-reconciled

The underlying public SDK exports are mergeItemDocuments, mergeHistoryStreams, mergeRelationshipEventStreams, mergeJsonDocuments, runMergeDriver, runMergeInstall, installMergeFence, findGitWorkspaceRoot, runMergeReconcile, runMergeReceiptReport, runMergeReceiptEvidenceReport, inspectMergeReceiptEvidence, listMergeReceipts, auditMergeDriverConfiguration, refreshMergeAttributeFenceIfInstalled, buildMergeAttributePatterns, and auditMergeAttributeFence from @unbrained/pm-cli/sdk. installMergeFence accepts explicit tracker and workspace roots, so custom init hosts do not depend on process cwd or CLI globals.

listMergeReceipts is the compatibility projection for callers that only need validated receipts. It cannot distinguish an empty evidence store from a store whose candidates were all rejected. Gates and diagnostic integrations should use inspectMergeReceiptEvidence, whose invalid_evidence_count preserves that distinction without returning malformed contents. runMergeReceiptEvidenceReport and pm merge report --json expose the same loss-aware contract through complete, invalid_evidence_count, bounded invalid_evidence[], invalid_evidence_truncated, and clone_local_evidence_resolved. Each rejected candidate reports a stable reason plus its clone_local, durable, or copy-consistency source. Schema and identity failures additionally expose a bounded validation_error such as required_fields, item_path, filename, or durable_decisions. A safe receipt filename is returned as receipt_id; unsafe candidate names are represented only by candidate_name_hash, and malformed contents are never returned. The detail list is capped at 100 rows while the count remains exact, so automated gates stay token-bounded. Directory traversal distinguishes a truly absent store from a non-directory or unreadable ancestor on Windows and POSIX instead of treating platform-specific ENOENT/ENOTDIR spellings as equivalent. Full health also cross-checks the privacy-safe receipt summaries in append-only history against valid pending and reconciled evidence. Missing evidence emits merge_receipt_history_reference_missing:<n> with bounded item, history-line, and receipt-id-or-hash coordinates. Recover an available receipt from an authoritative clone or backup first. For an exact reference whose history-event timestamp predates tracked durable receipts, pm merge reconcile --force can append a merge_reconcile audit event containing the original item, line, receipt id, timestamp, and the closed legacy_clone_local_only reason. Health accepts only that exact coordinate and reports it through accepted_missing_merge_receipt_dispositions; it never rewrites or deletes the original history. The audit event must also occur after the referenced history line; an earlier event cannot pre-authorize a later missing receipt. Missing post-durable evidence remains blocking and cannot be dispositioned through this compatibility path. The CLI exits nonzero when evidence is incomplete, even when the valid-receipt count is zero. Current SDK implementations always emit the new field, while its optional type preserves structural compatibility for existing typed adapters and test fixtures. A structurally valid preferred-era history summary that contains its complete privacy-safe receipt evidence is accepted in place: health counts it as accepted_legacy_merge_receipt_references and does not demand an external receipt file that the older writer never created. Incomplete, contradictory, or modern summaries still fail closed. runMergeReceiptReport remains the compatible valid-only report.

Historical receipt reader compatibility

Tracked by pm-2xtv84 and pm-v66zir. Version-1 preferred-era and identified requested_preference/clone_local receipts may omit base, ours, or theirs when the original value was undefined. Readers normalize those slots to the explicit missing-value marker in memory. They still require retained/discarded evidence and valid collections; reading never rewrites the original file. Collection failures expose a bounded validation_path, such as union_fields or decisions[0]. The diagnostic category collections is not a property that should be added to a receipt. The writer now encodes all five scalar slots itself, including undefined retained/discarded values supplied directly through the SDK, before JSON storage.

Paired clone-local and historical hash-only copies accept the original scalar hash encoding throughout inspection and settlement. Compatibility does not apply to durable copies declaring the modern value policy. Changed values or immutable coordinates remain copy-provenance failures. Hash-only evidence does not recover the original private value.

Receipts from an aborted rebase

Tracked by pm-466m0j. New receipts created during a rebase capture only its original commit and item blob in the typed MergeReceiptOperation contract. After aborting, run:

pm merge reconcile --dry-run --json
pm merge reconcile --message "Record restored original rebase state" --json

Settlement requires Git to have left every active merge/rebase/cherry-pick/revert operation, HEAD to match the original commit, and the item in HEAD, index, and working tree to match the original blob. The item history must already be clean. The history transaction rechecks the proof against its exact protected item snapshot. Apply appends an explicit merge_reconcile event with abandoned_receipts and the reason original_git_state_restored; it then marks both copies reconciled with that settlement reason. The result counts these in receipts.abandoned, separately from applied merge decisions. Preview performs the same eligibility checks and leaves both history and receipts untouched. If receipt persistence fails after the audit commits, retry reuses the identical verified disposition and finishes the receipt writes without appending another audit event. An unrelated earlier audit does not satisfy this check.

Old receipts without operation coordinates remain pending for ordinary review. Tracked merge-receipts/ sidecars are durable provenance and must remain tracked. Deleting or ignoring them would lose the evidence needed by other clones.

Cross-branch id collision safety

Tracked by pm-qx95lz.

Item ids are <prefix> plus random base36 characters. Local allocation reserves both live documents and retained history, but cannot see independent creations on another branch. The four-character default is a small, synchronized-workspace setting; it is not a fleet uniqueness guarantee. ids.token_length accepts 4–12. The allocator increases width after 32 local collisions to escape local density; this does not measure concurrent branch activity.

For a shared base containing n reserved ids and m unsynchronized creations, choose width L so m*(m-1)/(2*(36^L-n)) stays below the desired per-sync collision probability. This birthday union bound assumes independent uniform allocation and all branches know the same reserved ids. At one million reserved ids, eight characters keep 1,000 concurrent creations below one in a million; nine characters do so for 10,000 creations. Configure the width before branching:

pm config project set ids_token_length 8

The SDK item merge refuses an empty common ancestor with item_identity_conflict, even for equal item content: document equality alone cannot prove a common creation. It leaves the driver output untouched instead of combining two identities through scalar preference. The history merge also refuses different create events across its inputs, multiple creates in either input, or creations on both sides when the ancestor lacks a create event even when their bytes match, before fast-forwarding or reanchoring. A common ancestor containing the shared create event remains valid.

storage_integrity detects multiple physical documents and a second create event within one history stream, reporting its line in history_unparseable_streams as an invalid lifecycle. This check also protects merges Git resolves without invoking a content driver. pm get and SDK item lookup refuse multiple physical matches with item_identity_ambiguous; the message lists tracker-relative paths and SDK error context exposes a typed paths array. Format preference cannot select a winner. Only candidate paths are probed, so lookup does not enumerate every item in the workspace.

Preserve both branches when a collision is reported. Recover each item from its unambiguous source branch, create the second under a fresh id, and update its references before retrying the merge. Do not repair a fused stream merely to make its hashes pass: a new hash chain does not recover a lost identity.

Within one working tree, create and copy serialize on the candidate id and recheck every built-in and extension-defined type folder before the authoritative write. A raced collision fails with item_id_collision instead of replacing the existing document.

Executable convergence evidence

pm-1tns7o replaces the tag-only property with generated complete-document comparisons. Fixed branch snapshots are folded in original, reversed, and rotated order, with both ours/theirs directions. Cases cover conflicting scalar writes and bodies, collection additions, distinct and equal timestamps, disjoint edits, and optional-field deletion. Independent expected documents are constructed directly for every N-branch case to check retained values and preserved context. A policy table also asserts that the compatibility preferred_side option is directional. The field-class inventories are pinned so changes require an explicit test update.

These properties exercise the declared three-way policies; they do not turn the document-level timestamp into per-field causal provenance. In particular, the N-branch conflict fixture compares competing writes to the same scalar set. Arbitrary histories, ordered executable test definitions with receiving-clone trust, and relationship-event ordering retain their separate conformance contracts.

Required post-merge gate

Reconciliation resolves receipt discovery and settlement from the requested tracker. An explicit tracker outside Git does not consume clone-local receipts from an unrelated invocation directory; see pm-q5grv5.

After every branch merge that touches .agents/pm, run:

pm merge reconcile --dry-run --json
pm merge reconcile --message "Reconcile merged tracker histories" --json
# Required only to accept a receipt that lacks qualifying exact hash proof:
pm merge reconcile --force --message "Accept reviewed merge decisions" --json

The preview reports every drifted stream and pending receipt without mutation. It applies the same exact-snapshot proof requirement as apply: stale or unprovable receipts appear as failed streams in both modes, tracked by pm-ao0bu9. Lossless receipts do not become discarded-value decisions and reconcile without --force, but pm health reports merge_receipts_pending:<n> and remains non-green until the apply pass settles them. pm history-repair cannot clear that receipt finding. When a drifted item also has a pending receipt, the history_drift remediation map prioritizes pm merge reconcile only when canonical item path, changed-field, and merged-value hash evidence all attribute that finding to one or more receipts loaded from the clone-local Git evidence store or the authoritative durable receipt store. Every field declared by each receipt must match its current merged-value hash, even when only a subset appears in the history reconciliation diff. Disjoint valid receipts may collectively cover a multi-field reconciliation; the audit and settlement then retain every individually proven receipt id. Serialized source claims are ignored. Receipt readers validate the complete bounded schema, safe identifiers, filename and item-path identity, timestamps, and bounded decision structure before a sidecar enters health or reconciliation. Reads use size-preflighted, no-follow regular-file descriptors; durable decision values must conform to the declared bounded-inline policy or remain hash-only. Qualifying durable-only receipts are reloaded from the authoritative store and accepted only after exact canonical item path, declared-field, and merged-value hash verification. Legacy receipts, receipts whose declared fields disagree with their hashes, same-item tampering, and drift on unrelated items fail closed to the normal pm history-repair guidance. Health indexes authoritative evidence once by item and reconciliation uses the same per-item groups with a fixed receipt-only worker pool, so committed sidecars cannot amplify drift scans into unbounded parallel repair work. The machine-executable remediation for a missing receipt reference names pm merge reconcile --dry-run. It never publishes --force as an executable hint: the human-readable summary explains that exact eligible pre-durable coordinates may be dispositioned by a separately reviewed force pass. Ordinary pending lossless receipts retain their unforced apply remediation. Apply-mode reconciliation repeats the same proof against the exact item snapshot used by the audited history rewrite. The audit event and settlement include only the individually proven receipt id, so one valid receipt cannot authorize an untrusted same-item sibling. Failed or unproven receipts remain pending unless the coordinator explicitly reviews and supplies --force. Snapshot verification accepts both the current presence-domain digest and the legacy version-1 scalar digest, so already-written receipts remain repairable; new receipts always use the collision-free presence-domain scheme. Receipts with discarded scalar values retain the distinct merge_decisions_unreviewed:<n> finding. Matching authoritative hash proof allows those receipts to settle without --force; without qualifying proof, the apply pass refuses them until the coordinator explicitly supplies --force after review. The history_drift_merge_receipt remediation may therefore emit an unforced apply command that clears merge_decisions_unreviewed when the receipt proves the exact current merged values. This prevents routine repair from hiding unfinished reconciliation while avoiding redundant force for an already-proven canonical snapshot. The same --force boundary also handles an unrecoverable pre-durable clone-local-only history reference. Preview and apply results expose missing_history_references_before, legacy_disposition_eligible, legacy_disposition_recorded, and missing_history_references_after. When coordinates exceed the bounded health response, explicit result guidance requires repeated dry-run and reviewed force passes until health no longer reports truncated coordinate details and the remaining count is zero. An apply result cannot return ok: true while any missing reference or truncated evidence remains. It exits nonzero while either merge-critical validation check is non-green, so CI and explicit post-merge hooks cannot approve unresolved receipts or drift. The apply pass uses the audited history rewrite boundary to append a merge_reconcile event whose patch reproduces the merged item exactly. The event includes privacy-safe receipt provenance; a clean receipt-bearing stream gets a no-op merge event so the merge remains addressable even when replay already matches. The command immediately validates history drift plus storage integrity and exits nonzero when an invariant remains red. Default Git hooks remain unchanged: repositories that want automatic enforcement must opt in by invoking this command from their own post-merge hook.

The default validation surface includes storage_integrity. It fails on unreadable item documents, history conflict markers, malformed history tails, live items whose latest history operation is delete (a delete/modify resurrection candidate), and unparseable settings/schema files. This prevents the ordinary tolerant read path from turning corruption into a green gate.

A history union can be structurally valid while replayed history and the chosen item document describe different effective state. In that case inspect both authors' events before reconciliation, then run the audited repair:

pm history <item-id> --verify --strict-exit
pm history-repair <item-id> --dry-run
pm history-repair <item-id>
pm merge reconcile --dry-run --json

history-repair records the reconciliation patch and classifies its changed fields against the final item. Append-only collection unions and deterministic reordering are reported as preserved context without a data-loss warning. Fields whose replayed values are actually removed or replaced remain loud with discarded event authors/operations and recovery guidance. Re-apply any intended losing mutation as a normal pm update so it remains explicit and auditable.

History events now declare an item-hash epoch. Epochs are immutable writer contracts, not aliases for the current item serializer: epoch 1 sorts linked tests; epoch 2 preserves their insertion order and has both an earlier field-frozen form and a later expanded form because the writer surface grew before the marker advanced; epoch 3 is the current form. Verification accepts both recorded epoch-2 forms without allowing one entry to mix them, and repair preserves the form evidenced by each event. Unversioned streams are verified against the supported legacy canonicalizations. Current-document comparison selects the resolved epoch candidate that matches the chain head. A union merge may consume suffixes written by both epoch-2 forms, but its synthesized output uses one form for the complete re-anchored stream so every stored after_hash is exactly the next stored before_hash. An unknown explicit epoch is reported as unsupported_item_hash_version and repair refuses to guess. This keeps version incompatibility distinct from item corruption and is tracked by pm-2htk4p and pm-2qahia.

New history events also carry record_hash_version and record_hash. Unlike the item anchors, the record hash covers the complete immutable event: author and agent provenance, timestamp, operation, message, context, patch, item-hash epoch, and before/after anchors. A record that carries only one envelope field, uses an unsupported record epoch, or changes after sealing fails verification. Entries created before this envelope remain readable as explicit item_state_only coverage; they are not presented as record-authenticated.

Every maintenance rewrite verifies a present record hash before changing the stream and reseals the output. When anchors or patch representation change, the entry's append-only reanchor_evidence retains the prior anchors, item epoch, patch digest, and prior record envelope. Lenient repair additionally retains the complete replaced patch operations. verifyHistoryRewriteEvidence() reconstructs every available prior envelope and rejects a record that was modified and merely resealed after maintenance. Redaction never copies sensitive patch values into new evidence: it keeps the digest and drops a retained patch if the patch itself matched a redaction rule. Compaction baselines retain the pruned entry count and ordered stream digest plus an explicit individual_pruned_entries_require_pre_compaction_stream limitation. A holder of the pre-compaction stream can therefore validate the checkpoint, while the post-compaction stream does not falsely claim that it can reconstruct content that was intentionally pruned.

Delete versus modify policy

A delete on one branch and an edit on another is not safely resolvable by a generic file driver. The merged workspace must not silently resurrect the item. storage_integrity reports the live document plus delete-terminated history as a hard finding. The coordinator chooses one policy explicitly:

  • Honor deletion: remove the live item document, keep its append-only history, and commit the resolution.
  • Honor modification: restore/recreate through pm so the history contains an explicit post-delete operation and rationale.

Never remove conflict markers manually while leaving the authoritative item and history semantically inconsistent.

Runtime receipts and retention

transactions/ and checkpoints/ are per-branch crash-recovery state, not shared project context. pm init places both below the resolved tracker root in the managed .gitignore block, including custom --pm-path roots.

Ignore rules do not remove files that were already committed. pm health (integrity) and pm validate (storage_integrity) therefore scan Git's index for tracked files below runtime/, search/, locks/, transactions/, and checkpoints/. A finding includes repository-relative paths plus an exact git rm --cached -r -- ... command. That command removes only the indexed copies; local caches and recovery receipts remain on disk under the managed ignore fence. The intentional search/eval-queries.json relevance-evaluation corpus remains tracked and is excluded from this cache diagnostic.

Terminal SDK transaction journals use the same checkpoints.retention_days policy as rollback checkpoints. The default GC sweep includes both receipt classes:

pm gc --dry-run
pm gc --scope transactions --dry-run
pm gc --scope transactions

Only aged committed or compensated journals are removed. applying, compensating, unreadable, and unparseable journals are always retained so cleanup cannot destroy live recovery state.

Temporary-clone acceptance test

Before releasing merge-contract changes, validate the packed package in a temporary Git repository: initialize pm, install the merge contract, create one base item, branch twice, append disjoint metadata/history on both branches, merge, and run the strict validation commands above. Include a same-key conflict case and prove Git leaves it unresolved while the output remains parseable.

The packed first-run matrix exercises the installed README workflow, a real comment/history merge, and MCP on supported platforms.


Merge_safety remote
Report an issue