@unbrained/pm-cli 2026.9.22 → 2026.9.25

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.
Files changed (107) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/AGENTS.md +6 -20
  3. package/CHANGELOG.md +43 -0
  4. package/dist/cli/error-guidance.d.ts +9 -0
  5. package/dist/cli/error-guidance.js +1 -1
  6. package/dist/cli/help-content.js +1 -1
  7. package/dist/cli-bundle/bundle-manifest.json +144 -144
  8. package/dist/cli-bundle/chunks/{chunk-BJBBOUYQ.js → chunk-25KTCTBL.js} +2 -2
  9. package/dist/cli-bundle/chunks/{chunk-UDNYAMCM.js → chunk-3IB4THWX.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-3OFFMS2N.js → chunk-445ARBKY.js} +2 -2
  11. package/dist/cli-bundle/chunks/{chunk-SBTT42A4.js → chunk-5AP67ZXH.js} +3 -3
  12. package/dist/cli-bundle/chunks/{chunk-JSW33Q6R.js → chunk-COFQCKF4.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-4XOV7Q5R.js → chunk-CZ3VJJEA.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-ZSPZJOMK.js → chunk-GAU55CWI.js} +28 -28
  15. package/dist/cli-bundle/chunks/{chunk-ML42DLI3.js → chunk-GOWZEBTH.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-CM57QHVK.js → chunk-JDHWZYZU.js} +73 -73
  17. package/dist/cli-bundle/chunks/{chunk-GFTN5OS4.js → chunk-P7ZSJOWH.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-AVWHZUNC.js → chunk-YABJDOOX.js} +63 -62
  19. package/dist/cli-bundle/chunks/{chunk-D2OV2UBV.js → chunk-YDIGMRLZ.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-list-query-VOS5CBX4.js → register-list-query-IZ7ZVTDE.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-mutation-LWZH6UFJ.js → register-mutation-IPAZTFDZ.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-operations-YJK4DNFZ.js → register-operations-APN33LNI.js} +2 -2
  23. package/dist/cli-bundle/chunks/{register-setup-Q3CYF67Q.js → register-setup-HPHIKG5U.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/{chunk-CASXNCNQ.js → chunk-ABA3KRPY.js} +2 -2
  25. package/dist/cli-bundle/focused-chunks/{chunk-XR5EBU3B.js → chunk-HQPTDJLF.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/{chunk-PRMQTT7X.js → chunk-IXNNMP2R.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/chunk-KRIHJH5U.js +75 -0
  28. package/dist/cli-bundle/focused-chunks/{chunk-QFEDRPPI.js → chunk-MK5AKKHK.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-LH24XUPJ.js → chunk-NRHTXBTI.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-URH727T5.js → chunk-NVVB2HJC.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/{chunk-TSI73EEM.js → chunk-O7MIBEMK.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-V2NARGRH.js → chunk-OY3VHCTX.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-UT7VS4X2.js → chunk-PMPFLA6X.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-FKYUTTFL.js → chunk-Q355NPLH.js} +28 -28
  35. package/dist/cli-bundle/focused-chunks/{chunk-JCD5YESL.js → chunk-TLF6N56J.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-MXESHALQ.js → chunk-UIFVIE5F.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-IOL25GKH.js → chunk-V2X37U6J.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-AO5FR7PN.js → chunk-XKH2FC5D.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/{chunk-UAU4DJSR.js → chunk-Y2M4QLAA.js} +2 -2
  40. package/dist/cli-bundle/main.js +22 -22
  41. package/dist/cli-bundle/sdk-authoring.js +1 -1
  42. package/dist/cli-bundle/sdk-contracts.js +1 -1
  43. package/dist/cli-bundle/sdk-core.js +30 -45
  44. package/dist/cli-bundle/sdk-governance.js +1 -1
  45. package/dist/cli-bundle/sdk-graph.js +1 -1
  46. package/dist/cli-bundle/sdk-merge.js +58 -42
  47. package/dist/cli-bundle/sdk-query.js +1 -1
  48. package/dist/cli-bundle/sdk-runtime.js +1 -1
  49. package/dist/cli-bundle/sdk-testing.js +1 -1
  50. package/dist/cli-bundle/sdk.js +9 -10
  51. package/dist/core/policy/workflow-policy-store.js +1 -1
  52. package/dist/core/shared/errors.d.ts +13 -0
  53. package/dist/core/shared/errors.js +1 -1
  54. package/dist/sdk/cli-contracts/commander-types.d.ts +11 -11
  55. package/dist/sdk/cli-contracts/commander-types.js +1 -1
  56. package/dist/sdk/completion/bash.js +1 -1
  57. package/dist/sdk/governance/health.d.ts +1 -1
  58. package/dist/sdk/governance/health.js +1 -1
  59. package/dist/sdk/init-agent-guidance.d.ts +2 -1
  60. package/dist/sdk/init-agent-guidance.js +2 -2
  61. package/dist/sdk/merge/install.js +2 -2
  62. package/dist/sdk/merge/worktree-config.d.ts +9 -0
  63. package/dist/sdk/merge/worktree-config.js +2 -0
  64. package/dist/sdk/pagination.js +1 -1
  65. package/dist/sdk/public-surface.json +1 -1
  66. package/docs/AGENT_RECOVERY_AND_GUIDANCE.md +49 -0
  67. package/docs/CHATGPT_CODEX_PLUGIN_IMPLEMENTATION.md +2 -0
  68. package/docs/CLAUDE_CODE_PLUGIN.md +18 -7
  69. package/docs/CODEX_PLUGIN.md +5 -12
  70. package/docs/DEFECT_RECURRENCE.md +8 -1
  71. package/docs/DEPENDENCY_KIND_CONTRACT.md +27 -0
  72. package/docs/MERGE_SAFETY.md +28 -5
  73. package/docs/QUALITY_EVIDENCE.md +70 -0
  74. package/docs/README.md +1 -0
  75. package/docs/RELEASE_RELIABILITY.md +70 -0
  76. package/docs/RELEASING.md +4 -0
  77. package/docs/TESTING.md +25 -0
  78. package/docs/VALIDATION_PORTABILITY.md +20 -11
  79. package/marketplace.json +2 -2
  80. package/package.json +12 -6
  81. package/packages/pm-beads/package.json +1 -1
  82. package/packages/pm-calendar/package.json +1 -1
  83. package/packages/pm-command-kit/package.json +1 -1
  84. package/packages/pm-digital-twin/package.json +1 -1
  85. package/packages/pm-governance-audit/package.json +1 -1
  86. package/packages/pm-guide-shell/package.json +1 -1
  87. package/packages/pm-kanban/package.json +1 -1
  88. package/packages/pm-lifecycle-hooks/package.json +1 -1
  89. package/packages/pm-linked-test-adapters/package.json +1 -1
  90. package/packages/pm-search-advanced/package.json +1 -1
  91. package/packages/pm-templates/package.json +1 -1
  92. package/packages/pm-todos/package.json +1 -1
  93. package/packages/pm-vcs/package.json +1 -1
  94. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  95. package/plugins/pm-claude/README.md +6 -5
  96. package/plugins/pm-claude/hooks/hooks.json +1 -1
  97. package/plugins/pm-claude/hooks/session-start.mjs +9 -6
  98. package/plugins/pm-claude/package.json +9 -0
  99. package/plugins/pm-claude/scripts/plugin-runtime.mjs +84 -0
  100. package/plugins/pm-claude/scripts/pm-mcp-server.mjs +39 -96
  101. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  102. package/plugins/pm-codex/.mcp.json +0 -3
  103. package/plugins/pm-codex/README.md +1 -1
  104. package/plugins/pm-codex/package.json +9 -0
  105. package/plugins/pm-codex/scripts/plugin-runtime.mjs +84 -0
  106. package/plugins/pm-codex/scripts/pm-mcp-server.mjs +38 -99
  107. package/dist/cli-bundle/focused-chunks/chunk-QYN77MQP.js +0 -59
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ccc95309-685b-5516-936f-74106af14c74")}catch(e2){}})();import fs from"node:fs/promises";import path from"node:path";import{resolveTelemetryEnvironmentPolicy}from"../../core/telemetry/policy.js";import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isTerminalStatus}from"../../core/item/status.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{resolveRuntimeStatusRegistry}from"../../core/schema/runtime-schema.js";import{isFileMissingError,readFileIfExists}from"../../core/fs/fs-utils.js";import{activateExtensions,getActiveExtensionRegistrations,loadExtensions,runActiveOnReadHooks}from"../../core/extensions/index.js";import{collectRegisteredItemFieldNames}from"../../core/extensions/item-fields.js";import{KNOWN_EXTENSION_CAPABILITIES}from"../../core/extensions/loader.js";import{enforceHistoryStreamPolicyForItems}from"../../core/history/history-stream-policy.js";import{scanHistoryDrift}from"../../core/history/drift-scan.js";import{scanLockHealth}from"../../core/lock/lock-gc.js";import{readVectorizationStatusLedger,refreshSemanticEmbeddingsForMutatedItems}from"../../core/search/cache.js";import{resolveEmbeddingProviders,resolveProviderConfigSource}from"../../core/search/providers.js";import{resolveSettingsWithSemanticRuntimeDefaults}from"../../core/search/semantic-defaults.js";import{collectStaleVectorizationIds}from"../../core/search/staleness.js";import{buildVectorizationEmbeddingIdentity,hasVectorizationEmbeddingIdentityChanged}from"../../core/search/vectorization-metadata.js";import{resolveVectorStores}from"../../core/search/vector-stores.js";import{EXIT_CODE,PM_CORE_REQUIRED_SUBDIRS,TYPE_TO_FOLDER}from"../../core/shared/constants.js";import{findFirstMergeConflictMarker}from"../../core/shared/conflict-markers.js";import{PmCliError}from"../../core/shared/errors.js";import{toNonEmptyStringOrUndefined}from"../../core/shared/primitives.js";import{nowIso}from"../../core/shared/time.js";import{parseItemDocument}from"../../core/item/item-format.js";import{effectiveItemFormatVersion,scanItemFormatVersions}from"../../core/item/item-format-version.js";import{listAllItemMetadataLight,listAllItemMetadataWithBody}from"../../core/store/item-store.js";import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS,TELEMETRY_SCHEMA_VERSION}from"../../core/telemetry/runtime.js";import{getItemFormatFromPath,getSettingsPath,ITEM_FILE_EXTENSIONS,resolveGlobalPmRoot,resolvePmRoot,resolveWorkspaceRoot}from"../../core/store/paths.js";import{readSettingsWithMetadata}from"../../core/store/settings.js";import{buildRemediationMap,resolveRemediation}from"../../core/diagnostics/remediation.js";import{scanExtensionHostVersions}from"./extension-host-version.js";import{scanHistoryAuthorAttribution}from"../author-attribution.js";import{readManagedExtensionState}from"../extension.js";import{scanProvenanceResolverHealth}from"./provenance-health.js";import{applyStoredExtensionMigrationState}from"../extension/migrations.js";import{inspectExtensionAuthorManifest}from"../extension/author-manifest.js";import{buildCapabilityContractMetadata,buildRegistrationCollisionRemediation,collectUnknownCapabilityGuidance}from"../extension/doctor.js";import{scanStaleInProgressItems}from"./stale-work.js";import{scanTrackedRuntimeCache}from"./tracked-runtime-cache.js";import{auditMergeDriverConfiguration,findGitWorkspaceRoot}from"../merge/install.js";import{inspectMergeReceiptEvidence,partitionMergeReceipts}from"../merge/receipts.js";import{classifyHistoryMergeReceiptReferences,extractHistoryMergeReceiptDispositions,extractHistoryMergeReceiptReferences}from"./merge-receipt-history.js";import{runHistoryRepair}from"../history-repair.js";import{resolveWorkspaceRelationshipKindRegistry}from"../graph/assembly.js";import{analyzeHierarchyIntegrity}from"../graph/hierarchy-integrity.js";import{buildStatusRoleWarnings,inspectStatusRoleAssignments}from"./status-role-diagnostics.js";const PM_TELEMETRY_SOURCE_CONTEXT_SET=new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);const STALE_VECTORIZATION_SUMMARY_LIMIT=25;const BRIEF_HEALTH_DETAIL_LIMIT=8;const HEALTH_WARNING_LIMIT=100;const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl");const TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json");const TELEMETRY_ENDPOINT_PROBE_TIMEOUT_MS=2500;const TELEMETRY_QUEUE_HIGH_WATER_MARK=500;const TELEMETRY_QUEUE_HIGH_RETRY_THRESHOLD=TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS-3;const TELEMETRY_SERVER_MAX_SCHEMA_VERSION_HEADERS=["x-pm-telemetry-max-schema-version","x-pm-telemetry-max-version"];function isAdvisoryHealthWarning(warning,requireMergeDrivers=false){return warning.startsWith("telemetry_")||warning.startsWith("history_stream_over_compact_threshold:")||warning.startsWith("integrity_legacy_hierarchy_")||warning.startsWith("stale_in_progress_items:")||warning.startsWith("provenance_resolver_zero_success:")||warning.startsWith("provenance_value_domain_invalid:")||!requireMergeDrivers&&warning.startsWith("merge_driver_configuration_missing:")}function warningCode(value){const normalized=value.trim();const separator=normalized.indexOf(":");if(separator===-1){return normalized}return normalized.slice(0,separator)}function normalizeExtensionNameForMatch(value){return value.trim().toLowerCase()}function isExpectedUnmanagedExtension(name,directory){const normalizedName=normalizeExtensionNameForMatch(name);const normalizedDirectory=normalizeExtensionNameForMatch(directory);if(normalizedName.startsWith("builtin-")){return true}return normalizedDirectory==="beads"||normalizedDirectory==="todos"}async function isDirectory(targetPath){try{const stats=await fs.stat(targetPath);return stats.isDirectory()}catch{return false}}async function listStoredItemDocumentIds(pmRoot){const directories=(await fs.readdir(pmRoot,{withFileTypes:true})).filter(entry=>entry.isDirectory());const filesByDirectory=await Promise.all(directories.map(entry=>fs.readdir(path.join(pmRoot,entry.name),{withFileTypes:true})));return new Set(filesByDirectory.flatMap(entries=>entries.filter(entry=>entry.isFile()).filter(entry=>ITEM_FILE_EXTENSIONS.some(extension=>entry.name.endsWith(extension))).map(entry=>path.parse(entry.name).name)))}async function inspectHistoryStream(streamPath,itemId,compactPolicy,liveItemIds){const warnings=await runActiveOnReadHooks({path:streamPath,scope:"project"});const needsClassification=itemId!=="_workspace"&&!liveItemIds.has(itemId);if(!compactPolicy.enabled&&!needsClassification){return{warnings,overThreshold:false,classification:"live"}}let raw;try{raw=await fs.readFile(streamPath,"utf8")}catch{return{warnings,overThreshold:false,classification:"unreadable"}}let classification="live";if(needsClassification){const lastLine=raw.split(/\r?\n/).map(line=>line.trim()).filter(Boolean).at(-1);try{const lastEntry=JSON.parse(lastLine??"{}");classification=lastEntry.op==="delete"?"tombstone":"orphaned"}catch{classification="orphaned"}}const entryCount=compactPolicy.enabled?raw.split(/\r?\n/).filter(line=>line.trim().length>0).length:0;return{warnings,overThreshold:compactPolicy.enabled&&entryCount>compactPolicy.max_entries,classification}}async function countHistoryStreams(pmRoot,compactPolicy,liveItemIds){const historyDir=path.join(pmRoot,"history");if(!await isDirectory(historyDir)){return{count:0,warnings:[],over_threshold:[],max_entries:null,tombstones:[],orphaned:[]}}const historyFiles=(await fs.readdir(historyDir)).filter(entry=>entry.endsWith(".jsonl")).sort((left,right)=>left.localeCompare(right));const policyActive=compactPolicy.enabled;const maxEntries=policyActive?compactPolicy.max_entries:null;const warnings=[];const overThreshold=[];const tombstones=[];const orphaned=[];for(const fileName of historyFiles){const streamPath=path.join(historyDir,fileName);const itemId=fileName.slice(0,-".jsonl".length);const inspection=await inspectHistoryStream(streamPath,itemId,compactPolicy,liveItemIds);warnings.push(...inspection.warnings);if(inspection.classification==="tombstone")tombstones.push(itemId);if(inspection.classification==="orphaned")orphaned.push(itemId);if(inspection.overThreshold)overThreshold.push(itemId)}return{count:historyFiles.length,warnings:[...warnings,...overThreshold.map(id=>`history_stream_over_compact_threshold:${id}`),...orphaned.map(id=>`history_orphaned_stream:${id}`)],over_threshold:overThreshold,max_entries:maxEntries,tombstones,orphaned}}function normalizeRelativePath(pmRoot,targetPath){return path.relative(pmRoot,targetPath).replaceAll("\\","/")}async function listItemDocumentPaths(pmRoot,typeToFolder){const folders=[...new Set(Object.values(typeToFolder))].sort((left,right)=>left.localeCompare(right));const itemPaths=[];for(const folder of folders){const directoryPath=path.join(pmRoot,folder);let entries=[];try{entries=await fs.readdir(directoryPath)}catch(error){if(typeof error==="object"&&error!==null&&"code"in error&&isFileMissingError(error)){continue}continue}for(const entry of entries){if(!ITEM_FILE_EXTENSIONS.some(extension=>entry.toLowerCase().endsWith(extension))){continue}itemPaths.push(path.join(directoryPath,entry))}}itemPaths.sort((left,right)=>normalizeRelativePath(pmRoot,left).localeCompare(normalizeRelativePath(pmRoot,right)));return itemPaths}function shouldReportHistoryDirectoryUnreadable(error){return!(typeof error==="object"&&error!==null&&"code"in error&&isFileMissingError(error))}async function scanItemIntegrity(pmRoot,typeToFolder,schema){const paths=await listItemDocumentPaths(pmRoot,typeToFolder);const unreadable=[];const conflictMarkers=[];const parseFailures=[];const formatVersions=[];const extensionFieldNames=collectRegisteredItemFieldNames(getActiveExtensionRegistrations());for(const itemPath of paths){const relativePath=normalizeRelativePath(pmRoot,itemPath);let raw;try{raw=await fs.readFile(itemPath,"utf8")}catch{unreadable.push(relativePath);continue}const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker){conflictMarkers.push({path:relativePath,...conflictMarker});continue}try{const parsed=parseItemDocument(raw,{format:getItemFormatFromPath(itemPath),schema,extensionFieldNames});formatVersions.push({ref:relativePath,version:effectiveItemFormatVersion(parsed.metadata)})}catch{parseFailures.push(relativePath)}}return{paths,unreadable,conflictMarkers,parseFailures,formatVersions}}async function scanHistoryIntegrity(pmRoot){const historyDir=path.join(pmRoot,"history");const unreadable=[];const conflictMarkers=[];const invalidJson=[];const mergeReceiptReferences=[];const mergeReceiptDispositions=[];let files=[];try{files=(await fs.readdir(historyDir)).filter(entry=>entry.endsWith(".jsonl")).sort((left,right)=>left.localeCompare(right))}catch(error){if(shouldReportHistoryDirectoryUnreadable(error))unreadable.push("history")}for(const fileName of files){const itemId=fileName.slice(0,-".jsonl".length);let raw;try{raw=await fs.readFile(path.join(historyDir,fileName),"utf8")}catch{unreadable.push(itemId);continue}const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker){conflictMarkers.push({id:itemId,...conflictMarker});continue}raw.split(/\r?\n/).forEach((line,index)=>{if(!line.trim())return;try{const parsed=JSON.parse(line);mergeReceiptReferences.push(...extractHistoryMergeReceiptReferences(parsed,itemId).map(reference=>({itemId,line:index+1,...reference})));mergeReceiptDispositions.push(...extractHistoryMergeReceiptDispositions(parsed,itemId,index+1))}catch{invalidJson.push({id:itemId,line:index+1})}})}return{files,unreadable,conflictMarkers,invalidJson,mergeReceiptReferences,mergeReceiptDispositions}}function buildHierarchyIntegrityWarnings(analysis){return[...analysis.cycles.map(cycle=>cycle.legacy_terminal?`integrity_legacy_hierarchy_cycle:${cycle.item_ids.join(",")}`:`integrity_hierarchy_cycle:${cycle.item_ids.join(",")}`),...analysis.cardinality_violations.map(finding=>finding.legacy_terminal?`integrity_legacy_hierarchy_cardinality:${finding.child_id}`:`integrity_hierarchy_cardinality:${finding.child_id}`),...analysis.divergences.map(finding=>finding.legacy_terminal?`integrity_legacy_hierarchy_divergence:${finding.child_id}`:`integrity_hierarchy_divergence:${finding.child_id}`)]}function buildMergeReceiptEvidenceWarnings(params){const warnings=[];if(params.invalidEvidenceCount>0){warnings.push(`merge_receipt_evidence_invalid:${params.invalidEvidenceCount}`)}if(params.missingHistoryReferenceCount>0){warnings.push(`merge_receipt_history_reference_missing:${params.missingHistoryReferenceCount}`)}return warnings}async function buildIntegrityCheck(pmRoot,typeToFolder,schema,requireMergeDrivers,items){const itemScan=await scanItemIntegrity(pmRoot,typeToFolder,schema);const historyScan=await scanHistoryIntegrity(pmRoot);const formatVersionScan=scanItemFormatVersions(itemScan.formatVersions);const statusRegistry=resolveRuntimeStatusRegistry(schema);const hierarchyIntegrity=analyzeHierarchyIntegrity(items,status=>isTerminalStatus(status,statusRegistry),resolveWorkspaceRelationshipKindRegistry());const trackedRuntimeCache=await scanTrackedRuntimeCache(pmRoot);const gitWorkspaceRoot=await findGitWorkspaceRoot(pmRoot);const mergeDriverAudit=gitWorkspaceRoot===null?null:await auditMergeDriverConfiguration(gitWorkspaceRoot);const mergeReceiptEvidence=await inspectMergeReceiptEvidence(gitWorkspaceRoot??pmRoot,{includeReconciled:true,includeLossless:true,pmRoot});const availableMergeReceiptIds=new Set(mergeReceiptEvidence.receipts.map(receipt=>receipt.id));const historyReceiptClassification=classifyHistoryMergeReceiptReferences(historyScan.mergeReceiptReferences,availableMergeReceiptIds,historyScan.mergeReceiptDispositions);const missingMergeReceiptReferences=historyReceiptClassification.missing;const pendingMergeReceipts=mergeReceiptEvidence.receipts.filter(receipt=>receipt.state==="pending");const{pendingDecisions:pendingMergeDecisions,lossless:losslessMergeReceipts}=partitionMergeReceipts(pendingMergeReceipts);const mergeDriverInstallationMissing=mergeDriverAudit?.status==="missing"&&mergeDriverAudit.missing_keys.length===5&&mergeDriverAudit.drifted_keys.length===0;const warnings=[...itemScan.unreadable.map(entry=>`integrity_item_unreadable:${entry}`),...itemScan.conflictMarkers.map(entry=>`integrity_item_conflict_marker:${entry.path}:L${entry.line}`),...itemScan.parseFailures.map(entry=>`integrity_item_parse_failed:${entry}`),...historyScan.unreadable.map(entry=>`integrity_history_unreadable:${entry}`),...historyScan.conflictMarkers.map(entry=>`integrity_history_conflict_marker:${entry.id}:L${entry.line}`),...historyScan.invalidJson.map(entry=>`integrity_history_invalid_json:${entry.id}:L${entry.line}`),...formatVersionScan.outdated.map(entry=>`integrity_item_outdated_format_version:${entry}`),...formatVersionScan.ahead.map(entry=>`integrity_item_ahead_format_version:${entry}`),...buildHierarchyIntegrityWarnings(hierarchyIntegrity),...trackedRuntimeCache.tracked_path_count>0?[`tracked_runtime_cache_files:${trackedRuntimeCache.tracked_path_count}`]:[],...mergeDriverAudit!==null&&mergeDriverAudit.status!=="ok"?[`merge_driver_configuration_${mergeDriverInstallationMissing?"missing":"drift"}:${mergeDriverAudit.missing_keys.length+mergeDriverAudit.drifted_keys.length}`]:[],...pendingMergeDecisions.length>0?[`merge_decisions_unreviewed:${pendingMergeDecisions.length}`]:[],...losslessMergeReceipts.length>0?[`merge_receipts_pending:${losslessMergeReceipts.length}`]:[],...buildMergeReceiptEvidenceWarnings({invalidEvidenceCount:mergeReceiptEvidence.invalid_evidence_count,missingHistoryReferenceCount:missingMergeReceiptReferences.length})];const normalizedWarnings=[...new Set(warnings)].sort((left,right)=>left.localeCompare(right));const actionableWarnings=normalizedWarnings.filter(warning=>!warning.startsWith("integrity_legacy_hierarchy_"));return{check:{name:"integrity",status:actionableWarnings.length===0?"ok":"warn",ok:actionableWarnings.length===0,details:{checked_item_files:itemScan.paths.length,checked_history_streams:historyScan.files.length,counts:{item_unreadable:itemScan.unreadable.length,item_conflict_markers:itemScan.conflictMarkers.length,item_parse_failures:itemScan.parseFailures.length,history_unreadable:historyScan.unreadable.length,history_conflict_markers:historyScan.conflictMarkers.length,history_invalid_json:historyScan.invalidJson.length,item_outdated_format_version:formatVersionScan.outdated.length,item_ahead_format_version:formatVersionScan.ahead.length,hierarchy_cycles:hierarchyIntegrity.cycles.length,hierarchy_cardinality_violations:hierarchyIntegrity.cardinality_violations.length,hierarchy_parent_divergences:hierarchyIntegrity.divergences.length,tracked_runtime_cache_files:trackedRuntimeCache.tracked_path_count,merge_driver_configuration:mergeDriverAudit===null||mergeDriverAudit.status==="ok"?0:mergeDriverAudit.missing_keys.length+mergeDriverAudit.drifted_keys.length,pending_merge_decisions:pendingMergeDecisions.length,lossless_merge_receipts:losslessMergeReceipts.length,invalid_merge_receipt_evidence:mergeReceiptEvidence.invalid_evidence_count,missing_merge_receipt_history_references:missingMergeReceiptReferences.length,accepted_legacy_merge_receipt_references:historyReceiptClassification.acceptedLegacyCount,accepted_missing_merge_receipt_dispositions:historyReceiptClassification.acceptedDispositionCount},item_unreadable:itemScan.unreadable,item_conflict_markers:itemScan.conflictMarkers,item_parse_failures:itemScan.parseFailures,item_outdated_format_version:formatVersionScan.outdated,item_ahead_format_version:formatVersionScan.ahead,hierarchy_integrity:{...hierarchyIntegrity,relations:summarizeRecordList(hierarchyIntegrity.relations,BRIEF_HEALTH_DETAIL_LIMIT)},history_unreadable:historyScan.unreadable,history_conflict_markers:historyScan.conflictMarkers,history_invalid_json:historyScan.invalidJson,tracked_runtime_cache:{tracker_relative_root:trackedRuntimeCache.tracker_relative_root,tracked_paths:trackedRuntimeCache.tracked_paths,tracked_path_count:trackedRuntimeCache.tracked_path_count,remediation_command:trackedRuntimeCache.remediation_command},merge_driver_configuration:mergeDriverAudit===null?null:{...mergeDriverAudit,required:requireMergeDrivers},pending_merge_decision_items:[...new Set(pendingMergeDecisions.map(receipt=>receipt.item_id))].sort((left,right)=>left.localeCompare(right)),lossless_merge_receipt_items:[...new Set(losslessMergeReceipts.map(receipt=>receipt.item_id))].sort((left,right)=>left.localeCompare(right)),invalid_merge_receipt_evidence_details:mergeReceiptEvidence.invalid_evidence,invalid_merge_receipt_evidence_details_truncated:mergeReceiptEvidence.invalid_evidence_truncated,missing_merge_receipt_history_reference_details:missingMergeReceiptReferences.slice(0,HEALTH_WARNING_LIMIT),missing_merge_receipt_history_reference_details_truncated:missingMergeReceiptReferences.length>HEALTH_WARNING_LIMIT}},warnings:normalizedWarnings,gitWorkspaceRoot,pendingMergeReceipts}}function hasActivateExport(moduleRecord){if(typeof moduleRecord.activate==="function"){return true}const defaultExport=moduleRecord.default;if(typeof defaultExport!=="object"||defaultExport===null){return false}return typeof defaultExport.activate==="function"}function summarizeLoadedExtension(extension){const summary={layer:extension.layer,directory:extension.directory,manifest_path:extension.manifest_path,name:extension.name,version:extension.version,entry:extension.entry,priority:extension.priority,entry_path:extension.entry_path,has_activate:hasActivateExport(extension.module)};if(Array.isArray(extension.capabilities)){summary.capabilities=[...extension.capabilities]}return summary}function resolveMigrationId(definition,fallbackIndex){const explicitId=toNonEmptyStringOrUndefined(definition.id);if(explicitId){return explicitId}return`migration-${String(fallbackIndex+1).padStart(3,"0")}`}function resolveMigrationStatus(definition){const rawStatus=toNonEmptyStringOrUndefined(definition.status);const normalized=rawStatus?.toLowerCase();if(normalized==="failed"){return"failed"}if(normalized==="applied"){return"applied"}return"pending"}function resolveMigrationFailureReason(definition){return toNonEmptyStringOrUndefined(definition.reason)??toNonEmptyStringOrUndefined(definition.error)??toNonEmptyStringOrUndefined(definition.message)}function compareMigrationEntries(left,right){const byLayer=(left.layer??"").localeCompare(right.layer??"");if(byLayer!==0){return byLayer}const byName=(left.name??"").localeCompare(right.name??"");if(byName!==0){return byName}return(left.id??"").localeCompare(right.id??"")}function summarizeMigrationStatuses(migrations){const applied=[];const pending=[];const failed=[];migrations.forEach((migration,index)=>{const id=resolveMigrationId(migration.definition,index);const status=resolveMigrationStatus(migration.definition);if(status==="applied"){applied.push({layer:migration.layer,name:migration.name,id,status});return}if(status==="failed"){failed.push({layer:migration.layer,name:migration.name,id,status,reason:resolveMigrationFailureReason(migration.definition)});return}pending.push({layer:migration.layer,name:migration.name,id,status})});applied.sort(compareMigrationEntries);pending.sort(compareMigrationEntries);failed.sort(compareMigrationEntries);const warnings=[...failed.map(entry=>`extension_migration_failed:${entry.layer}:${entry.name}:${entry.id}`),...pending.map(entry=>`extension_migration_pending:${entry.layer}:${entry.name}:${entry.id}`)];return{summary:{applied,pending,failed,applied_count:applied.length,pending_count:pending.length,failed_count:failed.length},warnings}}function buildExtensionHealthTriageSummary(warnings,loadFailureCount,activationFailureCount,migrationStatus,managedStateWarningCount,managedExtensionEntriesCount,unmanagedLoadedExtensions,unmanagedExpectedExtensions,unmanagedActionRequiredExtensions){const normalizedWarnings=[...new Set(warnings)].sort((left,right)=>left.localeCompare(right));const warningCodes=[...new Set(normalizedWarnings.map(value=>warningCode(value)))].sort((left,right)=>left.localeCompare(right));const unknownCapabilityCount=normalizedWarnings.filter(warning=>warning.startsWith("extension_capability_unknown:")).length;const updateHealthPartial=unmanagedActionRequiredExtensions.length>0;const updateHealthCoverage=updateHealthPartial?"partial":"full";const remediation=[];const registrationCollisionRemediation=buildRegistrationCollisionRemediation(normalizedWarnings,{deactivate:"pm extension --deactivate <name> --project/--global",doctor:"pm extension --doctor --project/--global --detail deep --trace"});if(registrationCollisionRemediation){remediation.push(registrationCollisionRemediation)}if(loadFailureCount>0){remediation.push("Run pm extension --explore --project and pm extension --explore --global to inspect load failures.")}if(activationFailureCount>0){remediation.push("Review checks[name=extensions].details.activation.failed in pm health --json for activation error details.")}if(migrationStatus.failed_count>0||migrationStatus.pending_count>0){remediation.push("Resolve pending/failed extension migrations before write commands; use --force only when policy allows.")}if(managedStateWarningCount>0){remediation.push("Run pm extension --manage --project and pm extension --manage --global to refresh managed-state diagnostics.")}if(unknownCapabilityCount>0){remediation.push(`Unknown extension capabilities detected. Allowed capabilities: ${KNOWN_EXTENSION_CAPABILITIES.join(", ")}. Review extension_capability_unknown warning details for suggested replacements.`)}if(normalizedWarnings.some(warning=>warning.startsWith("extension_capability_legacy_alias:"))){remediation.push("Legacy extension capability aliases were auto-remapped to canonical capabilities. Update manifests to canonical names (migration/validation -> schema).")}if(normalizedWarnings.some(warning=>warning.startsWith("extension_command_definition_legacy_handler_alias:"))){remediation.push("Extension command definitions using legacy handler were auto-remapped. Update command definitions to use run: (context) => ... for forward compatibility.")}if(updateHealthPartial){remediation.push("Update-check coverage is partial because unmanaged extensions need adoption. Adopt existing installs via pm extension --manage --project/--global --fix-managed-state, pm extension --adopt-all --project/--global, or pm extension --adopt <name>.")}else if(unmanagedLoadedExtensions.length>0){remediation.push("Loaded unmanaged extensions are currently treated as informational. Use pm extension --manage --project/--global --fix-managed-state to adopt them for update checks.")}if(remediation.length===0){remediation.push("No immediate action required. Re-run pm health after extension configuration changes.")}return{status:normalizedWarnings.length===0?"ok":"warn",warning_count:normalizedWarnings.length,warning_codes:warningCodes,load_failure_count:loadFailureCount,activation_failure_count:activationFailureCount,migration_failed_count:migrationStatus.failed_count,migration_pending_count:migrationStatus.pending_count,managed_state_warning_count:managedStateWarningCount,managed_extension_entries_count:managedExtensionEntriesCount,unmanaged_loaded_extension_count:unmanagedLoadedExtensions.length,unmanaged_loaded_extensions:unmanagedLoadedExtensions,unmanaged_expected_extension_count:unmanagedExpectedExtensions.length,unmanaged_expected_extensions:unmanagedExpectedExtensions,unmanaged_action_required_extension_count:unmanagedActionRequiredExtensions.length,unmanaged_action_required_extensions:unmanagedActionRequiredExtensions,update_health_coverage:updateHealthCoverage,update_health_partial:updateHealthPartial,unknown_capability_count:unknownCapabilityCount,top_warnings:normalizedWarnings.slice(0,8),remediation}}async function buildExtensionCheck(pmRoot,settings,noExtensionsFlag){const authorManifest=await inspectExtensionAuthorManifest(resolveWorkspaceRoot(pmRoot));const loadResult=await loadExtensions({pmRoot,settings,cwd:process.cwd(),noExtensions:noExtensionsFlag});const loadedSummaries=loadResult.loaded.map(extension=>summarizeLoadedExtension(extension));const hostVersionCensus=await scanExtensionHostVersions(loadResult.loaded,resolveWorkspaceRoot(pmRoot));const activationResult=await activateExtensions({...loadResult,loaded:loadResult.loaded});const[projectManagedState,globalManagedState]=await Promise.all([readManagedExtensionState(loadResult.roots.project),readManagedExtensionState(loadResult.roots.global)]);await applyStoredExtensionMigrationState(pmRoot,activationResult.registrations.migrations);const migrationStatus=summarizeMigrationStatuses(activationResult.registrations.migrations);const activationDetails={failed:activationResult.failed,warnings:activationResult.warnings,hook_counts:activationResult.hook_counts,command_override_count:activationResult.command_override_count,command_handler_count:activationResult.command_handler_count,parser_override_count:activationResult.parser_override_count,preflight_override_count:activationResult.preflight_override_count,service_override_count:activationResult.service_override_count,renderer_override_count:activationResult.renderer_override_count,registration_counts:activationResult.registration_counts,registrations:activationResult.registrations,migration_status:migrationStatus.summary,managed_extensions:{project:{path:projectManagedState.path,count:projectManagedState.state.entries.length,entries:projectManagedState.state.entries},global:{path:globalManagedState.path,count:globalManagedState.state.entries.length,entries:globalManagedState.state.entries}}};const managedProjectNames=new Set(projectManagedState.state.entries.map(entry=>normalizeExtensionNameForMatch(entry.name)));const managedGlobalNames=new Set(globalManagedState.state.entries.map(entry=>normalizeExtensionNameForMatch(entry.name)));const unmanagedLoadedEntries=[...new Map(loadResult.loaded.filter(entry=>{const managedNames=entry.layer==="project"?managedProjectNames:managedGlobalNames;return!managedNames.has(normalizeExtensionNameForMatch(entry.name))}).map(entry=>[`${entry.layer}:${entry.name}`,{layer:entry.layer,name:entry.name,directory:entry.directory}])).values()].sort((left,right)=>{const leftKey=`${left.layer}:${left.name}`;const rightKey=`${right.layer}:${right.name}`;return leftKey.localeCompare(rightKey)});const unmanagedLoadedExtensions=unmanagedLoadedEntries.map(entry=>`${entry.layer}:${entry.name}`).sort((left,right)=>left.localeCompare(right));const unmanagedExpectedExtensions=unmanagedLoadedEntries.filter(entry=>isExpectedUnmanagedExtension(entry.name,entry.directory)).map(entry=>`${entry.layer}:${entry.name}`).sort((left,right)=>left.localeCompare(right));const unmanagedActionRequiredExtensions=unmanagedLoadedEntries.filter(entry=>!isExpectedUnmanagedExtension(entry.name,entry.directory)).map(entry=>`${entry.layer}:${entry.name}`).sort((left,right)=>left.localeCompare(right));const updateCoverageWarnings=unmanagedActionRequiredExtensions.length>0?[`extension_update_health_partial_coverage:skipped_unmanaged:${unmanagedActionRequiredExtensions.length}`]:[];const extensionWarnings=[...authorManifest.warnings,...loadResult.warnings,...activationDetails.warnings,...migrationStatus.warnings,...projectManagedState.warnings,...globalManagedState.warnings,...updateCoverageWarnings,...hostVersionCensus.warnings];const capabilityGuidance=collectUnknownCapabilityGuidance(extensionWarnings);const capabilityContract=buildCapabilityContractMetadata();const extensionTriage=buildExtensionHealthTriageSummary(extensionWarnings,loadResult.failed.length,activationResult.failed.length,migrationStatus.summary,projectManagedState.warnings.length+globalManagedState.warnings.length,projectManagedState.state.entries.length+globalManagedState.state.entries.length,unmanagedLoadedExtensions,unmanagedExpectedExtensions,unmanagedActionRequiredExtensions);return{check:{name:"extensions",status:extensionWarnings.length===0?"ok":"warn",ok:extensionWarnings.length===0,details:{...loadResult,loaded:loadedSummaries,warnings:extensionWarnings,activation:activationDetails,author_manifest:authorManifest,triage:extensionTriage,...migrationStatus.summary.pending_count>0?{remediation_map:{extension_migration_pending:"pm extension migrate --project"}}:{},capability_contract:capabilityContract,capability_guidance:capabilityGuidance,host_version_census:hostVersionCensus}},warnings:extensionWarnings}}function summarizeList(values,limit){if(values.length<=limit){return{values,truncated:false}}return{values:values.slice(0,limit),truncated:true}}function summarizeRecordList(value,limit){if(!Array.isArray(value)){return{count:0,sample:[],truncated:false}}return{count:value.length,sample:value.slice(0,limit),truncated:value.length>limit}}function summarizeExtensionRecord(value){if(typeof value!=="object"||value===null||Array.isArray(value)){return{}}const record=value;return{layer:record.layer,directory:record.directory,name:record.name,version:record.version,enabled:record.enabled,status:record.status,has_activate:record.has_activate,capabilities:record.capabilities}}function summarizeExtensionList(value,limit){const summary=summarizeRecordList(value,limit);return{...summary,sample:summary.sample.map(entry=>summarizeExtensionRecord(entry))}}function summarizeStringList(value,limit){if(!Array.isArray(value)){return{count:0,sample:[],truncated:false}}const strings=value.filter(entry=>typeof entry==="string");return{count:strings.length,sample:strings.slice(0,limit),truncated:strings.length>limit}}function summarizeActivationMigrationStatus(value){if(typeof value!=="object"||value===null){return null}const status=value;return{applied_count:status.applied_count,pending_count:status.pending_count,failed_count:status.failed_count}}const HEALTH_DETAIL_SUMMARIZERS={settings:(details,limit)=>({version:details.version,id_prefix:details.id_prefix,locks_ttl_seconds:details.locks_ttl_seconds,warnings:summarizeStringList(details.warnings,limit)}),directories:(details,limit)=>({required_count:Array.isArray(details.required)?details.required.length:0,optional_count:Array.isArray(details.optional)?details.optional.length:0,missing_required:summarizeStringList(details.missing_required,limit),missing_optional:summarizeStringList(details.missing_optional,limit),missing:summarizeStringList(details.missing,limit),strict_directories:details.strict_directories}),settings_values:(details,limit)=>({warnings:summarizeStringList(details.warnings,limit)}),telemetry:details=>({enabled:details.enabled,capture_level:details.capture_level,endpoint:details.endpoint,queue_exists:details.queue_exists,queue_entries:details.queue_entries,queue_draining:details.queue_draining,queue_invalid_rows:details.queue_invalid_rows,queue_rows_total:details.queue_rows_total,last_successful_flush_at:details.last_successful_flush_at,last_failed_flush_at:details.last_failed_flush_at,endpoint_probe:details.endpoint_probe,env_overrides:details.env_overrides}),extensions:(details,limit)=>{const activation=typeof details.activation==="object"&&details.activation!==null?details.activation:{};return{disabled_by_flag:details.disabled_by_flag,discovered:summarizeExtensionList(details.discovered,limit),effective:summarizeExtensionList(details.effective,limit),loaded:summarizeExtensionList(details.loaded,limit),failed:summarizeRecordList(details.failed,limit),warnings:summarizeStringList(details.warnings,limit),activation:{failed:summarizeRecordList(activation.failed,limit),warnings:summarizeStringList(activation.warnings,limit),hook_counts:activation.hook_counts,command_handler_count:activation.command_handler_count,service_override_count:activation.service_override_count,renderer_override_count:activation.renderer_override_count,registration_counts:activation.registration_counts,migration_status:summarizeActivationMigrationStatus(activation.migration_status)},author_manifest:details.author_manifest,triage:details.triage,capability_contract:details.capability_contract,capability_guidance:summarizeRecordList(details.capability_guidance,limit),host_version_census:details.host_version_census}},storage:(details,limit)=>{const authorAttribution=typeof details.author_attribution==="object"&&details.author_attribution!==null?details.author_attribution:void 0;return{...details,...authorAttribution?{author_attribution:{...authorAttribution,affected_item_ids:summarizeStringList(authorAttribution.affected_item_ids,limit),samples:summarizeRecordList(authorAttribution.samples,limit)}}:{}}},locks:details=>({active_lock_count:details.active_lock_count,stale_lock_count:details.stale_lock_count,unreadable_lock_count:details.unreadable_lock_count,unparseable_lock_count:details.unparseable_lock_count}),integrity:(details,limit)=>{const trackedRuntimeCache=typeof details.tracked_runtime_cache==="object"&&details.tracked_runtime_cache!==null?details.tracked_runtime_cache:void 0;return{checked_item_files:details.checked_item_files,checked_history_streams:details.checked_history_streams,counts:details.counts,item_unreadable:summarizeStringList(details.item_unreadable,limit),item_conflict_markers:summarizeRecordList(details.item_conflict_markers,limit),item_parse_failures:summarizeStringList(details.item_parse_failures,limit),tracked_runtime_cache:trackedRuntimeCache===void 0?details.tracked_runtime_cache:{...trackedRuntimeCache,tracked_paths:summarizeStringList(trackedRuntimeCache.tracked_paths,limit)},history_unreadable:summarizeStringList(details.history_unreadable,limit),history_conflict_markers:summarizeRecordList(details.history_conflict_markers,limit),history_invalid_json:summarizeRecordList(details.history_invalid_json,limit),skipped:details.skipped}},history_drift:(details,limit)=>{const cacheConfirmation=typeof details.cache_confirmation==="object"&&details.cache_confirmation!==null?details.cache_confirmation:void 0;return{checked_items:details.checked_items,cache_hit_verification:details.cache_hit_verification,cache_confirmation:cacheConfirmation===void 0?details.cache_confirmation:{...cacheConfirmation,candidate_items:summarizeStringList(cacheConfirmation.candidate_items,limit),confirmed_items:summarizeStringList(cacheConfirmation.confirmed_items,limit),resolved_false_positive_items:summarizeStringList(cacheConfirmation.resolved_false_positive_items,limit)},counts:details.counts,drifted_items:summarizeStringList(details.drifted_items,limit),merge_receipt_attributed_items:summarizeStringList(details.merge_receipt_attributed_items,limit),missing_streams:summarizeStringList(details.missing_streams,limit),unreadable_streams:summarizeStringList(details.unreadable_streams,limit),hash_mismatches:summarizeStringList(details.hash_mismatches,limit),chain_mismatches:summarizeStringList(details.chain_mismatches,limit),version_skews:summarizeStringList(details.version_skews,limit),workspace_state_mismatches:summarizeStringList(details.workspace_state_mismatches,limit),workspace_state_missing:summarizeStringList(details.workspace_state_missing,limit),workspace_state_unreadable:summarizeStringList(details.workspace_state_unreadable,limit),skipped:details.skipped}},vectorization:(details,limit)=>({semantic_runtime_available:details.semantic_runtime_available,compatibility_mode_auto_defaults:details.compatibility_mode_auto_defaults,auto_ollama_defaults_applied:details.auto_ollama_defaults_applied,auto_ollama_defaults_skipped_reason:details.auto_ollama_defaults_skipped_reason,auto_ollama_defaults_remediation:details.auto_ollama_defaults_remediation,refresh_policy:details.refresh_policy,provider_active:details.provider_active,vector_store_active:details.vector_store_active,items:details.items,ledger_entries_before:details.ledger_entries_before,stale_items_before_total:details.stale_items_before_total,stale_items_before:summarizeStringList(details.stale_items_before,limit),refresh_attempted:details.refresh_attempted,refresh_skipped_reason:details.refresh_skipped_reason,refresh_result:details.refresh_result,ledger_entries_after:details.ledger_entries_after,stale_items_after_total:details.stale_items_after_total,stale_items_after:summarizeStringList(details.stale_items_after,limit),skipped:details.skipped})};function summarizeHealthCheckDetails(check,limit){const summarize=HEALTH_DETAIL_SUMMARIZERS[check.name];return summarize?summarize(check.details,limit):check.details}function applyBriefHealthProjection(result){const warningsSummary=summarizeStringList(result.warnings,BRIEF_HEALTH_DETAIL_LIMIT);return{ok:result.ok,...result.verdict?{verdict:result.verdict}:{},checks:result.checks.map(check=>({name:check.name,status:check.status,ok:check.ok,details:summarizeHealthCheckDetails(check,BRIEF_HEALTH_DETAIL_LIMIT)})),warnings:warningsSummary.sample,findings:result.findings.filter(finding=>warningsSummary.sample.includes(finding.warning)||result.failed_because.includes(finding.warning)),failed_because:result.failed_because,projection:{mode:"brief",warning_count:warningsSummary.count,warnings_truncated:warningsSummary.truncated,detail_limit:BRIEF_HEALTH_DETAIL_LIMIT},generated_at:result.generated_at}}function isSkippedHealthCheck(check){return check.details.skipped===true}function applySummaryHealthProjection(result){const warningsSummary=summarizeStringList(result.warnings,BRIEF_HEALTH_DETAIL_LIMIT);const omittedChecks=result.checks.filter(isSkippedHealthCheck).map(check=>check.name);return{ok:result.ok,...result.verdict?{verdict:result.verdict}:{},checks:result.checks.filter(check=>!isSkippedHealthCheck(check)).map(check=>({name:check.name,status:check.status,ok:check.ok,details:{}})),warning_count:warningsSummary.count,warnings:warningsSummary.sample,findings:result.findings.filter(finding=>warningsSummary.sample.includes(finding.warning)||result.failed_because.includes(finding.warning)),failed_because:result.failed_because,projection:{mode:"summary",warning_count:warningsSummary.count,warnings_truncated:warningsSummary.truncated,detail_limit:BRIEF_HEALTH_DETAIL_LIMIT,omitted_checks:omittedChecks},generated_at:result.generated_at}}function selectStaleItemDetail(values,verboseStaleItems){if(verboseStaleItems){return{values,truncated:false,total:values.length}}const summary=summarizeList(values,STALE_VECTORIZATION_SUMMARY_LIMIT);return{values:summary.values,truncated:summary.truncated,total:values.length}}function telemetryEnvFlagEnabled(envKey){const value=(process.env[envKey]??"").trim().toLowerCase();return value==="1"||value==="true"||value==="yes"||value==="on"}function telemetrySourceContextOverride(){const value=(process.env.PM_TELEMETRY_SOURCE_CONTEXT??"").trim().toLowerCase();return PM_TELEMETRY_SOURCE_CONTEXT_SET.has(value)?value:null}function normalizeEndpointForDisplay(rawEndpoint){const trimmed=rawEndpoint.trim();if(trimmed.length===0){return""}try{const parsed=new URL(trimmed);parsed.username="";parsed.password="";parsed.search="";parsed.hash="";return parsed.toString()}catch{return trimmed}}function parseTelemetryQueue(raw){let validEntries=0;let invalidRows=0;let totalRows=0;let highRetryEntries=0;let maxAttempts=0;for(const line of raw.split("\n")){const trimmed=line.trim();if(trimmed.length===0){continue}totalRows+=1;try{const parsed=JSON.parse(trimmed);if(typeof parsed==="object"&&parsed!==null&&typeof parsed.attempts==="number"&&Number.isFinite(parsed.attempts)){const attempts=Math.max(0,Math.trunc(parsed.attempts));validEntries+=1;maxAttempts=Math.max(maxAttempts,attempts);if(attempts>=TELEMETRY_QUEUE_HIGH_RETRY_THRESHOLD){highRetryEntries+=1}}else{invalidRows+=1}}catch{invalidRows+=1}}return{validEntries,invalidRows,totalRows,highRetryEntries,maxAttempts}}function emptyTelemetryQueueSummary(){return{validEntries:0,invalidRows:0,totalRows:0,highRetryEntries:0,maxAttempts:0}}function parseTelemetryRuntimeState(stateRaw){if(!stateRaw||stateRaw.trim().length===0){return{runtimeState:{},stateParseFailed:false}}try{const parsed=JSON.parse(stateRaw);if(typeof parsed==="object"&&parsed!==null&&!Array.isArray(parsed)){return{runtimeState:parsed,stateParseFailed:false}}return{runtimeState:{},stateParseFailed:true}}catch{return{runtimeState:{},stateParseFailed:true}}}async function maybeProbeTelemetryEndpoint(settings,checkTelemetry){const endpoint=settings.telemetry.endpoint.trim();if(!checkTelemetry||!settings.telemetry.enabled||endpoint.length===0||resolveTelemetryEnvironmentPolicy().telemetry_disabled){return void 0}const probe=await probeTelemetryEndpointHealth(endpoint);return{attempted:true,...probe}}function collectTelemetryQueueWarnings(settings,queueSummary,runtimeState){const warnings=[];if(queueSummary.invalidRows>0){warnings.push(`telemetry_queue_invalid_rows:${queueSummary.invalidRows}`)}if(!settings.telemetry.enabled||queueSummary.validEntries===0){return warnings}const lastSuccess=runtimeState.last_successful_flush_at;const lastFailure=runtimeState.last_failed_flush_at;const activeFailure=lastFailure&&(!lastSuccess||lastFailure>lastSuccess);const neverFlushed=!lastSuccess;const highWater=queueSummary.validEntries>=TELEMETRY_QUEUE_HIGH_WATER_MARK;if(activeFailure||neverFlushed||highWater){warnings.push(`telemetry_queue_pending:${queueSummary.validEntries}`)}if(queueSummary.highRetryEntries>0){warnings.push(`telemetry_queue_high_retries:${queueSummary.highRetryEntries}`)}return warnings}function collectTelemetryEndpointWarnings(endpointProbe){if(!endpointProbe||endpointProbe.ok!==false){return[]}return typeof endpointProbe.status==="number"?[`telemetry_endpoint_probe_http_status:${endpointProbe.status}`]:["telemetry_endpoint_probe_failed"]}function collectTelemetrySchemaWarnings(endpointProbe){const parsedMaxSchemaVersion=Number.parseInt(endpointProbe?.max_schema_version??"",10);if(endpointProbe?.ok===true&&Number.isInteger(parsedMaxSchemaVersion)&&parsedMaxSchemaVersion>TELEMETRY_SCHEMA_VERSION){return[`telemetry_schema_version_behind:${parsedMaxSchemaVersion}`]}return[]}function collectTelemetryOtelWarnings(settings,runtimeState){const pendingOtelSpans=typeof runtimeState.pending_otel_spans==="number"?runtimeState.pending_otel_spans:0;const lastOtelSuccess=runtimeState.last_otel_success_at;const lastOtelFailure=runtimeState.last_otel_failure_at;const otelExportFailing=settings.telemetry.enabled&&pendingOtelSpans>0&&Boolean(lastOtelFailure)&&(!lastOtelSuccess||lastOtelFailure>=lastOtelSuccess);return otelExportFailing?[`telemetry_otel_export_failing:${pendingOtelSpans}`]:[]}function buildTelemetryEnvOverrideDetails(){return{...resolveTelemetryEnvironmentPolicy(),pm_no_telemetry:telemetryEnvFlagEnabled("PM_NO_TELEMETRY"),telemetry_otel_disabled:telemetryEnvFlagEnabled("PM_TELEMETRY_OTEL_DISABLED"),telemetry_inline_flush:telemetryEnvFlagEnabled("PM_TELEMETRY_INLINE_FLUSH"),telemetry_source_context:telemetrySourceContextOverride()}}function telemetryQueueHasEntries(settings,queueSummary){return settings.telemetry.enabled&&queueSummary.validEntries>0}function isTelemetryQueueDraining(queueHasEntries,warnings){return queueHasEntries&&warnings.every(warning=>!warning.startsWith("telemetry_queue_pending:")&&!warning.startsWith("telemetry_queue_high_retries:"))}async function probeTelemetryEndpointHealth(endpoint){let probeUrl=endpoint;try{const parsed=new URL(endpoint);parsed.pathname="/healthz";parsed.search="";parsed.hash="";probeUrl=parsed.toString()}catch{}try{const response=await fetch(probeUrl,{method:"GET",signal:AbortSignal.timeout(TELEMETRY_ENDPOINT_PROBE_TIMEOUT_MS)});return{probe_url:normalizeEndpointForDisplay(probeUrl),ok:response.ok,status:response.status,max_schema_version:(()=>{for(const headerName of TELEMETRY_SERVER_MAX_SCHEMA_VERSION_HEADERS){const value=response.headers.get(headerName)?.trim();if(value&&value.length>0){return value}}return void 0})()}}catch(error){return{probe_url:normalizeEndpointForDisplay(probeUrl),ok:false,error:error instanceof Error?error.message:"probe_failed"}}}async function buildTelemetryCheck(settings,options){const globalPmRoot=resolveGlobalPmRoot(process.cwd());const queuePath=path.join(globalPmRoot,TELEMETRY_QUEUE_RELATIVE_PATH);const statePath=path.join(globalPmRoot,TELEMETRY_STATE_RELATIVE_PATH);const queueRaw=await readFileIfExists(queuePath);const queueExists=queueRaw!==null;const queueSizeBytes=queueRaw?Buffer.byteLength(queueRaw,"utf8"):0;const queueSummary=queueRaw?parseTelemetryQueue(queueRaw):emptyTelemetryQueueSummary();const stateRaw=await readFileIfExists(statePath);const{runtimeState,stateParseFailed}=parseTelemetryRuntimeState(stateRaw);const endpoint=settings.telemetry.endpoint.trim();const endpointDisplay=normalizeEndpointForDisplay(endpoint);const endpointProbe=await maybeProbeTelemetryEndpoint(settings,options.checkTelemetry);const warnings=[];if(stateParseFailed){warnings.push("telemetry_state_invalid_json")}warnings.push(...collectTelemetryQueueWarnings(settings,queueSummary,runtimeState),...collectTelemetryEndpointWarnings(endpointProbe),...collectTelemetrySchemaWarnings(endpointProbe),...collectTelemetryOtelWarnings(settings,runtimeState));const queueHasEntries=telemetryQueueHasEntries(settings,queueSummary);const pendingOtelSpans=typeof runtimeState.pending_otel_spans==="number"?runtimeState.pending_otel_spans:0;return{check:{name:"telemetry",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{enabled:settings.telemetry.enabled,capture_level:settings.telemetry.capture_level,endpoint:endpointDisplay,global_pm_root:globalPmRoot,queue_path:queuePath,queue_exists:queueExists,queue_entries:queueSummary.validEntries,queue_draining:isTelemetryQueueDraining(queueHasEntries,warnings),queue_invalid_rows:queueSummary.invalidRows,queue_rows_total:queueSummary.totalRows,queue_size_bytes:queueSizeBytes,queue_high_retry_entries:queueSummary.highRetryEntries,queue_high_retry_threshold:TELEMETRY_QUEUE_HIGH_RETRY_THRESHOLD,queue_max_attempts:queueSummary.maxAttempts,runtime_state_path:statePath,last_attempted_flush_at:runtimeState.last_attempted_flush_at??null,last_successful_flush_at:runtimeState.last_successful_flush_at??null,last_failed_flush_at:runtimeState.last_failed_flush_at??null,last_failed_flush_error:runtimeState.last_failed_flush_error??null,pending_otel_spans:pendingOtelSpans,last_otel_attempt_at:runtimeState.last_otel_attempt_at??null,last_otel_success_at:runtimeState.last_otel_success_at??null,last_otel_failure_at:runtimeState.last_otel_failure_at??null,last_otel_failure_error:runtimeState.last_otel_failure_error??null,endpoint_probe:endpointProbe??{attempted:false},env_overrides:buildTelemetryEnvOverrideDetails()}},warnings}}async function buildLocksCheck(pmRoot){let scan;try{scan=await scanLockHealth(pmRoot)}catch(error){const message=error instanceof Error?error.message:String(error);return{check:{name:"locks",status:"warn",ok:false,details:{active_lock_count:0,stale_lock_count:0,unreadable_lock_count:0,unparseable_lock_count:0,scan_failed:true,error:message,pm_root:pmRoot}},warnings:[`locks_scan_failed:${message}`]}}const warnings=[];if(scan.stale_lock_count>0){warnings.push(`locks_stale_count:${scan.stale_lock_count}`)}if(scan.unreadable_lock_count>0){warnings.push(`locks_unreadable:${scan.unreadable_lock_count}`)}return{check:{name:"locks",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{active_lock_count:scan.active_lock_count,stale_lock_count:scan.stale_lock_count,unreadable_lock_count:scan.unreadable_lock_count,unparseable_lock_count:scan.unparseable_lock_count}},warnings}}async function buildHistoryDriftCheck(params){const cacheHitVerification="metadata";let items=params.items;let drift=await scanHistoryDrift(params.pmRoot,items,{cacheHitVerification});const cacheConfirmationCandidates=[...new Set([...drift.hashMismatches,...drift.chainMismatches,...drift.versionSkews])].sort((left,right)=>left.localeCompare(right));let confirmedItems=[];let resolvedFalsePositiveItems=[];if(cacheConfirmationCandidates.length>0){items=await listAllItemMetadataWithBody(params.pmRoot,params.settings.item_format,params.typeRegistry.type_to_folder,params.itemReadWarnings,params.settings.schema,{forceSourceScan:true});drift=await scanHistoryDrift(params.pmRoot,items);confirmedItems=[...new Set([...drift.hashMismatches,...drift.chainMismatches,...drift.versionSkews])].sort((left,right)=>left.localeCompare(right));const confirmedSet=new Set(confirmedItems);resolvedFalsePositiveItems=cacheConfirmationCandidates.filter(id=>!confirmedSet.has(id))}const{missingStreams,unreadableStreams,hashMismatches,chainMismatches,versionSkews,driftedItems,workspaceStateMismatches,workspaceStateMissing,workspaceStateUnreadable}=drift;const warnings=[...missingStreams.map(id=>`history_drift_missing_stream:${id}`),...unreadableStreams.map(id=>`history_drift_unreadable_stream:${id}`),...hashMismatches.map(id=>`history_drift_hash_mismatch:${id}`),...chainMismatches.map(id=>`history_drift_chain_mismatch:${id}`),...versionSkews.map(id=>`history_drift_version_skew:${id}`),...workspaceStateMismatches.map(documentPath=>`history_drift_workspace_state_mismatch:${documentPath}`),...workspaceStateMissing.map(documentPath=>`history_drift_workspace_state_missing:${documentPath}`),...workspaceStateUnreadable.map(documentPath=>`history_drift_workspace_state_unreadable:${documentPath}`)];return{check:{name:"history_drift",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{checked_items:items.length,cache_hit_verification:cacheConfirmationCandidates.length>0?"metadata_then_content_hash":cacheHitVerification,cache_confirmation:{triggered:cacheConfirmationCandidates.length>0,reason:cacheConfirmationCandidates.length>0?"cached_corruption_candidate":null,candidate_items:cacheConfirmationCandidates,confirmed_items:confirmedItems,resolved_false_positive_items:resolvedFalsePositiveItems,authoritative_item_source:cacheConfirmationCandidates.length>0},drifted_items:driftedItems,counts:{drifted:driftedItems.length,missing_streams:missingStreams.length,unreadable_streams:unreadableStreams.length,hash_mismatches:hashMismatches.length,chain_mismatches:chainMismatches.length,version_skews:versionSkews.length,workspace_state_mismatches:workspaceStateMismatches.length,workspace_state_missing:workspaceStateMissing.length,workspace_state_unreadable:workspaceStateUnreadable.length},missing_streams:missingStreams,unreadable_streams:unreadableStreams,hash_mismatches:hashMismatches,chain_mismatches:chainMismatches,version_skews:versionSkews,workspace_state_mismatches:workspaceStateMismatches,workspace_state_missing:workspaceStateMissing,workspace_state_unreadable:workspaceStateUnreadable}},warnings}}function buildVectorizationRuntimeSnapshot(settings,pmRoot){const runtimeDefaults=resolveSettingsWithSemanticRuntimeDefaults(settings);const providerResolution=resolveEmbeddingProviders(runtimeDefaults.settings);const vectorStoreResolution=resolveVectorStores(runtimeDefaults.settings,pmRoot);const runtimeEmbeddingIdentity=providerResolution.active?buildVectorizationEmbeddingIdentity(providerResolution.active.name,providerResolution.active.model):null;return{runtimeDefaults,providerResolution,vectorStoreResolution,runtimeEmbeddingIdentity,semanticRuntimeAvailable:Boolean(providerResolution.active&&vectorStoreResolution.active)}}function emptyVectorizationRefreshResult(){return{refreshed:[],skipped:[],warnings:[]}}async function refreshStaleVectorizationItems(params){if(!params.refreshPolicy.enabled||!params.snapshot.semanticRuntimeAvailable||params.staleBefore.length===0){return emptyVectorizationRefreshResult()}return refreshSemanticEmbeddingsForMutatedItems(params.pmRoot,params.staleBefore,{settings:params.snapshot.runtimeDefaults.settings,apply_runtime_defaults:false})}function vectorizationEmbeddingIdentityChanged(params){return params.strictVectorizationWarnings&&params.semanticRuntimeAvailable&&Boolean(params.ledgerBefore.embedding&&params.runtimeEmbeddingIdentity&&hasVectorizationEmbeddingIdentityChanged(params.ledgerBefore.embedding,params.runtimeEmbeddingIdentity))}function collectVectorizationWarnings(params){const warningSet=new Set([...params.ledgerBefore.warnings,...params.ledgerAfter.warnings]);if(params.strictVectorizationWarnings){for(const warning of params.refreshResult.warnings){warningSet.add(warning)}}if(params.embeddingIdentityChanged){warningSet.add("vectorization_embedding_identity_changed")}if(params.strictVectorizationWarnings&&params.semanticRuntimeAvailable&&params.staleAfter.length>0){warningSet.add(`vectorization_stale_items_remaining:${params.staleAfter.length}`)}return[...warningSet].sort((left,right)=>left.localeCompare(right))}function resolveVectorizationRefreshSkippedReason(refreshPolicy,semanticRuntimeAvailable,staleBefore){if(refreshPolicy.enabled&&semanticRuntimeAvailable&&staleBefore.length>0){return null}if(!refreshPolicy.enabled){return"refresh_disabled"}return semanticRuntimeAvailable?"no_stale_items":"semantic_runtime_unavailable"}function buildVectorizationProviderDetails(settings,snapshot){const activeProvider=snapshot.providerResolution.active?.name??null;const activeVectorStore=snapshot.vectorStoreResolution.active?.name??null;return{provider_active:activeProvider,provider_configured:typeof settings.search?.provider==="string"?settings.search.provider:null,provider_source:resolveProviderConfigSource(activeProvider,settings.search?.provider??null),vector_store_active:activeVectorStore,vector_store_configured:typeof settings.vector_store?.adapter==="string"?settings.vector_store.adapter:null,vector_store_source:resolveProviderConfigSource(activeVectorStore,settings.vector_store?.adapter??null)}}function buildVectorizationRefreshPolicyDetails(refreshPolicy){return{enabled:refreshPolicy.enabled,check_only:refreshPolicy.checkOnly,no_refresh:refreshPolicy.noRefresh,refresh_vectors:refreshPolicy.refreshVectors}}function vectorizationRefreshAttempted(refreshPolicy,semanticRuntimeAvailable,staleBefore){return refreshPolicy.enabled&&staleBefore.length>0&&semanticRuntimeAvailable}async function buildVectorizationCheck(pmRoot,settings,items,refreshPolicy,verboseStaleItems){const snapshot=buildVectorizationRuntimeSnapshot(settings,pmRoot);const ledgerBefore=await readVectorizationStatusLedger(pmRoot);const staleBefore=snapshot.semanticRuntimeAvailable?collectStaleVectorizationIds(items,ledgerBefore.entries):[];const refreshResult=await refreshStaleVectorizationItems({pmRoot,snapshot,refreshPolicy,staleBefore});const ledgerAfter=await readVectorizationStatusLedger(pmRoot);const staleAfter=snapshot.semanticRuntimeAvailable?collectStaleVectorizationIds(items,ledgerAfter.entries):[];const strictVectorizationWarnings=!snapshot.runtimeDefaults.auto_ollama_defaults_applied;const embeddingIdentityChanged=vectorizationEmbeddingIdentityChanged({strictVectorizationWarnings,semanticRuntimeAvailable:snapshot.semanticRuntimeAvailable,ledgerBefore,runtimeEmbeddingIdentity:snapshot.runtimeEmbeddingIdentity});const warnings=collectVectorizationWarnings({ledgerBefore,ledgerAfter,refreshResult,strictVectorizationWarnings,semanticRuntimeAvailable:snapshot.semanticRuntimeAvailable,embeddingIdentityChanged,staleAfter});const staleBeforeDetail=selectStaleItemDetail(staleBefore,verboseStaleItems);const staleAfterDetail=selectStaleItemDetail(staleAfter,verboseStaleItems);const refreshAttempted=vectorizationRefreshAttempted(refreshPolicy,snapshot.semanticRuntimeAvailable,staleBefore);return{check:{name:"vectorization",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{semantic_runtime_available:snapshot.semanticRuntimeAvailable,compatibility_mode_auto_defaults:snapshot.runtimeDefaults.auto_ollama_defaults_applied,auto_ollama_defaults_applied:snapshot.runtimeDefaults.auto_ollama_defaults_applied,auto_ollama_defaults_skipped_reason:snapshot.runtimeDefaults.auto_ollama_defaults_skipped_reason??null,auto_ollama_defaults_remediation:snapshot.runtimeDefaults.auto_ollama_defaults_remediation??null,refresh_policy:buildVectorizationRefreshPolicyDetails(refreshPolicy),...buildVectorizationProviderDetails(settings,snapshot),embedding_identity_changed:embeddingIdentityChanged,embedding_identity_before:ledgerBefore.embedding??null,embedding_identity_runtime:snapshot.runtimeEmbeddingIdentity??null,items:items.length,ledger_entries_before:Object.keys(ledgerBefore.entries).length,stale_items_detail_mode:verboseStaleItems?"full":"summary",stale_items_summary_limit:STALE_VECTORIZATION_SUMMARY_LIMIT,stale_items_before_total:staleBeforeDetail.total,stale_items_before:staleBeforeDetail.values,stale_items_before_truncated:staleBeforeDetail.truncated,refresh_attempted:refreshAttempted,refresh_skipped_reason:resolveVectorizationRefreshSkippedReason(refreshPolicy,snapshot.semanticRuntimeAvailable,staleBefore),refresh_result:refreshResult,ledger_entries_after:Object.keys(ledgerAfter.entries).length,stale_items_after_total:staleAfterDetail.total,stale_items_after:staleAfterDetail.values,stale_items_after_truncated:staleAfterDetail.truncated}},warnings}}function validateSettingsValues(settings){const warnings=[];if(settings.id_prefix.trim().length===0){warnings.push("settings:id_prefix_empty")}if(settings.locks.ttl_seconds<=0){warnings.push("settings:locks_ttl_non_positive")}return warnings}function resolveVectorRefreshPolicy(options){const checkOnly=options.checkOnly===true;const refreshVectors=options.refreshVectors===true;if(refreshVectors&&checkOnly){throw new PmCliError("--check-only cannot be combined with --refresh-vectors",EXIT_CODE.USAGE)}if(refreshVectors&&options.noRefresh===true){throw new PmCliError("--no-refresh cannot be combined with --refresh-vectors",EXIT_CODE.USAGE)}return{enabled:refreshVectors,checkOnly,noRefresh:!refreshVectors,refreshVectors}}const HEALTH_CLONE_OPTIONAL_DIRECTORIES=new Set(["extensions","locks","search"]);function resolveHealthDirectoryLists(typeRegistry){const requiredDirSet=new Set(PM_CORE_REQUIRED_SUBDIRS.filter(entry=>entry.length>0));const optionalDirSet=new Set;const builtinItemFolderSet=new Set(Object.values(TYPE_TO_FOLDER));for(const folder of typeRegistry.folders){if(requiredDirSet.has(folder)&&!builtinItemFolderSet.has(folder)){continue}requiredDirSet.delete(folder);optionalDirSet.add(folder)}for(const folder of HEALTH_CLONE_OPTIONAL_DIRECTORIES){requiredDirSet.delete(folder);optionalDirSet.add(folder)}return{requiredDirs:[...requiredDirSet].sort((left,right)=>left.localeCompare(right)),optionalDirs:[...optionalDirSet].sort((left,right)=>left.localeCompare(right)),optionalDirSet}}async function scanHealthDirectories(pmRoot,typeRegistry,strictDirectories){const{requiredDirs,optionalDirs,optionalDirSet}=resolveHealthDirectoryLists(typeRegistry);const missingRequiredDirs=[];const missingOptionalDirs=[];const hookWarnings=[];for(const relativeDir of[...requiredDirs,...optionalDirs]){const directoryPath=path.join(pmRoot,relativeDir);hookWarnings.push(...await runActiveOnReadHooks({path:directoryPath,scope:"project"}));if(await isDirectory(directoryPath)){continue}if(optionalDirSet.has(relativeDir)){missingOptionalDirs.push(relativeDir)}else{missingRequiredDirs.push(relativeDir)}}return{requiredDirs,optionalDirs,missingRequiredDirs,missingOptionalDirs,missingDirs:strictDirectories?[...missingRequiredDirs,...missingOptionalDirs]:[...missingRequiredDirs],hookWarnings}}function resolveHealthSkipPolicy(options){const checkOnlyDefaultSummary=options.checkOnly===true&&options.brief!==true&&options.summary!==true&&options.full!==true;const summaryMode=(options.summary===true||checkOnlyDefaultSummary)&&options.full!==true;const fastProjectionCheckOnly=options.checkOnly===true&&(options.brief===true||options.summary===true)&&options.full!==true;return{summaryMode,skipIntegrity:(options.skipIntegrity===true||fastProjectionCheckOnly)&&options.full!==true,skipDrift:(options.skipDrift===true||fastProjectionCheckOnly)&&options.full!==true,skipVectors:(options.skipVectors===true||fastProjectionCheckOnly)&&options.full!==true}}async function readHealthItems(params){if(params.skipPolicy.skipDrift&&params.skipPolicy.skipVectors){return listAllItemMetadataLight(params.pmRoot,params.settings.item_format,params.typeRegistry.type_to_folder,params.itemReadWarnings,params.settings.schema)}return listAllItemMetadataWithBody(params.pmRoot,params.settings.item_format,params.typeRegistry.type_to_folder,params.itemReadWarnings,params.settings.schema)}function buildSkippedHealthCheck(name){return{check:{name,status:"ok",ok:true,details:{skipped:true}},warnings:[]}}function buildSettingsHealthCheck(settingsPath,settings,normalizedSettingsReadWarnings){return{name:"settings",status:normalizedSettingsReadWarnings.length===0?"ok":"warn",ok:normalizedSettingsReadWarnings.length===0,details:{path:settingsPath,version:settings.version,id_prefix:settings.id_prefix,locks_ttl_seconds:settings.locks.ttl_seconds,warnings:normalizedSettingsReadWarnings}}}function buildDirectoriesHealthCheck(directoryState,strictDirectories){return{name:"directories",status:directoryState.missingDirs.length===0?"ok":"warn",ok:directoryState.missingDirs.length===0,details:{required:directoryState.requiredDirs,optional:directoryState.optionalDirs,missing_required:directoryState.missingRequiredDirs,missing_optional:directoryState.missingOptionalDirs,missing:directoryState.missingDirs,strict_directories:strictDirectories}}}function buildSettingsValuesHealthCheck(settingWarnings,statusRoleDiagnostics){return{name:"settings_values",status:settingWarnings.length===0?"ok":"warn",ok:settingWarnings.length===0,details:{warnings:settingWarnings,...statusRoleDiagnostics.roleless_status_count>0?{lifecycle_status_roles:statusRoleDiagnostics}:{}}}}const resolveUnknownAuthorEventCount=authorAttribution=>authorAttribution.unknown_event_count??0;const resolveActionableUnknownAuthorEventCount=authorAttribution=>authorAttribution.actionable_unknown_event_count??resolveUnknownAuthorEventCount(authorAttribution);function buildStorageHealthCheck(items,settings,historySummary,authorAttribution,staleInProgress,provenance){const unknownAuthorEventCount=resolveUnknownAuthorEventCount(authorAttribution);const actionableUnknownAuthorEventCount=resolveActionableUnknownAuthorEventCount(authorAttribution);const hasAuthorEvents=unknownAuthorEventCount>0;const hasActionableAuthorWarnings=actionableUnknownAuthorEventCount>0;const hasStaleInProgressItems=staleInProgress.count>0;return{name:"storage",status:historySummary.over_threshold.length===0&&historySummary.orphaned.length===0&&!hasActionableAuthorWarnings&&!hasStaleInProgressItems?"ok":"warn",ok:historySummary.over_threshold.length===0&&historySummary.orphaned.length===0&&!hasActionableAuthorWarnings&&!hasStaleInProgressItems,details:{items:items.length,history_streams:historySummary.count,tombstones:{retention_policy:"retain_append_only",gc_enabled:false,count:historySummary.tombstones.length,ids:historySummary.tombstones.slice(0,25),truncated:historySummary.tombstones.length>25},orphaned_history_streams:{count:historySummary.orphaned.length,ids:historySummary.orphaned.slice(0,25),truncated:historySummary.orphaned.length>25},...hasAuthorEvents?{author_attribution:authorAttribution}:{},...hasStaleInProgressItems?{stale_in_progress:staleInProgress}:{},...provenance.outcomes.length>0?{provenance_resolver_outcomes:provenance.outcomes}:{},...provenance.invalid_values.length>0?{provenance_invalid_values:provenance.invalid_values}:{},provenance_sample:provenance.sample,...historySummary.max_entries!==null?{compact_policy:{enabled:settings.history.compact_policy.enabled,max_entries:historySummary.max_entries,trigger:settings.history.compact_policy.trigger,over_threshold_count:historySummary.over_threshold.length,over_threshold:historySummary.over_threshold}}:{}}}}function buildStaleInProgressHealthSummary(scan){const warnings=scan.count===0?[]:[`stale_in_progress_items:${scan.count}`];return{scan,warnings}}function collectHealthWarnings(params){const warnings=[...params.directoryState.missingDirs.map(dir=>`missing_directory:${dir}`),...params.normalizedSettingsReadWarnings,...params.settingWarnings,...params.normalizedItemReadWarnings,...params.telemetryCheck.warnings,...params.extensionCheck.warnings,...params.historyPolicyWarnings,...params.historySummary.warnings,...params.authorAttributionWarnings,...params.staleInProgressWarnings,...params.provenanceWarnings,...params.locksCheck.warnings,...params.integrityCheck.warnings,...params.historyDriftCheck.warnings,...params.vectorizationCheck.warnings,...params.directoryState.hookWarnings];return[...new Set(warnings)]}function extractHistoryDriftedCount(historyDriftCheck){const counts=historyDriftCheck.check.details.counts;return typeof counts?.drifted==="number"?counts.drifted:0}function buildHealthRemediationSources(params){return{settings:params.normalizedSettingsReadWarnings,directories:params.directoryState.missingDirs.map(dir=>`missing_directory:${dir}`).concat(params.directoryState.hookWarnings),settings_values:params.settingWarnings,telemetry:params.telemetryCheck.warnings,extensions:params.extensionCheck.warnings,storage:[...params.historyPolicyWarnings,...params.historySummary.warnings,...params.authorAttributionWarnings,...params.staleInProgressWarnings,...params.provenanceWarnings],locks:params.locksCheck.warnings,integrity:[...params.normalizedItemReadWarnings,...params.integrityCheck.warnings],history_drift:params.historyDriftCheck.warnings,vectorization:params.vectorizationCheck.warnings}}function buildHealthFindings(params){const owners=new Map;for(const[check,warnings]of Object.entries(params.remediationSources)){for(const warning of warnings){if(!owners.has(warning))owners.set(warning,check)}}const checksByName=new Map(params.checks.map(check=>[check.name,check]));const findings=params.warnings.map(warning=>{const check=owners.get(warning)??"integrity";const code=resolveRemediation(warning)?.code??warningCode(warning);const details=checksByName.get(check)?.details;const remediationMap=typeof details?.remediation_map==="object"&&details.remediation_map!==null?details.remediation_map:{};const remediation=remediationMap[code];const severity=isAdvisoryHealthWarning(warning,params.requireMergeDrivers)?"advisory":"gate_failing";return{warning,code,check,severity,...typeof remediation==="string"?{remediation}:severity==="gate_failing"?{disposition:"no_safe_automatic_remediation"}:{}}});return findings}function rewriteBulkHealthRemediation(params){if(params.check.name==="history_drift"&&params.historyDriftedCount>1){for(const code of Object.keys(params.remediationMap)){if(code!=="history_drift_merge_receipt"&&code!=="history_drift_version_skew"){params.remediationMap[code]="pm history-repair --all"}}}if(params.check.name==="storage"&&params.overThresholdCount>1){for(const code of Object.keys(params.remediationMap)){params.remediationMap[code]="pm history-compact --all-streams"}}}function attachHealthRemediationMaps(params){for(const check of params.checks){const remediationMap=buildRemediationMap(params.remediationSources[check.name]);rewriteBulkHealthRemediation({check,remediationMap,historyDriftedCount:params.historyDriftedCount,overThresholdCount:params.overThresholdCount});if(Object.keys(remediationMap).length>0){check.details={...check.details,remediation_map:remediationMap}}}}async function correlateMergeReceiptHistoryDriftItems(params){if(params.gitWorkspaceRoot===null||params.pendingMergeReceipts.length===0){return[]}const details=params.historyDriftCheck.check.details;const hashMismatches=Array.isArray(details.hash_mismatches)?details.hash_mismatches.filter(entry=>typeof entry==="string"):[];const unsafeStreamIds=new Set([details.missing_streams,details.unreadable_streams,details.chain_mismatches].flatMap(value=>Array.isArray(value)?value:[]));const cloneLocalReceiptsByItem=new Map;for(const receipt of params.pendingMergeReceipts){if(receipt.evidence_source!=="clone_local")continue;const receipts=cloneLocalReceiptsByItem.get(receipt.item_id)??[];receipts.push(receipt);cloneLocalReceiptsByItem.set(receipt.item_id,receipts)}const attributed=[];for(const id of hashMismatches){if(unsafeStreamIds.has(id))continue;const receipts=cloneLocalReceiptsByItem.get(id);if(!receipts||receipts.length===0)continue;try{await runHistoryRepair(id,{dryRun:true,mergeReceiptProof:{gitWorkspaceRoot:params.gitWorkspaceRoot,receipts}},params.global);attributed.push(id)}catch{}}return[...new Set(attributed)].sort((left,right)=>left.localeCompare(right))}function applyMergeReceiptHistoryDriftAttribution(historyDriftCheck,attributedItems){const attributed=new Set(attributedItems);historyDriftCheck.warnings=[...historyDriftCheck.warnings.filter(warning=>{if(!warning.startsWith("history_drift_hash_mismatch:"))return true;return!attributed.has(warning.slice(warning.indexOf(":")+1))}),...attributedItems.map(id=>`history_drift_merge_receipt:${id}`)].sort((left,right)=>left.localeCompare(right));historyDriftCheck.check.details={...historyDriftCheck.check.details,merge_receipt_attributed_items:attributedItems}}function projectHealthResult(result,options,summaryMode){const warningCount=result.warning_count??result.warnings.length;const boundedResult={...result,warning_count:warningCount,warning_limit:HEALTH_WARNING_LIMIT,warnings_truncated:warningCount>HEALTH_WARNING_LIMIT,warnings:result.warnings.slice(0,HEALTH_WARNING_LIMIT),findings:(result.findings??[]).filter(finding=>result.warnings.slice(0,HEALTH_WARNING_LIMIT).includes(finding.warning)||result.failed_because.includes(finding.warning))};const projected=summaryMode?applySummaryHealthProjection(boundedResult):options.brief===true?applyBriefHealthProjection(boundedResult):boundedResult;return{...projected,warning_count:warningCount,warning_limit:HEALTH_WARNING_LIMIT,warnings_truncated:warningCount>projected.warnings.length,...projected.projection?{projection:{...projected.projection,warning_count:warningCount,warnings_truncated:warningCount>projected.warnings.length}}:{}}}async function runHealth(global2,options={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settingsPath=getSettingsPath(pmRoot);const{settings,warnings:settingsReadWarnings}=await readSettingsWithMetadata(pmRoot);const normalizedSettingsReadWarnings=[...new Set(settingsReadWarnings)];const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());const strictDirectories=options.strictDirectories===true;const strictExit=options.strictExit===true||options.failOnWarn===true;const requireMergeDrivers=options.requireMergeDrivers===true||strictExit;const refreshPolicy=resolveVectorRefreshPolicy(options);const directoryState=await scanHealthDirectories(pmRoot,typeRegistry,strictDirectories);const settingsValueWarnings=validateSettingsValues(settings);const telemetryCheck=await buildTelemetryCheck(settings,{checkTelemetry:options.checkTelemetry===true});const extensionCheck=await buildExtensionCheck(pmRoot,settings,Boolean(global2.noExtensions));const skipPolicy=resolveHealthSkipPolicy(options);const itemReadWarnings=[];const items=await readHealthItems({pmRoot,settings,typeRegistry,skipPolicy,itemReadWarnings});const itemsWithBody=items;const statusRoleDiagnostics=inspectStatusRoleAssignments(resolveRuntimeStatusRegistry(settings.schema),items);const settingWarnings=[...settingsValueWarnings,...buildStatusRoleWarnings(statusRoleDiagnostics)];const historyPolicy=skipPolicy.skipDrift?{warnings:[]}:await enforceHistoryStreamPolicyForItems({pmRoot,settings,itemIds:items.map(item=>item.id),commandLabel:"health"});const historySummary=await countHistoryStreams(pmRoot,settings.history.compact_policy,await listStoredItemDocumentIds(pmRoot));const authorAttribution=await scanHistoryAuthorAttribution(pmRoot,20,options.verboseAuthorEvents===true);const actionableUnknownAuthorEventCount=resolveActionableUnknownAuthorEventCount(authorAttribution);const authorAttributionWarnings=actionableUnknownAuthorEventCount>0?[`history_unknown_author_events:${actionableUnknownAuthorEventCount}`]:[];const staleInProgress=buildStaleInProgressHealthSummary(await scanStaleInProgressItems(pmRoot,items,{in_progress_status:settings.schema.workflow.in_progress_status,threshold_hours:settings.mutation_guard.stale_in_progress_hours}));const provenanceResolverHealth=await scanProvenanceResolverHealth(pmRoot);const provenanceWarnings=provenanceResolverHealth.warnings;const locksCheck=await buildLocksCheck(pmRoot);const integrityCheck=skipPolicy.skipIntegrity&&!requireMergeDrivers?{...buildSkippedHealthCheck("integrity"),gitWorkspaceRoot:null,pendingMergeReceipts:[]}:await buildIntegrityCheck(pmRoot,typeRegistry.type_to_folder,settings.schema,requireMergeDrivers,items);const historyDriftCheck=skipPolicy.skipDrift?buildSkippedHealthCheck("history_drift"):await buildHistoryDriftCheck({pmRoot,items:itemsWithBody,settings,typeRegistry,itemReadWarnings});const normalizedItemReadWarnings=[...new Set(itemReadWarnings)];const mergeReceiptAttributedHistoryDriftItems=await correlateMergeReceiptHistoryDriftItems({gitWorkspaceRoot:integrityCheck.gitWorkspaceRoot,pendingMergeReceipts:integrityCheck.pendingMergeReceipts,historyDriftCheck,global:global2});applyMergeReceiptHistoryDriftAttribution(historyDriftCheck,mergeReceiptAttributedHistoryDriftItems);const vectorizationCheck=skipPolicy.skipVectors?buildSkippedHealthCheck("vectorization"):await buildVectorizationCheck(pmRoot,settings,itemsWithBody,refreshPolicy,options.verboseStaleItems===true);const checks=[buildSettingsHealthCheck(settingsPath,settings,normalizedSettingsReadWarnings),buildDirectoriesHealthCheck(directoryState,strictDirectories),buildSettingsValuesHealthCheck(settingWarnings,statusRoleDiagnostics),telemetryCheck.check,extensionCheck.check,buildStorageHealthCheck(items,settings,historySummary,authorAttribution,staleInProgress.scan,provenanceResolverHealth),locksCheck.check,integrityCheck.check,historyDriftCheck.check,vectorizationCheck.check];const normalizedWarnings=collectHealthWarnings({directoryState,normalizedSettingsReadWarnings,settingWarnings,normalizedItemReadWarnings,telemetryCheck,extensionCheck,historyPolicyWarnings:historyPolicy.warnings,historySummary,authorAttributionWarnings,staleInProgressWarnings:staleInProgress.warnings,provenanceWarnings,locksCheck,integrityCheck,historyDriftCheck,vectorizationCheck});const remediationSources=buildHealthRemediationSources({directoryState,normalizedSettingsReadWarnings,settingWarnings,normalizedItemReadWarnings,telemetryCheck,extensionCheck,historyPolicyWarnings:historyPolicy.warnings,historySummary,authorAttributionWarnings,staleInProgressWarnings:staleInProgress.warnings,provenanceWarnings,locksCheck,integrityCheck,historyDriftCheck,vectorizationCheck});attachHealthRemediationMaps({checks,remediationSources,historyDriftedCount:extractHistoryDriftedCount(historyDriftCheck),overThresholdCount:historySummary.over_threshold.length});const blockingWarnings=normalizedWarnings.filter(warning=>!isAdvisoryHealthWarning(warning,requireMergeDrivers));const findings=buildHealthFindings({warnings:normalizedWarnings,checks,remediationSources,requireMergeDrivers});const failingChecks=new Set(findings.filter(finding=>finding.severity==="gate_failing").map(finding=>finding.check));const warningChecks=new Set(findings.map(finding=>finding.check));for(const check of checks){check.ok=!failingChecks.has(check.name);if(warningChecks.has(check.name))check.status="warn"}const result={ok:blockingWarnings.length===0,verdict:{authority:"ok",...strictExit?{strict_exit:true}:{},...requireMergeDrivers?{require_merge_drivers:true}:{},exit_code:strictExit&&blockingWarnings.length>0?EXIT_CODE.GENERIC_FAILURE:0},checks,warnings:normalizedWarnings,findings,failed_because:blockingWarnings,generated_at:nowIso()};return projectHealthResult(result,options,skipPolicy.summaryMode)}const _testOnlyHealthCommand={buildHierarchyIntegrityWarnings,buildExtensionHealthTriageSummary,buildHealthFindings,buildCapabilityContractMetadata,buildStaleInProgressHealthSummary,buildVectorizationProviderDetails,collectUnknownCapabilityGuidance,isAdvisoryHealthWarning,isDirectory,isExpectedUnmanagedExtension,listItemDocumentPaths,normalizeEndpointForDisplay,normalizeExtensionNameForMatch,parseTelemetryQueue,probeTelemetryEndpointHealth,projectHealthResult,resolveActionableUnknownAuthorEventCount,resolveHealthSkipPolicy,resolveUnknownAuthorEventCount,resolveVectorRefreshPolicy,selectStaleItemDetail,summarizeHealthCheckDetails,summarizeExtensionList,summarizeRecordList,summarizeStringList,telemetryEnvFlagEnabled,warningCode};export{_testOnlyHealthCommand,runHealth};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7386bc6e-f032-5faa-b6b0-1fbe9eee1420")}catch(e2){}})();import{runInitAgentGuidance}from"../init-agent-guidance.js";import fs from"node:fs/promises";import path from"node:path";import{resolveTelemetryEnvironmentPolicy}from"../../core/telemetry/policy.js";import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isTerminalStatus}from"../../core/item/status.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{resolveRuntimeStatusRegistry}from"../../core/schema/runtime-schema.js";import{isFileMissingError,readFileIfExists}from"../../core/fs/fs-utils.js";import{activateExtensions,getActiveExtensionRegistrations,loadExtensions,runActiveOnReadHooks}from"../../core/extensions/index.js";import{collectRegisteredItemFieldNames}from"../../core/extensions/item-fields.js";import{KNOWN_EXTENSION_CAPABILITIES}from"../../core/extensions/loader.js";import{enforceHistoryStreamPolicyForItems}from"../../core/history/history-stream-policy.js";import{scanHistoryDrift}from"../../core/history/drift-scan.js";import{scanLockHealth}from"../../core/lock/lock-gc.js";import{readVectorizationStatusLedger,refreshSemanticEmbeddingsForMutatedItems}from"../../core/search/cache.js";import{resolveEmbeddingProviders,resolveProviderConfigSource}from"../../core/search/providers.js";import{resolveSettingsWithSemanticRuntimeDefaults}from"../../core/search/semantic-defaults.js";import{collectStaleVectorizationIds}from"../../core/search/staleness.js";import{buildVectorizationEmbeddingIdentity,hasVectorizationEmbeddingIdentityChanged}from"../../core/search/vectorization-metadata.js";import{resolveVectorStores}from"../../core/search/vector-stores.js";import{EXIT_CODE,PM_CORE_REQUIRED_SUBDIRS,TYPE_TO_FOLDER}from"../../core/shared/constants.js";import{findFirstMergeConflictMarker}from"../../core/shared/conflict-markers.js";import{PmCliError}from"../../core/shared/errors.js";import{toNonEmptyStringOrUndefined}from"../../core/shared/primitives.js";import{nowIso}from"../../core/shared/time.js";import{parseItemDocument}from"../../core/item/item-format.js";import{effectiveItemFormatVersion,scanItemFormatVersions}from"../../core/item/item-format-version.js";import{listAllItemMetadataLight,listAllItemMetadataWithBody}from"../../core/store/item-store.js";import{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS,TELEMETRY_SCHEMA_VERSION}from"../../core/telemetry/runtime.js";import{getItemFormatFromPath,getSettingsPath,ITEM_FILE_EXTENSIONS,resolveGlobalPmRoot,resolvePmRoot,resolveWorkspaceRoot}from"../../core/store/paths.js";import{readSettingsWithMetadata}from"../../core/store/settings.js";import{buildRemediationMap,resolveRemediation}from"../../core/diagnostics/remediation.js";import{scanExtensionHostVersions}from"./extension-host-version.js";import{scanHistoryAuthorAttribution}from"../author-attribution.js";import{readManagedExtensionState}from"../extension.js";import{scanProvenanceResolverHealth}from"./provenance-health.js";import{applyStoredExtensionMigrationState}from"../extension/migrations.js";import{inspectExtensionAuthorManifest}from"../extension/author-manifest.js";import{buildCapabilityContractMetadata,buildRegistrationCollisionRemediation,collectUnknownCapabilityGuidance}from"../extension/doctor.js";import{scanStaleInProgressItems}from"./stale-work.js";import{scanTrackedRuntimeCache}from"./tracked-runtime-cache.js";import{auditMergeDriverConfiguration,findGitWorkspaceRoot}from"../merge/install.js";import{inspectMergeReceiptEvidence,partitionMergeReceipts}from"../merge/receipts.js";import{classifyHistoryMergeReceiptReferences,extractHistoryMergeReceiptDispositions,extractHistoryMergeReceiptReferences}from"./merge-receipt-history.js";import{runHistoryRepair}from"../history-repair.js";import{resolveWorkspaceRelationshipKindRegistry}from"../graph/assembly.js";import{analyzeHierarchyIntegrity}from"../graph/hierarchy-integrity.js";import{buildStatusRoleWarnings,inspectStatusRoleAssignments}from"./status-role-diagnostics.js";const PM_TELEMETRY_SOURCE_CONTEXT_SET=new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);const STALE_VECTORIZATION_SUMMARY_LIMIT=25;const BRIEF_HEALTH_DETAIL_LIMIT=8;const HEALTH_WARNING_LIMIT=100;const TELEMETRY_QUEUE_RELATIVE_PATH=path.join("runtime","telemetry","events.jsonl");const TELEMETRY_STATE_RELATIVE_PATH=path.join("runtime","telemetry","state.json");const TELEMETRY_ENDPOINT_PROBE_TIMEOUT_MS=2500;const TELEMETRY_QUEUE_HIGH_WATER_MARK=500;const TELEMETRY_QUEUE_HIGH_RETRY_THRESHOLD=TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS-3;const TELEMETRY_SERVER_MAX_SCHEMA_VERSION_HEADERS=["x-pm-telemetry-max-schema-version","x-pm-telemetry-max-version"];function isAdvisoryHealthWarning(warning,requireMergeDrivers=false){return warning.startsWith("agent_guidance_")||warning.startsWith("telemetry_")||warning.startsWith("history_stream_over_compact_threshold:")||warning.startsWith("integrity_legacy_hierarchy_")||warning.startsWith("stale_in_progress_items:")||warning.startsWith("provenance_resolver_zero_success:")||warning.startsWith("provenance_value_domain_invalid:")||!requireMergeDrivers&&warning.startsWith("merge_driver_configuration_missing:")}function warningCode(value){const normalized=value.trim();const separator=normalized.indexOf(":");if(separator===-1){return normalized}return normalized.slice(0,separator)}function normalizeExtensionNameForMatch(value){return value.trim().toLowerCase()}function isExpectedUnmanagedExtension(name,directory){const normalizedName=normalizeExtensionNameForMatch(name);const normalizedDirectory=normalizeExtensionNameForMatch(directory);if(normalizedName.startsWith("builtin-")){return true}return normalizedDirectory==="beads"||normalizedDirectory==="todos"}async function isDirectory(targetPath){try{const stats=await fs.stat(targetPath);return stats.isDirectory()}catch{return false}}async function listStoredItemDocumentIds(pmRoot){const directories=(await fs.readdir(pmRoot,{withFileTypes:true})).filter(entry=>entry.isDirectory());const filesByDirectory=await Promise.all(directories.map(entry=>fs.readdir(path.join(pmRoot,entry.name),{withFileTypes:true})));return new Set(filesByDirectory.flatMap(entries=>entries.filter(entry=>entry.isFile()).filter(entry=>ITEM_FILE_EXTENSIONS.some(extension=>entry.name.endsWith(extension))).map(entry=>path.parse(entry.name).name)))}async function inspectHistoryStream(streamPath,itemId,compactPolicy,liveItemIds){const warnings=await runActiveOnReadHooks({path:streamPath,scope:"project"});const needsClassification=itemId!=="_workspace"&&!liveItemIds.has(itemId);if(!compactPolicy.enabled&&!needsClassification){return{warnings,overThreshold:false,classification:"live"}}let raw;try{raw=await fs.readFile(streamPath,"utf8")}catch{return{warnings,overThreshold:false,classification:"unreadable"}}let classification="live";if(needsClassification){const lastLine=raw.split(/\r?\n/).map(line=>line.trim()).filter(Boolean).at(-1);try{const lastEntry=JSON.parse(lastLine??"{}");classification=lastEntry.op==="delete"?"tombstone":"orphaned"}catch{classification="orphaned"}}const entryCount=compactPolicy.enabled?raw.split(/\r?\n/).filter(line=>line.trim().length>0).length:0;return{warnings,overThreshold:compactPolicy.enabled&&entryCount>compactPolicy.max_entries,classification}}async function countHistoryStreams(pmRoot,compactPolicy,liveItemIds){const historyDir=path.join(pmRoot,"history");if(!await isDirectory(historyDir)){return{count:0,warnings:[],over_threshold:[],max_entries:null,tombstones:[],orphaned:[]}}const historyFiles=(await fs.readdir(historyDir)).filter(entry=>entry.endsWith(".jsonl")).sort((left,right)=>left.localeCompare(right));const policyActive=compactPolicy.enabled;const maxEntries=policyActive?compactPolicy.max_entries:null;const warnings=[];const overThreshold=[];const tombstones=[];const orphaned=[];for(const fileName of historyFiles){const streamPath=path.join(historyDir,fileName);const itemId=fileName.slice(0,-".jsonl".length);const inspection=await inspectHistoryStream(streamPath,itemId,compactPolicy,liveItemIds);warnings.push(...inspection.warnings);if(inspection.classification==="tombstone")tombstones.push(itemId);if(inspection.classification==="orphaned")orphaned.push(itemId);if(inspection.overThreshold)overThreshold.push(itemId)}return{count:historyFiles.length,warnings:[...warnings,...overThreshold.map(id=>`history_stream_over_compact_threshold:${id}`),...orphaned.map(id=>`history_orphaned_stream:${id}`)],over_threshold:overThreshold,max_entries:maxEntries,tombstones,orphaned}}function normalizeRelativePath(pmRoot,targetPath){return path.relative(pmRoot,targetPath).replaceAll("\\","/")}async function listItemDocumentPaths(pmRoot,typeToFolder){const folders=[...new Set(Object.values(typeToFolder))].sort((left,right)=>left.localeCompare(right));const itemPaths=[];for(const folder of folders){const directoryPath=path.join(pmRoot,folder);let entries=[];try{entries=await fs.readdir(directoryPath)}catch(error){if(typeof error==="object"&&error!==null&&"code"in error&&isFileMissingError(error)){continue}continue}for(const entry of entries){if(!ITEM_FILE_EXTENSIONS.some(extension=>entry.toLowerCase().endsWith(extension))){continue}itemPaths.push(path.join(directoryPath,entry))}}itemPaths.sort((left,right)=>normalizeRelativePath(pmRoot,left).localeCompare(normalizeRelativePath(pmRoot,right)));return itemPaths}function shouldReportHistoryDirectoryUnreadable(error){return!(typeof error==="object"&&error!==null&&"code"in error&&isFileMissingError(error))}async function scanItemIntegrity(pmRoot,typeToFolder,schema){const paths=await listItemDocumentPaths(pmRoot,typeToFolder);const unreadable=[];const conflictMarkers=[];const parseFailures=[];const formatVersions=[];const extensionFieldNames=collectRegisteredItemFieldNames(getActiveExtensionRegistrations());for(const itemPath of paths){const relativePath=normalizeRelativePath(pmRoot,itemPath);let raw;try{raw=await fs.readFile(itemPath,"utf8")}catch{unreadable.push(relativePath);continue}const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker){conflictMarkers.push({path:relativePath,...conflictMarker});continue}try{const parsed=parseItemDocument(raw,{format:getItemFormatFromPath(itemPath),schema,extensionFieldNames});formatVersions.push({ref:relativePath,version:effectiveItemFormatVersion(parsed.metadata)})}catch{parseFailures.push(relativePath)}}return{paths,unreadable,conflictMarkers,parseFailures,formatVersions}}async function scanHistoryIntegrity(pmRoot){const historyDir=path.join(pmRoot,"history");const unreadable=[];const conflictMarkers=[];const invalidJson=[];const mergeReceiptReferences=[];const mergeReceiptDispositions=[];let files=[];try{files=(await fs.readdir(historyDir)).filter(entry=>entry.endsWith(".jsonl")).sort((left,right)=>left.localeCompare(right))}catch(error){if(shouldReportHistoryDirectoryUnreadable(error))unreadable.push("history")}for(const fileName of files){const itemId=fileName.slice(0,-".jsonl".length);let raw;try{raw=await fs.readFile(path.join(historyDir,fileName),"utf8")}catch{unreadable.push(itemId);continue}const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker){conflictMarkers.push({id:itemId,...conflictMarker});continue}raw.split(/\r?\n/).forEach((line,index)=>{if(!line.trim())return;try{const parsed=JSON.parse(line);mergeReceiptReferences.push(...extractHistoryMergeReceiptReferences(parsed,itemId).map(reference=>({itemId,line:index+1,...reference})));mergeReceiptDispositions.push(...extractHistoryMergeReceiptDispositions(parsed,itemId,index+1))}catch{invalidJson.push({id:itemId,line:index+1})}})}return{files,unreadable,conflictMarkers,invalidJson,mergeReceiptReferences,mergeReceiptDispositions}}function buildHierarchyIntegrityWarnings(analysis){return[...analysis.cycles.map(cycle=>cycle.legacy_terminal?`integrity_legacy_hierarchy_cycle:${cycle.item_ids.join(",")}`:`integrity_hierarchy_cycle:${cycle.item_ids.join(",")}`),...analysis.cardinality_violations.map(finding=>finding.legacy_terminal?`integrity_legacy_hierarchy_cardinality:${finding.child_id}`:`integrity_hierarchy_cardinality:${finding.child_id}`),...analysis.divergences.map(finding=>finding.legacy_terminal?`integrity_legacy_hierarchy_divergence:${finding.child_id}`:`integrity_hierarchy_divergence:${finding.child_id}`)]}function buildMergeReceiptEvidenceWarnings(params){const warnings=[];if(params.invalidEvidenceCount>0){warnings.push(`merge_receipt_evidence_invalid:${params.invalidEvidenceCount}`)}if(params.missingHistoryReferenceCount>0){warnings.push(`merge_receipt_history_reference_missing:${params.missingHistoryReferenceCount}`)}return warnings}async function buildIntegrityCheck(pmRoot,typeToFolder,schema,requireMergeDrivers,items){const itemScan=await scanItemIntegrity(pmRoot,typeToFolder,schema);const historyScan=await scanHistoryIntegrity(pmRoot);const formatVersionScan=scanItemFormatVersions(itemScan.formatVersions);const statusRegistry=resolveRuntimeStatusRegistry(schema);const hierarchyIntegrity=analyzeHierarchyIntegrity(items,status=>isTerminalStatus(status,statusRegistry),resolveWorkspaceRelationshipKindRegistry());const trackedRuntimeCache=await scanTrackedRuntimeCache(pmRoot);const gitWorkspaceRoot=await findGitWorkspaceRoot(pmRoot);const mergeDriverAudit=gitWorkspaceRoot===null?null:await auditMergeDriverConfiguration(gitWorkspaceRoot);const mergeReceiptEvidence=await inspectMergeReceiptEvidence(gitWorkspaceRoot??pmRoot,{includeReconciled:true,includeLossless:true,pmRoot});const availableMergeReceiptIds=new Set(mergeReceiptEvidence.receipts.map(receipt=>receipt.id));const historyReceiptClassification=classifyHistoryMergeReceiptReferences(historyScan.mergeReceiptReferences,availableMergeReceiptIds,historyScan.mergeReceiptDispositions);const missingMergeReceiptReferences=historyReceiptClassification.missing;const pendingMergeReceipts=mergeReceiptEvidence.receipts.filter(receipt=>receipt.state==="pending");const{pendingDecisions:pendingMergeDecisions,lossless:losslessMergeReceipts}=partitionMergeReceipts(pendingMergeReceipts);const mergeDriverInstallationMissing=mergeDriverAudit?.status==="missing"&&mergeDriverAudit.missing_keys.length===5&&mergeDriverAudit.drifted_keys.length===0;const warnings=[...itemScan.unreadable.map(entry=>`integrity_item_unreadable:${entry}`),...itemScan.conflictMarkers.map(entry=>`integrity_item_conflict_marker:${entry.path}:L${entry.line}`),...itemScan.parseFailures.map(entry=>`integrity_item_parse_failed:${entry}`),...historyScan.unreadable.map(entry=>`integrity_history_unreadable:${entry}`),...historyScan.conflictMarkers.map(entry=>`integrity_history_conflict_marker:${entry.id}:L${entry.line}`),...historyScan.invalidJson.map(entry=>`integrity_history_invalid_json:${entry.id}:L${entry.line}`),...formatVersionScan.outdated.map(entry=>`integrity_item_outdated_format_version:${entry}`),...formatVersionScan.ahead.map(entry=>`integrity_item_ahead_format_version:${entry}`),...buildHierarchyIntegrityWarnings(hierarchyIntegrity),...trackedRuntimeCache.tracked_path_count>0?[`tracked_runtime_cache_files:${trackedRuntimeCache.tracked_path_count}`]:[],...mergeDriverAudit!==null&&mergeDriverAudit.status!=="ok"?[`merge_driver_configuration_${mergeDriverInstallationMissing?"missing":"drift"}:${mergeDriverAudit.missing_keys.length+mergeDriverAudit.drifted_keys.length}`]:[],...pendingMergeDecisions.length>0?[`merge_decisions_unreviewed:${pendingMergeDecisions.length}`]:[],...losslessMergeReceipts.length>0?[`merge_receipts_pending:${losslessMergeReceipts.length}`]:[],...buildMergeReceiptEvidenceWarnings({invalidEvidenceCount:mergeReceiptEvidence.invalid_evidence_count,missingHistoryReferenceCount:missingMergeReceiptReferences.length})];const normalizedWarnings=[...new Set(warnings)].sort((left,right)=>left.localeCompare(right));const actionableWarnings=normalizedWarnings.filter(warning=>!warning.startsWith("integrity_legacy_hierarchy_"));return{check:{name:"integrity",status:actionableWarnings.length===0?"ok":"warn",ok:actionableWarnings.length===0,details:{checked_item_files:itemScan.paths.length,checked_history_streams:historyScan.files.length,counts:{item_unreadable:itemScan.unreadable.length,item_conflict_markers:itemScan.conflictMarkers.length,item_parse_failures:itemScan.parseFailures.length,history_unreadable:historyScan.unreadable.length,history_conflict_markers:historyScan.conflictMarkers.length,history_invalid_json:historyScan.invalidJson.length,item_outdated_format_version:formatVersionScan.outdated.length,item_ahead_format_version:formatVersionScan.ahead.length,hierarchy_cycles:hierarchyIntegrity.cycles.length,hierarchy_cardinality_violations:hierarchyIntegrity.cardinality_violations.length,hierarchy_parent_divergences:hierarchyIntegrity.divergences.length,tracked_runtime_cache_files:trackedRuntimeCache.tracked_path_count,merge_driver_configuration:mergeDriverAudit===null||mergeDriverAudit.status==="ok"?0:mergeDriverAudit.missing_keys.length+mergeDriverAudit.drifted_keys.length,pending_merge_decisions:pendingMergeDecisions.length,lossless_merge_receipts:losslessMergeReceipts.length,invalid_merge_receipt_evidence:mergeReceiptEvidence.invalid_evidence_count,missing_merge_receipt_history_references:missingMergeReceiptReferences.length,accepted_legacy_merge_receipt_references:historyReceiptClassification.acceptedLegacyCount,accepted_missing_merge_receipt_dispositions:historyReceiptClassification.acceptedDispositionCount},item_unreadable:itemScan.unreadable,item_conflict_markers:itemScan.conflictMarkers,item_parse_failures:itemScan.parseFailures,item_outdated_format_version:formatVersionScan.outdated,item_ahead_format_version:formatVersionScan.ahead,hierarchy_integrity:{...hierarchyIntegrity,relations:summarizeRecordList(hierarchyIntegrity.relations,BRIEF_HEALTH_DETAIL_LIMIT)},history_unreadable:historyScan.unreadable,history_conflict_markers:historyScan.conflictMarkers,history_invalid_json:historyScan.invalidJson,tracked_runtime_cache:{tracker_relative_root:trackedRuntimeCache.tracker_relative_root,tracked_paths:trackedRuntimeCache.tracked_paths,tracked_path_count:trackedRuntimeCache.tracked_path_count,remediation_command:trackedRuntimeCache.remediation_command},merge_driver_configuration:mergeDriverAudit===null?null:{...mergeDriverAudit,required:requireMergeDrivers},pending_merge_decision_items:[...new Set(pendingMergeDecisions.map(receipt=>receipt.item_id))].sort((left,right)=>left.localeCompare(right)),lossless_merge_receipt_items:[...new Set(losslessMergeReceipts.map(receipt=>receipt.item_id))].sort((left,right)=>left.localeCompare(right)),invalid_merge_receipt_evidence_details:mergeReceiptEvidence.invalid_evidence,invalid_merge_receipt_evidence_details_truncated:mergeReceiptEvidence.invalid_evidence_truncated,missing_merge_receipt_history_reference_details:missingMergeReceiptReferences.slice(0,HEALTH_WARNING_LIMIT),missing_merge_receipt_history_reference_details_truncated:missingMergeReceiptReferences.length>HEALTH_WARNING_LIMIT}},warnings:normalizedWarnings,gitWorkspaceRoot,pendingMergeReceipts}}function hasActivateExport(moduleRecord){if(typeof moduleRecord.activate==="function"){return true}const defaultExport=moduleRecord.default;if(typeof defaultExport!=="object"||defaultExport===null){return false}return typeof defaultExport.activate==="function"}function summarizeLoadedExtension(extension){const summary={layer:extension.layer,directory:extension.directory,manifest_path:extension.manifest_path,name:extension.name,version:extension.version,entry:extension.entry,priority:extension.priority,entry_path:extension.entry_path,has_activate:hasActivateExport(extension.module)};if(Array.isArray(extension.capabilities)){summary.capabilities=[...extension.capabilities]}return summary}function resolveMigrationId(definition,fallbackIndex){const explicitId=toNonEmptyStringOrUndefined(definition.id);if(explicitId){return explicitId}return`migration-${String(fallbackIndex+1).padStart(3,"0")}`}function resolveMigrationStatus(definition){const rawStatus=toNonEmptyStringOrUndefined(definition.status);const normalized=rawStatus?.toLowerCase();if(normalized==="failed"){return"failed"}if(normalized==="applied"){return"applied"}return"pending"}function resolveMigrationFailureReason(definition){return toNonEmptyStringOrUndefined(definition.reason)??toNonEmptyStringOrUndefined(definition.error)??toNonEmptyStringOrUndefined(definition.message)}function compareMigrationEntries(left,right){const byLayer=(left.layer??"").localeCompare(right.layer??"");if(byLayer!==0){return byLayer}const byName=(left.name??"").localeCompare(right.name??"");if(byName!==0){return byName}return(left.id??"").localeCompare(right.id??"")}function summarizeMigrationStatuses(migrations){const applied=[];const pending=[];const failed=[];migrations.forEach((migration,index)=>{const id=resolveMigrationId(migration.definition,index);const status=resolveMigrationStatus(migration.definition);if(status==="applied"){applied.push({layer:migration.layer,name:migration.name,id,status});return}if(status==="failed"){failed.push({layer:migration.layer,name:migration.name,id,status,reason:resolveMigrationFailureReason(migration.definition)});return}pending.push({layer:migration.layer,name:migration.name,id,status})});applied.sort(compareMigrationEntries);pending.sort(compareMigrationEntries);failed.sort(compareMigrationEntries);const warnings=[...failed.map(entry=>`extension_migration_failed:${entry.layer}:${entry.name}:${entry.id}`),...pending.map(entry=>`extension_migration_pending:${entry.layer}:${entry.name}:${entry.id}`)];return{summary:{applied,pending,failed,applied_count:applied.length,pending_count:pending.length,failed_count:failed.length},warnings}}function buildExtensionHealthTriageSummary(warnings,loadFailureCount,activationFailureCount,migrationStatus,managedStateWarningCount,managedExtensionEntriesCount,unmanagedLoadedExtensions,unmanagedExpectedExtensions,unmanagedActionRequiredExtensions){const normalizedWarnings=[...new Set(warnings)].sort((left,right)=>left.localeCompare(right));const warningCodes=[...new Set(normalizedWarnings.map(value=>warningCode(value)))].sort((left,right)=>left.localeCompare(right));const unknownCapabilityCount=normalizedWarnings.filter(warning=>warning.startsWith("extension_capability_unknown:")).length;const updateHealthPartial=unmanagedActionRequiredExtensions.length>0;const updateHealthCoverage=updateHealthPartial?"partial":"full";const remediation=[];const registrationCollisionRemediation=buildRegistrationCollisionRemediation(normalizedWarnings,{deactivate:"pm extension --deactivate <name> --project/--global",doctor:"pm extension --doctor --project/--global --detail deep --trace"});if(registrationCollisionRemediation){remediation.push(registrationCollisionRemediation)}if(loadFailureCount>0){remediation.push("Run pm extension --explore --project and pm extension --explore --global to inspect load failures.")}if(activationFailureCount>0){remediation.push("Review checks[name=extensions].details.activation.failed in pm health --json for activation error details.")}if(migrationStatus.failed_count>0||migrationStatus.pending_count>0){remediation.push("Resolve pending/failed extension migrations before write commands; use --force only when policy allows.")}if(managedStateWarningCount>0){remediation.push("Run pm extension --manage --project and pm extension --manage --global to refresh managed-state diagnostics.")}if(unknownCapabilityCount>0){remediation.push(`Unknown extension capabilities detected. Allowed capabilities: ${KNOWN_EXTENSION_CAPABILITIES.join(", ")}. Review extension_capability_unknown warning details for suggested replacements.`)}if(normalizedWarnings.some(warning=>warning.startsWith("extension_capability_legacy_alias:"))){remediation.push("Legacy extension capability aliases were auto-remapped to canonical capabilities. Update manifests to canonical names (migration/validation -> schema).")}if(normalizedWarnings.some(warning=>warning.startsWith("extension_command_definition_legacy_handler_alias:"))){remediation.push("Extension command definitions using legacy handler were auto-remapped. Update command definitions to use run: (context) => ... for forward compatibility.")}if(updateHealthPartial){remediation.push("Update-check coverage is partial because unmanaged extensions need adoption. Adopt existing installs via pm extension --manage --project/--global --fix-managed-state, pm extension --adopt-all --project/--global, or pm extension --adopt <name>.")}else if(unmanagedLoadedExtensions.length>0){remediation.push("Loaded unmanaged extensions are currently treated as informational. Use pm extension --manage --project/--global --fix-managed-state to adopt them for update checks.")}if(remediation.length===0){remediation.push("No immediate action required. Re-run pm health after extension configuration changes.")}return{status:normalizedWarnings.length===0?"ok":"warn",warning_count:normalizedWarnings.length,warning_codes:warningCodes,load_failure_count:loadFailureCount,activation_failure_count:activationFailureCount,migration_failed_count:migrationStatus.failed_count,migration_pending_count:migrationStatus.pending_count,managed_state_warning_count:managedStateWarningCount,managed_extension_entries_count:managedExtensionEntriesCount,unmanaged_loaded_extension_count:unmanagedLoadedExtensions.length,unmanaged_loaded_extensions:unmanagedLoadedExtensions,unmanaged_expected_extension_count:unmanagedExpectedExtensions.length,unmanaged_expected_extensions:unmanagedExpectedExtensions,unmanaged_action_required_extension_count:unmanagedActionRequiredExtensions.length,unmanaged_action_required_extensions:unmanagedActionRequiredExtensions,update_health_coverage:updateHealthCoverage,update_health_partial:updateHealthPartial,unknown_capability_count:unknownCapabilityCount,top_warnings:normalizedWarnings.slice(0,8),remediation}}async function buildExtensionCheck(pmRoot,settings,noExtensionsFlag){const authorManifest=await inspectExtensionAuthorManifest(resolveWorkspaceRoot(pmRoot));const loadResult=await loadExtensions({pmRoot,settings,cwd:process.cwd(),noExtensions:noExtensionsFlag});const loadedSummaries=loadResult.loaded.map(extension=>summarizeLoadedExtension(extension));const hostVersionCensus=await scanExtensionHostVersions(loadResult.loaded,resolveWorkspaceRoot(pmRoot));const activationResult=await activateExtensions({...loadResult,loaded:loadResult.loaded});const[projectManagedState,globalManagedState]=await Promise.all([readManagedExtensionState(loadResult.roots.project),readManagedExtensionState(loadResult.roots.global)]);await applyStoredExtensionMigrationState(pmRoot,activationResult.registrations.migrations);const migrationStatus=summarizeMigrationStatuses(activationResult.registrations.migrations);const activationDetails={failed:activationResult.failed,warnings:activationResult.warnings,hook_counts:activationResult.hook_counts,command_override_count:activationResult.command_override_count,command_handler_count:activationResult.command_handler_count,parser_override_count:activationResult.parser_override_count,preflight_override_count:activationResult.preflight_override_count,service_override_count:activationResult.service_override_count,renderer_override_count:activationResult.renderer_override_count,registration_counts:activationResult.registration_counts,registrations:activationResult.registrations,migration_status:migrationStatus.summary,managed_extensions:{project:{path:projectManagedState.path,count:projectManagedState.state.entries.length,entries:projectManagedState.state.entries},global:{path:globalManagedState.path,count:globalManagedState.state.entries.length,entries:globalManagedState.state.entries}}};const managedProjectNames=new Set(projectManagedState.state.entries.map(entry=>normalizeExtensionNameForMatch(entry.name)));const managedGlobalNames=new Set(globalManagedState.state.entries.map(entry=>normalizeExtensionNameForMatch(entry.name)));const unmanagedLoadedEntries=[...new Map(loadResult.loaded.filter(entry=>{const managedNames=entry.layer==="project"?managedProjectNames:managedGlobalNames;return!managedNames.has(normalizeExtensionNameForMatch(entry.name))}).map(entry=>[`${entry.layer}:${entry.name}`,{layer:entry.layer,name:entry.name,directory:entry.directory}])).values()].sort((left,right)=>{const leftKey=`${left.layer}:${left.name}`;const rightKey=`${right.layer}:${right.name}`;return leftKey.localeCompare(rightKey)});const unmanagedLoadedExtensions=unmanagedLoadedEntries.map(entry=>`${entry.layer}:${entry.name}`).sort((left,right)=>left.localeCompare(right));const unmanagedExpectedExtensions=unmanagedLoadedEntries.filter(entry=>isExpectedUnmanagedExtension(entry.name,entry.directory)).map(entry=>`${entry.layer}:${entry.name}`).sort((left,right)=>left.localeCompare(right));const unmanagedActionRequiredExtensions=unmanagedLoadedEntries.filter(entry=>!isExpectedUnmanagedExtension(entry.name,entry.directory)).map(entry=>`${entry.layer}:${entry.name}`).sort((left,right)=>left.localeCompare(right));const updateCoverageWarnings=unmanagedActionRequiredExtensions.length>0?[`extension_update_health_partial_coverage:skipped_unmanaged:${unmanagedActionRequiredExtensions.length}`]:[];const extensionWarnings=[...authorManifest.warnings,...loadResult.warnings,...activationDetails.warnings,...migrationStatus.warnings,...projectManagedState.warnings,...globalManagedState.warnings,...updateCoverageWarnings,...hostVersionCensus.warnings];const capabilityGuidance=collectUnknownCapabilityGuidance(extensionWarnings);const capabilityContract=buildCapabilityContractMetadata();const extensionTriage=buildExtensionHealthTriageSummary(extensionWarnings,loadResult.failed.length,activationResult.failed.length,migrationStatus.summary,projectManagedState.warnings.length+globalManagedState.warnings.length,projectManagedState.state.entries.length+globalManagedState.state.entries.length,unmanagedLoadedExtensions,unmanagedExpectedExtensions,unmanagedActionRequiredExtensions);return{check:{name:"extensions",status:extensionWarnings.length===0?"ok":"warn",ok:extensionWarnings.length===0,details:{...loadResult,loaded:loadedSummaries,warnings:extensionWarnings,activation:activationDetails,author_manifest:authorManifest,triage:extensionTriage,...migrationStatus.summary.pending_count>0?{remediation_map:{extension_migration_pending:"pm extension migrate --project"}}:{},capability_contract:capabilityContract,capability_guidance:capabilityGuidance,host_version_census:hostVersionCensus}},warnings:extensionWarnings}}function summarizeList(values,limit){if(values.length<=limit){return{values,truncated:false}}return{values:values.slice(0,limit),truncated:true}}function summarizeRecordList(value,limit){if(!Array.isArray(value)){return{count:0,sample:[],truncated:false}}return{count:value.length,sample:value.slice(0,limit),truncated:value.length>limit}}function summarizeExtensionRecord(value){if(typeof value!=="object"||value===null||Array.isArray(value)){return{}}const record=value;return{layer:record.layer,directory:record.directory,name:record.name,version:record.version,enabled:record.enabled,status:record.status,has_activate:record.has_activate,capabilities:record.capabilities}}function summarizeExtensionList(value,limit){const summary=summarizeRecordList(value,limit);return{...summary,sample:summary.sample.map(entry=>summarizeExtensionRecord(entry))}}function summarizeStringList(value,limit){if(!Array.isArray(value)){return{count:0,sample:[],truncated:false}}const strings=value.filter(entry=>typeof entry==="string");return{count:strings.length,sample:strings.slice(0,limit),truncated:strings.length>limit}}function summarizeActivationMigrationStatus(value){if(typeof value!=="object"||value===null){return null}const status=value;return{applied_count:status.applied_count,pending_count:status.pending_count,failed_count:status.failed_count}}const HEALTH_DETAIL_SUMMARIZERS={settings:(details,limit)=>({version:details.version,id_prefix:details.id_prefix,locks_ttl_seconds:details.locks_ttl_seconds,warnings:summarizeStringList(details.warnings,limit)}),directories:(details,limit)=>({required_count:Array.isArray(details.required)?details.required.length:0,optional_count:Array.isArray(details.optional)?details.optional.length:0,missing_required:summarizeStringList(details.missing_required,limit),missing_optional:summarizeStringList(details.missing_optional,limit),missing:summarizeStringList(details.missing,limit),strict_directories:details.strict_directories}),settings_values:(details,limit)=>({warnings:summarizeStringList(details.warnings,limit)}),telemetry:details=>({enabled:details.enabled,capture_level:details.capture_level,endpoint:details.endpoint,queue_exists:details.queue_exists,queue_entries:details.queue_entries,queue_draining:details.queue_draining,queue_invalid_rows:details.queue_invalid_rows,queue_rows_total:details.queue_rows_total,last_successful_flush_at:details.last_successful_flush_at,last_failed_flush_at:details.last_failed_flush_at,endpoint_probe:details.endpoint_probe,env_overrides:details.env_overrides}),extensions:(details,limit)=>{const activation=typeof details.activation==="object"&&details.activation!==null?details.activation:{};return{disabled_by_flag:details.disabled_by_flag,discovered:summarizeExtensionList(details.discovered,limit),effective:summarizeExtensionList(details.effective,limit),loaded:summarizeExtensionList(details.loaded,limit),failed:summarizeRecordList(details.failed,limit),warnings:summarizeStringList(details.warnings,limit),activation:{failed:summarizeRecordList(activation.failed,limit),warnings:summarizeStringList(activation.warnings,limit),hook_counts:activation.hook_counts,command_handler_count:activation.command_handler_count,service_override_count:activation.service_override_count,renderer_override_count:activation.renderer_override_count,registration_counts:activation.registration_counts,migration_status:summarizeActivationMigrationStatus(activation.migration_status)},author_manifest:details.author_manifest,triage:details.triage,capability_contract:details.capability_contract,capability_guidance:summarizeRecordList(details.capability_guidance,limit),host_version_census:details.host_version_census}},storage:(details,limit)=>{const authorAttribution=typeof details.author_attribution==="object"&&details.author_attribution!==null?details.author_attribution:void 0;return{...details,...authorAttribution?{author_attribution:{...authorAttribution,affected_item_ids:summarizeStringList(authorAttribution.affected_item_ids,limit),samples:summarizeRecordList(authorAttribution.samples,limit)}}:{}}},locks:details=>({active_lock_count:details.active_lock_count,stale_lock_count:details.stale_lock_count,unreadable_lock_count:details.unreadable_lock_count,unparseable_lock_count:details.unparseable_lock_count}),integrity:(details,limit)=>{const trackedRuntimeCache=typeof details.tracked_runtime_cache==="object"&&details.tracked_runtime_cache!==null?details.tracked_runtime_cache:void 0;return{checked_item_files:details.checked_item_files,checked_history_streams:details.checked_history_streams,counts:details.counts,item_unreadable:summarizeStringList(details.item_unreadable,limit),item_conflict_markers:summarizeRecordList(details.item_conflict_markers,limit),item_parse_failures:summarizeStringList(details.item_parse_failures,limit),tracked_runtime_cache:trackedRuntimeCache===void 0?details.tracked_runtime_cache:{...trackedRuntimeCache,tracked_paths:summarizeStringList(trackedRuntimeCache.tracked_paths,limit)},history_unreadable:summarizeStringList(details.history_unreadable,limit),history_conflict_markers:summarizeRecordList(details.history_conflict_markers,limit),history_invalid_json:summarizeRecordList(details.history_invalid_json,limit),skipped:details.skipped}},history_drift:(details,limit)=>{const cacheConfirmation=typeof details.cache_confirmation==="object"&&details.cache_confirmation!==null?details.cache_confirmation:void 0;return{checked_items:details.checked_items,cache_hit_verification:details.cache_hit_verification,cache_confirmation:cacheConfirmation===void 0?details.cache_confirmation:{...cacheConfirmation,candidate_items:summarizeStringList(cacheConfirmation.candidate_items,limit),confirmed_items:summarizeStringList(cacheConfirmation.confirmed_items,limit),resolved_false_positive_items:summarizeStringList(cacheConfirmation.resolved_false_positive_items,limit)},counts:details.counts,drifted_items:summarizeStringList(details.drifted_items,limit),merge_receipt_attributed_items:summarizeStringList(details.merge_receipt_attributed_items,limit),missing_streams:summarizeStringList(details.missing_streams,limit),unreadable_streams:summarizeStringList(details.unreadable_streams,limit),hash_mismatches:summarizeStringList(details.hash_mismatches,limit),chain_mismatches:summarizeStringList(details.chain_mismatches,limit),version_skews:summarizeStringList(details.version_skews,limit),workspace_state_mismatches:summarizeStringList(details.workspace_state_mismatches,limit),workspace_state_missing:summarizeStringList(details.workspace_state_missing,limit),workspace_state_unreadable:summarizeStringList(details.workspace_state_unreadable,limit),skipped:details.skipped}},vectorization:(details,limit)=>({semantic_runtime_available:details.semantic_runtime_available,compatibility_mode_auto_defaults:details.compatibility_mode_auto_defaults,auto_ollama_defaults_applied:details.auto_ollama_defaults_applied,auto_ollama_defaults_skipped_reason:details.auto_ollama_defaults_skipped_reason,auto_ollama_defaults_remediation:details.auto_ollama_defaults_remediation,refresh_policy:details.refresh_policy,provider_active:details.provider_active,vector_store_active:details.vector_store_active,items:details.items,ledger_entries_before:details.ledger_entries_before,stale_items_before_total:details.stale_items_before_total,stale_items_before:summarizeStringList(details.stale_items_before,limit),refresh_attempted:details.refresh_attempted,refresh_skipped_reason:details.refresh_skipped_reason,refresh_result:details.refresh_result,ledger_entries_after:details.ledger_entries_after,stale_items_after_total:details.stale_items_after_total,stale_items_after:summarizeStringList(details.stale_items_after,limit),skipped:details.skipped})};function summarizeHealthCheckDetails(check,limit){const summarize=HEALTH_DETAIL_SUMMARIZERS[check.name];return summarize?summarize(check.details,limit):check.details}function applyBriefHealthProjection(result){const warningsSummary=summarizeStringList(result.warnings,BRIEF_HEALTH_DETAIL_LIMIT);return{ok:result.ok,...result.verdict?{verdict:result.verdict}:{},checks:result.checks.map(check=>({name:check.name,status:check.status,ok:check.ok,details:summarizeHealthCheckDetails(check,BRIEF_HEALTH_DETAIL_LIMIT)})),warnings:warningsSummary.sample,findings:result.findings.filter(finding=>warningsSummary.sample.includes(finding.warning)||result.failed_because.includes(finding.warning)),failed_because:result.failed_because,projection:{mode:"brief",warning_count:warningsSummary.count,warnings_truncated:warningsSummary.truncated,detail_limit:BRIEF_HEALTH_DETAIL_LIMIT},generated_at:result.generated_at}}function isSkippedHealthCheck(check){return check.details.skipped===true}function applySummaryHealthProjection(result){const warningsSummary=summarizeStringList(result.warnings,BRIEF_HEALTH_DETAIL_LIMIT);const omittedChecks=result.checks.filter(isSkippedHealthCheck).map(check=>check.name);return{ok:result.ok,...result.verdict?{verdict:result.verdict}:{},checks:result.checks.filter(check=>!isSkippedHealthCheck(check)).map(check=>({name:check.name,status:check.status,ok:check.ok,details:{}})),warning_count:warningsSummary.count,warnings:warningsSummary.sample,findings:result.findings.filter(finding=>warningsSummary.sample.includes(finding.warning)||result.failed_because.includes(finding.warning)),failed_because:result.failed_because,projection:{mode:"summary",warning_count:warningsSummary.count,warnings_truncated:warningsSummary.truncated,detail_limit:BRIEF_HEALTH_DETAIL_LIMIT,omitted_checks:omittedChecks},generated_at:result.generated_at}}function selectStaleItemDetail(values,verboseStaleItems){if(verboseStaleItems){return{values,truncated:false,total:values.length}}const summary=summarizeList(values,STALE_VECTORIZATION_SUMMARY_LIMIT);return{values:summary.values,truncated:summary.truncated,total:values.length}}function telemetryEnvFlagEnabled(envKey){const value=(process.env[envKey]??"").trim().toLowerCase();return value==="1"||value==="true"||value==="yes"||value==="on"}function telemetrySourceContextOverride(){const value=(process.env.PM_TELEMETRY_SOURCE_CONTEXT??"").trim().toLowerCase();return PM_TELEMETRY_SOURCE_CONTEXT_SET.has(value)?value:null}function normalizeEndpointForDisplay(rawEndpoint){const trimmed=rawEndpoint.trim();if(trimmed.length===0){return""}try{const parsed=new URL(trimmed);parsed.username="";parsed.password="";parsed.search="";parsed.hash="";return parsed.toString()}catch{return trimmed}}function parseTelemetryQueue(raw){let validEntries=0;let invalidRows=0;let totalRows=0;let highRetryEntries=0;let maxAttempts=0;for(const line of raw.split("\n")){const trimmed=line.trim();if(trimmed.length===0){continue}totalRows+=1;try{const parsed=JSON.parse(trimmed);if(typeof parsed==="object"&&parsed!==null&&typeof parsed.attempts==="number"&&Number.isFinite(parsed.attempts)){const attempts=Math.max(0,Math.trunc(parsed.attempts));validEntries+=1;maxAttempts=Math.max(maxAttempts,attempts);if(attempts>=TELEMETRY_QUEUE_HIGH_RETRY_THRESHOLD){highRetryEntries+=1}}else{invalidRows+=1}}catch{invalidRows+=1}}return{validEntries,invalidRows,totalRows,highRetryEntries,maxAttempts}}function emptyTelemetryQueueSummary(){return{validEntries:0,invalidRows:0,totalRows:0,highRetryEntries:0,maxAttempts:0}}function parseTelemetryRuntimeState(stateRaw){if(!stateRaw||stateRaw.trim().length===0){return{runtimeState:{},stateParseFailed:false}}try{const parsed=JSON.parse(stateRaw);if(typeof parsed==="object"&&parsed!==null&&!Array.isArray(parsed)){return{runtimeState:parsed,stateParseFailed:false}}return{runtimeState:{},stateParseFailed:true}}catch{return{runtimeState:{},stateParseFailed:true}}}async function maybeProbeTelemetryEndpoint(settings,checkTelemetry){const endpoint=settings.telemetry.endpoint.trim();if(!checkTelemetry||!settings.telemetry.enabled||endpoint.length===0||resolveTelemetryEnvironmentPolicy().telemetry_disabled){return void 0}const probe=await probeTelemetryEndpointHealth(endpoint);return{attempted:true,...probe}}function collectTelemetryQueueWarnings(settings,queueSummary,runtimeState){const warnings=[];if(queueSummary.invalidRows>0){warnings.push(`telemetry_queue_invalid_rows:${queueSummary.invalidRows}`)}if(!settings.telemetry.enabled||queueSummary.validEntries===0){return warnings}const lastSuccess=runtimeState.last_successful_flush_at;const lastFailure=runtimeState.last_failed_flush_at;const activeFailure=lastFailure&&(!lastSuccess||lastFailure>lastSuccess);const neverFlushed=!lastSuccess;const highWater=queueSummary.validEntries>=TELEMETRY_QUEUE_HIGH_WATER_MARK;if(activeFailure||neverFlushed||highWater){warnings.push(`telemetry_queue_pending:${queueSummary.validEntries}`)}if(queueSummary.highRetryEntries>0){warnings.push(`telemetry_queue_high_retries:${queueSummary.highRetryEntries}`)}return warnings}function collectTelemetryEndpointWarnings(endpointProbe){if(!endpointProbe||endpointProbe.ok!==false){return[]}return typeof endpointProbe.status==="number"?[`telemetry_endpoint_probe_http_status:${endpointProbe.status}`]:["telemetry_endpoint_probe_failed"]}function collectTelemetrySchemaWarnings(endpointProbe){const parsedMaxSchemaVersion=Number.parseInt(endpointProbe?.max_schema_version??"",10);if(endpointProbe?.ok===true&&Number.isInteger(parsedMaxSchemaVersion)&&parsedMaxSchemaVersion>TELEMETRY_SCHEMA_VERSION){return[`telemetry_schema_version_behind:${parsedMaxSchemaVersion}`]}return[]}function collectTelemetryOtelWarnings(settings,runtimeState){const pendingOtelSpans=typeof runtimeState.pending_otel_spans==="number"?runtimeState.pending_otel_spans:0;const lastOtelSuccess=runtimeState.last_otel_success_at;const lastOtelFailure=runtimeState.last_otel_failure_at;const otelExportFailing=settings.telemetry.enabled&&pendingOtelSpans>0&&Boolean(lastOtelFailure)&&(!lastOtelSuccess||lastOtelFailure>=lastOtelSuccess);return otelExportFailing?[`telemetry_otel_export_failing:${pendingOtelSpans}`]:[]}function buildTelemetryEnvOverrideDetails(){return{...resolveTelemetryEnvironmentPolicy(),pm_no_telemetry:telemetryEnvFlagEnabled("PM_NO_TELEMETRY"),telemetry_otel_disabled:telemetryEnvFlagEnabled("PM_TELEMETRY_OTEL_DISABLED"),telemetry_inline_flush:telemetryEnvFlagEnabled("PM_TELEMETRY_INLINE_FLUSH"),telemetry_source_context:telemetrySourceContextOverride()}}function telemetryQueueHasEntries(settings,queueSummary){return settings.telemetry.enabled&&queueSummary.validEntries>0}function isTelemetryQueueDraining(queueHasEntries,warnings){return queueHasEntries&&warnings.every(warning=>!warning.startsWith("telemetry_queue_pending:")&&!warning.startsWith("telemetry_queue_high_retries:"))}async function probeTelemetryEndpointHealth(endpoint){let probeUrl=endpoint;try{const parsed=new URL(endpoint);parsed.pathname="/healthz";parsed.search="";parsed.hash="";probeUrl=parsed.toString()}catch{}try{const response=await fetch(probeUrl,{method:"GET",signal:AbortSignal.timeout(TELEMETRY_ENDPOINT_PROBE_TIMEOUT_MS)});return{probe_url:normalizeEndpointForDisplay(probeUrl),ok:response.ok,status:response.status,max_schema_version:(()=>{for(const headerName of TELEMETRY_SERVER_MAX_SCHEMA_VERSION_HEADERS){const value=response.headers.get(headerName)?.trim();if(value&&value.length>0){return value}}return void 0})()}}catch(error){return{probe_url:normalizeEndpointForDisplay(probeUrl),ok:false,error:error instanceof Error?error.message:"probe_failed"}}}async function buildTelemetryCheck(settings,options){const globalPmRoot=resolveGlobalPmRoot(process.cwd());const queuePath=path.join(globalPmRoot,TELEMETRY_QUEUE_RELATIVE_PATH);const statePath=path.join(globalPmRoot,TELEMETRY_STATE_RELATIVE_PATH);const queueRaw=await readFileIfExists(queuePath);const queueExists=queueRaw!==null;const queueSizeBytes=queueRaw?Buffer.byteLength(queueRaw,"utf8"):0;const queueSummary=queueRaw?parseTelemetryQueue(queueRaw):emptyTelemetryQueueSummary();const stateRaw=await readFileIfExists(statePath);const{runtimeState,stateParseFailed}=parseTelemetryRuntimeState(stateRaw);const endpoint=settings.telemetry.endpoint.trim();const endpointDisplay=normalizeEndpointForDisplay(endpoint);const endpointProbe=await maybeProbeTelemetryEndpoint(settings,options.checkTelemetry);const warnings=[];if(stateParseFailed){warnings.push("telemetry_state_invalid_json")}warnings.push(...collectTelemetryQueueWarnings(settings,queueSummary,runtimeState),...collectTelemetryEndpointWarnings(endpointProbe),...collectTelemetrySchemaWarnings(endpointProbe),...collectTelemetryOtelWarnings(settings,runtimeState));const queueHasEntries=telemetryQueueHasEntries(settings,queueSummary);const pendingOtelSpans=typeof runtimeState.pending_otel_spans==="number"?runtimeState.pending_otel_spans:0;return{check:{name:"telemetry",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{enabled:settings.telemetry.enabled,capture_level:settings.telemetry.capture_level,endpoint:endpointDisplay,global_pm_root:globalPmRoot,queue_path:queuePath,queue_exists:queueExists,queue_entries:queueSummary.validEntries,queue_draining:isTelemetryQueueDraining(queueHasEntries,warnings),queue_invalid_rows:queueSummary.invalidRows,queue_rows_total:queueSummary.totalRows,queue_size_bytes:queueSizeBytes,queue_high_retry_entries:queueSummary.highRetryEntries,queue_high_retry_threshold:TELEMETRY_QUEUE_HIGH_RETRY_THRESHOLD,queue_max_attempts:queueSummary.maxAttempts,runtime_state_path:statePath,last_attempted_flush_at:runtimeState.last_attempted_flush_at??null,last_successful_flush_at:runtimeState.last_successful_flush_at??null,last_failed_flush_at:runtimeState.last_failed_flush_at??null,last_failed_flush_error:runtimeState.last_failed_flush_error??null,pending_otel_spans:pendingOtelSpans,last_otel_attempt_at:runtimeState.last_otel_attempt_at??null,last_otel_success_at:runtimeState.last_otel_success_at??null,last_otel_failure_at:runtimeState.last_otel_failure_at??null,last_otel_failure_error:runtimeState.last_otel_failure_error??null,endpoint_probe:endpointProbe??{attempted:false},env_overrides:buildTelemetryEnvOverrideDetails()}},warnings}}async function buildLocksCheck(pmRoot){let scan;try{scan=await scanLockHealth(pmRoot)}catch(error){const message=error instanceof Error?error.message:String(error);return{check:{name:"locks",status:"warn",ok:false,details:{active_lock_count:0,stale_lock_count:0,unreadable_lock_count:0,unparseable_lock_count:0,scan_failed:true,error:message,pm_root:pmRoot}},warnings:[`locks_scan_failed:${message}`]}}const warnings=[];if(scan.stale_lock_count>0){warnings.push(`locks_stale_count:${scan.stale_lock_count}`)}if(scan.unreadable_lock_count>0){warnings.push(`locks_unreadable:${scan.unreadable_lock_count}`)}return{check:{name:"locks",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{active_lock_count:scan.active_lock_count,stale_lock_count:scan.stale_lock_count,unreadable_lock_count:scan.unreadable_lock_count,unparseable_lock_count:scan.unparseable_lock_count}},warnings}}async function buildHistoryDriftCheck(params){const cacheHitVerification="metadata";let items=params.items;let drift=await scanHistoryDrift(params.pmRoot,items,{cacheHitVerification});const cacheConfirmationCandidates=[...new Set([...drift.hashMismatches,...drift.chainMismatches,...drift.versionSkews])].sort((left,right)=>left.localeCompare(right));let confirmedItems=[];let resolvedFalsePositiveItems=[];if(cacheConfirmationCandidates.length>0){items=await listAllItemMetadataWithBody(params.pmRoot,params.settings.item_format,params.typeRegistry.type_to_folder,params.itemReadWarnings,params.settings.schema,{forceSourceScan:true});drift=await scanHistoryDrift(params.pmRoot,items);confirmedItems=[...new Set([...drift.hashMismatches,...drift.chainMismatches,...drift.versionSkews])].sort((left,right)=>left.localeCompare(right));const confirmedSet=new Set(confirmedItems);resolvedFalsePositiveItems=cacheConfirmationCandidates.filter(id=>!confirmedSet.has(id))}const{missingStreams,unreadableStreams,hashMismatches,chainMismatches,versionSkews,driftedItems,workspaceStateMismatches,workspaceStateMissing,workspaceStateUnreadable}=drift;const warnings=[...missingStreams.map(id=>`history_drift_missing_stream:${id}`),...unreadableStreams.map(id=>`history_drift_unreadable_stream:${id}`),...hashMismatches.map(id=>`history_drift_hash_mismatch:${id}`),...chainMismatches.map(id=>`history_drift_chain_mismatch:${id}`),...versionSkews.map(id=>`history_drift_version_skew:${id}`),...workspaceStateMismatches.map(documentPath=>`history_drift_workspace_state_mismatch:${documentPath}`),...workspaceStateMissing.map(documentPath=>`history_drift_workspace_state_missing:${documentPath}`),...workspaceStateUnreadable.map(documentPath=>`history_drift_workspace_state_unreadable:${documentPath}`)];return{check:{name:"history_drift",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{checked_items:items.length,cache_hit_verification:cacheConfirmationCandidates.length>0?"metadata_then_content_hash":cacheHitVerification,cache_confirmation:{triggered:cacheConfirmationCandidates.length>0,reason:cacheConfirmationCandidates.length>0?"cached_corruption_candidate":null,candidate_items:cacheConfirmationCandidates,confirmed_items:confirmedItems,resolved_false_positive_items:resolvedFalsePositiveItems,authoritative_item_source:cacheConfirmationCandidates.length>0},drifted_items:driftedItems,counts:{drifted:driftedItems.length,missing_streams:missingStreams.length,unreadable_streams:unreadableStreams.length,hash_mismatches:hashMismatches.length,chain_mismatches:chainMismatches.length,version_skews:versionSkews.length,workspace_state_mismatches:workspaceStateMismatches.length,workspace_state_missing:workspaceStateMissing.length,workspace_state_unreadable:workspaceStateUnreadable.length},missing_streams:missingStreams,unreadable_streams:unreadableStreams,hash_mismatches:hashMismatches,chain_mismatches:chainMismatches,version_skews:versionSkews,workspace_state_mismatches:workspaceStateMismatches,workspace_state_missing:workspaceStateMissing,workspace_state_unreadable:workspaceStateUnreadable}},warnings}}function buildVectorizationRuntimeSnapshot(settings,pmRoot){const runtimeDefaults=resolveSettingsWithSemanticRuntimeDefaults(settings);const providerResolution=resolveEmbeddingProviders(runtimeDefaults.settings);const vectorStoreResolution=resolveVectorStores(runtimeDefaults.settings,pmRoot);const runtimeEmbeddingIdentity=providerResolution.active?buildVectorizationEmbeddingIdentity(providerResolution.active.name,providerResolution.active.model):null;return{runtimeDefaults,providerResolution,vectorStoreResolution,runtimeEmbeddingIdentity,semanticRuntimeAvailable:Boolean(providerResolution.active&&vectorStoreResolution.active)}}function emptyVectorizationRefreshResult(){return{refreshed:[],skipped:[],warnings:[]}}async function refreshStaleVectorizationItems(params){if(!params.refreshPolicy.enabled||!params.snapshot.semanticRuntimeAvailable||params.staleBefore.length===0){return emptyVectorizationRefreshResult()}return refreshSemanticEmbeddingsForMutatedItems(params.pmRoot,params.staleBefore,{settings:params.snapshot.runtimeDefaults.settings,apply_runtime_defaults:false})}function vectorizationEmbeddingIdentityChanged(params){return params.strictVectorizationWarnings&&params.semanticRuntimeAvailable&&Boolean(params.ledgerBefore.embedding&&params.runtimeEmbeddingIdentity&&hasVectorizationEmbeddingIdentityChanged(params.ledgerBefore.embedding,params.runtimeEmbeddingIdentity))}function collectVectorizationWarnings(params){const warningSet=new Set([...params.ledgerBefore.warnings,...params.ledgerAfter.warnings]);if(params.strictVectorizationWarnings){for(const warning of params.refreshResult.warnings){warningSet.add(warning)}}if(params.embeddingIdentityChanged){warningSet.add("vectorization_embedding_identity_changed")}if(params.strictVectorizationWarnings&&params.semanticRuntimeAvailable&&params.staleAfter.length>0){warningSet.add(`vectorization_stale_items_remaining:${params.staleAfter.length}`)}return[...warningSet].sort((left,right)=>left.localeCompare(right))}function resolveVectorizationRefreshSkippedReason(refreshPolicy,semanticRuntimeAvailable,staleBefore){if(refreshPolicy.enabled&&semanticRuntimeAvailable&&staleBefore.length>0){return null}if(!refreshPolicy.enabled){return"refresh_disabled"}return semanticRuntimeAvailable?"no_stale_items":"semantic_runtime_unavailable"}function buildVectorizationProviderDetails(settings,snapshot){const activeProvider=snapshot.providerResolution.active?.name??null;const activeVectorStore=snapshot.vectorStoreResolution.active?.name??null;return{provider_active:activeProvider,provider_configured:typeof settings.search?.provider==="string"?settings.search.provider:null,provider_source:resolveProviderConfigSource(activeProvider,settings.search?.provider??null),vector_store_active:activeVectorStore,vector_store_configured:typeof settings.vector_store?.adapter==="string"?settings.vector_store.adapter:null,vector_store_source:resolveProviderConfigSource(activeVectorStore,settings.vector_store?.adapter??null)}}function buildVectorizationRefreshPolicyDetails(refreshPolicy){return{enabled:refreshPolicy.enabled,check_only:refreshPolicy.checkOnly,no_refresh:refreshPolicy.noRefresh,refresh_vectors:refreshPolicy.refreshVectors}}function vectorizationRefreshAttempted(refreshPolicy,semanticRuntimeAvailable,staleBefore){return refreshPolicy.enabled&&staleBefore.length>0&&semanticRuntimeAvailable}async function buildVectorizationCheck(pmRoot,settings,items,refreshPolicy,verboseStaleItems){const snapshot=buildVectorizationRuntimeSnapshot(settings,pmRoot);const ledgerBefore=await readVectorizationStatusLedger(pmRoot);const staleBefore=snapshot.semanticRuntimeAvailable?collectStaleVectorizationIds(items,ledgerBefore.entries):[];const refreshResult=await refreshStaleVectorizationItems({pmRoot,snapshot,refreshPolicy,staleBefore});const ledgerAfter=await readVectorizationStatusLedger(pmRoot);const staleAfter=snapshot.semanticRuntimeAvailable?collectStaleVectorizationIds(items,ledgerAfter.entries):[];const strictVectorizationWarnings=!snapshot.runtimeDefaults.auto_ollama_defaults_applied;const embeddingIdentityChanged=vectorizationEmbeddingIdentityChanged({strictVectorizationWarnings,semanticRuntimeAvailable:snapshot.semanticRuntimeAvailable,ledgerBefore,runtimeEmbeddingIdentity:snapshot.runtimeEmbeddingIdentity});const warnings=collectVectorizationWarnings({ledgerBefore,ledgerAfter,refreshResult,strictVectorizationWarnings,semanticRuntimeAvailable:snapshot.semanticRuntimeAvailable,embeddingIdentityChanged,staleAfter});const staleBeforeDetail=selectStaleItemDetail(staleBefore,verboseStaleItems);const staleAfterDetail=selectStaleItemDetail(staleAfter,verboseStaleItems);const refreshAttempted=vectorizationRefreshAttempted(refreshPolicy,snapshot.semanticRuntimeAvailable,staleBefore);return{check:{name:"vectorization",status:warnings.length===0?"ok":"warn",ok:warnings.length===0,details:{semantic_runtime_available:snapshot.semanticRuntimeAvailable,compatibility_mode_auto_defaults:snapshot.runtimeDefaults.auto_ollama_defaults_applied,auto_ollama_defaults_applied:snapshot.runtimeDefaults.auto_ollama_defaults_applied,auto_ollama_defaults_skipped_reason:snapshot.runtimeDefaults.auto_ollama_defaults_skipped_reason??null,auto_ollama_defaults_remediation:snapshot.runtimeDefaults.auto_ollama_defaults_remediation??null,refresh_policy:buildVectorizationRefreshPolicyDetails(refreshPolicy),...buildVectorizationProviderDetails(settings,snapshot),embedding_identity_changed:embeddingIdentityChanged,embedding_identity_before:ledgerBefore.embedding??null,embedding_identity_runtime:snapshot.runtimeEmbeddingIdentity??null,items:items.length,ledger_entries_before:Object.keys(ledgerBefore.entries).length,stale_items_detail_mode:verboseStaleItems?"full":"summary",stale_items_summary_limit:STALE_VECTORIZATION_SUMMARY_LIMIT,stale_items_before_total:staleBeforeDetail.total,stale_items_before:staleBeforeDetail.values,stale_items_before_truncated:staleBeforeDetail.truncated,refresh_attempted:refreshAttempted,refresh_skipped_reason:resolveVectorizationRefreshSkippedReason(refreshPolicy,snapshot.semanticRuntimeAvailable,staleBefore),refresh_result:refreshResult,ledger_entries_after:Object.keys(ledgerAfter.entries).length,stale_items_after_total:staleAfterDetail.total,stale_items_after:staleAfterDetail.values,stale_items_after_truncated:staleAfterDetail.truncated}},warnings}}function validateSettingsValues(settings){const warnings=[];if(settings.id_prefix.trim().length===0){warnings.push("settings:id_prefix_empty")}if(settings.locks.ttl_seconds<=0){warnings.push("settings:locks_ttl_non_positive")}return warnings}function resolveVectorRefreshPolicy(options){const checkOnly=options.checkOnly===true;const refreshVectors=options.refreshVectors===true;if(refreshVectors&&checkOnly){throw new PmCliError("--check-only cannot be combined with --refresh-vectors",EXIT_CODE.USAGE)}if(refreshVectors&&options.noRefresh===true){throw new PmCliError("--no-refresh cannot be combined with --refresh-vectors",EXIT_CODE.USAGE)}return{enabled:refreshVectors,checkOnly,noRefresh:!refreshVectors,refreshVectors}}const HEALTH_CLONE_OPTIONAL_DIRECTORIES=new Set(["extensions","locks","search"]);function resolveHealthDirectoryLists(typeRegistry){const requiredDirSet=new Set(PM_CORE_REQUIRED_SUBDIRS.filter(entry=>entry.length>0));const optionalDirSet=new Set;const builtinItemFolderSet=new Set(Object.values(TYPE_TO_FOLDER));for(const folder of typeRegistry.folders){if(requiredDirSet.has(folder)&&!builtinItemFolderSet.has(folder)){continue}requiredDirSet.delete(folder);optionalDirSet.add(folder)}for(const folder of HEALTH_CLONE_OPTIONAL_DIRECTORIES){requiredDirSet.delete(folder);optionalDirSet.add(folder)}return{requiredDirs:[...requiredDirSet].sort((left,right)=>left.localeCompare(right)),optionalDirs:[...optionalDirSet].sort((left,right)=>left.localeCompare(right)),optionalDirSet}}async function scanHealthDirectories(pmRoot,typeRegistry,strictDirectories){const{requiredDirs,optionalDirs,optionalDirSet}=resolveHealthDirectoryLists(typeRegistry);const missingRequiredDirs=[];const missingOptionalDirs=[];const hookWarnings=[];for(const relativeDir of[...requiredDirs,...optionalDirs]){const directoryPath=path.join(pmRoot,relativeDir);hookWarnings.push(...await runActiveOnReadHooks({path:directoryPath,scope:"project"}));if(await isDirectory(directoryPath)){continue}if(optionalDirSet.has(relativeDir)){missingOptionalDirs.push(relativeDir)}else{missingRequiredDirs.push(relativeDir)}}return{requiredDirs,optionalDirs,missingRequiredDirs,missingOptionalDirs,missingDirs:strictDirectories?[...missingRequiredDirs,...missingOptionalDirs]:[...missingRequiredDirs],hookWarnings}}function resolveHealthSkipPolicy(options){const checkOnlyDefaultSummary=options.checkOnly===true&&options.brief!==true&&options.summary!==true&&options.full!==true;const summaryMode=(options.summary===true||checkOnlyDefaultSummary)&&options.full!==true;const fastProjectionCheckOnly=options.checkOnly===true&&(options.brief===true||options.summary===true)&&options.full!==true;return{summaryMode,skipIntegrity:(options.skipIntegrity===true||fastProjectionCheckOnly)&&options.full!==true,skipDrift:(options.skipDrift===true||fastProjectionCheckOnly)&&options.full!==true,skipVectors:(options.skipVectors===true||fastProjectionCheckOnly)&&options.full!==true}}async function readHealthItems(params){if(params.skipPolicy.skipDrift&&params.skipPolicy.skipVectors){return listAllItemMetadataLight(params.pmRoot,params.settings.item_format,params.typeRegistry.type_to_folder,params.itemReadWarnings,params.settings.schema)}return listAllItemMetadataWithBody(params.pmRoot,params.settings.item_format,params.typeRegistry.type_to_folder,params.itemReadWarnings,params.settings.schema)}function buildSkippedHealthCheck(name){return{check:{name,status:"ok",ok:true,details:{skipped:true}},warnings:[]}}function buildSettingsHealthCheck(settingsPath,settings,normalizedSettingsReadWarnings){return{name:"settings",status:normalizedSettingsReadWarnings.length===0?"ok":"warn",ok:normalizedSettingsReadWarnings.length===0,details:{path:settingsPath,version:settings.version,id_prefix:settings.id_prefix,locks_ttl_seconds:settings.locks.ttl_seconds,warnings:normalizedSettingsReadWarnings}}}function buildDirectoriesHealthCheck(directoryState,strictDirectories){return{name:"directories",status:directoryState.missingDirs.length===0?"ok":"warn",ok:directoryState.missingDirs.length===0,details:{required:directoryState.requiredDirs,optional:directoryState.optionalDirs,missing_required:directoryState.missingRequiredDirs,missing_optional:directoryState.missingOptionalDirs,missing:directoryState.missingDirs,strict_directories:strictDirectories}}}function buildSettingsValuesHealthCheck(settingWarnings,statusRoleDiagnostics){return{name:"settings_values",status:settingWarnings.length===0?"ok":"warn",ok:settingWarnings.length===0,details:{warnings:settingWarnings,...statusRoleDiagnostics.roleless_status_count>0?{lifecycle_status_roles:statusRoleDiagnostics}:{}}}}const resolveUnknownAuthorEventCount=authorAttribution=>authorAttribution.unknown_event_count??0;const resolveActionableUnknownAuthorEventCount=authorAttribution=>authorAttribution.actionable_unknown_event_count??resolveUnknownAuthorEventCount(authorAttribution);function buildStorageHealthCheck(items,settings,historySummary,authorAttribution,staleInProgress,provenance){const unknownAuthorEventCount=resolveUnknownAuthorEventCount(authorAttribution);const actionableUnknownAuthorEventCount=resolveActionableUnknownAuthorEventCount(authorAttribution);const hasAuthorEvents=unknownAuthorEventCount>0;const hasActionableAuthorWarnings=actionableUnknownAuthorEventCount>0;const hasStaleInProgressItems=staleInProgress.count>0;return{name:"storage",status:historySummary.over_threshold.length===0&&historySummary.orphaned.length===0&&!hasActionableAuthorWarnings&&!hasStaleInProgressItems?"ok":"warn",ok:historySummary.over_threshold.length===0&&historySummary.orphaned.length===0&&!hasActionableAuthorWarnings&&!hasStaleInProgressItems,details:{items:items.length,history_streams:historySummary.count,tombstones:{retention_policy:"retain_append_only",gc_enabled:false,count:historySummary.tombstones.length,ids:historySummary.tombstones.slice(0,25),truncated:historySummary.tombstones.length>25},orphaned_history_streams:{count:historySummary.orphaned.length,ids:historySummary.orphaned.slice(0,25),truncated:historySummary.orphaned.length>25},...hasAuthorEvents?{author_attribution:authorAttribution}:{},...hasStaleInProgressItems?{stale_in_progress:staleInProgress}:{},...provenance.outcomes.length>0?{provenance_resolver_outcomes:provenance.outcomes}:{},...provenance.invalid_values.length>0?{provenance_invalid_values:provenance.invalid_values}:{},provenance_sample:provenance.sample,...historySummary.max_entries!==null?{compact_policy:{enabled:settings.history.compact_policy.enabled,max_entries:historySummary.max_entries,trigger:settings.history.compact_policy.trigger,over_threshold_count:historySummary.over_threshold.length,over_threshold:historySummary.over_threshold}}:{}}}}function buildStaleInProgressHealthSummary(scan){const warnings=scan.count===0?[]:[`stale_in_progress_items:${scan.count}`];return{scan,warnings}}function collectHealthWarnings(params){const warnings=[...params.directoryState.missingDirs.map(dir=>`missing_directory:${dir}`),...params.normalizedSettingsReadWarnings,...params.settingWarnings,...params.normalizedItemReadWarnings,...params.telemetryCheck.warnings,...params.extensionCheck.warnings,...params.historyPolicyWarnings,...params.historySummary.warnings,...params.authorAttributionWarnings,...params.staleInProgressWarnings,...params.provenanceWarnings,...params.locksCheck.warnings,...params.integrityCheck.warnings,...params.historyDriftCheck.warnings,...params.vectorizationCheck.warnings,...params.directoryState.hookWarnings];return[...new Set(warnings)]}function extractHistoryDriftedCount(historyDriftCheck){const counts=historyDriftCheck.check.details.counts;return typeof counts?.drifted==="number"?counts.drifted:0}function buildHealthRemediationSources(params){return{settings:params.normalizedSettingsReadWarnings,directories:params.directoryState.missingDirs.map(dir=>`missing_directory:${dir}`).concat(params.directoryState.hookWarnings),settings_values:params.settingWarnings,telemetry:params.telemetryCheck.warnings,extensions:params.extensionCheck.warnings,storage:[...params.historyPolicyWarnings,...params.historySummary.warnings,...params.authorAttributionWarnings,...params.staleInProgressWarnings,...params.provenanceWarnings],locks:params.locksCheck.warnings,integrity:[...params.normalizedItemReadWarnings,...params.integrityCheck.warnings],history_drift:params.historyDriftCheck.warnings,vectorization:params.vectorizationCheck.warnings}}function buildHealthFindings(params){const owners=new Map;for(const[check,warnings]of Object.entries(params.remediationSources)){for(const warning of warnings){if(!owners.has(warning))owners.set(warning,check)}}const checksByName=new Map(params.checks.map(check=>[check.name,check]));const findings=params.warnings.map(warning=>{const check=owners.get(warning)??"integrity";const code=resolveRemediation(warning)?.code??warningCode(warning);const details=checksByName.get(check)?.details;const remediationMap=typeof details?.remediation_map==="object"&&details.remediation_map!==null?details.remediation_map:{};const remediation=code==="agent_guidance_outdated"?"pm init --agent-guidance add":code==="agent_guidance_unreadable"?"Check AGENTS.md and CLAUDE.md read permissions and file types, then retry pm health.":remediationMap[code];const severity=isAdvisoryHealthWarning(warning,params.requireMergeDrivers)?"advisory":"gate_failing";return{warning,code,check,severity,...typeof remediation==="string"?{remediation}:severity==="gate_failing"?{disposition:"no_safe_automatic_remediation"}:{}}});return findings}function rewriteBulkHealthRemediation(params){if(params.check.name==="history_drift"&&params.historyDriftedCount>1){for(const code of Object.keys(params.remediationMap)){if(code!=="history_drift_merge_receipt"&&code!=="history_drift_version_skew"){params.remediationMap[code]="pm history-repair --all"}}}if(params.check.name==="storage"&&params.overThresholdCount>1){for(const code of Object.keys(params.remediationMap)){params.remediationMap[code]="pm history-compact --all-streams"}}}function attachHealthRemediationMaps(params){for(const check of params.checks){const remediationMap=buildRemediationMap(params.remediationSources[check.name]);rewriteBulkHealthRemediation({check,remediationMap,historyDriftedCount:params.historyDriftedCount,overThresholdCount:params.overThresholdCount});if(Object.keys(remediationMap).length>0){check.details={...check.details,remediation_map:remediationMap}}}}async function correlateMergeReceiptHistoryDriftItems(params){if(params.gitWorkspaceRoot===null||params.pendingMergeReceipts.length===0){return[]}const details=params.historyDriftCheck.check.details;const hashMismatches=Array.isArray(details.hash_mismatches)?details.hash_mismatches.filter(entry=>typeof entry==="string"):[];const unsafeStreamIds=new Set([details.missing_streams,details.unreadable_streams,details.chain_mismatches].flatMap(value=>Array.isArray(value)?value:[]));const cloneLocalReceiptsByItem=new Map;for(const receipt of params.pendingMergeReceipts){if(receipt.evidence_source!=="clone_local")continue;const receipts=cloneLocalReceiptsByItem.get(receipt.item_id)??[];receipts.push(receipt);cloneLocalReceiptsByItem.set(receipt.item_id,receipts)}const attributed=[];for(const id of hashMismatches){if(unsafeStreamIds.has(id))continue;const receipts=cloneLocalReceiptsByItem.get(id);if(!receipts||receipts.length===0)continue;try{await runHistoryRepair(id,{dryRun:true,mergeReceiptProof:{gitWorkspaceRoot:params.gitWorkspaceRoot,receipts}},params.global);attributed.push(id)}catch{}}return[...new Set(attributed)].sort((left,right)=>left.localeCompare(right))}function applyMergeReceiptHistoryDriftAttribution(historyDriftCheck,attributedItems){const attributed=new Set(attributedItems);historyDriftCheck.warnings=[...historyDriftCheck.warnings.filter(warning=>{if(!warning.startsWith("history_drift_hash_mismatch:"))return true;return!attributed.has(warning.slice(warning.indexOf(":")+1))}),...attributedItems.map(id=>`history_drift_merge_receipt:${id}`)].sort((left,right)=>left.localeCompare(right));historyDriftCheck.check.details={...historyDriftCheck.check.details,merge_receipt_attributed_items:attributedItems}}function projectHealthResult(result,options,summaryMode){const warningCount=result.warning_count??result.warnings.length;const boundedResult={...result,warning_count:warningCount,warning_limit:HEALTH_WARNING_LIMIT,warnings_truncated:warningCount>HEALTH_WARNING_LIMIT,warnings:result.warnings.slice(0,HEALTH_WARNING_LIMIT),findings:(result.findings??[]).filter(finding=>result.warnings.slice(0,HEALTH_WARNING_LIMIT).includes(finding.warning)||result.failed_because.includes(finding.warning))};const projected=summaryMode?applySummaryHealthProjection(boundedResult):options.brief===true?applyBriefHealthProjection(boundedResult):boundedResult;return{...projected,warning_count:warningCount,warning_limit:HEALTH_WARNING_LIMIT,warnings_truncated:warningCount>projected.warnings.length,...projected.projection?{projection:{...projected.projection,warning_count:warningCount,warnings_truncated:warningCount>projected.warnings.length}}:{}}}async function runHealth(global2,options={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settingsPath=getSettingsPath(pmRoot);const{settings,warnings:settingsReadWarnings}=await readSettingsWithMetadata(pmRoot);const normalizedSettingsReadWarnings=[...new Set(settingsReadWarnings)];const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());const strictDirectories=options.strictDirectories===true;const strictExit=options.strictExit===true||options.failOnWarn===true;const requireMergeDrivers=options.requireMergeDrivers===true||strictExit;const refreshPolicy=resolveVectorRefreshPolicy(options);const directoryState=await scanHealthDirectories(pmRoot,typeRegistry,strictDirectories);const settingsValueWarnings=validateSettingsValues(settings);const telemetryCheck=await buildTelemetryCheck(settings,{checkTelemetry:options.checkTelemetry===true});const extensionCheck=await buildExtensionCheck(pmRoot,settings,Boolean(global2.noExtensions));const skipPolicy=resolveHealthSkipPolicy(options);const itemReadWarnings=[];const items=await readHealthItems({pmRoot,settings,typeRegistry,skipPolicy,itemReadWarnings});const itemsWithBody=items;const statusRoleDiagnostics=inspectStatusRoleAssignments(resolveRuntimeStatusRegistry(settings.schema),items);const agentGuidance=await runInitAgentGuidance({pm_root:pmRoot,cwd:process.cwd(),mode:"status",interactive:false,settings}).catch(()=>({warnings:["agent_guidance_unreadable:AGENTS.md,CLAUDE.md"]}));const settingWarnings=[...agentGuidance.warnings.filter(warning=>warning.startsWith("agent_guidance_")),...settingsValueWarnings,...buildStatusRoleWarnings(statusRoleDiagnostics)];const historyPolicy=skipPolicy.skipDrift?{warnings:[]}:await enforceHistoryStreamPolicyForItems({pmRoot,settings,itemIds:items.map(item=>item.id),commandLabel:"health"});const historySummary=await countHistoryStreams(pmRoot,settings.history.compact_policy,await listStoredItemDocumentIds(pmRoot));const authorAttribution=await scanHistoryAuthorAttribution(pmRoot,20,options.verboseAuthorEvents===true);const actionableUnknownAuthorEventCount=resolveActionableUnknownAuthorEventCount(authorAttribution);const authorAttributionWarnings=actionableUnknownAuthorEventCount>0?[`history_unknown_author_events:${actionableUnknownAuthorEventCount}`]:[];const staleInProgress=buildStaleInProgressHealthSummary(await scanStaleInProgressItems(pmRoot,items,{in_progress_status:settings.schema.workflow.in_progress_status,threshold_hours:settings.mutation_guard.stale_in_progress_hours}));const provenanceResolverHealth=await scanProvenanceResolverHealth(pmRoot);const provenanceWarnings=provenanceResolverHealth.warnings;const locksCheck=await buildLocksCheck(pmRoot);const integrityCheck=skipPolicy.skipIntegrity&&!requireMergeDrivers?{...buildSkippedHealthCheck("integrity"),gitWorkspaceRoot:null,pendingMergeReceipts:[]}:await buildIntegrityCheck(pmRoot,typeRegistry.type_to_folder,settings.schema,requireMergeDrivers,items);const historyDriftCheck=skipPolicy.skipDrift?buildSkippedHealthCheck("history_drift"):await buildHistoryDriftCheck({pmRoot,items:itemsWithBody,settings,typeRegistry,itemReadWarnings});const normalizedItemReadWarnings=[...new Set(itemReadWarnings)];const mergeReceiptAttributedHistoryDriftItems=await correlateMergeReceiptHistoryDriftItems({gitWorkspaceRoot:integrityCheck.gitWorkspaceRoot,pendingMergeReceipts:integrityCheck.pendingMergeReceipts,historyDriftCheck,global:global2});applyMergeReceiptHistoryDriftAttribution(historyDriftCheck,mergeReceiptAttributedHistoryDriftItems);const vectorizationCheck=skipPolicy.skipVectors?buildSkippedHealthCheck("vectorization"):await buildVectorizationCheck(pmRoot,settings,itemsWithBody,refreshPolicy,options.verboseStaleItems===true);const checks=[buildSettingsHealthCheck(settingsPath,settings,normalizedSettingsReadWarnings),buildDirectoriesHealthCheck(directoryState,strictDirectories),buildSettingsValuesHealthCheck(settingWarnings,statusRoleDiagnostics),telemetryCheck.check,extensionCheck.check,buildStorageHealthCheck(items,settings,historySummary,authorAttribution,staleInProgress.scan,provenanceResolverHealth),locksCheck.check,integrityCheck.check,historyDriftCheck.check,vectorizationCheck.check];const normalizedWarnings=collectHealthWarnings({directoryState,normalizedSettingsReadWarnings,settingWarnings,normalizedItemReadWarnings,telemetryCheck,extensionCheck,historyPolicyWarnings:historyPolicy.warnings,historySummary,authorAttributionWarnings,staleInProgressWarnings:staleInProgress.warnings,provenanceWarnings,locksCheck,integrityCheck,historyDriftCheck,vectorizationCheck});const remediationSources=buildHealthRemediationSources({directoryState,normalizedSettingsReadWarnings,settingWarnings,normalizedItemReadWarnings,telemetryCheck,extensionCheck,historyPolicyWarnings:historyPolicy.warnings,historySummary,authorAttributionWarnings,staleInProgressWarnings:staleInProgress.warnings,provenanceWarnings,locksCheck,integrityCheck,historyDriftCheck,vectorizationCheck});attachHealthRemediationMaps({checks,remediationSources,historyDriftedCount:extractHistoryDriftedCount(historyDriftCheck),overThresholdCount:historySummary.over_threshold.length});const blockingWarnings=normalizedWarnings.filter(warning=>!isAdvisoryHealthWarning(warning,requireMergeDrivers));const findings=buildHealthFindings({warnings:normalizedWarnings,checks,remediationSources,requireMergeDrivers});const failingChecks=new Set(findings.filter(finding=>finding.severity==="gate_failing").map(finding=>finding.check));const warningChecks=new Set(findings.map(finding=>finding.check));for(const check of checks){check.ok=!failingChecks.has(check.name);if(warningChecks.has(check.name))check.status="warn"}const result={ok:blockingWarnings.length===0,verdict:{authority:"ok",...strictExit?{strict_exit:true}:{},...requireMergeDrivers?{require_merge_drivers:true}:{},exit_code:strictExit&&blockingWarnings.length>0?EXIT_CODE.GENERIC_FAILURE:0},checks,warnings:normalizedWarnings,findings,failed_because:blockingWarnings,generated_at:nowIso()};return projectHealthResult(result,options,skipPolicy.summaryMode)}const _testOnlyHealthCommand={buildHierarchyIntegrityWarnings,buildExtensionHealthTriageSummary,buildHealthFindings,buildCapabilityContractMetadata,buildStaleInProgressHealthSummary,buildVectorizationProviderDetails,collectUnknownCapabilityGuidance,isAdvisoryHealthWarning,isDirectory,isExpectedUnmanagedExtension,listItemDocumentPaths,normalizeEndpointForDisplay,normalizeExtensionNameForMatch,parseTelemetryQueue,probeTelemetryEndpointHealth,projectHealthResult,resolveActionableUnknownAuthorEventCount,resolveHealthSkipPolicy,resolveUnknownAuthorEventCount,resolveVectorRefreshPolicy,selectStaleItemDetail,summarizeHealthCheckDetails,summarizeExtensionList,summarizeRecordList,summarizeStringList,telemetryEnvFlagEnabled,warningCode};export{_testOnlyHealthCommand,runHealth};
2
2
  //# sourceMappingURL=health.js.map
