@unbrained/pm-cli 2026.10.21 → 2026.10.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +134 -77
- package/dist/cli/error-guidance.d.ts +12 -0
- package/dist/cli/error-guidance.js +2 -2
- package/dist/cli/register-setup.js +1 -1
- package/dist/cli-bundle/bundle-manifest.json +1 -1
- package/dist/cli-bundle/chunks/{chunk-DIR3YEFD.js → chunk-2LTGJ5DL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-EMGMLKRV.js → chunk-2UX2TAN2.js} +15 -15
- package/dist/cli-bundle/chunks/{chunk-2B5HAZFK.js → chunk-3S5FLCG7.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-5DKCD4KV.js +126 -0
- package/dist/cli-bundle/chunks/{chunk-V3XONSVC.js → chunk-5V4HU6GK.js} +48 -48
- package/dist/cli-bundle/chunks/{chunk-QPV6UD55.js → chunk-AAX7CNL7.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TMXWWOPJ.js → chunk-AXGFNNI3.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-F76ZUP73.js +113 -0
- package/dist/cli-bundle/chunks/chunk-HDKY2YX3.js +3 -0
- package/dist/cli-bundle/chunks/{chunk-DR6DUBTU.js → chunk-KY34HTT2.js} +29 -29
- package/dist/cli-bundle/chunks/chunk-MMVX5L32.js +20 -0
- package/dist/cli-bundle/chunks/{chunk-C6SAXKBO.js → chunk-MTRYEVZR.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-QSY55FTA.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-GWIGZDRS.js → chunk-R7KWBFM2.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5PZ7JNMI.js → chunk-REXCO5AG.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-ZDVTXLA6.js +9 -0
- package/dist/cli-bundle/chunks/{chunk-DJQVNDXO.js → chunk-ZEI3DC5E.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-MOC5BJHW.js → chunk-ZMJF5HQW.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-ZNDYAZZ6.js +6 -0
- package/dist/cli-bundle/chunks/{indexed-receipt-blobs-65XXSPPR.js → indexed-receipt-blobs-XANVELIV.js} +2 -2
- package/dist/cli-bundle/chunks/{mutation-admission-FNWOVJLN.js → mutation-admission-P6LOBNLO.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-6PT5Y2EZ.js → register-list-query-JOB65KDN.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-TAIQV46L.js → register-mutation-QMNIN3RJ.js} +2 -2
- package/dist/cli-bundle/chunks/{register-operations-ONIRO22G.js → register-operations-Z4VET3I7.js} +2 -2
- package/dist/cli-bundle/chunks/register-setup-GNKWL3VL.js +2 -0
- package/dist/cli-bundle/chunks/{settlement-hook-UVFYSBMU.js → settlement-hook-YUVCO65H.js} +2 -2
- package/dist/cli-bundle/chunks/{stage-FCPVFO3B.js → stage-FW5OXCCR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-VD64TPXI.js → chunk-4MNUQCGR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-6GTZ24YV.js +3 -0
- package/dist/cli-bundle/focused-chunks/{chunk-XE7P7N5X.js → chunk-BM652VCB.js} +6 -6
- package/dist/cli-bundle/focused-chunks/{chunk-3LWH2RJC.js → chunk-BUZ2Z4P3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-CGL36F6I.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-KVYUQS6Y.js → chunk-DWQMYLFM.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-4HJVAUFX.js → chunk-EDXTOAXP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-FO4U3FIP.js +91 -0
- package/dist/cli-bundle/focused-chunks/chunk-GXKP56W7.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-I2USTQNQ.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-44353U27.js → chunk-JDN34LEZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-CUWNNU4N.js → chunk-KI5YFKNN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-7UD7XTOE.js → chunk-LEHGCPZ6.js} +11 -11
- package/dist/cli-bundle/focused-chunks/{chunk-HNCMYF2W.js → chunk-MLET6I3I.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-PDOWLRHC.js → chunk-NSMZY6IK.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-OMXMYTEX.js +26 -0
- package/dist/cli-bundle/focused-chunks/{chunk-JI3RXXRN.js → chunk-P7DPS5M4.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-R536272H.js +9 -0
- package/dist/cli-bundle/focused-chunks/{chunk-5IMM7GOF.js → chunk-UNTCCJPL.js} +3 -3
- package/dist/cli-bundle/focused-chunks/{chunk-32ZKLRWM.js → chunk-XIZYJDYW.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-Z5LDTMZ3.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-ZHMF34DT.js +65 -0
- package/dist/cli-bundle/focused-chunks/{chunk-P5D7MHDS.js → chunk-ZR6ZKQUK.js} +15 -15
- package/dist/cli-bundle/focused-chunks/{indexed-receipt-blobs-CRP6HAZY.js → indexed-receipt-blobs-FVOA3XMI.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{mutation-admission-KM57KDDF.js → mutation-admission-HTFAIHJL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{settlement-hook-MNCHFCAX.js → settlement-hook-2VXEB6PP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{stage-UJYGWNZ7.js → stage-X3BUGEJT.js} +2 -2
- package/dist/cli-bundle/main.js +21 -21
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +5 -2
- package/dist/cli-bundle/sdk-core.js +33 -33
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +58 -58
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +12 -9
- package/dist/core/config/nested-settings.js +1 -1
- package/dist/core/extensions/loader.js +1 -1
- package/dist/core/extensions/version-diagnostics.d.ts +2 -0
- package/dist/core/extensions/version-diagnostics.js +2 -0
- package/dist/core/lock/lock.d.ts +40 -6
- package/dist/core/lock/lock.js +3 -3
- package/dist/core/shared/errors.d.ts +28 -0
- package/dist/core/shared/errors.js +1 -1
- package/dist/core/store/item-store.js +1 -1
- package/dist/mcp/http-server.js +2 -2
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +2 -2
- package/dist/sdk/agent/command-recovery.d.ts +2 -0
- package/dist/sdk/agent/command-recovery.js +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +1 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +6 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1
- package/dist/sdk/context-intent-contracts.d.ts +13 -0
- package/dist/sdk/context-intent-contracts.js +1 -1
- package/dist/sdk/contracts.d.ts +2 -1
- package/dist/sdk/contracts.js +1 -1
- package/dist/sdk/core.d.ts +2 -2
- package/dist/sdk/core.js +1 -1
- package/dist/sdk/define.d.ts +15 -16
- package/dist/sdk/define.js +1 -1
- package/dist/sdk/dependencies.js +1 -1
- package/dist/sdk/extension/doctor.js +1 -1
- package/dist/sdk/extension/install-receipts.js +1 -1
- package/dist/sdk/extension/install-snapshot.d.ts +11 -0
- package/dist/sdk/extension/install-snapshot.js +1 -1
- package/dist/sdk/extension.d.ts +12 -0
- package/dist/sdk/extension.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
- package/dist/sdk/governance/health.d.ts +1 -0
- package/dist/sdk/governance/health.js +2 -2
- package/dist/sdk/index.d.ts +3 -2
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -1
- package/dist/sdk/lifecycle/restore.js +1 -1
- package/dist/sdk/mcp/executable.d.ts +13 -0
- package/dist/sdk/mcp/executable.js +5 -0
- package/dist/sdk/merge/install.js +2 -2
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/context.d.ts +5 -0
- package/dist/sdk/query/context.js +2 -2
- package/dist/sdk/read-output/session-result.d.ts +39 -0
- package/dist/sdk/read-output/session-result.js +2 -0
- package/dist/sdk/read-output-contracts.d.ts +18 -5
- package/dist/sdk/read-output-contracts.js +1 -1
- package/dist/sdk/read-output-session.d.ts +2 -0
- package/dist/sdk/read-output-session.js +1 -1
- package/dist/sdk/relationship-context.js +1 -1
- package/dist/sdk/runtime-input.js +1 -1
- package/dist/sdk/runtime-primitives.d.ts +7 -1
- package/dist/sdk/runtime-primitives.js +1 -1
- package/dist/sdk/runtime.d.ts +11 -9
- package/dist/sdk/runtime.js +1 -1
- package/dist/sdk/workspace-snapshot.d.ts +5 -1
- package/dist/sdk/workspace-snapshot.js +3 -3
- package/dist/sdk/workspace.d.ts +3 -1
- package/dist/sdk/workspace.js +8 -5
- package/docs/CONFIGURATION.md +28 -3
- package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +30 -0
- package/docs/EXTENSION_AUTHOR_CONTRACTS.md +2 -1
- package/docs/EXTENSION_LIFECYCLE.md +47 -0
- package/docs/MCP_OPTION_CONFORMANCE.md +27 -1
- package/docs/MCP_REMOTE_TRANSPORT_SECURITY.md +16 -1
- package/docs/MERGE_SAFETY.md +8 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +79 -0
- package/docs/RELATIONSHIP_GRAPH.md +15 -0
- package/docs/RELEASING.md +17 -0
- package/docs/SDK.md +76 -12
- package/docs/SDK_STORAGE_LIFECYCLE.md +2 -1
- package/docs/TESTING.md +16 -7
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +6 -3
- package/marketplace.json +1 -1
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/package.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/package.json +1 -1
- package/plugins/pm-codex/plugin.json +1 -1
- package/runtime-dependencies.json +1 -1
- package/dist/cli-bundle/chunks/chunk-4OYU5OXQ.js +0 -6
- package/dist/cli-bundle/chunks/chunk-DIKQ2AL5.js +0 -2
- package/dist/cli-bundle/chunks/chunk-KBSVPUFD.js +0 -113
- package/dist/cli-bundle/chunks/chunk-MZZIAC6S.js +0 -20
- package/dist/cli-bundle/chunks/chunk-NNB65OOO.js +0 -3
- package/dist/cli-bundle/chunks/chunk-V5GJTXYW.js +0 -126
- package/dist/cli-bundle/chunks/chunk-ZNKFMIVA.js +0 -6
- package/dist/cli-bundle/chunks/register-setup-OQMUZBJV.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-6QSZHRM7.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-E2S42XCT.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-GRSQGMRR.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-IAGFXKMZ.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-JMZPZQHR.js +0 -26
- package/dist/cli-bundle/focused-chunks/chunk-O3M6YWVL.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-T27TLSEU.js +0 -65
- package/dist/cli-bundle/focused-chunks/chunk-VE6MTRH5.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-YIWDX6KO.js +0 -91
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="930f2c41-96dd-5812-9cbb-c0fa4ee620c2")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{normalizeItemFormatVersion,requiredItemFormatVersion}from"../../core/item/item-format-version.js";import{assertProjectRuntimeFormatGuard}from"../environment/project-runtime-compatibility.js";import{enforceWorkflowMutation}from"../../core/policy/workflow-policy-store.js";import jsonPatch from"fast-json-patch";import fs from"node:fs/promises";import{readLocatedItemSnapshot}from"../../core/store/item-store.js";import{readHistorySnapshot}from"../../core/history/read.js";import{verifyHistoryRewriteNoDrift}from"../../core/history/history-rewrite.js";import{resolveHistorySubject}from"../history/subject.js";import{historyVersionOffset}from"../../core/history/version-address.js";import{writeFileAtomic,appendHistoryEntry,createHistoryEntry,replayToCanonicalItemDocument,replayToItemDocument,toReplayDocument,enforceHistoryStreamPolicyForItem,canonicalDocument,serializeItemDocument,resolveItemTypeRegistry,acquireLock,EXIT_CODE,PmCliError,nowIso,getActiveExtensionRegistrations,projectAfterCommandItemSnapshot,recordAfterCommandAffectedItem,runActiveOnWriteHooks,runActiveBeforeMutationHooks,createMutationGuardSdk,getItemPath,resolvePmRoot,resolveWorkspaceRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{applyHistoryPatch,ensureMaterializedHistoryTarget as ensureMaterializedRestoreTarget,extractPatchFailureContext,replayHistoryToTarget as replayToTarget,resolveHistoryTarget}from"../history-read.js";import{acquireItemMetadataDerivedIndexLock,refreshItemMetadataDerivedIndex}from"../item-metadata-index.js";async function readRestoreItem(located,settings,history){const snapshot=await readLocatedItemSnapshot(located,{schema:settings.schema});return snapshot.error===null?{raw:snapshot.raw,document:snapshot.document}:{raw:snapshot.raw,document:replayCurrentDocument(history),recovered:!0}}function ensureReplayTarget(target,history){return resolveHistoryTarget(target,history,{errorSubject:"restore",allowFutureTimestamp:!0})}function replayCurrentDocument(history){const currentReplay=replayToTarget(history,history.length-1);return Object.keys(currentReplay.metadata).length===0?{metadata:{},body:currentReplay.body}:canonicalDocument(replayToItemDocument(currentReplay))}async function resolveRestoreSubject(pmRoot,id,settings,typeToFolder){const subject=await resolveHistorySubject(pmRoot,id,settings,typeToFolder),historyPolicy=subject.located?await enforceHistoryStreamPolicyForItem({pmRoot,settings,itemId:subject.id,commandLabel:"restore"}):{warnings:[]};return{...subject,historyPolicyWarnings:historyPolicy.warnings}}function changedFields(beforeDocument,afterDocument){const beforeReplay=toReplayDocument(beforeDocument),afterReplay=toReplayDocument(afterDocument),patch=jsonPatch.compare(beforeReplay,afterReplay),fields=new Set;for(const op of patch){if(op.path==="/body"||op.path.startsWith("/body/")){fields.add("body");continue}const segment=op.path.replace(/^\/(?:metadata|front_matter)\/?/,"").split("/")[0];fields.add(segment.replaceAll("~1","/").replaceAll("~0","~"))}return Array.from(fields).sort((a,b)=>a.localeCompare(b))}async function loadRestoreStateUnderLock(params){const verified=await verifyHistoryRewriteNoDrift({pmRoot:params.pmRoot,subject:params.subject,settings:params.settings,typeRegistry:params.typeRegistry,historyRawBeforeLock:params.historyRawBeforeLock,currentItemRawBeforeLock:params.currentItemRawBeforeLock,operation:"restore",readItem:located=>readRestoreItem(located,params.settings,params.history)});return{loadedItemUnderLock:verified.loadedItemUnderLock,existingItemPath:verified.locatedUnderLock?.itemPath??null}}function resolveRestoreCurrentState(loadedItemUnderLock,history){return loadedItemUnderLock?{document:loadedItemUnderLock.document,originalRaw:loadedItemUnderLock.raw}:{document:replayCurrentDocument(history),originalRaw:null}}function collectRestoreOwnershipWarnings(params){const assigned=params.document.metadata.assignee?.trim();if(!(assigned&&assigned!==params.author&&!params.force))return[];if(params.enforcement==="strict")throw new PmCliError(`Item ${params.resolvedId} is assigned to ${assigned}. Use --force to override.`,EXIT_CODE.CONFLICT);return params.enforcement==="warn"?[`ownership_warning:assignee_conflict:${params.resolvedId}:${assigned}`]:[]}async function restorePreviousItemAfterHistoryFailure(params){if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null&¶ms.restoredItemPath!==params.existingItemPath){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw),await fs.rm(params.restoredItemPath,{force:!0});return}if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw);return}await fs.rm(params.restoredItemPath,{force:!0})}async function runRestoreWriteHooks(params){return[...await runActiveOnWriteHooks({path:params.restoredItemPath,scope:"project",op:"restore",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]}),...await runActiveOnWriteHooks({path:params.historyPath,scope:"project",op:"restore:history",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]})]}async function runRestore(id,target,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),subject=await resolveRestoreSubject(pmRoot,id,settings,typeRegistry.type_to_folder),resolvedId=subject.id,{raw:historyRawBeforeLock,entries:history}=await readHistorySnapshot(subject.historyPath,resolvedId);if(history.length===0)throw new PmCliError(`No history exists for ${resolvedId}; restore is unavailable.`,EXIT_CODE.NOT_FOUND);const resolvedTarget=ensureReplayTarget(target,history),replayDocument=ensureMaterializedRestoreTarget(replayToTarget(history,resolvedTarget.historyIndex),resolvedTarget),restoredDocument=replayToCanonicalItemDocument(replayDocument,{schema:settings.schema});if(restoredDocument.metadata.id!==resolvedId)throw new PmCliError(`Restore target resolved to item ${restoredDocument.metadata.id}, expected ${resolvedId}.`,EXIT_CODE.GENERIC_FAILURE);const currentItemRawBeforeLock=(subject.located?await readRestoreItem(subject.located,settings,history):null)?.raw??null,author=resolveAuthor(options.author,settings.author_default),releaseLock=await acquireLock(pmRoot,resolvedId,settings.locks.ttl_seconds,author,!!options.force,settings.governance.force_required_for_stale_lock,settings.locks.wait_ms);try{const{loadedItemUnderLock,existingItemPath}=await loadRestoreStateUnderLock({pmRoot,subject,settings,typeRegistry,historyRawBeforeLock,currentItemRawBeforeLock,history}),itemFormat="toon",currentState=resolveRestoreCurrentState(loadedItemUnderLock,history);restoredDocument.metadata.pm_format_version=normalizeItemFormatVersion(Math.max(requiredItemFormatVersion(restoredDocument.metadata),requiredItemFormatVersion(currentState.document.metadata))),assertProjectRuntimeFormatGuard(resolveWorkspaceRoot(pmRoot),requiredItemFormatVersion(restoredDocument.metadata));const ownershipWarnings=collectRestoreOwnershipWarnings({document:currentState.document,author,force:options.force,enforcement:settings.governance.ownership_enforcement,resolvedId}),restoreChangedFields=changedFields(currentState.document,restoredDocument),workflowPolicy=await enforceWorkflowMutation({pmRoot,settings,operation:"restore",author,before:currentState.document,after:restoredDocument});await runActiveBeforeMutationHooks({pm_root:pmRoot,operation:"restore",before:currentState.document,after:restoredDocument,changed_fields:restoreChangedFields,sdk:createMutationGuardSdk({pmRoot,settings,typeToFolder:typeRegistry.type_to_folder})});const serializedRestore=serializeItemDocument(restoredDocument,{format:itemFormat,schema:settings.schema}),restoredItemPath=getItemPath(pmRoot,restoredDocument.metadata.type,resolvedId,itemFormat,typeRegistry.type_to_folder),releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(pmRoot,author);let derivedIndexWarnings=[];try{await writeFileAtomic(restoredItemPath,serializedRestore),existingItemPath&&restoredItemPath!==existingItemPath&&await fs.rm(existingItemPath);const historyEntry=createHistoryEntry({nowIso:nowIso(),author,op:"restore",before:currentState.document,after:restoredDocument,message:options.message,context:workflowPolicy.decisions.length===0?void 0:{workflow_policies:workflowPolicy.decisions}});try{await appendHistoryEntry(subject.historyPath,historyEntry)}catch(error){throw await restorePreviousItemAfterHistoryFailure({existingItemPath,resolvedOriginalRaw:currentState.originalRaw,restoredItemPath}),error}derivedIndexWarnings=await refreshItemMetadataDerivedIndex({pmRoot,preferredFormat:settings.item_format,typeToFolder:typeRegistry.type_to_folder,schema:settings.schema,itemPath:restoredItemPath,previousItemPath:existingItemPath??void 0,document:restoredDocument})}finally{await releaseDerivedIndexLock()}const hookWarnings=await runRestoreWriteHooks({restoredItemPath,historyPath:subject.historyPath,before:currentState.document,after:restoredDocument});recordAfterCommandAffectedItem({id:restoredDocument.metadata.id,op:"restore",item_type:restoredDocument.metadata.type,previous_status:currentState.document.metadata.status,status:restoredDocument.metadata.status,previous:projectAfterCommandItemSnapshot(currentState.document.metadata,restoreChangedFields),current:projectAfterCommandItemSnapshot(restoredDocument.metadata,restoreChangedFields),changed_fields:restoreChangedFields});const targetEntry=history[resolvedTarget.historyIndex],offset=historyVersionOffset(history,!0);return{item:restoredDocument.metadata,restored_from:{kind:resolvedTarget.kind,target:resolvedTarget.raw,history_index:resolvedTarget.historyIndex+1,version:offset===null?null:offset+resolvedTarget.historyIndex+1,entry_ts:targetEntry.ts,entry_op:targetEntry.op},changed_fields:restoreChangedFields,warnings:[...workflowPolicy.warnings,...loadedItemUnderLock?.recovered?["restore_unreadable_item_recovered"]:[],...subject.historyPolicyWarnings,...ownershipWarnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}const _testOnlyRestoreCommand={applyHistoryPatch,changedFields,ensureMaterializedRestoreTarget,ensureReplayTarget,extractPatchFailureContext,replayCurrentDocument,replayToTarget,resolveRestoreSubject};export{_testOnlyRestoreCommand,runRestore};
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ce212ffb-1f13-5893-9690-31dbb4e0de13")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{normalizeItemFormatVersion,requiredItemFormatVersion}from"../../core/item/item-format-version.js";import{assertProjectRuntimeFormatGuard}from"../environment/project-runtime-compatibility.js";import{enforceWorkflowMutation}from"../../core/policy/workflow-policy-store.js";import jsonPatch from"fast-json-patch";import fs from"node:fs/promises";import{readLocatedItemSnapshot}from"../../core/store/item-store.js";import{readHistorySnapshot}from"../../core/history/read.js";import{verifyHistoryRewriteNoDrift}from"../../core/history/history-rewrite.js";import{resolveHistorySubject}from"../history/subject.js";import{historyVersionOffset}from"../../core/history/version-address.js";import{writeFileAtomic,appendHistoryEntry,createHistoryEntry,replayToCanonicalItemDocument,replayToItemDocument,toReplayDocument,enforceHistoryStreamPolicyForItem,canonicalDocument,serializeItemDocument,resolveItemTypeRegistry,acquireLockLease,EXIT_CODE,PmCliError,nowIso,getActiveExtensionRegistrations,projectAfterCommandItemSnapshot,recordAfterCommandAffectedItem,runActiveOnWriteHooks,runActiveBeforeMutationHooks,createMutationGuardSdk,getItemPath,resolvePmRoot,resolveWorkspaceRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{applyHistoryPatch,ensureMaterializedHistoryTarget as ensureMaterializedRestoreTarget,extractPatchFailureContext,replayHistoryToTarget as replayToTarget,resolveHistoryTarget}from"../history-read.js";import{acquireItemMetadataDerivedIndexLock,refreshItemMetadataDerivedIndex}from"../item-metadata-index.js";async function readRestoreItem(located,settings,history){const snapshot=await readLocatedItemSnapshot(located,{schema:settings.schema});return snapshot.error===null?{raw:snapshot.raw,document:snapshot.document}:{raw:snapshot.raw,document:replayCurrentDocument(history),recovered:!0}}function ensureReplayTarget(target,history){return resolveHistoryTarget(target,history,{errorSubject:"restore",allowFutureTimestamp:!0})}function replayCurrentDocument(history){const currentReplay=replayToTarget(history,history.length-1);return Object.keys(currentReplay.metadata).length===0?{metadata:{},body:currentReplay.body}:canonicalDocument(replayToItemDocument(currentReplay))}async function resolveRestoreSubject(pmRoot,id,settings,typeToFolder){const subject=await resolveHistorySubject(pmRoot,id,settings,typeToFolder),historyPolicy=subject.located?await enforceHistoryStreamPolicyForItem({pmRoot,settings,itemId:subject.id,commandLabel:"restore"}):{warnings:[]};return{...subject,historyPolicyWarnings:historyPolicy.warnings}}function changedFields(beforeDocument,afterDocument){const beforeReplay=toReplayDocument(beforeDocument),afterReplay=toReplayDocument(afterDocument),patch=jsonPatch.compare(beforeReplay,afterReplay),fields=new Set;for(const op of patch){if(op.path==="/body"||op.path.startsWith("/body/")){fields.add("body");continue}const segment=op.path.replace(/^\/(?:metadata|front_matter)\/?/,"").split("/")[0];fields.add(segment.replaceAll("~1","/").replaceAll("~0","~"))}return Array.from(fields).sort((a,b)=>a.localeCompare(b))}async function loadRestoreStateUnderLock(params){const verified=await verifyHistoryRewriteNoDrift({pmRoot:params.pmRoot,subject:params.subject,settings:params.settings,typeRegistry:params.typeRegistry,historyRawBeforeLock:params.historyRawBeforeLock,currentItemRawBeforeLock:params.currentItemRawBeforeLock,operation:"restore",readItem:located=>readRestoreItem(located,params.settings,params.history)});return{loadedItemUnderLock:verified.loadedItemUnderLock,existingItemPath:verified.locatedUnderLock?.itemPath??null}}function resolveRestoreCurrentState(loadedItemUnderLock,history){return loadedItemUnderLock?{document:loadedItemUnderLock.document,originalRaw:loadedItemUnderLock.raw}:{document:replayCurrentDocument(history),originalRaw:null}}function collectRestoreOwnershipWarnings(params){const assigned=params.document.metadata.assignee?.trim();if(!(assigned&&assigned!==params.author&&!params.force))return[];if(params.enforcement==="strict")throw new PmCliError(`Item ${params.resolvedId} is assigned to ${assigned}. Use --force to override.`,EXIT_CODE.CONFLICT);return params.enforcement==="warn"?[`ownership_warning:assignee_conflict:${params.resolvedId}:${assigned}`]:[]}async function restorePreviousItemAfterHistoryFailure(params){if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null&¶ms.restoredItemPath!==params.existingItemPath){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw),await fs.rm(params.restoredItemPath,{force:!0});return}if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw);return}await fs.rm(params.restoredItemPath,{force:!0})}async function runRestoreWriteHooks(params){return[...await runActiveOnWriteHooks({path:params.restoredItemPath,scope:"project",op:"restore",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]}),...await runActiveOnWriteHooks({path:params.historyPath,scope:"project",op:"restore:history",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]})]}async function runRestore(id,target,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),subject=await resolveRestoreSubject(pmRoot,id,settings,typeRegistry.type_to_folder),resolvedId=subject.id,{raw:historyRawBeforeLock,entries:history}=await readHistorySnapshot(subject.historyPath,resolvedId);if(history.length===0)throw new PmCliError(`No history exists for ${resolvedId}; restore is unavailable.`,EXIT_CODE.NOT_FOUND);const resolvedTarget=ensureReplayTarget(target,history),replayDocument=ensureMaterializedRestoreTarget(replayToTarget(history,resolvedTarget.historyIndex),resolvedTarget),restoredDocument=replayToCanonicalItemDocument(replayDocument,{schema:settings.schema});if(restoredDocument.metadata.id!==resolvedId)throw new PmCliError(`Restore target resolved to item ${restoredDocument.metadata.id}, expected ${resolvedId}.`,EXIT_CODE.GENERIC_FAILURE);const currentItemRawBeforeLock=(subject.located?await readRestoreItem(subject.located,settings,history):null)?.raw??null,author=resolveAuthor(options.author,settings.author_default),lease=await acquireLockLease(pmRoot,resolvedId,settings.locks.ttl_seconds,author,!!options.force,settings.governance.force_required_for_stale_lock,settings.locks.wait_ms,{waitPolicy:"progress"}),releaseLock=lease.release;try{const{loadedItemUnderLock,existingItemPath}=await loadRestoreStateUnderLock({pmRoot,subject,settings,typeRegistry,historyRawBeforeLock,currentItemRawBeforeLock,history}),itemFormat="toon",currentState=resolveRestoreCurrentState(loadedItemUnderLock,history);restoredDocument.metadata.pm_format_version=normalizeItemFormatVersion(Math.max(requiredItemFormatVersion(restoredDocument.metadata),requiredItemFormatVersion(currentState.document.metadata))),assertProjectRuntimeFormatGuard(resolveWorkspaceRoot(pmRoot),requiredItemFormatVersion(restoredDocument.metadata));const ownershipWarnings=collectRestoreOwnershipWarnings({document:currentState.document,author,force:options.force,enforcement:settings.governance.ownership_enforcement,resolvedId}),restoreChangedFields=changedFields(currentState.document,restoredDocument),workflowPolicy=await enforceWorkflowMutation({pmRoot,settings,operation:"restore",author,before:currentState.document,after:restoredDocument});await runActiveBeforeMutationHooks({pm_root:pmRoot,operation:"restore",before:currentState.document,after:restoredDocument,changed_fields:restoreChangedFields,sdk:createMutationGuardSdk({pmRoot,settings,typeToFolder:typeRegistry.type_to_folder})});const serializedRestore=serializeItemDocument(restoredDocument,{format:itemFormat,schema:settings.schema}),restoredItemPath=getItemPath(pmRoot,restoredDocument.metadata.type,resolvedId,itemFormat,typeRegistry.type_to_folder),derivedIndexWarnings=await lease.fence(async()=>{const releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(pmRoot,author);let derivedIndexWarnings2;try{await writeFileAtomic(restoredItemPath,serializedRestore),existingItemPath&&restoredItemPath!==existingItemPath&&await fs.rm(existingItemPath);const historyEntry=createHistoryEntry({nowIso:nowIso(),author,op:"restore",before:currentState.document,after:restoredDocument,message:options.message,context:workflowPolicy.decisions.length===0?void 0:{workflow_policies:workflowPolicy.decisions}});try{await appendHistoryEntry(subject.historyPath,historyEntry)}catch(error){throw await restorePreviousItemAfterHistoryFailure({existingItemPath,resolvedOriginalRaw:currentState.originalRaw,restoredItemPath}),error}derivedIndexWarnings2=await refreshItemMetadataDerivedIndex({pmRoot,preferredFormat:settings.item_format,typeToFolder:typeRegistry.type_to_folder,schema:settings.schema,itemPath:restoredItemPath,previousItemPath:existingItemPath??void 0,document:restoredDocument})}finally{await releaseDerivedIndexLock()}return derivedIndexWarnings2}),hookWarnings=await runRestoreWriteHooks({restoredItemPath,historyPath:subject.historyPath,before:currentState.document,after:restoredDocument});recordAfterCommandAffectedItem({id:restoredDocument.metadata.id,op:"restore",item_type:restoredDocument.metadata.type,previous_status:currentState.document.metadata.status,status:restoredDocument.metadata.status,previous:projectAfterCommandItemSnapshot(currentState.document.metadata,restoreChangedFields),current:projectAfterCommandItemSnapshot(restoredDocument.metadata,restoreChangedFields),changed_fields:restoreChangedFields});const targetEntry=history[resolvedTarget.historyIndex],offset=historyVersionOffset(history,!0);return{item:restoredDocument.metadata,restored_from:{kind:resolvedTarget.kind,target:resolvedTarget.raw,history_index:resolvedTarget.historyIndex+1,version:offset===null?null:offset+resolvedTarget.historyIndex+1,entry_ts:targetEntry.ts,entry_op:targetEntry.op},changed_fields:restoreChangedFields,warnings:[...workflowPolicy.warnings,...loadedItemUnderLock?.recovered?["restore_unreadable_item_recovered"]:[],...subject.historyPolicyWarnings,...ownershipWarnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}const _testOnlyRestoreCommand={applyHistoryPatch,changedFields,ensureMaterializedRestoreTarget,ensureReplayTarget,extractPatchFailureContext,replayCurrentDocument,replayToTarget,resolveRestoreSubject};export{_testOnlyRestoreCommand,runRestore};
|
|
2
2
|
//# sourceMappingURL=restore.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Transport selected by an MCP executable or embedded launcher. */
|
|
2
|
+
export type PmMcpExecutableTransport = "stdio" | "http";
|
|
3
|
+
/** Pure startup decision that a host renders before opening stdin or a listener. */
|
|
4
|
+
export type PmMcpExecutableInvocation = {
|
|
5
|
+
kind:"serve";
|
|
6
|
+
} | {
|
|
7
|
+
kind:"exit";
|
|
8
|
+
exitCode:0 | 64;
|
|
9
|
+
stdout:string;
|
|
10
|
+
stderr:string;
|
|
11
|
+
};
|
|
12
|
+
/** Resolve help/version/usage before the host reads environment settings or starts serving. */
|
|
13
|
+
export declare function resolvePmMcpExecutableInvocation(argv:readonly string[],transport:PmMcpExecutableTransport,version:string):PmMcpExecutableInvocation;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d4a56906-c542-567e-9265-15184a5c330b")}catch{}})();import{PM_MCP_LEGACY_PROTOCOL_VERSIONS,PM_MCP_SUPPORTED_PROTOCOL_VERSIONS}from"./protocol.js";const PROBE_FLAGS=new Set(["--help","-h","--version","-V"]);function executableHelp(transport,version){const lines=[`Usage: ${transport==="stdio"?"pm-mcp":"pm-mcp-http"} [--help | --version]`,"",transport==="stdio"?"JSON-RPC over stdin/stdout. With no arguments, starts the stdio server.":"Streamable HTTP POST /mcp. With no arguments, starts the HTTP server.","","Options:"," -h, --help Print help and exit before transport startup."," -V, --version Print the package version and exit.","","Environment:"," PM_PATH Tracker root (otherwise discovered from cwd)."," PM_GLOBAL_PATH Global settings root."," PM_MCP_PROFILE core (default), standard, full, or custom."," PM_MCP_TOOLS Comma-separated tool allowlist for custom profile."," PM_MCP_DISCOVERY_CURSOR_KEY Shared discovery cursor secret, at least 32 UTF-8 bytes."," PM_MCP_BAGGAGE_ALLOWLIST Comma-separated permitted trace baggage keys."];return transport==="http"&&lines.push(" PM_MCP_HTTP_HOST Bind host (default 127.0.0.1)."," PM_MCP_HTTP_PORT Bind port, 0..65535 (default 3000)."," PM_MCP_HTTP_ALLOWED_ORIGINS Comma-separated exact browser origins (default none)."," PM_MCP_HTTP_BEARER_TOKEN Deployment token for the bundled verifier."," PM_MCP_HTTP_AUTH_ISSUER Exact HTTPS authorization-server issuer."," PM_MCP_HTTP_RESOURCE Canonical resource/audience URI."," PM_MCP_HTTP_SCOPES Space-separated scopes (default pm:read pm:write).","","Non-loopback HTTP requires bearer token, issuer, and resource together."),lines.push("",`MCP protocol: ${PM_MCP_SUPPORTED_PROTOCOL_VERSIONS.join(", ")}.`,transport==="stdio"?`Legacy initialize compatibility: ${PM_MCP_LEGACY_PROTOCOL_VERSIONS.join(", ")}.`:"HTTP requires modern per-request metadata; legacy initialize is stdio-only.","",transport==="stdio"?"Client configuration:":"Example loopback server:",transport==="stdio"?JSON.stringify({mcpServers:{pm:{command:"npx",args:["--yes","--package",`@unbrained/pm-cli@${version}`,"pm-mcp"]}}}):`PM_MCP_HTTP_PORT=3000 npx --yes --package @unbrained/pm-cli@${version} pm-mcp-http`,...transport==="http"?["HTTP client configuration:",JSON.stringify({mcpServers:{pm:{url:"http://127.0.0.1:3000/mcp"}}})]:[],"","Configuration: https://github.com/unbraind/pm-cli/blob/main/docs/MCP_REMOTE_TRANSPORT_SECURITY.md",""),lines.join(`
|
|
2
|
+
`)}function resolvePmMcpExecutableInvocation(argv,transport,version){if(argv.length===0)return{kind:"serve"};const unknown=argv.find(argument=>!PROBE_FLAGS.has(argument));if(unknown!==void 0){const name=transport==="stdio"?"pm-mcp":"pm-mcp-http";return{kind:"exit",exitCode:64,stdout:"",stderr:`Unsupported argument ${JSON.stringify(unknown)}. Run ${name} --help.
|
|
3
|
+
`}}return{kind:"exit",exitCode:0,stdout:argv.includes("--help")||argv.includes("-h")?executableHelp(transport,version):`${version}
|
|
4
|
+
`,stderr:""}}export{resolvePmMcpExecutableInvocation};
|
|
5
|
+
//# sourceMappingURL=executable.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="da37bda1-1520-5db0-9dad-bb1acc556de8")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isFileMissingError,readFileIfExists,writeFileAtomic}from"../../core/fs/fs-utils.js";import{access,readFile,realpath}from"node:fs/promises";import{constants}from"node:fs";import{execFile}from"node:child_process";import path from"node:path";import{promisify}from"node:util";import{pathExists}from"../../core/fs/fs-utils.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{acquireLock}from"../../core/lock/lock.js";import{resolvePmPackageRootFromModule}from"../../core/packages/root.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolveAuthor}from"../../core/shared/author.js";import{nowIso}from"../../core/shared/time.js";import{resolvePmRoot}from"../../core/store/paths.js";import{readSettings,resolveGovernanceKnobs}from"../../core/store/settings.js";import{isPathOutsideRoot}from"../workspace.js";import{resolveSourceContextWritePolicy}from"../environment/source-context.js";import{gitWorkspaceEnvironment,resolveMergeDriverConfigScope,writeMergeDriverGitConfig}from"./worktree-config.js";import{discoverProjectRuntimeVersionPins}from"../environment/project-runtime-compatibility.js";const execFileAsync=promisify(execFile),PM_GITATTRIBUTES_START="# pm-cli:merge-drivers:start",PM_GITATTRIBUTES_END="# pm-cli:merge-drivers:end",PM_GITATTRIBUTES_V2_START="# pm-cli:merge-drivers:v2:start",PM_GITATTRIBUTES_V2_END="# pm-cli:merge-drivers:v2:end",MERGE_FENCE_LOCK_ID="merge-fence",MERGE_ATTRIBUTES_LOCK_ID="merge-attributes";function quoteMergeDriverArgument(value){return`'${value.replaceAll("'",`'"'"'`)}'`}async function resolveMatchingBunLauncher(candidate,version){const resolvedCandidate=await realpath(candidate);if(/(?:^|[\\/])bun-node-[^\\/]+[\\/]bun(?:\.exe)?$/iu.test(resolvedCandidate))return;const{stdout}=await execFileAsync(candidate,["--version"],{encoding:"utf8",windowsHide:!0,timeout:1e4});return stdout.trim()===version?resolvedCandidate:void 0}async function resolveMergeDriverCliCommand(){const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);let executable=process.execPath,bunLauncherFound=!1;const runtimeIdentity=await realpath(process.execPath),bunVersion=process.versions.bun,pathCandidates=(process.env.PATH??"").split(path.delimiter).filter(directory=>path.isAbsolute(directory)).map(directory=>path.join(directory,bunVersion===void 0?path.basename(process.execPath):process.platform==="win32"?"bun.exe":"bun")),candidates=bunVersion===void 0?pathCandidates:[process.env.npm_execpath??"",...pathCandidates,runtimeIdentity].filter(candidate=>path.isAbsolute(candidate)&&/^(?:bun|bun\.exe)$/iu.test(path.basename(candidate)));for(const candidate of candidates)try{if(await access(candidate,constants.X_OK),bunVersion!==void 0){const launcher=await resolveMatchingBunLauncher(candidate,bunVersion);if(launcher!==void 0){executable=launcher,bunLauncherFound=!0;break}continue}if(candidate!==runtimeIdentity&&await realpath(candidate)===runtimeIdentity){executable=candidate;break}}catch{}if(bunVersion!==void 0&&!bunLauncherFound)throw new PmCliError("Cannot install Bun merge drivers without a durable executable matching the current Bun version.",EXIT_CODE.DEPENDENCY_FAILED,{code:"merge_bun_launcher_unavailable",why:"The current Bun process may be a temporary bunx launcher that Git cannot reuse after this command exits.",nextSteps:["Run with a durable version-matched Bun executable, expose one on an absolute PATH entry, or invoke pm through a Bun runner that publishes an absolute npm_execpath.","Retry pm merge install, then check pm health --strict-exit before merging branches."]});return`${quoteMergeDriverArgument(executable)} ${quoteMergeDriverArgument(path.join(packageRoot,"dist","cli.js"))}`}const MERGE_DRIVER_DEFINITIONS=[{key:"pm-item-toon",name:"pm field-aware TOON item document merge",artifact:"item",itemPath:"%P"},{key:"pm-item-markdown",name:"pm field-aware JSON-markdown item document merge",artifact:"item",itemPath:"%P"},{key:"pm-history",name:"pm append-only history stream merge",artifact:"history",itemPath:void 0},{key:"pm-relationship",name:"pm append-only relationship event store merge",artifact:"relationship",itemPath:void 0},{key:"pm-json",name:"pm key-level JSON config merge",artifact:"json",itemPath:void 0}];function resolveMergeInstallContext(options){const explicitPath=options.explicitPath?.trim(),sourceWorkspaceRoot=options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim(),sourcePmRoot=options.environment.PM_SOURCE_PM_PATH?.trim(),sourcePolicy=resolveSourceContextWritePolicy(options.environment),sourceCoordinatesAvailable=!!(sourceWorkspaceRoot&&sourcePmRoot),sourceContextSelected=explicitPath===void 0&&sourceCoordinatesAvailable&&(options.dryRun||sourcePolicy.source_writes_allowed);if(explicitPath!==void 0){const pmRoot=resolvePmRoot(options.cwd,explicitPath);return{pm_root:pmRoot,workspace_start:pmRoot,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:!1,source_policy:sourcePolicy}}return sourceContextSelected?{pm_root:path.resolve(sourcePmRoot),workspace_start:path.resolve(sourceWorkspaceRoot),source_coordinates_available:!0,source_context_selected:!0,source_policy:sourcePolicy}:{pm_root:sourceCoordinatesAvailable?resolvePmRoot(options.cwd,".agents/pm"):resolvePmRoot(options.cwd),workspace_start:options.cwd,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:!1,source_policy:sourcePolicy}}async function findGitWorkspaceRoot(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--show-toplevel"],{cwd,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:!0,timeout:1e4});return await realpath(stdout.trim())}catch{return null}}async function resolveGitWorkspaceRoot(cwd){const workspaceRoot=await findGitWorkspaceRoot(cwd);if(workspaceRoot===null)throw new PmCliError("pm merge install requires a git repository (merge drivers are git configuration).",EXIT_CODE.USAGE);return workspaceRoot}function toPosixRelative(fromPath,toPath){return path.relative(fromPath,toPath).replaceAll("\\","/")}function quoteGitAttributePattern(value){return`"${value.replaceAll("\\","\\\\").replaceAll('"','\\"')}"`}function readSingleQuotedArgument(command,offset){if(command[offset]!=="'")return null;let value="";for(let index=offset+1;index<command.length;index+=1){if(command.startsWith(`'"'"'`,index)){value+="'",index+=4;continue}if(command[index]==="'")return{value,nextOffset:index+1};value+=command[index]}return null}async function isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,version){if(discoverProjectRuntimeVersionPins(workspaceRoot).filter(pin=>pin.constraint==="exact").some(pin=>pin.version!==version))return!1;const driverWorkspace=await findGitWorkspaceRoot(packageRoot);if(driverWorkspace!==null&&driverWorkspace!==await realpath(workspaceRoot)){const commonDirectories=await Promise.all([driverWorkspace,workspaceRoot].map(async cwd=>{const result=await execFileAsync("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd,env:gitWorkspaceEnvironment(),timeout:1e4});return realpath(result.stdout.trim())}));if(commonDirectories[0]===commonDirectories[1])return!1}return!0}async function isPortableMergeDriverCommand(configured,expectedSuffix,workspaceRoot){const nodeArgument=readSingleQuotedArgument(configured,0);if(nodeArgument===null||configured[nodeArgument.nextOffset]!==" ")return!1;const cliArgument=readSingleQuotedArgument(configured,nodeArgument.nextOffset+1);if(cliArgument===null||configured.slice(cliArgument.nextOffset)!==expectedSuffix||!/^(?:node|bun)(?:\.exe)?$/iu.test(path.basename(nodeArgument.value))||path.basename(cliArgument.value)!=="cli.js"||path.basename(path.dirname(cliArgument.value))!=="dist"||!await pathExists(nodeArgument.value)||!await pathExists(cliArgument.value))return!1;try{const packageRoot=path.dirname(path.dirname(cliArgument.value)),manifest=JSON.parse(await readFile(path.join(packageRoot,"package.json"),"utf8")),pmBin=typeof manifest.bin=="string"?manifest.bin:manifest.bin?.pm;return await isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,manifest.version)?manifest.name==="@unbrained/pm-cli"&&pmBin==="dist/cli.js":!1}catch{return!1}}function buildMergeAttributePatterns(trackerRelativeRoot,typeFolders){const prefix=trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"",patterns=[`${quoteGitAttributePattern(`${prefix}**/*.toon`)} merge=pm-item-toon`,`${quoteGitAttributePattern(`${prefix}**/*.md`)} merge=pm-item-markdown`];for(const folder of typeFolders)patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.toon`)} merge=pm-item-toon`),patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.md`)} merge=pm-item-markdown`);return patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.jsonl`)} merge=pm-relationship`),patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`),patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`),patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.json`)} merge=pm-json`),patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/**`)} merge=text`),patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`),patterns}function managedMergeBlocks(content){const blocks=[];let cursor=0;for(;cursor<content.length;){const legacyStart=content.indexOf(PM_GITATTRIBUTES_START,cursor),versionedStart=content.indexOf(PM_GITATTRIBUTES_V2_START,cursor),start=legacyStart===-1?versionedStart:versionedStart===-1?legacyStart:Math.min(legacyStart,versionedStart);if(start===-1)break;const versioned=start===versionedStart,startMarker=versioned?PM_GITATTRIBUTES_V2_START:PM_GITATTRIBUTES_START,endMarker=versioned?PM_GITATTRIBUTES_V2_END:PM_GITATTRIBUTES_END,closing=content.indexOf(endMarker,start+startMarker.length),end=closing===-1?content.length:closing+endMarker.length;blocks.push({start,end,closed:closing!==-1,lines:content.slice(start+startMarker.length,closing===-1?end:closing).split(`
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b1828465-0619-514c-8956-2a81dea9efbc")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isFileMissingError,readFileIfExists,writeFileAtomic}from"../../core/fs/fs-utils.js";import{access,readFile,realpath}from"node:fs/promises";import{constants}from"node:fs";import{execFile}from"node:child_process";import path from"node:path";import{promisify}from"node:util";import{pathExists}from"../../core/fs/fs-utils.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{acquireLock}from"../../core/lock/lock.js";import{resolvePmPackageRootFromModule}from"../../core/packages/root.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolveAuthor}from"../../core/shared/author.js";import{nowIso}from"../../core/shared/time.js";import{resolvePmRoot}from"../../core/store/paths.js";import{readSettings,resolveGovernanceKnobs}from"../../core/store/settings.js";import{isPathOutsideRoot}from"../workspace.js";import{resolveSourceContextWritePolicy}from"../environment/source-context.js";import{gitWorkspaceEnvironment,resolveMergeDriverConfigScope,writeMergeDriverGitConfig}from"./worktree-config.js";import{discoverProjectRuntimeVersionPins}from"../environment/project-runtime-compatibility.js";const execFileAsync=promisify(execFile),PM_GITATTRIBUTES_START="# pm-cli:merge-drivers:start",PM_GITATTRIBUTES_END="# pm-cli:merge-drivers:end",PM_GITATTRIBUTES_V2_START="# pm-cli:merge-drivers:v2:start",PM_GITATTRIBUTES_V2_END="# pm-cli:merge-drivers:v2:end",MERGE_FENCE_LOCK_ID="merge-fence",MERGE_ATTRIBUTES_LOCK_ID="merge-attributes";function quoteMergeDriverArgument(value){return`'${value.replaceAll("'",`'"'"'`)}'`}async function resolveMatchingBunLauncher(candidate,version){const resolvedCandidate=await realpath(candidate);if(/(?:^|[\\/])bun-node-[^\\/]+[\\/]bun(?:\.exe)?$/iu.test(resolvedCandidate))return;const{stdout}=await execFileAsync(candidate,["--version"],{encoding:"utf8",windowsHide:!0,timeout:1e4});return stdout.trim()===version?resolvedCandidate:void 0}async function resolveMergeDriverCliCommand(){const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);let executable=process.execPath,bunLauncherFound=!1;const runtimeIdentity=await realpath(process.execPath),bunVersion=process.versions.bun,pathCandidates=(process.env.PATH??"").split(path.delimiter).filter(directory=>path.isAbsolute(directory)).map(directory=>path.join(directory,bunVersion===void 0?path.basename(process.execPath):process.platform==="win32"?"bun.exe":"bun")),candidates=bunVersion===void 0?pathCandidates:[process.env.npm_execpath??"",...pathCandidates,runtimeIdentity].filter(candidate=>path.isAbsolute(candidate)&&/^(?:bun|bun\.exe)$/iu.test(path.basename(candidate)));for(const candidate of candidates)try{if(await access(candidate,constants.X_OK),bunVersion!==void 0){const launcher=await resolveMatchingBunLauncher(candidate,bunVersion);if(launcher!==void 0){executable=launcher,bunLauncherFound=!0;break}continue}if(candidate!==runtimeIdentity&&await realpath(candidate)===runtimeIdentity){executable=candidate;break}}catch{}if(bunVersion!==void 0&&!bunLauncherFound)throw new PmCliError("Cannot install Bun merge drivers without a durable executable matching the current Bun version.",EXIT_CODE.DEPENDENCY_FAILED,{code:"merge_bun_launcher_unavailable",why:"The current Bun process may be a temporary bunx launcher that Git cannot reuse after this command exits.",nextSteps:["Run with a durable version-matched Bun executable, expose one on an absolute PATH entry, or invoke pm through a Bun runner that publishes an absolute npm_execpath.","Retry pm merge install, then check pm health --strict-exit before merging branches."]});return`${quoteMergeDriverArgument(executable)} ${quoteMergeDriverArgument(path.join(packageRoot,"dist","cli.js"))}`}const MERGE_DRIVER_DEFINITIONS=[{key:"pm-item-toon",name:"pm field-aware TOON item document merge",artifact:"item",itemPath:"%P"},{key:"pm-item-markdown",name:"pm field-aware JSON-markdown item document merge",artifact:"item",itemPath:"%P"},{key:"pm-history",name:"pm append-only history stream merge",artifact:"history",itemPath:void 0},{key:"pm-relationship",name:"pm append-only relationship event store merge",artifact:"relationship",itemPath:void 0},{key:"pm-json",name:"pm key-level JSON config merge",artifact:"json",itemPath:void 0}];function resolveMergeInstallContext(options){const explicitPath=options.explicitPath?.trim(),sourceWorkspaceRoot=options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim(),sourcePmRoot=options.environment.PM_SOURCE_PM_PATH?.trim(),sourcePolicy=resolveSourceContextWritePolicy(options.environment),sourceCoordinatesAvailable=!!(sourceWorkspaceRoot&&sourcePmRoot),sourceContextSelected=explicitPath===void 0&&sourceCoordinatesAvailable&&(options.dryRun||sourcePolicy.source_writes_allowed);if(explicitPath!==void 0){const pmRoot=resolvePmRoot(options.cwd,explicitPath);return{pm_root:pmRoot,workspace_start:pmRoot,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:!1,source_policy:sourcePolicy}}return sourceContextSelected?{pm_root:path.resolve(sourcePmRoot),workspace_start:path.resolve(sourceWorkspaceRoot),source_coordinates_available:!0,source_context_selected:!0,source_policy:sourcePolicy}:{pm_root:sourceCoordinatesAvailable?resolvePmRoot(options.cwd,".agents/pm"):resolvePmRoot(options.cwd),workspace_start:options.cwd,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:!1,source_policy:sourcePolicy}}async function findGitWorkspaceRoot(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--show-toplevel"],{cwd,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:!0,timeout:1e4});return await realpath(stdout.trim())}catch{return null}}async function resolveGitWorkspaceRoot(cwd){const workspaceRoot=await findGitWorkspaceRoot(cwd);if(workspaceRoot===null)throw new PmCliError("pm merge install requires a git repository (merge drivers are git configuration).",EXIT_CODE.USAGE);return workspaceRoot}function toPosixRelative(fromPath,toPath){return path.relative(fromPath,toPath).split(path.sep).join("/")}function literalGitAttributePath(value){return value.replace(/[\\*?[\]!]/gu,"\\$&")}function quoteGitAttributePattern(value){return`"${value.replaceAll("\\","\\\\").replaceAll('"','\\"')}"`}function readSingleQuotedArgument(command,offset){if(command[offset]!=="'")return null;let value="";for(let index=offset+1;index<command.length;index+=1){if(command.startsWith(`'"'"'`,index)){value+="'",index+=4;continue}if(command[index]==="'")return{value,nextOffset:index+1};value+=command[index]}return null}async function isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,version){if(discoverProjectRuntimeVersionPins(workspaceRoot).filter(pin=>pin.constraint==="exact").some(pin=>pin.version!==version))return!1;const driverWorkspace=await findGitWorkspaceRoot(packageRoot);if(driverWorkspace!==null&&driverWorkspace!==await realpath(workspaceRoot)){const commonDirectories=await Promise.all([driverWorkspace,workspaceRoot].map(async cwd=>{const result=await execFileAsync("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd,env:gitWorkspaceEnvironment(),timeout:1e4});return realpath(result.stdout.trim())}));if(commonDirectories[0]===commonDirectories[1])return!1}return!0}async function isPortableMergeDriverCommand(configured,expectedSuffix,workspaceRoot){const nodeArgument=readSingleQuotedArgument(configured,0);if(nodeArgument===null||configured[nodeArgument.nextOffset]!==" ")return!1;const cliArgument=readSingleQuotedArgument(configured,nodeArgument.nextOffset+1);if(cliArgument===null||configured.slice(cliArgument.nextOffset)!==expectedSuffix||!/^(?:node|bun)(?:\.exe)?$/iu.test(path.basename(nodeArgument.value))||path.basename(cliArgument.value)!=="cli.js"||path.basename(path.dirname(cliArgument.value))!=="dist"||!await pathExists(nodeArgument.value)||!await pathExists(cliArgument.value))return!1;try{const packageRoot=path.dirname(path.dirname(cliArgument.value)),manifest=JSON.parse(await readFile(path.join(packageRoot,"package.json"),"utf8")),pmBin=typeof manifest.bin=="string"?manifest.bin:manifest.bin?.pm;return await isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,manifest.version)?manifest.name==="@unbrained/pm-cli"&&pmBin==="dist/cli.js":!1}catch{return!1}}function buildMergeAttributePatterns(trackerRelativeRoot,typeFolders){const prefix=trackerRelativeRoot.length>0?`${literalGitAttributePath(trackerRelativeRoot)}/`:"",patterns=[`${quoteGitAttributePattern(`${prefix}**/*.toon`)} merge=pm-item-toon`,`${quoteGitAttributePattern(`${prefix}**/*.md`)} merge=pm-item-markdown`];for(const folder of typeFolders){const literalFolder=literalGitAttributePath(folder);patterns.push(`${quoteGitAttributePattern(`${prefix}${literalFolder}/*.toon`)} merge=pm-item-toon`),patterns.push(`${quoteGitAttributePattern(`${prefix}${literalFolder}/*.md`)} merge=pm-item-markdown`)}return patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.jsonl`)} merge=pm-relationship`),patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`),patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`),patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.json`)} merge=pm-json`),patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/**`)} merge=text`),patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`),patterns}function managedMergeBlocks(content){const blocks=[];let cursor=0;for(;cursor<content.length;){const legacyStart=content.indexOf(PM_GITATTRIBUTES_START,cursor),versionedStart=content.indexOf(PM_GITATTRIBUTES_V2_START,cursor),start=legacyStart===-1?versionedStart:versionedStart===-1?legacyStart:Math.min(legacyStart,versionedStart);if(start===-1)break;const versioned=start===versionedStart,startMarker=versioned?PM_GITATTRIBUTES_V2_START:PM_GITATTRIBUTES_START,endMarker=versioned?PM_GITATTRIBUTES_V2_END:PM_GITATTRIBUTES_END,closing=content.indexOf(endMarker,start+startMarker.length),end=closing===-1?content.length:closing+endMarker.length;blocks.push({start,end,closed:closing!==-1,lines:content.slice(start+startMarker.length,closing===-1?end:closing).split(`
|
|
2
2
|
`).map(line=>line.trim()).filter(Boolean)}),cursor=end}return blocks}function blockBelongsToTracker(lines,patterns,trackerRelativeRoot){const ownedPatterns=new Set(patterns),prefix=quoteGitAttributePattern(trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"").slice(0,-1);return lines.some(line=>ownedPatterns.has(line)||line.startsWith(prefix)&&/^[^/]+\/\*\.(?:toon|md)" merge=pm-item-(?:toon|markdown)$/u.test(line.slice(prefix.length)))}async function reconcileGitattributesBlock(workspaceRoot,trackerRelativeRoot,patterns,dryRun){const gitattributesPath=path.join(workspaceRoot,".gitattributes"),gitDirectory=dryRun?null:(await execFileAsync("git",["rev-parse","--absolute-git-dir"],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:!0,timeout:1e4})).stdout.trim(),releaseLock=gitDirectory===null?null:await acquireLock(gitDirectory,MERGE_ATTRIBUTES_LOCK_ID,120,"merge-fence",!1,!0,5e3);try{const current=await readFileIfExists(gitattributesPath)??"",block=[PM_GITATTRIBUTES_V2_START,...patterns,PM_GITATTRIBUTES_V2_END].join(`
|
|
3
|
-
`),blocks=managedMergeBlocks(current),owned=blocks.filter(candidate=>blockBelongsToTracker(candidate.lines,patterns,trackerRelativeRoot));owned.length===0&&trackerRelativeRoot===".agents/pm"&&blocks.length===1&&blocks[0].lines.every(line=>!line.includes("
|
|
3
|
+
`),blocks=managedMergeBlocks(current),owned=blocks.filter(candidate=>blockBelongsToTracker(candidate.lines,patterns,trackerRelativeRoot));owned.length===0&&trackerRelativeRoot===".agents/pm"&&blocks.length===1&&blocks[0].lines.every(line=>!line.includes("/"))&&owned.push(blocks[0]);let next;if(owned.length>0){const first=owned[0];next=current;for(const duplicate of owned.slice(1).reverse())next=`${next.slice(0,duplicate.start)}${next.slice(duplicate.end)}`;next=`${next.slice(0,first.start)}${block}${next.slice(first.end)}`}else{const prefix=current.trimEnd();next=`${prefix.length>0?`${prefix}
|
|
4
4
|
|
|
5
5
|
`:""}${block}
|
|
6
6
|
`}return next===current?{path:gitattributesPath,changed:!1}:(dryRun||await writeFileAtomic(gitattributesPath,next),{path:gitattributesPath,changed:!0})}finally{await releaseLock?.()}}function resolveProjectMergeTypeFolders(settings){const registry=resolveItemTypeRegistry(settings,null);return[...new Set(Object.values(registry.type_to_folder))].sort((left,right)=>left.localeCompare(right))}async function auditMergeAttributeFence(pmRoot,typeFolders){const resolvedRoot=path.resolve(pmRoot);let fenceDirectory=null,fenceContent="",directory=resolvedRoot;for(let depth=0;depth<8;depth+=1){const candidate=path.join(directory,".gitattributes");try{const raw=await readFile(candidate,"utf8");if(raw.includes(PM_GITATTRIBUTES_V2_START)||raw.includes(PM_GITATTRIBUTES_START)){fenceDirectory=directory,fenceContent=raw;break}}catch{}const parent=path.dirname(directory);if(parent===directory)break;directory=parent}if(fenceDirectory===null)return{status:"not_installed",missing_patterns:[],stale_patterns:[],schema_scope:"project"};const fencePath=path.join(fenceDirectory,".gitattributes"),relativeRoot=toPosixRelative(fenceDirectory,resolvedRoot),blocks=managedMergeBlocks(fenceContent),expected=buildMergeAttributePatterns(relativeRoot,typeFolders),owned=blocks.filter(block=>blockBelongsToTracker(block.lines,expected,relativeRoot)),committed=owned.flatMap(block=>block.closed?block.lines:[]),committedSet=new Set(committed),expectedSet=new Set(expected),missing=expected.filter(line=>!committedSet.has(line)),stale=committed.filter(line=>!expectedSet.has(line));return{status:owned.length!==1||!owned[0].closed||missing.length>0||stale.length>0?"drift":"ok",path:fencePath,missing_patterns:missing,stale_patterns:stale,schema_scope:"project"}}async function auditMergeDriverConfiguration(workspaceRoot){const missingKeys=[],driftedKeys=[];for(const definition of MERGE_DRIVER_DEFINITIONS){const key=`merge.${definition.key}.driver`,expectedSuffix=` merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`;try{const{stdout}=await execFileAsync("git",["config","--get",key],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:!0,timeout:1e4}),configured=stdout.trim();await isPortableMergeDriverCommand(configured,expectedSuffix,workspaceRoot)||driftedKeys.push(key)}catch{missingKeys.push(key)}}return{status:missingKeys.length>0?"missing":driftedKeys.length>0?"drift":"ok",missing_keys:missingKeys,drifted_keys:driftedKeys}}async function refreshMergeAttributeFenceIfInstalled(pmRoot){let workspaceRoot;try{workspaceRoot=await resolveGitWorkspaceRoot(path.resolve(pmRoot))}catch{return{status:"no_git"}}const trackerRelativeRoot=toPosixRelative(workspaceRoot,path.resolve(pmRoot)),lockSettings=await readSettings(pmRoot),owner=resolveAuthor(void 0,lockSettings.author_default),releaseLock=await acquireLock(pmRoot,MERGE_FENCE_LOCK_ID,lockSettings.locks.ttl_seconds,owner,!1,resolveGovernanceKnobs(lockSettings).force_required_for_stale_lock,lockSettings.locks.wait_ms);try{const gitattributesPath=path.join(workspaceRoot,".gitattributes");let current;try{current=await readFile(gitattributesPath,"utf8")}catch(error){if(error instanceof Error&&"code"in error&&isFileMissingError(error))return{status:"not_installed",path:gitattributesPath};throw error}if(!current.includes(PM_GITATTRIBUTES_V2_START)&&!current.includes(PM_GITATTRIBUTES_START))return{status:"not_installed",path:gitattributesPath};const settings=await readSettings(pmRoot),typeFolders=resolveProjectMergeTypeFolders(settings),outcome=await reconcileGitattributesBlock(workspaceRoot,trackerRelativeRoot,buildMergeAttributePatterns(trackerRelativeRoot,typeFolders),!1);return{status:outcome.changed?"refreshed":"unchanged",path:outcome.path}}finally{await releaseLock()}}async function runMergeInstall(options,global2){const context=resolveMergeInstallContext({cwd:process.cwd(),explicitPath:global2.path,dryRun:options.dryRun===!0,environment:process.env}),pmRoot=context.pm_root;await assertInitializedTracker(pmRoot);const workspaceRoot=await resolveGitWorkspaceRoot(context.workspace_start);return installMergeFence({pmRoot,workspaceRoot,dryRun:options.dryRun===!0,preCommitHook:options.preCommitHook===!0})}async function installMergeDriverConfiguration(workspaceRoot,entries){const commonDirectory=(await execFileAsync("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),timeout:1e4})).stdout.trim(),release=await acquireLock(commonDirectory,"merge-driver-config",120,"merge-install",!1,!0,5e3);try{const scope=await resolveMergeDriverConfigScope(workspaceRoot);let stdout;try{stdout=(await execFileAsync("git",["config",scope,"--null","--get-regexp","."],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),timeout:1e4})).stdout}catch(error){if(typeof error!="object"||error===null||!("code"in error)||error.code!==1)throw error;stdout=""}const current=new Map(stdout.split("\0").filter(Boolean).map(entry=>{const separator=entry.indexOf(`
|