@@ -29,6 +29,7 @@ interface AgentGuidanceFileScan {
29
29
  exists: boolean;
30
30
  has_guidance: boolean;
31
31
  has_marker: boolean;
32
+ outdated?: boolean;
32
33
  }
33
34
  interface AgentGuidanceBlockRange {
34
35
  start_index: number;
@@ -110,6 +111,6 @@ declare function writeGuidanceFile(filePath: string, projectRoot?: string): Prom
110
111
  changed: boolean;
111
112
  warnings: string[];
112
113
  }>;
113
- /** Implements run init agent guidance for the public runtime surface of this module. */
114
+ /** Inspect, offer or refresh managed guidance; preserve surrounding prose and return state for the caller's settings transaction. */
114
115
  export declare function runInitAgentGuidance(options: RunInitAgentGuidanceOptions): Promise<RunInitAgentGuidanceResult>;
115
116
  export {};
@@ -1,3 +1,3 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e5ae3e66-4a45-5c62-9144-46f8f5bff7cf")}catch(e2){}})();import fs from"node:fs/promises";import path from"node:path";import readline from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import{runActiveOnWriteHooks}from"../core/extensions/index.js";import{pathExists,writeFileAtomic}from"../core/fs/fs-utils.js";const INIT_AGENT_GUIDANCE_MODE_VALUES=["ask","add","skip","status"];const AGENT_GUIDANCE_TARGET_FILENAMES=["AGENTS.md","CLAUDE.md"];const AGENT_GUIDANCE_REQUIRED_TOKENS=["pm init","pm context","pm search","pm create","pm claim","pm files","pm docs","pm test --run","pm close","pm release","pm_author"];const AGENT_GUIDANCE_REQUIRED_TOKEN_THRESHOLD=8;const AGENT_GUIDANCE_TEMPLATE_VERSION=1;const AGENT_GUIDANCE_START_MARKER_PREFIX="<!-- pm-cli:agent-guidance:start:";const AGENT_GUIDANCE_START_MARKER=`<!-- pm-cli:agent-guidance:start:v${AGENT_GUIDANCE_TEMPLATE_VERSION} -->`;const AGENT_GUIDANCE_END_MARKER="<!-- pm-cli:agent-guidance:end -->";const AGENT_GUIDANCE_ADD_LATER_HINT="Add workflow guidance later: pm init --agent-guidance add";const _testOnly={toPortableRelativePath,ensureTrailingNewline,detectLineEnding,findGuidanceBlockRange,buildAgentGuidanceBlock,upsertAgentGuidanceBlock,resolveProjectRoot,resolveTargetGuidancePath,parsePromptChoice,pushUnique,promptForGuidanceWrite,normalizeAgentGuidanceState,applyAgentGuidanceState,writeGuidanceFile,setAgentGuidanceReadlineFactoryForTests};let createAgentGuidanceReadlineInterface=()=>readline.createInterface({input,output});function setAgentGuidanceReadlineFactoryForTests(factory){createAgentGuidanceReadlineInterface=factory??(()=>readline.createInterface({input,output}))}function toPortableRelativePath(projectRoot,targetPath){const relative=path.relative(projectRoot,targetPath);if(relative.length===0){return path.basename(targetPath)}return relative.split(path.sep).join("/")}function ensureTrailingNewline(value){return value.endsWith("\n")?value:`${value}
2
- `}function detectLineEnding(value){return value.includes("\r\n")?"\r\n":"\n"}function findGuidanceBlockRange(content){const startIndex=content.indexOf(AGENT_GUIDANCE_START_MARKER_PREFIX);if(startIndex===-1){return null}const endMarkerIndex=content.indexOf(AGENT_GUIDANCE_END_MARKER,startIndex);if(endMarkerIndex===-1){return null}return{start_index:startIndex,end_index:endMarkerIndex+AGENT_GUIDANCE_END_MARKER.length}}function hasGuidanceMarker(content){return findGuidanceBlockRange(content)!==null}function buildAgentGuidanceBlock(lineEnding,projectTestCommand="<your project test command>"){const lines=[AGENT_GUIDANCE_START_MARKER,"## pm Workflow (Agent Quickstart)","",'- Cold start with the measured canonical orientation: `pm context --limit 10 --for orient`; before item mutation, also run `pm search "<keywords>" --limit 10`, `pm list --status open --limit 20`, and `pm list --status in_progress --limit 20`.',"- Claim and execute: `pm claim <id>` then `pm update <id> --status in_progress`.",`- Link evidence while coding: \`pm files <id> --add ...\`, \`pm docs <id> --add ...\`, \`pm test <id> --add command="${projectTestCommand}"\`.`,'- Verify and close: `pm test <id> --run --progress`, then atomically record closure evidence with `pm close <id> "<reason>" --resolution "<what changed>" --expected "<expected outcome>" --actual "<observed outcome>" --validate-close warn`, then `pm release <id>`.',"- Author identity is automatic for supported agent harnesses; use `--author` only for an explicit override.","",AGENT_GUIDANCE_END_MARKER,""];return lines.join(lineEnding)}function upsertAgentGuidanceBlock(existingContent,projectTestCommand="<your project test command>"){const lineEnding=detectLineEnding(existingContent);const nextBlock=buildAgentGuidanceBlock(lineEnding,projectTestCommand);const existingRange=findGuidanceBlockRange(existingContent);if(existingRange){const trailingContent=existingContent.slice(existingRange.end_index);const normalizedTrailingContent=trailingContent.startsWith("\r\n")?trailingContent.slice(2):trailingContent.startsWith("\n")?trailingContent.slice(1):trailingContent;const nextContent2=ensureTrailingNewline(`${existingContent.slice(0,existingRange.start_index)}${nextBlock}${normalizedTrailingContent}`);return{next_content:nextContent2,changed:nextContent2!==existingContent}}const separator=existingContent.length===0?"":existingContent.endsWith("\n")?"\n":"\n\n";const nextContent=ensureTrailingNewline(`${existingContent}${separator}${nextBlock}`);return{next_content:nextContent,changed:nextContent!==existingContent}}async function resolveProjectTestCommand(projectRoot){if(await pathExists(path.join(projectRoot,"scripts","run-tests.mjs"))){return"node scripts/run-tests.mjs test"}let packageDocument;try{packageDocument=JSON.parse(await fs.readFile(path.join(projectRoot,"package.json"),"utf8"))}catch{return"<your project test command>"}const manifest=normalizeProjectPackageManifest(packageDocument);if(manifest===void 0){return"<your project test command>"}const packageManager=manifest.packageManager?.split("@")[0];if(packageManager==="pnpm"){return"pnpm test"}if(packageManager==="bun"){return"bun run test"}if(packageManager==="yarn"){return"yarn test"}if(packageManager==="npm")return"npm test";if(await pathExists(path.join(projectRoot,"pnpm-lock.yaml"))){return"pnpm test"}if(await pathExists(path.join(projectRoot,"bun.lock"))||await pathExists(path.join(projectRoot,"bun.lockb"))){return"bun run test"}if(await pathExists(path.join(projectRoot,"yarn.lock")))return"yarn test";return"npm test"}function normalizeProjectPackageManifest(value){if(typeof value!=="object"||value===null||!("scripts"in value)){return void 0}const scripts=value.scripts;if(typeof scripts!=="object"||scripts===null||!("test"in scripts)||typeof scripts.test!=="string"||scripts.test.trim().length===0){return void 0}return{scripts:{test:scripts.test},..."packageManager"in value&&typeof value.packageManager==="string"?{packageManager:value.packageManager}:{}}}function resolveProjectRoot(pmRoot,cwd){const parent=path.dirname(pmRoot);if(path.basename(pmRoot)==="pm"&&path.basename(parent)===".agents"){return path.dirname(parent)}return path.resolve(cwd,pmRoot)}function resolveTargetGuidancePath(scans,projectRoot){const existingAgents=scans.find(entry=>path.basename(entry.file_path)==="AGENTS.md"&&entry.exists);if(existingAgents){return existingAgents.file_path}const existingAny=scans.find(entry=>entry.exists);if(existingAny){return existingAny.file_path}return path.join(projectRoot,"AGENTS.md")}function parsePromptChoice(answer,currentDefault){const normalized=answer.trim().toLowerCase();if(normalized.length===0){return currentDefault}if(normalized==="y"||normalized==="yes"){return true}if(normalized==="n"||normalized==="no"){return false}return currentDefault}async function promptForGuidanceWrite(targetRelativePath){const rl=createAgentGuidanceReadlineInterface();try{output.write("\nAgent guidance check\n");output.write("No AGENTS.md/CLAUDE.md file currently contains compact pm workflow guidance.\n");const answer=await rl.question(`Add a compact pm workflow section to ${targetRelativePath}? [Y/n] `);output.write("\n");return parsePromptChoice(answer,true)}finally{rl.close()}}function normalizeAgentGuidanceState(settings){const current=settings.agent_guidance;return{prompt_completed:current?.prompt_completed===true,declined:current?.declined===true,declined_at:typeof current?.declined_at==="string"?current.declined_at:"",template_version:typeof current?.template_version==="number"&&Number.isInteger(current.template_version)&&current.template_version>0?current.template_version:AGENT_GUIDANCE_TEMPLATE_VERSION,last_checked_files:Array.isArray(current?.last_checked_files)?[...new Set(current.last_checked_files.map(value=>value.trim()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right)):[]}}async function scanGuidanceFiles(projectRoot){const scans=[];for(const filename of AGENT_GUIDANCE_TARGET_FILENAMES){const filePath=path.join(projectRoot,filename);const exists=await pathExists(filePath);if(!exists){scans.push({file_path:filePath,exists,has_guidance:false,has_marker:false});continue}const content=await fs.readFile(filePath,"utf8");const contentLower=content.toLowerCase();const tokenHits=AGENT_GUIDANCE_REQUIRED_TOKENS.filter(token=>contentLower.includes(token));const hasMarker=hasGuidanceMarker(content);scans.push({file_path:filePath,exists,has_guidance:hasMarker||tokenHits.length>=AGENT_GUIDANCE_REQUIRED_TOKEN_THRESHOLD,has_marker:hasMarker})}return scans}function pushUnique(target,value){if(!target.includes(value)){target.push(value)}}function applyAgentGuidanceState(settings,currentState){const existing=normalizeAgentGuidanceState(settings);const changed=JSON.stringify(existing)!==JSON.stringify(currentState);if(changed){settings.agent_guidance=currentState}return{changed,state:currentState}}async function writeGuidanceFile(filePath,projectRoot=path.dirname(filePath)){const exists=await pathExists(filePath);const currentContent=exists?await fs.readFile(filePath,"utf8"):"";const nextContent=upsertAgentGuidanceBlock(currentContent,await resolveProjectTestCommand(projectRoot));if(!nextContent.changed){return{changed:false,warnings:[]}}await writeFileAtomic(filePath,nextContent.next_content);return{changed:true,warnings:await runActiveOnWriteHooks({path:filePath,scope:"project",op:"init:agent_guidance_file"})}}function buildInitAgentGuidanceSummary(params){return{mode:params.mode,present:params.scans.some(entry=>entry.has_guidance),prompted:params.prompted,applied:params.applied,skipped:params.skipped,declined:params.state.declined,prompt_completed:params.state.prompt_completed,template_version:params.state.template_version,target_file:params.targetRelativePath,checked_files:params.scans.map(entry=>toPortableRelativePath(params.projectRoot,entry.file_path)),files_with_guidance:params.scans.filter(entry=>entry.has_guidance).map(entry=>toPortableRelativePath(params.projectRoot,entry.file_path)),missing_files:params.scans.filter(entry=>!entry.exists).map(entry=>toPortableRelativePath(params.projectRoot,entry.file_path))}}async function refreshGuidanceScansAfterApply(applied,scans,projectRoot){return applied?await scanGuidanceFiles(projectRoot):scans}function markAgentGuidanceRunState(flow,checkedFiles,partial){flow.state={...flow.state,...partial,template_version:AGENT_GUIDANCE_TEMPLATE_VERSION,last_checked_files:checkedFiles}}async function addAgentGuidanceBlockIfMissing(flow,context){if(context.presentBefore){return}const writeResult=await writeGuidanceFile(context.targetPath,context.projectRoot);flow.warnings.push(...writeResult.warnings);if(writeResult.changed){flow.applied=true;flow.warnings.push(`agent_guidance:added:${context.targetRelativePath}`)}}function handleAgentGuidanceStatusMode(flow,presentBefore){if(!presentBefore){flow.warnings.push("agent_guidance:missing");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}}function handleAgentGuidanceSkipMode(flow,checkedFiles){flow.skipped=true;markAgentGuidanceRunState(flow,checkedFiles,{prompt_completed:true,declined:true,declined_at:flow.state.declined_at||new Date().toISOString()});flow.warnings.push("agent_guidance:explicit_skip");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}async function handleAgentGuidanceAddMode(flow,context){await addAgentGuidanceBlockIfMissing(flow,context);markAgentGuidanceRunState(flow,context.checkedFiles,{prompt_completed:true,declined:false,declined_at:""})}function handlePresentAgentGuidance(flow,checkedFiles){if(flow.state.declined){markAgentGuidanceRunState(flow,checkedFiles,{prompt_completed:true,declined:false,declined_at:""})}}function handleDeclinedAgentGuidance(flow){flow.skipped=true;flow.warnings.push("agent_guidance:skipped_declined");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}async function handleInteractiveAgentGuidancePrompt(flow,context){flow.prompted=true;const approved=await promptForGuidanceWrite(context.targetRelativePath);if(approved){await addAgentGuidanceBlockIfMissing(flow,context);markAgentGuidanceRunState(flow,context.checkedFiles,{prompt_completed:true,declined:false,declined_at:""});return}flow.skipped=true;markAgentGuidanceRunState(flow,context.checkedFiles,{prompt_completed:true,declined:true,declined_at:new Date().toISOString()});flow.warnings.push("agent_guidance:declined");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}function handleNonInteractiveMissingAgentGuidance(flow){flow.warnings.push("agent_guidance:missing_non_interactive");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}async function applyAgentGuidanceMode(initialState,context){const flow={warnings:[],nextSteps:[],prompted:false,applied:false,skipped:false,state:initialState};if(context.mode==="status"){handleAgentGuidanceStatusMode(flow,context.presentBefore);return flow}if(context.mode==="skip"){handleAgentGuidanceSkipMode(flow,context.checkedFiles);return flow}if(context.mode==="add"){await handleAgentGuidanceAddMode(flow,context);return flow}if(context.presentBefore){handlePresentAgentGuidance(flow,context.checkedFiles);return flow}if(flow.state.prompt_completed&&flow.state.declined){handleDeclinedAgentGuidance(flow);return flow}if(context.interactive){await handleInteractiveAgentGuidancePrompt(flow,context);return flow}handleNonInteractiveMissingAgentGuidance(flow);return flow}async function runInitAgentGuidance(options){const projectRoot=resolveProjectRoot(options.pm_root,options.cwd);let scans=await scanGuidanceFiles(projectRoot);const targetPath=resolveTargetGuidancePath(scans,projectRoot);const targetRelativePath=toPortableRelativePath(projectRoot,targetPath);const checkedFiles=scans.map(entry=>toPortableRelativePath(projectRoot,entry.file_path));const presentBefore=scans.some(entry=>entry.has_guidance);const flow=await applyAgentGuidanceMode(normalizeAgentGuidanceState(options.settings),{mode:options.mode,interactive:options.interactive,targetPath,targetRelativePath,checkedFiles,presentBefore,projectRoot});const stateUpdate=applyAgentGuidanceState(options.settings,flow.state);scans=await refreshGuidanceScansAfterApply(flow.applied,scans,projectRoot);const summary=buildInitAgentGuidanceSummary({mode:options.mode,scans,projectRoot,targetRelativePath,prompted:flow.prompted,applied:flow.applied,skipped:flow.skipped,state:flow.state});return{summary,warnings:flow.warnings,next_steps:flow.nextSteps,settings_changed:stateUpdate.changed}}export{INIT_AGENT_GUIDANCE_MODE_VALUES,_testOnly,resolveProjectTestCommand,runInitAgentGuidance};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f0c60332-623f-52c0-b217-acb15fcd2218")}catch(e2){}})();import fs from"node:fs/promises";import path from"node:path";import readline from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import{runActiveOnWriteHooks}from"../core/extensions/index.js";import{pathExists,writeFileAtomic}from"../core/fs/fs-utils.js";const INIT_AGENT_GUIDANCE_MODE_VALUES=["ask","add","skip","status"];const AGENT_GUIDANCE_TARGET_FILENAMES=["AGENTS.md","CLAUDE.md"];const AGENT_GUIDANCE_REQUIRED_TOKENS=["pm init","pm context","pm search","pm create","pm claim","pm files","pm docs","pm test --run","pm close","pm release","pm_author"];const AGENT_GUIDANCE_REQUIRED_TOKEN_THRESHOLD=8;const AGENT_GUIDANCE_TEMPLATE_VERSION=1;const AGENT_GUIDANCE_START_MARKER_PREFIX="<!-- pm-cli:agent-guidance:start:";const AGENT_GUIDANCE_START_MARKER=`<!-- pm-cli:agent-guidance:start:v${AGENT_GUIDANCE_TEMPLATE_VERSION} -->`;const AGENT_GUIDANCE_END_MARKER="<!-- pm-cli:agent-guidance:end -->";const AGENT_GUIDANCE_ADD_LATER_HINT="Add workflow guidance later: pm init --agent-guidance add";const _testOnly={toPortableRelativePath,ensureTrailingNewline,detectLineEnding,findGuidanceBlockRange,buildAgentGuidanceBlock,upsertAgentGuidanceBlock,resolveProjectRoot,resolveTargetGuidancePath,parsePromptChoice,pushUnique,promptForGuidanceWrite,normalizeAgentGuidanceState,applyAgentGuidanceState,writeGuidanceFile,setAgentGuidanceReadlineFactoryForTests};let createAgentGuidanceReadlineInterface=()=>readline.createInterface({input,output});function setAgentGuidanceReadlineFactoryForTests(factory){createAgentGuidanceReadlineInterface=factory??(()=>readline.createInterface({input,output}))}function toPortableRelativePath(projectRoot,targetPath){const relative=path.relative(projectRoot,targetPath);if(relative.length===0){return path.basename(targetPath)}return relative.split(path.sep).join("/")}function ensureTrailingNewline(value){return value.endsWith("\n")?value:`${value}
2
+ `}function detectLineEnding(value){return value.includes("\r\n")?"\r\n":"\n"}function findGuidanceBlockRange(content){const startIndex=content.indexOf(AGENT_GUIDANCE_START_MARKER_PREFIX);if(startIndex===-1){return null}const endMarkerIndex=content.indexOf(AGENT_GUIDANCE_END_MARKER,startIndex);if(endMarkerIndex===-1){return null}return{start_index:startIndex,end_index:endMarkerIndex+AGENT_GUIDANCE_END_MARKER.length}}function hasGuidanceMarker(content){return findGuidanceBlockRange(content)!==null}function buildAgentGuidanceBlock(lineEnding,projectTestCommand="<your project test command>"){const lines=[AGENT_GUIDANCE_START_MARKER,"## pm Workflow (Agent Quickstart)","",'- Cold start with the measured canonical orientation: `pm context --limit 10 --for orient`; before item mutation, also run `pm search "<keywords>" --limit 10`, `pm list --status open --limit 20`, and `pm list --status in_progress --limit 20`.',"- Claim and start atomically: `pm claim <id> --start`.",`- Link evidence while coding: \`pm files <id> --add ...\`, \`pm docs <id> --add ...\`, \`pm test <id> --add command="${projectTestCommand}"\`.`,'- Verify and close: `pm test <id> --run --progress`, then atomically record closure evidence with `pm close <id> "<reason>" --resolution "<what changed>" --expected "<expected outcome>" --actual "<observed outcome>" --validate-close warn`, then `pm release <id>`.',"- Author identity is automatic for supported agent harnesses; use `--author` only for an explicit override.","",AGENT_GUIDANCE_END_MARKER,""];return lines.join(lineEnding)}function upsertAgentGuidanceBlock(existingContent,projectTestCommand="<your project test command>"){const lineEnding=detectLineEnding(existingContent);const nextBlock=buildAgentGuidanceBlock(lineEnding,projectTestCommand);const existingRange=findGuidanceBlockRange(existingContent);if(existingRange){const trailingContent=existingContent.slice(existingRange.end_index);const normalizedTrailingContent=trailingContent.startsWith("\r\n")?trailingContent.slice(2):trailingContent.startsWith("\n")?trailingContent.slice(1):trailingContent;const nextContent2=ensureTrailingNewline(`${existingContent.slice(0,existingRange.start_index)}${nextBlock}${normalizedTrailingContent}`);return{next_content:nextContent2,changed:nextContent2!==existingContent}}const separator=existingContent.length===0?"":existingContent.endsWith("\n")?"\n":"\n\n";const nextContent=ensureTrailingNewline(`${existingContent}${separator}${nextBlock}`);return{next_content:nextContent,changed:nextContent!==existingContent}}async function resolveProjectTestCommand(projectRoot){if(await pathExists(path.join(projectRoot,"scripts","run-tests.mjs"))){return"node scripts/run-tests.mjs test"}let packageDocument;try{packageDocument=JSON.parse(await fs.readFile(path.join(projectRoot,"package.json"),"utf8"))}catch{return"<your project test command>"}const manifest=normalizeProjectPackageManifest(packageDocument);if(manifest===void 0){return"<your project test command>"}const packageManager=manifest.packageManager?.split("@")[0];if(packageManager==="pnpm"){return"pnpm test"}if(packageManager==="bun"){return"bun run test"}if(packageManager==="yarn"){return"yarn test"}if(packageManager==="npm")return"npm test";if(await pathExists(path.join(projectRoot,"pnpm-lock.yaml"))){return"pnpm test"}if(await pathExists(path.join(projectRoot,"bun.lock"))||await pathExists(path.join(projectRoot,"bun.lockb"))){return"bun run test"}if(await pathExists(path.join(projectRoot,"yarn.lock")))return"yarn test";return"npm test"}function normalizeProjectPackageManifest(value){if(typeof value!=="object"||value===null||!("scripts"in value)){return void 0}const scripts=value.scripts;if(typeof scripts!=="object"||scripts===null||!("test"in scripts)||typeof scripts.test!=="string"||scripts.test.trim().length===0){return void 0}return{scripts:{test:scripts.test},..."packageManager"in value&&typeof value.packageManager==="string"?{packageManager:value.packageManager}:{}}}function resolveProjectRoot(pmRoot,cwd){const parent=path.dirname(pmRoot);if(path.basename(pmRoot)==="pm"&&path.basename(parent)===".agents"){return path.dirname(parent)}return path.resolve(cwd,pmRoot)}function resolveTargetGuidancePath(scans,projectRoot){const existingAgents=scans.find(entry=>path.basename(entry.file_path)==="AGENTS.md"&&entry.exists);if(existingAgents){return existingAgents.file_path}const existingAny=scans.find(entry=>entry.exists);if(existingAny){return existingAny.file_path}return path.join(projectRoot,"AGENTS.md")}function parsePromptChoice(answer,currentDefault){const normalized=answer.trim().toLowerCase();if(normalized.length===0){return currentDefault}if(normalized==="y"||normalized==="yes"){return true}if(normalized==="n"||normalized==="no"){return false}return currentDefault}async function promptForGuidanceWrite(targetRelativePath){const rl=createAgentGuidanceReadlineInterface();try{output.write("\nAgent guidance check\n");output.write("No AGENTS.md/CLAUDE.md file currently contains compact pm workflow guidance.\n");const answer=await rl.question(`Add a compact pm workflow section to ${targetRelativePath}? [Y/n] `);output.write("\n");return parsePromptChoice(answer,true)}finally{rl.close()}}function normalizeAgentGuidanceState(settings){const current=settings.agent_guidance;return{prompt_completed:current?.prompt_completed===true,declined:current?.declined===true,declined_at:typeof current?.declined_at==="string"?current.declined_at:"",template_version:typeof current?.template_version==="number"&&Number.isInteger(current.template_version)&&current.template_version>0?current.template_version:AGENT_GUIDANCE_TEMPLATE_VERSION,last_checked_files:Array.isArray(current?.last_checked_files)?[...new Set(current.last_checked_files.map(value=>value.trim()).filter(value=>value.length>0))].sort((left,right)=>left.localeCompare(right)):[]}}async function scanGuidanceFiles(projectRoot){const scans=[];const testCommand=await resolveProjectTestCommand(projectRoot);for(const filename of AGENT_GUIDANCE_TARGET_FILENAMES){const filePath=path.join(projectRoot,filename);const exists=await pathExists(filePath);if(!exists){scans.push({file_path:filePath,exists,has_guidance:false,has_marker:false});continue}const content=await fs.readFile(filePath,"utf8");const contentLower=content.toLowerCase();const tokenHits=AGENT_GUIDANCE_REQUIRED_TOKENS.filter(token=>contentLower.includes(token));const hasMarker=hasGuidanceMarker(content);scans.push({file_path:filePath,exists,has_guidance:hasMarker||tokenHits.length>=AGENT_GUIDANCE_REQUIRED_TOKEN_THRESHOLD,has_marker:hasMarker,outdated:hasMarker&&upsertAgentGuidanceBlock(content,testCommand).changed})}return scans}function pushUnique(target,value){if(!target.includes(value)){target.push(value)}}function applyAgentGuidanceState(settings,currentState){const existing=normalizeAgentGuidanceState(settings);const changed=JSON.stringify(existing)!==JSON.stringify(currentState);if(changed){settings.agent_guidance=currentState}return{changed,state:currentState}}async function writeGuidanceFile(filePath,projectRoot=path.dirname(filePath)){const exists=await pathExists(filePath);const currentContent=exists?await fs.readFile(filePath,"utf8"):"";const nextContent=upsertAgentGuidanceBlock(currentContent,await resolveProjectTestCommand(projectRoot));if(!nextContent.changed){return{changed:false,warnings:[]}}await writeFileAtomic(filePath,nextContent.next_content);return{changed:true,warnings:await runActiveOnWriteHooks({path:filePath,scope:"project",op:"init:agent_guidance_file"})}}function buildInitAgentGuidanceSummary(params){return{mode:params.mode,present:params.scans.some(entry=>entry.has_guidance),prompted:params.prompted,applied:params.applied,skipped:params.skipped,declined:params.state.declined,prompt_completed:params.state.prompt_completed,template_version:params.state.template_version,target_file:params.targetRelativePath,checked_files:params.scans.map(entry=>toPortableRelativePath(params.projectRoot,entry.file_path)),files_with_guidance:params.scans.filter(entry=>entry.has_guidance).map(entry=>toPortableRelativePath(params.projectRoot,entry.file_path)),missing_files:params.scans.filter(entry=>!entry.exists).map(entry=>toPortableRelativePath(params.projectRoot,entry.file_path))}}async function refreshGuidanceScansAfterApply(applied,scans,projectRoot){return applied?await scanGuidanceFiles(projectRoot):scans}function markAgentGuidanceRunState(flow,checkedFiles,partial){flow.state={...flow.state,...partial,template_version:AGENT_GUIDANCE_TEMPLATE_VERSION,last_checked_files:checkedFiles}}async function addAgentGuidanceBlockIfMissing(flow,context){if(context.presentBefore){return}const writeResult=await writeGuidanceFile(context.targetPath,context.projectRoot);flow.warnings.push(...writeResult.warnings);if(writeResult.changed){flow.applied=true;flow.warnings.push(`agent_guidance:added:${context.targetRelativePath}`)}}function handleAgentGuidanceStatusMode(flow,presentBefore){if(!presentBefore){flow.warnings.push("agent_guidance:missing");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}}function handleAgentGuidanceSkipMode(flow,checkedFiles){flow.skipped=true;markAgentGuidanceRunState(flow,checkedFiles,{prompt_completed:true,declined:true,declined_at:flow.state.declined_at||new Date().toISOString()});flow.warnings.push("agent_guidance:explicit_skip");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}async function handleAgentGuidanceAddMode(flow,context){await addAgentGuidanceBlockIfMissing(flow,context);markAgentGuidanceRunState(flow,context.checkedFiles,{prompt_completed:true,declined:false,declined_at:""})}function handlePresentAgentGuidance(flow,checkedFiles){if(flow.state.declined){markAgentGuidanceRunState(flow,checkedFiles,{prompt_completed:true,declined:false,declined_at:""})}}function handleDeclinedAgentGuidance(flow){flow.skipped=true;flow.warnings.push("agent_guidance:skipped_declined");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}async function handleInteractiveAgentGuidancePrompt(flow,context){flow.prompted=true;const approved=await promptForGuidanceWrite(context.targetRelativePath);if(approved){await addAgentGuidanceBlockIfMissing(flow,context);markAgentGuidanceRunState(flow,context.checkedFiles,{prompt_completed:true,declined:false,declined_at:""});return}flow.skipped=true;markAgentGuidanceRunState(flow,context.checkedFiles,{prompt_completed:true,declined:true,declined_at:new Date().toISOString()});flow.warnings.push("agent_guidance:declined");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}function handleNonInteractiveMissingAgentGuidance(flow){flow.warnings.push("agent_guidance:missing_non_interactive");pushUnique(flow.nextSteps,AGENT_GUIDANCE_ADD_LATER_HINT)}async function applyAgentGuidanceMode(initialState,context){const flow={warnings:[],nextSteps:[],prompted:false,applied:false,skipped:false,state:initialState};if(context.mode==="status"){handleAgentGuidanceStatusMode(flow,context.presentBefore);return flow}if(context.mode==="skip"){handleAgentGuidanceSkipMode(flow,context.checkedFiles);return flow}if(context.mode==="add"){await handleAgentGuidanceAddMode(flow,context);return flow}if(context.presentBefore){handlePresentAgentGuidance(flow,context.checkedFiles);return flow}if(flow.state.prompt_completed&&flow.state.declined){handleDeclinedAgentGuidance(flow);return flow}if(context.interactive){await handleInteractiveAgentGuidancePrompt(flow,context);return flow}handleNonInteractiveMissingAgentGuidance(flow);return flow}async function runInitAgentGuidance(options){const projectRoot=resolveProjectRoot(options.pm_root,options.cwd);let scans=await scanGuidanceFiles(projectRoot);const targetPath=resolveTargetGuidancePath(scans,projectRoot);const targetRelativePath=toPortableRelativePath(projectRoot,targetPath);const checkedFiles=scans.map(entry=>toPortableRelativePath(projectRoot,entry.file_path));const presentBefore=scans.some(entry=>entry.has_guidance);const flow=await applyAgentGuidanceMode(normalizeAgentGuidanceState(options.settings),{mode:options.mode,interactive:options.interactive,targetPath,targetRelativePath,checkedFiles,presentBefore,projectRoot});if(options.mode==="add"){for(const scan of scans.filter(entry=>entry.outdated)){const refreshed=await writeGuidanceFile(scan.file_path,projectRoot);flow.applied||=refreshed.changed;flow.warnings.push(...refreshed.warnings)}}const stateUpdate=applyAgentGuidanceState(options.settings,flow.state);scans=await refreshGuidanceScansAfterApply(flow.applied,scans,projectRoot);const outdated=scans.filter(entry=>entry.outdated).map(entry=>toPortableRelativePath(projectRoot,entry.file_path));if(outdated.length>0){flow.warnings.push(`agent_guidance_outdated:${outdated.join(",")}`);pushUnique(flow.nextSteps,"pm init --agent-guidance add")}const summary=buildInitAgentGuidanceSummary({mode:options.mode,scans,projectRoot,targetRelativePath,prompted:flow.prompted,applied:flow.applied,skipped:flow.skipped,state:flow.state});return{summary,warnings:flow.warnings,next_steps:flow.nextSteps,settings_changed:stateUpdate.changed}}export{INIT_AGENT_GUIDANCE_MODE_VALUES,_testOnly,resolveProjectTestCommand,runInitAgentGuidance};
3
3
  //# sourceMappingURL=init-agent-guidance.js.map
@@ -1,5 +1,5 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6b9c865a-c932-5394-b068-6fcf0dce5d3a")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isFileMissingError}from"../../core/fs/fs-utils.js";import{access,readFile,realpath,writeFile}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";const execFileAsync=promisify(execFile);const PM_GITATTRIBUTES_START="# pm-cli:merge-drivers:start";const PM_GITATTRIBUTES_END="# pm-cli:merge-drivers:end";const PM_GITATTRIBUTES_V2_START="# pm-cli:merge-drivers:v2:start";const PM_GITATTRIBUTES_V2_END="# pm-cli:merge-drivers:v2:end";const MERGE_FENCE_LOCK_ID="merge-fence";function quoteMergeDriverArgument(value){return`'${value.replaceAll("'",`'"'"'`)}'`}async function resolveMergeDriverCliCommand(){const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);let executable=process.execPath;const runtimeIdentity=await realpath(process.execPath);for(const directory of(process.env.PATH??"").split(path.delimiter)){if(!path.isAbsolute(directory))continue;const candidate=path.join(directory,path.basename(process.execPath));try{await access(candidate,constants.X_OK);if(candidate!==runtimeIdentity&&await realpath(candidate)===runtimeIdentity){executable=candidate;break}}catch{}}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();const sourceWorkspaceRoot=options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim();const sourcePmRoot=options.environment.PM_SOURCE_PM_PATH?.trim();const sourcePolicy=resolveSourceContextWritePolicy(options.environment);const sourceCoordinatesAvailable=Boolean(sourceWorkspaceRoot&&sourcePmRoot);const 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:false,source_policy:sourcePolicy}}if(sourceContextSelected){return{pm_root:path.resolve(sourcePmRoot),workspace_start:path.resolve(sourceWorkspaceRoot),source_coordinates_available:true,source_context_selected:true,source_policy:sourcePolicy}}return{pm_root:sourceCoordinatesAvailable?resolvePmRoot(options.cwd,".agents/pm"):resolvePmRoot(options.cwd),workspace_start:options.cwd,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}async function findGitWorkspaceRoot(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--show-toplevel"],{cwd,encoding:"utf8",windowsHide:true,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 isPortableMergeDriverCommand(configured,expectedSuffix){const nodeArgument=readSingleQuotedArgument(configured,0);if(nodeArgument===null||configured[nodeArgument.nextOffset]!==" "){return false}const cliArgument=readSingleQuotedArgument(configured,nodeArgument.nextOffset+1);if(cliArgument===null||configured.slice(cliArgument.nextOffset)!==expectedSuffix||!/^node(?:\.exe)?$/iu.test(path.basename(nodeArgument.value))||path.basename(cliArgument.value)!=="cli.js"||path.basename(path.dirname(cliArgument.value))!=="dist"){return false}if(!await pathExists(nodeArgument.value)||!await pathExists(cliArgument.value)){return false}try{const packageRoot=path.dirname(path.dirname(cliArgument.value));const manifest=JSON.parse(await readFile(path.join(packageRoot,"package.json"),"utf8"));const pmBin=typeof manifest.bin==="object"&&manifest.bin!==null&&"pm"in manifest.bin?manifest.bin.pm:void 0;return manifest.name==="@unbrained/pm-cli"&&(manifest.bin==="dist/cli.js"||pmBin==="dist/cli.js")}catch{return false}}function buildMergeAttributePatterns(trackerRelativeRoot,typeFolders){const prefix=trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"";const 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`)}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`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);return patterns}function removeManagedBlock(content,startMarker,endMarker){const start=content.indexOf(startMarker);const end=content.indexOf(endMarker);return start>=0&&end>start?`${content.slice(0,start)}${content.slice(end+endMarker.length)}`:content.replace(startMarker,"").replace(endMarker,"")}async function reconcileGitattributesBlock(workspaceRoot,patterns,dryRun){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))){throw error}}const block=[PM_GITATTRIBUTES_V2_START,...patterns,PM_GITATTRIBUTES_V2_END].join("\n");const withoutManagedBlock=removeManagedBlock(removeManagedBlock(current,PM_GITATTRIBUTES_V2_START,PM_GITATTRIBUTES_V2_END),PM_GITATTRIBUTES_START,PM_GITATTRIBUTES_END);const prefix=withoutManagedBlock.trimEnd();const next=`${prefix.length>0?`${prefix}
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8f999825-ace7-55cd-b83c-8c6c4b94fd9f")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isFileMissingError}from"../../core/fs/fs-utils.js";import{access,readFile,realpath,writeFile}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}from"./worktree-config.js";import{discoverProjectRuntimeVersionPins}from"../environment/project-runtime-compatibility.js";const execFileAsync=promisify(execFile);const PM_GITATTRIBUTES_START="# pm-cli:merge-drivers:start";const PM_GITATTRIBUTES_END="# pm-cli:merge-drivers:end";const PM_GITATTRIBUTES_V2_START="# pm-cli:merge-drivers:v2:start";const PM_GITATTRIBUTES_V2_END="# pm-cli:merge-drivers:v2:end";const MERGE_FENCE_LOCK_ID="merge-fence";function quoteMergeDriverArgument(value){return`'${value.replaceAll("'",`'"'"'`)}'`}async function resolveMergeDriverCliCommand(){const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);let executable=process.execPath;const runtimeIdentity=await realpath(process.execPath);for(const directory of(process.env.PATH??"").split(path.delimiter)){if(!path.isAbsolute(directory))continue;const candidate=path.join(directory,path.basename(process.execPath));try{await access(candidate,constants.X_OK);if(candidate!==runtimeIdentity&&await realpath(candidate)===runtimeIdentity){executable=candidate;break}}catch{}}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();const sourceWorkspaceRoot=options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim();const sourcePmRoot=options.environment.PM_SOURCE_PM_PATH?.trim();const sourcePolicy=resolveSourceContextWritePolicy(options.environment);const sourceCoordinatesAvailable=Boolean(sourceWorkspaceRoot&&sourcePmRoot);const 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:false,source_policy:sourcePolicy}}if(sourceContextSelected){return{pm_root:path.resolve(sourcePmRoot),workspace_start:path.resolve(sourceWorkspaceRoot),source_coordinates_available:true,source_context_selected:true,source_policy:sourcePolicy}}return{pm_root:sourceCoordinatesAvailable?resolvePmRoot(options.cwd,".agents/pm"):resolvePmRoot(options.cwd),workspace_start:options.cwd,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}async function findGitWorkspaceRoot(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--show-toplevel"],{cwd,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,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){const exactPins=discoverProjectRuntimeVersionPins(workspaceRoot).filter(pin=>pin.constraint==="exact");if(exactPins.some(pin=>pin.version!==version))return false;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 false}return true}async function isPortableMergeDriverCommand(configured,expectedSuffix,workspaceRoot){const nodeArgument=readSingleQuotedArgument(configured,0);if(nodeArgument===null||configured[nodeArgument.nextOffset]!==" "){return false}const cliArgument=readSingleQuotedArgument(configured,nodeArgument.nextOffset+1);if(cliArgument===null||configured.slice(cliArgument.nextOffset)!==expectedSuffix||!/^node(?:\.exe)?$/iu.test(path.basename(nodeArgument.value))||path.basename(cliArgument.value)!=="cli.js"||path.basename(path.dirname(cliArgument.value))!=="dist"){return false}if(!await pathExists(nodeArgument.value)||!await pathExists(cliArgument.value)){return false}try{const packageRoot=path.dirname(path.dirname(cliArgument.value));const manifest=JSON.parse(await readFile(path.join(packageRoot,"package.json"),"utf8"));const pmBin=typeof manifest.bin==="string"?manifest.bin:manifest.bin?.pm;if(!await isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,manifest.version))return false;return manifest.name==="@unbrained/pm-cli"&&pmBin==="dist/cli.js"}catch{return false}}function buildMergeAttributePatterns(trackerRelativeRoot,typeFolders){const prefix=trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"";const 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`)}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`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);return patterns}function removeManagedBlock(content,startMarker,endMarker){const start=content.indexOf(startMarker);const end=content.indexOf(endMarker);return start>=0&&end>start?`${content.slice(0,start)}${content.slice(end+endMarker.length)}`:content.replace(startMarker,"").replace(endMarker,"")}async function reconcileGitattributesBlock(workspaceRoot,patterns,dryRun){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))){throw error}}const block=[PM_GITATTRIBUTES_V2_START,...patterns,PM_GITATTRIBUTES_V2_END].join("\n");const withoutManagedBlock=removeManagedBlock(removeManagedBlock(current,PM_GITATTRIBUTES_V2_START,PM_GITATTRIBUTES_V2_END),PM_GITATTRIBUTES_START,PM_GITATTRIBUTES_END);const prefix=withoutManagedBlock.trimEnd();const next=`${prefix.length>0?`${prefix}
2
2
 
3
3
  `:""}${block}
4
- `;if(next===current){return{path:gitattributesPath,changed:false}}if(!dryRun){await writeFile(gitattributesPath,next,"utf8")}return{path:gitattributesPath,changed:true}}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;let fenceContent="";let 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");const usesV2=fenceContent.includes(PM_GITATTRIBUTES_V2_START);const startMarker=usesV2?PM_GITATTRIBUTES_V2_START:PM_GITATTRIBUTES_START;const endMarker=usesV2?PM_GITATTRIBUTES_V2_END:PM_GITATTRIBUTES_END;const start=fenceContent.indexOf(startMarker);const end=fenceContent.indexOf(endMarker);const committed=end>start?fenceContent.slice(start+startMarker.length,end).split("\n").map(line=>line.trim()).filter(line=>line.length>0):[];const expected=buildMergeAttributePatterns(toPosixRelative(fenceDirectory,resolvedRoot),typeFolders);const committedSet=new Set(committed);const expectedSet=new Set(expected);const missing=expected.filter(line=>!committedSet.has(line));const stale=committed.filter(line=>!expectedSet.has(line));return{status:missing.length>0||stale.length>0?"drift":"ok",path:fencePath,missing_patterns:missing,stale_patterns:stale,schema_scope:"project"}}async function auditMergeDriverConfiguration(workspaceRoot){const cliCommand=await resolveMergeDriverCliCommand();const missingKeys=[];const driftedKeys=[];for(const definition of MERGE_DRIVER_DEFINITIONS){const key=`merge.${definition.key}.driver`;const expectedSuffix=` merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`;const expected=`${cliCommand}${expectedSuffix}`;try{const{stdout}=await execFileAsync("git",["config","--local","--get",key],{cwd:workspaceRoot,encoding:"utf8",windowsHide:true,timeout:1e4});const configured=stdout.trim();if(configured!==expected&&!await isPortableMergeDriverCommand(configured,expectedSuffix)){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));const lockSettings=await readSettings(pmRoot);const owner=resolveAuthor(void 0,lockSettings.author_default);const releaseLock=await acquireLock(pmRoot,MERGE_FENCE_LOCK_ID,lockSettings.locks.ttl_seconds,owner,false,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);const typeFolders=resolveProjectMergeTypeFolders(settings);const outcome=await reconcileGitattributesBlock(workspaceRoot,buildMergeAttributePatterns(trackerRelativeRoot,typeFolders),false);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===true,environment:process.env});const pmRoot=context.pm_root;await assertInitializedTracker(pmRoot);const workspaceRoot=await resolveGitWorkspaceRoot(context.workspace_start);return installMergeFence({pmRoot,workspaceRoot,dryRun:options.dryRun===true})}async function installMergeFence(options){const pmRoot=path.resolve(options.pmRoot);const workspaceRoot=path.resolve(options.workspaceRoot);const dryRun=options.dryRun===true;let canonicalPmRoot;let canonicalWorkspaceRoot;try{[canonicalPmRoot,canonicalWorkspaceRoot]=await Promise.all([realpath(pmRoot),realpath(workspaceRoot)])}catch(error){throw new PmCliError(`Cannot resolve tracker root ${pmRoot} or workspace root ${workspaceRoot}: ${String(error)}`,EXIT_CODE.NOT_FOUND,{code:"merge_root_not_found",nextSteps:["Initialize the tracker and ensure both paths are accessible.",'Retry "pm merge install" from the repository workspace.']})}const trackerRelativeRoot=toPosixRelative(canonicalWorkspaceRoot,canonicalPmRoot);if(isPathOutsideRoot(trackerRelativeRoot)){throw new PmCliError(`Tracker root ${pmRoot} is outside the git repository ${workspaceRoot}; there is nothing to configure for this repository.`,EXIT_CODE.USAGE)}const settings=await readSettings(canonicalPmRoot);const typeFolders=resolveProjectMergeTypeFolders(settings);const patterns=buildMergeAttributePatterns(trackerRelativeRoot,typeFolders);const gitConfigEntries=[];const cliCommand=await resolveMergeDriverCliCommand();for(const definition of MERGE_DRIVER_DEFINITIONS){gitConfigEntries.push({key:`merge.${definition.key}.name`,value:definition.name});gitConfigEntries.push({key:`merge.${definition.key}.driver`,value:`${cliCommand} merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`})}if(!dryRun){try{for(const entry of gitConfigEntries){await execFileAsync("git",["config","--local",entry.key,entry.value],{cwd:canonicalWorkspaceRoot,encoding:"utf8",windowsHide:true,timeout:1e4})}}catch{throw new PmCliError(`Cannot install repository-local merge drivers in ${canonicalWorkspaceRoot}. Ensure the repository Git config is writable and no other Git process holds its lock, then retry.`,EXIT_CODE.DEPENDENCY_FAILED,{code:"merge_git_config_unwritable",why:"pm merge install must persist clone-local driver commands before publishing their shared .gitattributes mappings.",nextSteps:["Make the repository Git config writable or wait for the process holding its lock to finish.",'Retry "pm merge install"; the operation is idempotent.','Use "pm merge install --dry-run --json" when the workspace is intentionally read-only.']})}}const gitattributes=await reconcileGitattributesBlock(canonicalWorkspaceRoot,patterns,dryRun);return{ok:true,dry_run:dryRun,workspace_root:canonicalWorkspaceRoot,pm_root:canonicalPmRoot,gitattributes:{path:gitattributes.path,changed:gitattributes.changed,patterns,schema_scope:"project"},git_config:gitConfigEntries,guidance:["Commit .gitattributes so every branch and collaborator shares the merge mapping.",'git config is per-clone: each collaborator (and each fresh worktree/clone) runs "pm merge install" once.','After merging branches, run "pm merge reconcile --dry-run" to inspect the complete receipt and history repair, then apply "pm merge reconcile"; use --force only after explicitly accepting any discarded values.',"Custom item types registered later refresh this fence automatically (pm schema add-type/remove-type); rerun pm merge install only after out-of-band type-folder edits."],generated_at:nowIso()}}export{PM_GITATTRIBUTES_END,PM_GITATTRIBUTES_START,PM_GITATTRIBUTES_V2_END,PM_GITATTRIBUTES_V2_START,auditMergeAttributeFence,auditMergeDriverConfiguration,buildMergeAttributePatterns,findGitWorkspaceRoot,installMergeFence,refreshMergeAttributeFenceIfInstalled,resolveMergeInstallContext,resolveProjectMergeTypeFolders,runMergeInstall};
4
+ `;if(next===current){return{path:gitattributesPath,changed:false}}if(!dryRun){await writeFile(gitattributesPath,next,"utf8")}return{path:gitattributesPath,changed:true}}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;let fenceContent="";let 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");const usesV2=fenceContent.includes(PM_GITATTRIBUTES_V2_START);const startMarker=usesV2?PM_GITATTRIBUTES_V2_START:PM_GITATTRIBUTES_START;const endMarker=usesV2?PM_GITATTRIBUTES_V2_END:PM_GITATTRIBUTES_END;const start=fenceContent.indexOf(startMarker);const end=fenceContent.indexOf(endMarker);const committed=end>start?fenceContent.slice(start+startMarker.length,end).split("\n").map(line=>line.trim()).filter(line=>line.length>0):[];const expected=buildMergeAttributePatterns(toPosixRelative(fenceDirectory,resolvedRoot),typeFolders);const committedSet=new Set(committed);const expectedSet=new Set(expected);const missing=expected.filter(line=>!committedSet.has(line));const stale=committed.filter(line=>!expectedSet.has(line));return{status: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=[];const driftedKeys=[];for(const definition of MERGE_DRIVER_DEFINITIONS){const key=`merge.${definition.key}.driver`;const 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:true,timeout:1e4});const configured=stdout.trim();if(!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));const lockSettings=await readSettings(pmRoot);const owner=resolveAuthor(void 0,lockSettings.author_default);const releaseLock=await acquireLock(pmRoot,MERGE_FENCE_LOCK_ID,lockSettings.locks.ttl_seconds,owner,false,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);const typeFolders=resolveProjectMergeTypeFolders(settings);const outcome=await reconcileGitattributesBlock(workspaceRoot,buildMergeAttributePatterns(trackerRelativeRoot,typeFolders),false);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===true,environment:process.env});const pmRoot=context.pm_root;await assertInitializedTracker(pmRoot);const workspaceRoot=await resolveGitWorkspaceRoot(context.workspace_start);return installMergeFence({pmRoot,workspaceRoot,dryRun:options.dryRun===true})}async function installMergeFence(options){const pmRoot=path.resolve(options.pmRoot);const workspaceRoot=path.resolve(options.workspaceRoot);const dryRun=options.dryRun===true;let canonicalPmRoot;let canonicalWorkspaceRoot;try{[canonicalPmRoot,canonicalWorkspaceRoot]=await Promise.all([realpath(pmRoot),realpath(workspaceRoot)])}catch(error){throw new PmCliError(`Cannot resolve tracker root ${pmRoot} or workspace root ${workspaceRoot}: ${String(error)}`,EXIT_CODE.NOT_FOUND,{code:"merge_root_not_found",nextSteps:["Initialize the tracker and ensure both paths are accessible.",'Retry "pm merge install" from the repository workspace.']})}const trackerRelativeRoot=toPosixRelative(canonicalWorkspaceRoot,canonicalPmRoot);if(isPathOutsideRoot(trackerRelativeRoot)){throw new PmCliError(`Tracker root ${pmRoot} is outside the git repository ${workspaceRoot}; there is nothing to configure for this repository.`,EXIT_CODE.USAGE)}const settings=await readSettings(canonicalPmRoot);const typeFolders=resolveProjectMergeTypeFolders(settings);const patterns=buildMergeAttributePatterns(trackerRelativeRoot,typeFolders);const gitConfigEntries=[];const cliCommand=await resolveMergeDriverCliCommand();for(const definition of MERGE_DRIVER_DEFINITIONS){gitConfigEntries.push({key:`merge.${definition.key}.name`,value:definition.name});gitConfigEntries.push({key:`merge.${definition.key}.driver`,value:`${cliCommand} merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`})}if(!dryRun){try{const configScope=await resolveMergeDriverConfigScope(canonicalWorkspaceRoot);for(const entry of gitConfigEntries){await execFileAsync("git",["config",configScope,entry.key,entry.value],{cwd:canonicalWorkspaceRoot,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,timeout:1e4})}}catch{throw new PmCliError(`Cannot install repository-local merge drivers in ${canonicalWorkspaceRoot}. Ensure the repository Git config is writable and no other Git process holds its lock, then retry.`,EXIT_CODE.DEPENDENCY_FAILED,{code:"merge_git_config_unwritable",why:"pm merge install must persist clone-local driver commands before publishing their shared .gitattributes mappings.",nextSteps:["Make the repository Git config writable or wait for the process holding its lock to finish.",'Retry "pm merge install"; the operation is idempotent.','Use "pm merge install --dry-run --json" when the workspace is intentionally read-only.']})}}const gitattributes=await reconcileGitattributesBlock(canonicalWorkspaceRoot,patterns,dryRun);return{ok:true,dry_run:dryRun,workspace_root:canonicalWorkspaceRoot,pm_root:canonicalPmRoot,gitattributes:{path:gitattributes.path,changed:gitattributes.changed,patterns,schema_scope:"project"},git_config:gitConfigEntries,guidance:["Commit .gitattributes so every branch and collaborator shares the merge mapping.",'git config is per-clone: each collaborator (and each fresh worktree/clone) runs "pm merge install" once.','After merging branches, run "pm merge reconcile --dry-run" to inspect the complete receipt and history repair, then apply "pm merge reconcile"; use --force only after explicitly accepting any discarded values.',"Custom item types registered later refresh this fence automatically (pm schema add-type/remove-type); rerun pm merge install only after out-of-band type-folder edits."],generated_at:nowIso()}}export{PM_GITATTRIBUTES_END,PM_GITATTRIBUTES_START,PM_GITATTRIBUTES_V2_END,PM_GITATTRIBUTES_V2_START,auditMergeAttributeFence,auditMergeDriverConfiguration,buildMergeAttributePatterns,findGitWorkspaceRoot,installMergeFence,refreshMergeAttributeFenceIfInstalled,resolveMergeInstallContext,resolveProjectMergeTypeFolders,runMergeInstall};
5
5
  //# sourceMappingURL=install.js.map
@@ -0,0 +1,9 @@
1
+ /** Preserve caller tools and preferences while binding Git repository discovery and writes to the explicit cwd. */
2
+ export declare function gitWorkspaceEnvironment(): NodeJS.ProcessEnv;
3
+ /**
4
+ * Keep simple clones on local config. Linked worktrees opt into Git's native
5
+ * per-worktree layer, first preserving the main worktree's special core keys.
6
+ * Drivers already installed in the main tree are copied into its layer so
7
+ * later installations cannot replace the main tree's runtime selection.
8
+ */
9
+ export declare function resolveMergeDriverConfigScope(workspaceRoot: string): Promise<"--local" | "--worktree">;