@unbrained/pm-cli 2026.9.13 → 2026.9.15

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 (97) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +34 -0
  3. package/dist/cli/commander-usage.js +2 -2
  4. package/dist/cli/error-guidance.js +1 -1
  5. package/dist/cli/extension-command-help.d.ts +2 -2
  6. package/dist/cli/extension-command-help.js +2 -2
  7. package/dist/cli-bundle/bundle-manifest.json +144 -144
  8. package/dist/cli-bundle/chunks/{chunk-KM4XVZR7.js → chunk-3AHONKLL.js} +2 -2
  9. package/dist/cli-bundle/chunks/{chunk-ZZI7IHMM.js → chunk-3RB6Z7XE.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-GQQR6JAL.js → chunk-5P5PYCZX.js} +2 -2
  11. package/dist/cli-bundle/chunks/{chunk-XM7RWQLM.js → chunk-BOZ4HVYL.js} +2 -2
  12. package/dist/cli-bundle/chunks/chunk-J4DRE3WN.js +237 -0
  13. package/dist/cli-bundle/chunks/{chunk-LA44JECQ.js → chunk-RKPUO75B.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-XEZOGC3P.js → chunk-RM2OGG65.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-YQTJACN5.js → chunk-UKLOSZV6.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-GBK5MV6N.js → chunk-WDF7PP4P.js} +26 -26
  17. package/dist/cli-bundle/chunks/chunk-WLJJ4MAU.js +2 -0
  18. package/dist/cli-bundle/chunks/{chunk-YDSV4QIQ.js → chunk-Y2P3DSSO.js} +2 -2
  19. package/dist/cli-bundle/chunks/{chunk-3DWX3CKN.js → chunk-YMMLKKEP.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-list-query-WMJTBWNW.js → register-list-query-IWSPNFFD.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-mutation-EXGOXP3D.js → register-mutation-3DVF4R64.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-operations-2H4CDRGU.js → register-operations-LXP3MECQ.js} +2 -2
  23. package/dist/cli-bundle/chunks/{register-setup-NYBWGPOS.js → register-setup-KFQSNBDX.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/chunk-4YTDKIPF.js +30 -0
  25. package/dist/cli-bundle/focused-chunks/{chunk-LQ67C7ZO.js → chunk-533DCWPY.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/{chunk-B6JAANOH.js → chunk-5SBU4QDC.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/{chunk-SDQCJF4H.js → chunk-63YRRGKX.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-KP3N6PVZ.js → chunk-6C3CUU2G.js} +3 -3
  29. package/dist/cli-bundle/focused-chunks/{chunk-TUHRUFID.js → chunk-AXDAIBT3.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-FBCLVOBE.js → chunk-BMATJLPT.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/{chunk-DSJYL4VP.js → chunk-JKJYXCT6.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-V7PSTKHD.js → chunk-MD7ADLME.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-OENAWWP4.js → chunk-OGGF2RBL.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-FPNI4U2B.js → chunk-PBJC2ZNA.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/chunk-SHF57M2H.js +2 -0
  36. package/dist/cli-bundle/focused-chunks/{chunk-F66QJWI4.js → chunk-UACMCSCC.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-XCCM7P7V.js → chunk-YBQTVE5S.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-ZAMG7HBB.js → chunk-ZHX3433X.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-ZOE2NSJB.js +20 -0
  40. package/dist/cli-bundle/main.js +19 -19
  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 +24 -24
  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 +40 -40
  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 +8 -8
  51. package/dist/core/extensions/index.d.ts +7 -0
  52. package/dist/core/extensions/index.js +1 -1
  53. package/dist/core/lock/lock.js +2 -2
  54. package/dist/core/output/output.js +3 -3
  55. package/dist/core/telemetry/policy.d.ts +2 -0
  56. package/dist/core/telemetry/policy.js +1 -1
  57. package/dist/core/telemetry/read-sampling.d.ts +8 -0
  58. package/dist/core/telemetry/read-sampling.js +3 -0
  59. package/dist/core/telemetry/runtime.d.ts +35 -8
  60. package/dist/core/telemetry/runtime.js +5 -4
  61. package/dist/sdk/agent/command-suggestions.d.ts +6 -0
  62. package/dist/sdk/agent/command-suggestions.js +1 -1
  63. package/dist/sdk/cli-contracts/command-aliases.js +1 -1
  64. package/dist/sdk/cli-contracts/grammar-contracts.d.ts +2 -2
  65. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
  66. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +7 -3
  67. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
  68. package/dist/sdk/public-surface.json +1 -1
  69. package/dist/sdk/telemetry.js +1 -1
  70. package/docs/AGENT_UX_CONTRACTS.md +10 -2
  71. package/docs/CLI_GRAMMAR.md +28 -0
  72. package/docs/CONFIGURATION.md +41 -3
  73. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +1 -1
  74. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -0
  75. package/docs/generated/FLAG_LEXICON_BUDGETS.md +1 -0
  76. package/marketplace.json +2 -2
  77. package/package.json +5 -5
  78. package/packages/pm-beads/package.json +1 -1
  79. package/packages/pm-calendar/package.json +1 -1
  80. package/packages/pm-command-kit/package.json +1 -1
  81. package/packages/pm-digital-twin/package.json +1 -1
  82. package/packages/pm-governance-audit/package.json +1 -1
  83. package/packages/pm-guide-shell/package.json +1 -1
  84. package/packages/pm-kanban/package.json +1 -1
  85. package/packages/pm-lifecycle-hooks/package.json +1 -1
  86. package/packages/pm-linked-test-adapters/package.json +1 -1
  87. package/packages/pm-search-advanced/package.json +1 -1
  88. package/packages/pm-templates/package.json +1 -1
  89. package/packages/pm-todos/package.json +1 -1
  90. package/packages/pm-vcs/package.json +1 -1
  91. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  92. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  93. package/dist/cli-bundle/chunks/chunk-6KHYW3FH.js +0 -235
  94. package/dist/cli-bundle/chunks/chunk-AKTBOX6U.js +0 -2
  95. package/dist/cli-bundle/focused-chunks/chunk-7JR6M2JR.js +0 -30
  96. package/dist/cli-bundle/focused-chunks/chunk-YUXBHIUV.js +0 -20
  97. package/dist/cli-bundle/focused-chunks/chunk-ZF5PXK6A.js +0 -2
@@ -38,6 +38,13 @@ export declare function resetActiveExtensionRuntimeState(): void;
38
38
  export declare function setActiveCommandContext(context: Omit<CommandOverrideContext, "result"> | null): void;
39
39
  /** Return a defensive snapshot of the current invocation's command context. */
40
40
  export declare function getActiveCommandContext(): Omit<CommandOverrideContext, "result"> | null;
41
+ /**
42
+ * Prove that the active command has no extension execution surface. Unrelated
43
+ * command registrations are harmless; hooks, services, renderers, migrations,
44
+ * and matching handlers/parsers make ownership uncertain and fail closed.
45
+ * Snapshot this predicate before entering an isolated infrastructure context.
46
+ */
47
+ export declare function isActiveCommandUnextended(command: string): boolean;
41
48
  /** Implements set active command result for the public runtime surface of this module. */
42
49
  export declare function setActiveCommandResult(result: unknown): void;
43
50
  /** Implements get active command result for the public runtime surface of this module. */
@@ -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]="0989270e-6969-5059-b3df-06411211f701")}catch(e2){}})();import{existsSync}from"node:fs";import{AsyncLocalStorage}from"node:async_hooks";import path from"node:path";import{runCommandHandler,runBeforeMutationHooks,runCommandOverride,runOnIndexHooks,runParserOverride,runPreflightOverride,runOnReadHooks,runRendererOverride,runServiceOverride,runServiceOverrideSync,runOnWriteHooks}from"./loader.js";let activeExtensionHooks=null;let activeExtensionCommands=null;let activeExtensionParsers=null;let activeExtensionPreflight=null;let activeExtensionServices=null;let activeExtensionRenderers=null;let activeExtensionRegistrations=null;let activeCommandContext=null;let activeCommandResult=void 0;let activeAfterCommandAffectedItems=[];const isolatedExtensionRuntime=new AsyncLocalStorage;function runtimeState(){return isolatedExtensionRuntime.getStore()}function runWithIsolatedExtensionRuntime(run){return isolatedExtensionRuntime.run({hooks:null,commands:null,parsers:null,preflight:null,services:null,renderers:null,registrations:null,commandContext:null,commandResult:void 0,affectedItems:[]},run)}const AFTER_COMMAND_SNAPSHOT_OMITTED_FIELDS=new Set(["body","comments","dependencies","docs","events","files","learnings","notes","reminders","test_runs","tests"]);function findSourceRepositoryRoot(candidate){let cursor=path.resolve(candidate);while(true){if(existsSync(path.join(cursor,".git"))){return cursor}const parent=path.dirname(cursor);if(parent===cursor){return void 0}cursor=parent}}function resolvePortableWorkspaceContext(pmRoot){const sourceCandidate=process.env.PM_SOURCE_WORKSPACE_ROOT?.trim()||process.cwd();const sourceWorkspaceRoot=findSourceRepositoryRoot(sourceCandidate)??path.resolve(sourceCandidate);const repoRoot=findSourceRepositoryRoot(sourceWorkspaceRoot);if(!pmRoot){return{source_workspace_root:sourceWorkspaceRoot,...repoRoot?{repo_root:repoRoot}:{}}}const relativePmRoot=path.relative(sourceWorkspaceRoot,path.resolve(pmRoot));const contained=relativePmRoot.length>0&&!relativePmRoot.startsWith(`..${path.sep}`)&&relativePmRoot!==".."&&!path.isAbsolute(relativePmRoot);return{source_workspace_root:sourceWorkspaceRoot,...repoRoot?{repo_root:repoRoot}:{},...contained?{pm_root_rel:relativePmRoot.split(path.sep).join("/")}:{}}}function setActiveExtensionHooks(hooks){const state=runtimeState();if(state){state.hooks=hooks;return}activeExtensionHooks=hooks}function setActiveExtensionCommands(commands){const state=runtimeState();if(state){state.commands=commands;return}activeExtensionCommands=commands}function setActiveExtensionParsers(parsers){const state=runtimeState();if(state){state.parsers=parsers;return}activeExtensionParsers=parsers}function setActiveExtensionPreflight(preflight){const state=runtimeState();if(state){state.preflight=preflight;return}activeExtensionPreflight=preflight}function setActiveExtensionServices(services){const state=runtimeState();if(state){state.services=services;return}activeExtensionServices=services}function setActiveExtensionRenderers(renderers){const state=runtimeState();if(state){state.renderers=renderers;return}activeExtensionRenderers=renderers}function setActiveExtensionRegistrations(registrations){const state=runtimeState();if(state){state.registrations=registrations;return}activeExtensionRegistrations=registrations}function getActiveExtensionRegistrations(){const state=runtimeState();return state?state.registrations:activeExtensionRegistrations}function resetActiveExtensionRuntimeState(){const state=runtimeState();if(state){state.hooks=null;state.commands=null;state.parsers=null;state.preflight=null;state.services=null;state.renderers=null;state.registrations=null;state.commandContext=null;state.commandResult=null;state.affectedItems=[];return}activeExtensionHooks=null;activeExtensionCommands=null;activeExtensionParsers=null;activeExtensionPreflight=null;activeExtensionServices=null;activeExtensionRenderers=null;activeExtensionRegistrations=null;activeCommandContext=null;activeCommandResult=null}function setActiveCommandContext(context){const resolved=context?{...context,...resolvePortableWorkspaceContext(context.pm_root)}:null;const state=runtimeState();if(state){state.commandContext=resolved;return}activeCommandContext=resolved}function getActiveCommandContext(){const state=runtimeState();const context=state?state.commandContext:activeCommandContext;return context?{...context,args:[...context.args],options:context.options?{...context.options}:{},global:context.global?{...context.global}:void 0}:null}function setActiveCommandResult(result){const state=runtimeState();if(state){state.commandResult=result;return}activeCommandResult=result}function getActiveCommandResult(){const state=runtimeState();return state?state.commandResult:activeCommandResult}function recordAfterCommandAffectedItem(item){if(!item){return}const state=runtimeState();if(state){state.affectedItems.push(item)}else{activeAfterCommandAffectedItems.push(item)}}function projectAfterCommandItemSnapshot(metadata,changedFields){if(!metadata||!metadata.id){return{}}const snapshot={id:metadata.id,type:metadata.type,status:metadata.status};if(!Array.isArray(changedFields)){return snapshot}const source=metadata;for(const field of changedFields){if(typeof field!=="string"){continue}const actualField=field.startsWith("unset:")?field.slice("unset:".length):field;if(actualField==="id"||actualField==="type"||actualField==="status"||AFTER_COMMAND_SNAPSHOT_OMITTED_FIELDS.has(actualField)){continue}if(Object.hasOwn(source,actualField)&&source[actualField]!==void 0){snapshot[actualField]=source[actualField]}}return snapshot}function consumeAfterCommandAffectedItems(){const state=runtimeState();const affectedItems=state?.affectedItems??activeAfterCommandAffectedItems;if(affectedItems.length===0){return void 0}const affected=affectedItems;if(state){state.affectedItems=[]}else{activeAfterCommandAffectedItems=[]}return affected}function clearActiveExtensionHooks(){const state=runtimeState();if(state){state.hooks=null;state.commands=null;state.parsers=null;state.preflight=null;state.services=null;state.renderers=null;state.registrations=null;state.commandContext=null;state.commandResult=void 0;state.affectedItems=[];return}activeExtensionHooks=null;activeExtensionCommands=null;activeExtensionParsers=null;activeExtensionPreflight=null;activeExtensionServices=null;activeExtensionRenderers=null;activeExtensionRegistrations=null;activeCommandContext=null;activeCommandResult=void 0;activeAfterCommandAffectedItems=[]}async function runActiveOnWriteHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks){return[]}return runOnWriteHooks(hooks,context)}async function runActiveBeforeMutationHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks)return;await runBeforeMutationHooks(hooks,context)}async function runActiveOnReadHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks){return[]}return runOnReadHooks(hooks,context)}function hasActiveOnReadHooks(){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;return(hooks?.onRead?.length??0)>0}async function runActiveOnIndexHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks){return[]}return runOnIndexHooks(hooks,context)}function runActiveCommandOverride(result){const state=runtimeState();const commands=state?state.commands:activeExtensionCommands;const commandContext=state?state.commandContext:activeCommandContext;if(!commands||!commandContext){return{overridden:false,result,warnings:[]}}return runCommandOverride(commands,{command:commandContext.command,args:[...commandContext.args],options:commandContext.options?{...commandContext.options}:{},global:commandContext.global?{...commandContext.global}:void 0,pm_root:commandContext.pm_root,source_workspace_root:commandContext.source_workspace_root,repo_root:commandContext.repo_root,pm_root_rel:commandContext.pm_root_rel,result})}async function runActiveCommandHandler(context){const state=runtimeState();const commands=state?state.commands:activeExtensionCommands;if(!commands){return{handled:false,result:null,warnings:[]}}return runCommandHandler(commands,{...context,...resolvePortableWorkspaceContext(context.pm_root)})}async function runActiveParserOverride(context){const state=runtimeState();const parsers=state?state.parsers:activeExtensionParsers;if(!parsers){return{overridden:false,context:{command:context.command,args:[...context.args],options:{...context.options},global:{...context.global},pm_root:context.pm_root},warnings:[]}}return runParserOverride(parsers,{...context,...resolvePortableWorkspaceContext(context.pm_root)})}async function runActivePreflightOverride(context){const state=runtimeState();const preflight=state?state.preflight:activeExtensionPreflight;if(!preflight){return{overridden:false,context:{command:context.command,args:[...context.args],options:{...context.options},global:{...context.global},pm_root:context.pm_root},decision:{...context.decision},warnings:[]}}return runPreflightOverride(preflight,{...context,...resolvePortableWorkspaceContext(context.pm_root)})}function runActiveRendererOverride(format,result){const state=runtimeState();const renderers=state?state.renderers:activeExtensionRenderers;const commandContext=state?state.commandContext:activeCommandContext;if(!renderers){return{overridden:false,rendered:null,warnings:[]}}return runRendererOverride(renderers,{format,command:commandContext?.command,args:commandContext?[...commandContext.args]:[],options:commandContext?.options?{...commandContext.options}:{},global:commandContext?.global?{...commandContext.global}:void 0,pm_root:commandContext?.pm_root,source_workspace_root:commandContext?.source_workspace_root,repo_root:commandContext?.repo_root,pm_root_rel:commandContext?.pm_root_rel,result})}function buildServiceContext(service,payload){const state=runtimeState();const commandContext=state?state.commandContext:activeCommandContext;return{service,command:commandContext?.command,args:commandContext?[...commandContext.args]:[],options:commandContext?.options?{...commandContext.options}:{},global:commandContext?.global?{...commandContext.global}:void 0,pm_root:commandContext?.pm_root,source_workspace_root:commandContext?.source_workspace_root,repo_root:commandContext?.repo_root,pm_root_rel:commandContext?.pm_root_rel,payload}}async function runActiveServiceOverride(service,payload){const state=runtimeState();const services=state?state.services:activeExtensionServices;if(!services){return{handled:false,result:payload,warnings:[]}}return runServiceOverride(services,buildServiceContext(service,payload))}function runActiveServiceOverrideSync(service,payload){const state=runtimeState();const services=state?state.services:activeExtensionServices;if(!services){return{handled:false,result:payload,warnings:[]}}return runServiceOverrideSync(services,buildServiceContext(service,payload))}export*from"./loader.js";export*from"./command-hook-context.js";import{createSerialQueue}from"../shared/serial-queue.js";import{EXTENSION_CAPABILITY_REGISTRATION_SURFACES,collectUsedExtensionCapabilities,reconcileExtensionCapabilityUsage}from"./capability-usage.js";export{EXTENSION_CAPABILITY_REGISTRATION_SURFACES,clearActiveExtensionHooks,collectUsedExtensionCapabilities,consumeAfterCommandAffectedItems,createSerialQueue,getActiveCommandContext,getActiveCommandResult,getActiveExtensionRegistrations,hasActiveOnReadHooks,projectAfterCommandItemSnapshot,reconcileExtensionCapabilityUsage,recordAfterCommandAffectedItem,resetActiveExtensionRuntimeState,resolvePortableWorkspaceContext,runActiveBeforeMutationHooks,runActiveCommandHandler,runActiveCommandOverride,runActiveOnIndexHooks,runActiveOnReadHooks,runActiveOnWriteHooks,runActiveParserOverride,runActivePreflightOverride,runActiveRendererOverride,runActiveServiceOverride,runActiveServiceOverrideSync,runWithIsolatedExtensionRuntime,setActiveCommandContext,setActiveCommandResult,setActiveExtensionCommands,setActiveExtensionHooks,setActiveExtensionParsers,setActiveExtensionPreflight,setActiveExtensionRegistrations,setActiveExtensionRenderers,setActiveExtensionServices};
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]="40b169fc-3c5f-5b2a-8fed-a9388b07d9f7")}catch(e2){}})();import{existsSync}from"node:fs";import{AsyncLocalStorage}from"node:async_hooks";import path from"node:path";import{runCommandHandler,runBeforeMutationHooks,runCommandOverride,runOnIndexHooks,runParserOverride,runPreflightOverride,runOnReadHooks,runRendererOverride,runServiceOverride,runServiceOverrideSync,runOnWriteHooks}from"./loader.js";let activeExtensionHooks=null;let activeExtensionCommands=null;let activeExtensionParsers=null;let activeExtensionPreflight=null;let activeExtensionServices=null;let activeExtensionRenderers=null;let activeExtensionRegistrations=null;let activeCommandContext=null;let activeCommandResult=void 0;let activeAfterCommandAffectedItems=[];const isolatedExtensionRuntime=new AsyncLocalStorage;function runtimeState(){return isolatedExtensionRuntime.getStore()}function runWithIsolatedExtensionRuntime(run){return isolatedExtensionRuntime.run({hooks:null,commands:null,parsers:null,preflight:null,services:null,renderers:null,registrations:null,commandContext:null,commandResult:void 0,affectedItems:[]},run)}const AFTER_COMMAND_SNAPSHOT_OMITTED_FIELDS=new Set(["body","comments","dependencies","docs","events","files","learnings","notes","reminders","test_runs","tests"]);function findSourceRepositoryRoot(candidate){let cursor=path.resolve(candidate);while(true){if(existsSync(path.join(cursor,".git"))){return cursor}const parent=path.dirname(cursor);if(parent===cursor){return void 0}cursor=parent}}function resolvePortableWorkspaceContext(pmRoot){const sourceCandidate=process.env.PM_SOURCE_WORKSPACE_ROOT?.trim()||process.cwd();const sourceWorkspaceRoot=findSourceRepositoryRoot(sourceCandidate)??path.resolve(sourceCandidate);const repoRoot=findSourceRepositoryRoot(sourceWorkspaceRoot);if(!pmRoot){return{source_workspace_root:sourceWorkspaceRoot,...repoRoot?{repo_root:repoRoot}:{}}}const relativePmRoot=path.relative(sourceWorkspaceRoot,path.resolve(pmRoot));const contained=relativePmRoot.length>0&&!relativePmRoot.startsWith(`..${path.sep}`)&&relativePmRoot!==".."&&!path.isAbsolute(relativePmRoot);return{source_workspace_root:sourceWorkspaceRoot,...repoRoot?{repo_root:repoRoot}:{},...contained?{pm_root_rel:relativePmRoot.split(path.sep).join("/")}:{}}}function setActiveExtensionHooks(hooks){const state=runtimeState();if(state){state.hooks=hooks;return}activeExtensionHooks=hooks}function setActiveExtensionCommands(commands){const state=runtimeState();if(state){state.commands=commands;return}activeExtensionCommands=commands}function setActiveExtensionParsers(parsers){const state=runtimeState();if(state){state.parsers=parsers;return}activeExtensionParsers=parsers}function setActiveExtensionPreflight(preflight){const state=runtimeState();if(state){state.preflight=preflight;return}activeExtensionPreflight=preflight}function setActiveExtensionServices(services){const state=runtimeState();if(state){state.services=services;return}activeExtensionServices=services}function setActiveExtensionRenderers(renderers){const state=runtimeState();if(state){state.renderers=renderers;return}activeExtensionRenderers=renderers}function setActiveExtensionRegistrations(registrations){const state=runtimeState();if(state){state.registrations=registrations;return}activeExtensionRegistrations=registrations}function getActiveExtensionRegistrations(){const state=runtimeState();return state?state.registrations:activeExtensionRegistrations}function resetActiveExtensionRuntimeState(){const state=runtimeState();if(state){state.hooks=null;state.commands=null;state.parsers=null;state.preflight=null;state.services=null;state.renderers=null;state.registrations=null;state.commandContext=null;state.commandResult=null;state.affectedItems=[];return}activeExtensionHooks=null;activeExtensionCommands=null;activeExtensionParsers=null;activeExtensionPreflight=null;activeExtensionServices=null;activeExtensionRenderers=null;activeExtensionRegistrations=null;activeCommandContext=null;activeCommandResult=null}function setActiveCommandContext(context){const resolved=context?{...context,...resolvePortableWorkspaceContext(context.pm_root)}:null;const state=runtimeState();if(state){state.commandContext=resolved;return}activeCommandContext=resolved}function getActiveCommandContext(){const state=runtimeState();const context=state?state.commandContext:activeCommandContext;return context?{...context,args:[...context.args],options:context.options?{...context.options}:{},global:context.global?{...context.global}:void 0}:null}function isActiveCommandUnextended(command){const state=runtimeState()??{commandContext:activeCommandContext,hooks:activeExtensionHooks,commands:activeExtensionCommands,parsers:activeExtensionParsers,preflight:activeExtensionPreflight,services:activeExtensionServices,renderers:activeExtensionRenderers,registrations:activeExtensionRegistrations};if(state.commandContext?.command!==command)return false;const broadInterceptors=[state.hooks,state.preflight,state.services,state.renderers];if(broadInterceptors.some(registry=>Object.values(registry??{}).some(entries=>entries.length>0)))return false;const commandInterceptors=[state.commands,state.parsers];if(commandInterceptors.some(registry=>Object.values(registry??{}).some(entries=>entries.some(entry=>entry.command===command))))return false;return!Object.entries(state.registrations??{}).some(([key,entries])=>["migrations","search_providers","vector_store_adapters","assurance_providers"].includes(key)&&entries.length>0)}function setActiveCommandResult(result){const state=runtimeState();if(state){state.commandResult=result;return}activeCommandResult=result}function getActiveCommandResult(){const state=runtimeState();return state?state.commandResult:activeCommandResult}function recordAfterCommandAffectedItem(item){if(!item){return}const state=runtimeState();if(state){state.affectedItems.push(item)}else{activeAfterCommandAffectedItems.push(item)}}function projectAfterCommandItemSnapshot(metadata,changedFields){if(!metadata||!metadata.id){return{}}const snapshot={id:metadata.id,type:metadata.type,status:metadata.status};if(!Array.isArray(changedFields)){return snapshot}const source=metadata;for(const field of changedFields){if(typeof field!=="string"){continue}const actualField=field.startsWith("unset:")?field.slice("unset:".length):field;if(actualField==="id"||actualField==="type"||actualField==="status"||AFTER_COMMAND_SNAPSHOT_OMITTED_FIELDS.has(actualField)){continue}if(Object.hasOwn(source,actualField)&&source[actualField]!==void 0){snapshot[actualField]=source[actualField]}}return snapshot}function consumeAfterCommandAffectedItems(){const state=runtimeState();const affectedItems=state?.affectedItems??activeAfterCommandAffectedItems;if(affectedItems.length===0){return void 0}const affected=affectedItems;if(state){state.affectedItems=[]}else{activeAfterCommandAffectedItems=[]}return affected}function clearActiveExtensionHooks(){const state=runtimeState();if(state){state.hooks=null;state.commands=null;state.parsers=null;state.preflight=null;state.services=null;state.renderers=null;state.registrations=null;state.commandContext=null;state.commandResult=void 0;state.affectedItems=[];return}activeExtensionHooks=null;activeExtensionCommands=null;activeExtensionParsers=null;activeExtensionPreflight=null;activeExtensionServices=null;activeExtensionRenderers=null;activeExtensionRegistrations=null;activeCommandContext=null;activeCommandResult=void 0;activeAfterCommandAffectedItems=[]}async function runActiveOnWriteHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks){return[]}return runOnWriteHooks(hooks,context)}async function runActiveBeforeMutationHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks)return;await runBeforeMutationHooks(hooks,context)}async function runActiveOnReadHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks){return[]}return runOnReadHooks(hooks,context)}function hasActiveOnReadHooks(){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;return(hooks?.onRead?.length??0)>0}async function runActiveOnIndexHooks(context){const state=runtimeState();const hooks=state?state.hooks:activeExtensionHooks;if(!hooks){return[]}return runOnIndexHooks(hooks,context)}function runActiveCommandOverride(result){const state=runtimeState();const commands=state?state.commands:activeExtensionCommands;const commandContext=state?state.commandContext:activeCommandContext;if(!commands||!commandContext){return{overridden:false,result,warnings:[]}}return runCommandOverride(commands,{command:commandContext.command,args:[...commandContext.args],options:commandContext.options?{...commandContext.options}:{},global:commandContext.global?{...commandContext.global}:void 0,pm_root:commandContext.pm_root,source_workspace_root:commandContext.source_workspace_root,repo_root:commandContext.repo_root,pm_root_rel:commandContext.pm_root_rel,result})}async function runActiveCommandHandler(context){const state=runtimeState();const commands=state?state.commands:activeExtensionCommands;if(!commands){return{handled:false,result:null,warnings:[]}}return runCommandHandler(commands,{...context,...resolvePortableWorkspaceContext(context.pm_root)})}async function runActiveParserOverride(context){const state=runtimeState();const parsers=state?state.parsers:activeExtensionParsers;if(!parsers){return{overridden:false,context:{command:context.command,args:[...context.args],options:{...context.options},global:{...context.global},pm_root:context.pm_root},warnings:[]}}return runParserOverride(parsers,{...context,...resolvePortableWorkspaceContext(context.pm_root)})}async function runActivePreflightOverride(context){const state=runtimeState();const preflight=state?state.preflight:activeExtensionPreflight;if(!preflight){return{overridden:false,context:{command:context.command,args:[...context.args],options:{...context.options},global:{...context.global},pm_root:context.pm_root},decision:{...context.decision},warnings:[]}}return runPreflightOverride(preflight,{...context,...resolvePortableWorkspaceContext(context.pm_root)})}function runActiveRendererOverride(format,result){const state=runtimeState();const renderers=state?state.renderers:activeExtensionRenderers;const commandContext=state?state.commandContext:activeCommandContext;if(!renderers){return{overridden:false,rendered:null,warnings:[]}}return runRendererOverride(renderers,{format,command:commandContext?.command,args:commandContext?[...commandContext.args]:[],options:commandContext?.options?{...commandContext.options}:{},global:commandContext?.global?{...commandContext.global}:void 0,pm_root:commandContext?.pm_root,source_workspace_root:commandContext?.source_workspace_root,repo_root:commandContext?.repo_root,pm_root_rel:commandContext?.pm_root_rel,result})}function buildServiceContext(service,payload){const state=runtimeState();const commandContext=state?state.commandContext:activeCommandContext;return{service,command:commandContext?.command,args:commandContext?[...commandContext.args]:[],options:commandContext?.options?{...commandContext.options}:{},global:commandContext?.global?{...commandContext.global}:void 0,pm_root:commandContext?.pm_root,source_workspace_root:commandContext?.source_workspace_root,repo_root:commandContext?.repo_root,pm_root_rel:commandContext?.pm_root_rel,payload}}async function runActiveServiceOverride(service,payload){const state=runtimeState();const services=state?state.services:activeExtensionServices;if(!services){return{handled:false,result:payload,warnings:[]}}return runServiceOverride(services,buildServiceContext(service,payload))}function runActiveServiceOverrideSync(service,payload){const state=runtimeState();const services=state?state.services:activeExtensionServices;if(!services){return{handled:false,result:payload,warnings:[]}}return runServiceOverrideSync(services,buildServiceContext(service,payload))}export*from"./loader.js";export*from"./command-hook-context.js";import{createSerialQueue}from"../shared/serial-queue.js";import{EXTENSION_CAPABILITY_REGISTRATION_SURFACES,collectUsedExtensionCapabilities,reconcileExtensionCapabilityUsage}from"./capability-usage.js";export{EXTENSION_CAPABILITY_REGISTRATION_SURFACES,clearActiveExtensionHooks,collectUsedExtensionCapabilities,consumeAfterCommandAffectedItems,createSerialQueue,getActiveCommandContext,getActiveCommandResult,getActiveExtensionRegistrations,hasActiveOnReadHooks,isActiveCommandUnextended,projectAfterCommandItemSnapshot,reconcileExtensionCapabilityUsage,recordAfterCommandAffectedItem,resetActiveExtensionRuntimeState,resolvePortableWorkspaceContext,runActiveBeforeMutationHooks,runActiveCommandHandler,runActiveCommandOverride,runActiveOnIndexHooks,runActiveOnReadHooks,runActiveOnWriteHooks,runActiveParserOverride,runActivePreflightOverride,runActiveRendererOverride,runActiveServiceOverride,runActiveServiceOverrideSync,runWithIsolatedExtensionRuntime,setActiveCommandContext,setActiveCommandResult,setActiveExtensionCommands,setActiveExtensionHooks,setActiveExtensionParsers,setActiveExtensionPreflight,setActiveExtensionRegistrations,setActiveExtensionRenderers,setActiveExtensionServices};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
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]="962659bb-37dc-52fa-9d07-6216d34c0d53")}catch(e2){}})();import{isFileMissingError}from"../fs/fs-utils.js";import{constants as fsConstants}from"node:fs";import fs from"node:fs/promises";import path from"node:path";import{randomUUID}from"node:crypto";import{runActiveOnReadHooks,runActiveOnWriteHooks,runActiveServiceOverride}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{toErrorMessage}from"../shared/primitives.js";import{getLockPath}from"../store/paths.js";import{nowIso}from"../shared/time.js";function parseLockInfo(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return{info:null,warnings:["lock_info_invalid_json"]}}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){return{info:null,warnings:["lock_info_invalid_shape"]}}const candidate=parsed;const id=candidate.id;const pid=candidate.pid;const owner=candidate.owner;const token=candidate.token;const createdAt=candidate.created_at;const ttlSeconds=candidate.ttl_seconds;if(typeof id!=="string"||typeof pid!=="number"||!Number.isFinite(pid)||typeof owner!=="string"||token!==void 0&&(typeof token!=="string"||token.trim().length===0)||typeof createdAt!=="string"||typeof ttlSeconds!=="number"||!Number.isFinite(ttlSeconds)){return{info:null,warnings:["lock_info_invalid_shape"]}}return{info:{id,pid,owner,...typeof token==="string"?{token}:{},created_at:createdAt,ttl_seconds:ttlSeconds},warnings:[]}}async function readLockInfo(lockPath,emitReadHook=true){try{const raw=await fs.readFile(lockPath,"utf8");if(emitReadHook){await runActiveOnReadHooks({path:lockPath,scope:"project"})}return parseLockInfo(raw)}catch(error){if(isFileMissingError(error)){return{info:null,warnings:[]}}return{info:null,warnings:["lock_info_read_failed"]}}}function isErrno(error,code){return typeof error==="object"&&error!==null&&"code"in error&&error.code===code}async function isLockCreateContention(error,lockPath,platform=process.platform){if(isErrno(error,"EEXIST"))return true;if(!isErrno(error,"EPERM")&&!isErrno(error,"EACCES")&&!isErrno(error,"EBUSY")){return false}try{await fs.lstat(lockPath);return true}catch(probeError){if(platform!=="win32"||!isFileMissingError(probeError)&&!isErrno(probeError,"EPERM")&&!isErrno(probeError,"EACCES")&&!isErrno(probeError,"EBUSY")){return false}}try{await fs.access(path.dirname(lockPath),fsConstants.W_OK);return true}catch{return false}}async function emitLockWriteHook(lockPath,op){await runActiveOnWriteHooks({path:lockPath,scope:"project",op})}function buildLockPayload(id,owner,ttlSeconds,token=randomUUID()){return{id,pid:process.pid,owner,token,created_at:nowIso(),ttl_seconds:ttlSeconds}}async function createLockFile(lockPath,id,owner,ttlSeconds,token){await fs.mkdir(path.dirname(lockPath),{recursive:true});const handle=await fs.open(lockPath,"wx");try{await handle.writeFile(`${JSON.stringify(buildLockPayload(id,owner,ttlSeconds,token),null,2)}
2
- `,"utf8")}finally{await handle.close()}await emitLockWriteHook(lockPath,"lock:create")}async function unlinkLockWithHook(lockPath,op){try{await fs.unlink(lockPath);await emitLockWriteHook(lockPath,op);return true}catch{return false}}async function releaseOwnedLock(lockPath,id,owner,token){const startedAtMs=Date.now();let backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;for(;;){const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate!==null){try{const current2=await readLockInfo(lockPath,false);if(isOwnedLock(current2.info,id,owner,token)){await unlinkLockWithHook(lockPath,"lock:release")}}finally{await releaseCleanupGate()}return}const current=await readLockInfo(lockPath,false);if(!isOwnedLock(current.info,id,owner,token)){return}const elapsedMs=Date.now()-startedAtMs;if(elapsedMs>=LOCK_RELEASE_GATE_WAIT_MS){return}await sleepWithJitter(Math.min(backoffMs,LOCK_RELEASE_GATE_WAIT_MS-elapsedMs));backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}function isOwnedLock(info,id,owner,token){return info?.id===id&&info.pid===process.pid&&info.owner===owner&&info.token===token}function isStaleLock(info,ttlSeconds){const createdAtMs=info?.created_at?Date.parse(info.created_at):Number.NaN;const ageMs=Number.isFinite(createdAtMs)?Date.now()-createdAtMs:Number.POSITIVE_INFINITY;return ageMs>ttlSeconds*1e3}function lockOwnerSuffix(info){return info?.owner?` (owner ${info.owner})`:""}const LOCK_WAIT_INITIAL_DELAY_MS=25;const LOCK_WAIT_MAX_DELAY_MS=200;const LOCK_CONFLICT_RETRY_HINT_MS=250;const MAX_STALE_LOCK_REMOVALS=3;const STALE_CLEANUP_GATE_SUFFIX=".stale-cleanup";const STALE_CLEANUP_GATE_OWNER_FILE="owner.json";const STALE_CLEANUP_GATE_STALE_MS=1e4;const LOCK_RELEASE_GATE_WAIT_MS=STALE_CLEANUP_GATE_STALE_MS+LOCK_WAIT_MAX_DELAY_MS;const STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS=60*6e4;function parseNonNegativeIntegerWaitMs(value){if(typeof value==="string"){const trimmed=value.trim();if(!/^\d+$/.test(trimmed)){return void 0}const parsed=Number(trimmed);return Number.isSafeInteger(parsed)?parsed:void 0}if(typeof value==="number"&&Number.isFinite(value)&&value>=0){return Math.trunc(value)}return void 0}function resolveLockWaitMs(waitMs){const envRaw=process.env.PM_LOCK_WAIT_MS;const envParsed=parseNonNegativeIntegerWaitMs(envRaw);if(envParsed!==void 0){return envParsed}const callerParsed=parseNonNegativeIntegerWaitMs(waitMs);if(callerParsed!==void 0){return callerParsed}return 0}function sleepWithJitter(baseDelayMs){const jitteredMs=Math.max(1,Math.round(baseDelayMs*(.5+Math.random())));return new Promise(resolve=>setTimeout(resolve,jitteredMs))}function buildLockConflictError(id,info,waitedMs){const waitedSuffix=waitedMs>0?` after waiting ${waitedMs}ms`:"";return new PmCliError(`Item ${id} is locked${lockOwnerSuffix(info)}${waitedSuffix}`,EXIT_CODE.CONFLICT,{code:"lock_conflict",recovery:{retry_after_ms:LOCK_CONFLICT_RETRY_HINT_MS}})}function resolveLockOverrideRelease(result){if(typeof result==="function"){return result}if(typeof result==="object"&&result!==null&&"release"in result){const release=result.release;return typeof release==="function"?release:null}return null}function throwIfStaleLockNeedsForce(id,lockInfo,force,forceRequired){if(!force&&forceRequired){const warningSuffix=lockInfo.warnings.length>0?` (${lockInfo.warnings.join(",")})`:"";throw new PmCliError(`Item ${id} lock is stale${warningSuffix}; rerun with --force when supported for this command`,EXIT_CODE.CONFLICT)}}function parseStaleCleanupGateOwner(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return null}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){return null}const candidate=parsed;const pid=candidate.pid;const token=candidate.token;const processStartIdentity=candidate.process_start_identity;if(typeof pid!=="number"||!Number.isInteger(pid)||pid<=0||typeof token!=="string"||token.length===0||processStartIdentity!==void 0&&(typeof processStartIdentity!=="string"||!/^\d+$/u.test(processStartIdentity))){return null}return{pid,token,...typeof processStartIdentity==="string"?{process_start_identity:processStartIdentity}:{}}}async function readStaleCleanupGateOwner(gatePath){try{return parseStaleCleanupGateOwner(await fs.readFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),"utf8"))}catch{return null}}function isProcessAlive(pid){if(!Number.isSafeInteger(pid)||pid<=0)return false;try{process.kill(pid,0);return true}catch(error){if(isErrno(error,"ESRCH")){return false}return true}}function parseLinuxProcessStartIdentity(raw){const closeParenIndex=raw.lastIndexOf(")");if(closeParenIndex<0)return null;const startTime=raw.slice(closeParenIndex+2).trim().split(/\s+/u)[19];return startTime!==void 0&&/^\d+$/u.test(startTime)?startTime:null}async function readProcessStartIdentity(pid){try{return parseLinuxProcessStartIdentity(await fs.readFile(`/proc/${pid}/stat`,"utf8"))}catch{return null}}async function captureProcessIdentity(pid=process.pid){const processStartIdentity=await readProcessStartIdentity(pid);return{pid,...processStartIdentity===null?{}:{process_start_identity:processStartIdentity}}}async function isProcessIdentityAlive(identity,unverifiedAgeMs,maxUnverifiedAgeMs){if(!isProcessAlive(identity.pid))return false;const currentStartIdentity=await readProcessStartIdentity(identity.pid);if(identity.process_start_identity!==void 0&&currentStartIdentity!==null){return currentStartIdentity===identity.process_start_identity}return unverifiedAgeMs<=maxUnverifiedAgeMs}async function removeStaleCleanupGateDirectory(gatePath){try{await fs.rm(gatePath,{recursive:true,force:true});return true}catch{return false}}async function releaseStaleCleanupGate(gatePath,token){const owner=await readStaleCleanupGateOwner(gatePath);if(owner===null||owner.token!==token){return}await removeStaleCleanupGateDirectory(gatePath)}async function tryCreateStaleCleanupGate(gatePath){try{await fs.mkdir(gatePath)}catch(error){if(isErrno(error,"EEXIST")){return null}return null}const owner={...await captureProcessIdentity(),token:randomUUID()};try{await fs.writeFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),`${JSON.stringify(owner)}
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]="f0484213-41f9-583e-bd0f-f85e507682b2")}catch(e2){}})();import{isFileMissingError}from"../fs/fs-utils.js";import{constants as fsConstants}from"node:fs";import fs from"node:fs/promises";import path from"node:path";import{randomUUID}from"node:crypto";import{runActiveOnReadHooks,runActiveOnWriteHooks,runActiveServiceOverride}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{toErrorMessage}from"../shared/primitives.js";import{getLockPath}from"../store/paths.js";import{nowIso}from"../shared/time.js";function parseLockInfo(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return{info:null,warnings:["lock_info_invalid_json"]}}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){return{info:null,warnings:["lock_info_invalid_shape"]}}const candidate=parsed;const id=candidate.id;const pid=candidate.pid;const owner=candidate.owner;const token=candidate.token;const createdAt=candidate.created_at;const ttlSeconds=candidate.ttl_seconds;if(typeof id!=="string"||typeof pid!=="number"||!Number.isFinite(pid)||typeof owner!=="string"||token!==void 0&&(typeof token!=="string"||token.trim().length===0)||typeof createdAt!=="string"||typeof ttlSeconds!=="number"||!Number.isFinite(ttlSeconds)){return{info:null,warnings:["lock_info_invalid_shape"]}}return{info:{id,pid,owner,...typeof token==="string"?{token}:{},created_at:createdAt,ttl_seconds:ttlSeconds},warnings:[]}}async function readLockInfo(lockPath,emitReadHook=true){try{const raw=await fs.readFile(lockPath,"utf8");if(emitReadHook){await runActiveOnReadHooks({path:lockPath,scope:"project"})}return parseLockInfo(raw)}catch(error){if(isFileMissingError(error)){return{info:null,warnings:[]}}return{info:null,warnings:["lock_info_read_failed"]}}}function isErrno(error,code){return typeof error==="object"&&error!==null&&"code"in error&&error.code===code}async function isLockCreateContention(error,lockPath,platform=process.platform){if(isErrno(error,"EEXIST"))return true;if(!isErrno(error,"EPERM")&&!isErrno(error,"EACCES")&&!isErrno(error,"EBUSY")){return false}try{await fs.lstat(lockPath);return true}catch(probeError){if(platform!=="win32"||!isFileMissingError(probeError)&&!isErrno(probeError,"EPERM")&&!isErrno(probeError,"EACCES")&&!isErrno(probeError,"EBUSY")){return false}}try{await fs.access(path.dirname(lockPath),fsConstants.W_OK);return true}catch{return false}}async function emitLockWriteHook(lockPath,op){await runActiveOnWriteHooks({path:lockPath,scope:"project",op})}function buildLockPayload(id,owner,ttlSeconds,token=randomUUID()){return{id,pid:process.pid,owner,token,created_at:nowIso(),ttl_seconds:ttlSeconds}}async function createLockFile(lockPath,id,owner,ttlSeconds,token){await fs.mkdir(path.dirname(lockPath),{recursive:true});const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate===null){throw Object.assign(new Error("Lock initialization is contended"),{code:"EEXIST"})}try{const handle=await fs.open(lockPath,"wx");try{try{await handle.writeFile(`${JSON.stringify(buildLockPayload(id,owner,ttlSeconds,token),null,2)}
2
+ `,"utf8")}finally{await handle.close()}}catch(error){await unlinkLockWithHook(lockPath,"lock:release");throw error}}finally{await releaseCleanupGate()}await emitLockWriteHook(lockPath,"lock:create")}async function unlinkLockWithHook(lockPath,op){try{await fs.unlink(lockPath);await emitLockWriteHook(lockPath,op);return true}catch{return false}}async function releaseOwnedLock(lockPath,id,owner,token){const startedAtMs=Date.now();let backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;for(;;){const releaseCleanupGate=await acquireStaleCleanupGate(lockPath,id);if(releaseCleanupGate!==null){try{const current2=await readLockInfo(lockPath,false);if(isOwnedLock(current2.info,id,owner,token)){await unlinkLockWithHook(lockPath,"lock:release")}}finally{await releaseCleanupGate()}return}const current=await readLockInfo(lockPath,false);if(!isOwnedLock(current.info,id,owner,token)){return}const elapsedMs=Date.now()-startedAtMs;if(elapsedMs>=LOCK_RELEASE_GATE_WAIT_MS){return}await sleepWithJitter(Math.min(backoffMs,LOCK_RELEASE_GATE_WAIT_MS-elapsedMs));backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}function isOwnedLock(info,id,owner,token){return info?.id===id&&info.pid===process.pid&&info.owner===owner&&info.token===token}function isStaleLock(info,ttlSeconds){const createdAtMs=info?.created_at?Date.parse(info.created_at):Number.NaN;const ageMs=Number.isFinite(createdAtMs)?Date.now()-createdAtMs:Number.POSITIVE_INFINITY;return ageMs>ttlSeconds*1e3}function lockOwnerSuffix(info){return info?.owner?` (owner ${info.owner})`:""}const LOCK_WAIT_INITIAL_DELAY_MS=25;const LOCK_WAIT_MAX_DELAY_MS=200;const LOCK_CONFLICT_RETRY_HINT_MS=250;const MAX_STALE_LOCK_REMOVALS=3;const STALE_CLEANUP_GATE_SUFFIX=".stale-cleanup";const STALE_CLEANUP_GATE_OWNER_FILE="owner.json";const STALE_CLEANUP_GATE_STALE_MS=1e4;const LOCK_RELEASE_GATE_WAIT_MS=STALE_CLEANUP_GATE_STALE_MS+LOCK_WAIT_MAX_DELAY_MS;const STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS=60*6e4;function parseNonNegativeIntegerWaitMs(value){if(typeof value==="string"){const trimmed=value.trim();if(!/^\d+$/.test(trimmed)){return void 0}const parsed=Number(trimmed);return Number.isSafeInteger(parsed)?parsed:void 0}if(typeof value==="number"&&Number.isFinite(value)&&value>=0){return Math.trunc(value)}return void 0}function resolveLockWaitMs(waitMs){const envRaw=process.env.PM_LOCK_WAIT_MS;const envParsed=parseNonNegativeIntegerWaitMs(envRaw);if(envParsed!==void 0){return envParsed}const callerParsed=parseNonNegativeIntegerWaitMs(waitMs);if(callerParsed!==void 0){return callerParsed}return 0}function sleepWithJitter(baseDelayMs){const jitteredMs=Math.max(1,Math.round(baseDelayMs*(.5+Math.random())));return new Promise(resolve=>setTimeout(resolve,jitteredMs))}function buildLockConflictError(id,info,waitedMs){const waitedSuffix=waitedMs>0?` after waiting ${waitedMs}ms`:"";return new PmCliError(`Item ${id} is locked${lockOwnerSuffix(info)}${waitedSuffix}`,EXIT_CODE.CONFLICT,{code:"lock_conflict",recovery:{retry_after_ms:LOCK_CONFLICT_RETRY_HINT_MS}})}function resolveLockOverrideRelease(result){if(typeof result==="function"){return result}if(typeof result==="object"&&result!==null&&"release"in result){const release=result.release;return typeof release==="function"?release:null}return null}function throwIfStaleLockNeedsForce(id,lockInfo,force,forceRequired){if(!force&&forceRequired){const warningSuffix=lockInfo.warnings.length>0?` (${lockInfo.warnings.join(",")})`:"";throw new PmCliError(`Item ${id} lock is stale${warningSuffix}; rerun with --force when supported for this command`,EXIT_CODE.CONFLICT)}}function parseStaleCleanupGateOwner(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return null}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){return null}const candidate=parsed;const pid=candidate.pid;const token=candidate.token;const processStartIdentity=candidate.process_start_identity;if(typeof pid!=="number"||!Number.isInteger(pid)||pid<=0||typeof token!=="string"||token.length===0||processStartIdentity!==void 0&&(typeof processStartIdentity!=="string"||!/^\d+$/u.test(processStartIdentity))){return null}return{pid,token,...typeof processStartIdentity==="string"?{process_start_identity:processStartIdentity}:{}}}async function readStaleCleanupGateOwner(gatePath){try{return parseStaleCleanupGateOwner(await fs.readFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),"utf8"))}catch{return null}}function isProcessAlive(pid){if(!Number.isSafeInteger(pid)||pid<=0)return false;try{process.kill(pid,0);return true}catch(error){if(isErrno(error,"ESRCH")){return false}return true}}function parseLinuxProcessStartIdentity(raw){const closeParenIndex=raw.lastIndexOf(")");if(closeParenIndex<0)return null;const startTime=raw.slice(closeParenIndex+2).trim().split(/\s+/u)[19];return startTime!==void 0&&/^\d+$/u.test(startTime)?startTime:null}async function readProcessStartIdentity(pid){try{return parseLinuxProcessStartIdentity(await fs.readFile(`/proc/${pid}/stat`,"utf8"))}catch{return null}}async function captureProcessIdentity(pid=process.pid){const processStartIdentity=await readProcessStartIdentity(pid);return{pid,...processStartIdentity===null?{}:{process_start_identity:processStartIdentity}}}async function isProcessIdentityAlive(identity,unverifiedAgeMs,maxUnverifiedAgeMs){if(!isProcessAlive(identity.pid))return false;const currentStartIdentity=await readProcessStartIdentity(identity.pid);if(identity.process_start_identity!==void 0&&currentStartIdentity!==null){return currentStartIdentity===identity.process_start_identity}return unverifiedAgeMs<=maxUnverifiedAgeMs}async function removeStaleCleanupGateDirectory(gatePath){try{await fs.rm(gatePath,{recursive:true,force:true});return true}catch{return false}}async function releaseStaleCleanupGate(gatePath,token){const owner=await readStaleCleanupGateOwner(gatePath);if(owner===null||owner.token!==token){return}await removeStaleCleanupGateDirectory(gatePath)}async function tryCreateStaleCleanupGate(gatePath){try{await fs.mkdir(gatePath)}catch(error){if(isErrno(error,"EEXIST")){return null}return null}const owner={...await captureProcessIdentity(),token:randomUUID()};try{await fs.writeFile(path.join(gatePath,STALE_CLEANUP_GATE_OWNER_FILE),`${JSON.stringify(owner)}
3
3
  `,"utf8")}catch{await removeStaleCleanupGateDirectory(gatePath);return null}return owner}async function removeExpiredStaleCleanupGate(gatePath){let gateAgeMs;try{const stats=await fs.stat(gatePath);gateAgeMs=Date.now()-stats.mtimeMs;if(gateAgeMs<=STALE_CLEANUP_GATE_STALE_MS){return false}}catch(error){return isFileMissingError(error)}const owner=await readStaleCleanupGateOwner(gatePath);if(owner!==null&&await isProcessIdentityAlive(owner,gateAgeMs,STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS)){return false}return removeStaleCleanupGateDirectory(gatePath)}async function acquireStaleCleanupGate(lockPath,_id){const gatePath=`${lockPath}${STALE_CLEANUP_GATE_SUFFIX}`;const owner=await tryCreateStaleCleanupGate(gatePath);if(owner!==null){return async()=>releaseStaleCleanupGate(gatePath,owner.token)}if(!await removeExpiredStaleCleanupGate(gatePath)){return null}const recoveredOwner=await tryCreateStaleCleanupGate(gatePath);if(recoveredOwner===null){return null}return async()=>releaseStaleCleanupGate(gatePath,recoveredOwner.token)}async function removeConfirmedStaleLock(params){const releaseCleanupGate=await acquireStaleCleanupGate(params.lockPath,params.id);if(releaseCleanupGate===null){return{lockInfo:params.fallbackLockInfo,shouldRetryCreate:false,staleRemovalCounted:false}}try{const currentLockInfo=await readLockInfo(params.lockPath);if(currentLockInfo.info===null&&currentLockInfo.warnings.length===0){return{lockInfo:currentLockInfo,shouldRetryCreate:true,staleRemovalCounted:false}}if(!isStaleLock(currentLockInfo.info,params.ttlSeconds)){return{lockInfo:currentLockInfo,shouldRetryCreate:false,staleRemovalCounted:false}}throwIfStaleLockNeedsForce(params.id,currentLockInfo,params.force,params.forceRequiredForStaleLock);if(params.staleRemovals>=MAX_STALE_LOCK_REMOVALS){throw buildLockConflictError(params.id,currentLockInfo.info,Date.now()-params.startedAtMs)}return{lockInfo:currentLockInfo,shouldRetryCreate:await unlinkLockWithHook(params.lockPath,"lock:stale_remove"),staleRemovalCounted:true}}finally{await releaseCleanupGate()}}const _testOnly={parseLockInfo,readLockInfo,isErrno,isLockCreateContention,buildLockPayload,isStaleLock,lockOwnerSuffix,resolveLockWaitMs,parseLinuxProcessStartIdentity,readProcessStartIdentity,acquireStaleCleanupGate,removeConfirmedStaleLock};async function acquireLock(pmRoot,id,ttlSeconds,owner,force=false,forceRequiredForStaleLock=true,waitMs){const lockOverride=await runActiveServiceOverride("lock_acquire",{pm_root:pmRoot,id,ttl_seconds:ttlSeconds,owner,force,force_required_for_stale_lock:forceRequiredForStaleLock});if(lockOverride.handled){const release=resolveLockOverrideRelease(lockOverride.result);if(release){return async()=>{await Promise.resolve(release());await runActiveServiceOverride("lock_release",{pm_root:pmRoot,id,owner})}}}const lockPath=getLockPath(pmRoot,id);const waitBudgetMs=resolveLockWaitMs(waitMs);const startedAtMs=Date.now();let staleRemovals=0;let backoffMs=LOCK_WAIT_INITIAL_DELAY_MS;const token=randomUUID();for(;;){try{await createLockFile(lockPath,id,owner,ttlSeconds,token);return async()=>{await releaseOwnedLock(lockPath,id,owner,token);await runActiveServiceOverride("lock_release",{pm_root:pmRoot,id,owner})}}catch(error){if(!await isLockCreateContention(error,lockPath)){throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`,EXIT_CODE.GENERIC_FAILURE)}let lockInfo=await readLockInfo(lockPath);if(isStaleLock(lockInfo.info,ttlSeconds)){const staleRemoval=await removeConfirmedStaleLock({lockPath,id,ttlSeconds,force,forceRequiredForStaleLock,staleRemovals,waitBudgetMs,startedAtMs,fallbackLockInfo:lockInfo});lockInfo=staleRemoval.lockInfo;if(staleRemoval.staleRemovalCounted){staleRemovals+=1}if(staleRemoval.shouldRetryCreate){continue}}const elapsedMs=Date.now()-startedAtMs;if(waitBudgetMs===0||elapsedMs>=waitBudgetMs){throw buildLockConflictError(id,lockInfo.info,waitBudgetMs===0?0:elapsedMs)}await sleepWithJitter(Math.min(backoffMs,waitBudgetMs-elapsedMs));backoffMs=Math.min(backoffMs*2,LOCK_WAIT_MAX_DELAY_MS)}}}export{_testOnly,acquireLock,captureProcessIdentity,isProcessIdentityAlive,readProcessStartIdentity};
4
4
  //# sourceMappingURL=lock.js.map
@@ -1,9 +1,9 @@
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]="1a9ff3c9-9c7e-50ec-bb12-8a7f91de757f")}catch(e2){}})();import{getActiveCommandContext,runActiveCommandOverride,runActiveRendererOverride,runActiveServiceOverrideSync,setActiveCommandResult}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{isHostOutputSuppressed}from"./output-control.js";import{projectMutationResult}from"./mutation-projection.js";import{attachReadOutputContracts}from"../../sdk/context-intent-contracts.js";import{attachOutputTokenAccounting}from"../../sdk/output-token-accounting.js";import{propagateContextUsageServingReceipt}from"../../sdk/context-usage.js";import{isReadOutputBudgetExceeded,resolveReadOutputEncoding}from"../../sdk/read-output-contracts.js";import{encode as encodeToon}from"@toon-format/toon";const DECLARED_PROCESS_EXIT_CODES=new Set(Object.values(EXIT_CODE));const NATIVE_OUTPUT_MARKER="__pm_native_output";let streamErrorHandlersInstalled=false;function isPlainObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function setActiveCommandResultOmitted(source){const omitted={read_output:{result_omitted:true}};propagateContextUsageServingReceipt(source,omitted);setActiveCommandResult(omitted)}function setActiveCommandDeliveryResult(result,receiptSource,structuredDeliveryPreserved){if(structuredDeliveryPreserved){setActiveCommandResult(result);return}setActiveCommandResultOmitted(receiptSource)}function shouldUseNativeOutput(result){return isPlainObject(result)&&result[NATIVE_OUTPUT_MARKER]===true}function stripNativeOutputMarker(result){if(!isPlainObject(result)||result[NATIVE_OUTPUT_MARKER]!==true){return result}const{[NATIVE_OUTPUT_MARKER]:_marker,...rest}=result;return rest}function isBrokenPipeError(error){return typeof error==="object"&&error!==null&&error.code==="EPIPE"}function markStdoutBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.SUCCESS}}function markStderrBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.GENERIC_FAILURE}}function markBrokenPipeExitCode(target){if(target==="stdout"){markStdoutBrokenPipeExitCode();return}markStderrBrokenPipeExitCode()}function handleUnhandledStreamError(error){const unhandled=error instanceof Error?error:new Error(String(error));setImmediate(()=>{throw unhandled})}function installStreamErrorHandlers(){if(streamErrorHandlersInstalled){return}streamErrorHandlersInstalled=true;process.stdout.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stdout");return}handleUnhandledStreamError(error)});process.stderr.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stderr");return}handleUnhandledStreamError(error)})}function writeToStream(target,text){installStreamErrorHandlers();try{if(target==="stdout"){process.stdout.write(text)}else{process.stderr.write(text)}return true}catch(error){if(isBrokenPipeError(error)){markBrokenPipeExitCode(target);return false}throw error}}function writeStdout(text){return writeToStream("stdout",text)}function writeStderr(text){return writeToStream("stderr",text)}function renderScalar(value){if(typeof value==="string")return JSON.stringify(value);if(typeof value==="number"||typeof value==="boolean")return String(value);if(value===null)return"null";return JSON.stringify(value)}function isToonPrimitive(value){return value===null||typeof value==="string"||typeof value==="number"||typeof value==="boolean"}function tabularObjectArray(value){if(value.length===0||!value.every(isPlainObject))return false;const keys=Object.keys(value[0]);return keys.length>0&&value.every(entry=>Object.keys(entry).length===keys.length&&keys.every(key=>Object.hasOwn(entry,key)&&isToonPrimitive(entry[key])))}function indentToon(encoded,depth){const indent=" ".repeat(depth);return encoded.split("\n").map(line=>`${indent}${line}`).join("\n")}function renderToonObjectEntry(key,entry,depth){const indent=" ".repeat(depth);if(!isPlainObject(entry)&&!Array.isArray(entry)){return`${indent}${key}: ${renderScalar(entry)}`}if(Array.isArray(entry)&&entry.length===0){return`${indent}${key}: []`}if(Array.isArray(entry)&&tabularObjectArray(entry)){return indentToon(encodeToon({[key]:entry}),depth)}if(isPlainObject(entry)&&Object.keys(entry).length===0){return`${indent}${key}: {}`}return`${indent}${key}:
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]="2ca9480d-0ae4-50e8-887e-c4183501d92c")}catch(e2){}})();import{getActiveCommandContext,runActiveCommandOverride,runActiveRendererOverride,runActiveServiceOverrideSync,setActiveCommandResult}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{isHostOutputSuppressed}from"./output-control.js";import{projectMutationResult}from"./mutation-projection.js";import{attachReadOutputContracts}from"../../sdk/context-intent-contracts.js";import{attachOutputTokenAccounting}from"../../sdk/output-token-accounting.js";import{propagateContextUsageServingReceipt}from"../../sdk/context-usage.js";import{isReadOutputBudgetExceeded,resolveReadOutputEncoding}from"../../sdk/read-output-contracts.js";import{encode as encodeToon}from"@toon-format/toon";const DECLARED_PROCESS_EXIT_CODES=new Set(Object.values(EXIT_CODE));const NATIVE_OUTPUT_MARKER="__pm_native_output";let streamErrorHandlersInstalled=false;function isPlainObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function setActiveCommandResultOmitted(source){const omitted={read_output:{result_omitted:true}};propagateContextUsageServingReceipt(source,omitted);setActiveCommandResult(omitted)}function setActiveCommandDeliveryResult(result,receiptSource,structuredDeliveryPreserved){if(structuredDeliveryPreserved){setActiveCommandResult(result);return}setActiveCommandResultOmitted(receiptSource)}function shouldUseNativeOutput(result){return isPlainObject(result)&&result[NATIVE_OUTPUT_MARKER]===true}function stripNativeOutputMarker(result){if(!isPlainObject(result)||result[NATIVE_OUTPUT_MARKER]!==true){return result}const{[NATIVE_OUTPUT_MARKER]:_marker,...rest}=result;return rest}function isBrokenPipeError(error){return typeof error==="object"&&error!==null&&error.code==="EPIPE"}function markStdoutBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.SUCCESS}}function markStderrBrokenPipeExitCode(){if(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS){process.exitCode=EXIT_CODE.GENERIC_FAILURE}}function markBrokenPipeExitCode(target){if(target==="stdout"){markStdoutBrokenPipeExitCode();return}markStderrBrokenPipeExitCode()}function handleUnhandledStreamError(error){const unhandled=error instanceof Error?error:new Error(String(error));setImmediate(()=>{throw unhandled})}function installStreamErrorHandlers(){if(streamErrorHandlersInstalled){return}streamErrorHandlersInstalled=true;process.stdout.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stdout");return}handleUnhandledStreamError(error)});process.stderr.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stderr");return}handleUnhandledStreamError(error)})}function writeToStream(target,text){installStreamErrorHandlers();try{if(target==="stdout"){process.stdout.write(text)}else{process.stderr.write(text)}return true}catch(error){if(isBrokenPipeError(error)){markBrokenPipeExitCode(target);return false}throw error}}function writeStdout(text){return writeToStream("stdout",text)}function writeStderr(text){return writeToStream("stderr",text)}function renderScalar(value){if(typeof value==="string")return JSON.stringify(value);if(typeof value==="number"||typeof value==="boolean")return String(value);if(value===null)return"null";return JSON.stringify(value)}function isToonPrimitive(value){return value===null||typeof value==="string"||typeof value==="number"||typeof value==="boolean"}function tabularObjectArray(value){if(value.length===0||!value.every(isPlainObject))return false;const keys=Object.keys(value[0]);return keys.length>0&&value.every(entry=>Object.keys(entry).length===keys.length&&keys.every(key=>Object.hasOwn(entry,key)&&isToonPrimitive(entry[key])))}function indentToon(encoded,depth){const indent=" ".repeat(depth);return encoded.split("\n").map(line=>`${indent}${line}`).join("\n")}function renderToonObjectEntry(key,entry,depth){const indent=" ".repeat(depth);if(!isPlainObject(entry)&&!Array.isArray(entry)){return`${indent}${key}: ${renderScalar(entry)}`}if(Array.isArray(entry)&&entry.length===0){return`${indent}${key}: []`}if(Array.isArray(entry)&&tabularObjectArray(entry)){return indentToon(encodeToon({[key]:entry}),depth)}if(isPlainObject(entry)&&Object.keys(entry).length===0){return`${indent}${key}: {}`}return`${indent}${key}:
2
2
  ${renderToonValue(entry,depth+1)}`}function compactToonValue(value){if(value===null||value===void 0){return void 0}if(Array.isArray(value)){const compactedEntries=value.map(entry=>compactToonValue(entry)).filter(entry=>entry!==void 0);return compactedEntries.length>0?compactedEntries:void 0}if(isPlainObject(value)){const compacted={};for(const[key,entry]of Object.entries(value)){if(key==="omitted_field_groups"&&Array.isArray(entry)&&entry.length===0){compacted[key]=[];continue}const compactedEntry=compactToonValue(entry);if(compactedEntry!==void 0){compacted[key]=compactedEntry}}return Object.keys(compacted).length>0?compacted:void 0}return value}function renderToonValue(value,depth){const indent=" ".repeat(depth);if(Array.isArray(value)){if(value.length===0)return"[]";if(tabularObjectArray(value)){return indentToon(encodeToon(value),depth)}return value.map(entry=>{if(!isPlainObject(entry)&&!Array.isArray(entry)){return`${indent}- ${renderScalar(entry)}`}const rendered=renderToonValue(entry,depth+1);const lines=rendered.split("\n");const[firstLine,...rest]=lines;if(rest.length===0){return`${indent}- ${firstLine.trimStart()}`}return`${indent}- ${firstLine.trimStart()}
3
3
  ${rest.join("\n")}`}).join("\n")}if(isPlainObject(value)){const entries=Object.entries(value);if(entries.length===0)return"{}";return entries.map(([key,entry])=>renderToonObjectEntry(key,entry,depth)).join("\n")}return`${indent}${renderScalar(value)}`}function renderDefaultMarkdownResult(value){if(!isPlainObject(value)||value.output_default!=="markdown"){return null}if(typeof value.view!=="string"||!Array.isArray(value.events)||!Array.isArray(value.days)){return null}const lines=[`# pm calendar (${value.view})`,""];const summary=isPlainObject(value.summary)?value.summary:{};lines.push(`- events: ${String(summary.events??0)}`);lines.push("");if(value.events.length===0){lines.push("No calendar events matched the selected filters.");return`${lines.join("\n")}
4
4
  `}for(const event of value.events){if(!isPlainObject(event)){continue}const kind=typeof event.kind==="string"?event.kind:"event";const title=typeof event.item_title==="string"?event.item_title:"";const itemId=typeof event.item_id==="string"?event.item_id:"";const reminderText=typeof event.reminder_text==="string"&&event.reminder_text.length>0?` ${event.reminder_text}`:"";lines.push(`- [${kind}] ${itemId} ${title}${reminderText}`.trim())}return`${lines.join("\n")}
5
- `}function resolveOutputFormat(options){return options.json===true||options.json===void 0&&options.defaultOutputFormat==="json"?"json":"toon"}const LEAN_READ_ENVELOPE_ECHO_KEYS=new Set(["filters","now","projection","sorting"]);function projectLeanJsonValue(value){const compacted=compactToonValue(value);if(!isPlainObject(compacted)||!Array.isArray(compacted.items)){return compacted??null}const projected=Object.fromEntries(Object.entries(compacted).filter(([key])=>!LEAN_READ_ENVELOPE_ECHO_KEYS.has(key)));if(projected.has_more!==true){delete projected.next_cursor}return projected}function projectLinkedTestEvidence(value,lean){if(!isPlainObject(value)||!Array.isArray(value.run_results)){return value}if(!value.run_results.every(isPlainObject)){return value}const rows=value.run_results;const contexts=rows.map(row=>row.execution_context).filter(context=>context!==void 0);const sharedContext=contexts.length===rows.length&&contexts.length>0&&contexts.every(context=>JSON.stringify(context)===JSON.stringify(contexts[0]))?contexts[0]:void 0;const runResults=rows.map(row=>{const{execution_context:_executionContext,stdout,stderr,...rest}=row;if(sharedContext===void 0){return row}if(!lean||row.status!=="passed"){return{...rest,stdout,stderr}}return rest});return{...value,...sharedContext===void 0?{}:{execution_context:sharedContext},run_results:runResults}}function formatBuiltInOutput(result,format){if(format==="json"){return`${JSON.stringify(result,null,2)}
6
- `}const compactedToon=compactToonValue(result);return compactedToon===void 0?"{}\n":`${renderToonValue(compactedToon,0)}
5
+ `}function resolveOutputFormat(options){return options.json===true||options.json===void 0&&options.defaultOutputFormat==="json"?"json":"toon"}const LEAN_READ_ENVELOPE_ECHO_KEYS=new Set(["filters","now","projection","sorting"]);function projectLeanJsonValue(value){const compacted=compactToonValue(value);if(!isPlainObject(compacted)||!Array.isArray(compacted.items)){return compacted??null}const projected=Object.fromEntries(Object.entries(compacted).filter(([key])=>!LEAN_READ_ENVELOPE_ECHO_KEYS.has(key)));if(projected.has_more!==true){delete projected.next_cursor}return projected}function projectLinkedTestEvidence(value,lean){if(!isPlainObject(value)||!Array.isArray(value.run_results)){return value}if(!value.run_results.every(isPlainObject)){return value}const rows=value.run_results;const contexts=rows.map(row=>row.execution_context).filter(context=>context!==void 0);const sharedContext=contexts.length===rows.length&&contexts.length>0&&contexts.every(context=>JSON.stringify(context)===JSON.stringify(contexts[0]))?contexts[0]:void 0;const runResults=rows.map(row=>{const{execution_context:_executionContext,stdout,stderr,...rest}=row;if(sharedContext===void 0){return row}if(!lean||row.status!=="passed"){return{...rest,stdout,stderr}}return rest});return{...value,...sharedContext===void 0?{}:{execution_context:sharedContext},run_results:runResults}}function projectCompleteBriefList(value){if(!isPlainObject(value)||!Array.isArray(value.items)||Object.hasOwn(value,"details")||!isPlainObject(value.projection)||value.projection.mode!=="brief"||!isPlainObject(value.completeness)||value.completeness.status!=="complete"||[value.completeness.unreadable_item_count,value.completeness.unreadable_directory_count].some(count=>count!==0)||[value.has_more,value.truncated].some(flag=>flag!==false)||value.count!==value.items.length||value.total!==value.count||!isPlainObject(value.omission_receipt)||JSON.stringify(value.omission_receipt.omitted_field_groups)!==JSON.stringify([{name:"full_item_fields",restore_with:"--full"}])){return value}const{total:_total,has_more:_hasMore,truncated:_truncated,next_cursor:_nextCursor,completeness:_completeness,projection:_projection,now:_now,omission_receipt:_omissions,sorting,...rest}=value;return{...rest,...isPlainObject(sorting)&&sorting.sort==="default"?{}:{sorting},details:"--full"}}function formatBuiltInOutput(result,format){if(format==="json"){return`${JSON.stringify(result,null,2)}
6
+ `}const compactedToon=compactToonValue(projectCompleteBriefList(result));return compactedToon===void 0?"{}\n":`${renderToonValue(compactedToon,0)}
7
7
  `}function resolveOutputService(effectiveResult,nativeOutput,options,format){const serviceOverride=nativeOutput?{handled:false,result:effectiveResult,warnings:[]}:runActiveServiceOverrideSync("output_format",{command:options.command,args:options.commandArgs,command_options:options.commandOptions,global:{...options},pm_root:options.pmRoot,format,options:{...options},result:effectiveResult});const legacyPayloadEchoWarning=serviceOverride.warnings.find(warning=>warning.startsWith("extension_output_format_payload_echo_deprecated:"));if(legacyPayloadEchoWarning!==void 0){writeStderr(`Warning: ${legacyPayloadEchoWarning}. Returning context.payload now declines safely for compatibility; migrate the override to declineServiceOverride() or { handled: false }.
8
8
  `)}if(serviceOverride.handled&&typeof serviceOverride.result==="string"){return{result:serviceOverride.result,rendered:serviceOverride.result.endsWith("\n")?serviceOverride.result:`${serviceOverride.result}
9
9
  `,structuredDeliveryPreserved:false}}return{result:serviceOverride.handled?serviceOverride.result:effectiveResult,rendered:null,structuredDeliveryPreserved:!serviceOverride.handled||isPlainObject(serviceOverride.result)}}function formatEffectiveOutput(effectiveResult,nativeOutput,options){const activeCommandContext=getActiveCommandContext();const command=options.command??activeCommandContext?.command;const commandOptions={...activeCommandContext?.options,...options.commandOptions,...Object.fromEntries([["outputInclude",options.outputInclude],["outputLimit",options.outputLimit],["outputBudget",options.outputBudget],["outputFormat",options.outputFormat],["outputSession",options.outputSession],["outputCursor",options.outputCursor],["outputRowContract",options.outputRowContract]].filter(entry=>entry[1]!==void 0))};const format=resolveReadOutputEncoding(command??"",commandOptions)??resolveOutputFormat(options);const resolvedCommandOptions={...commandOptions,resolvedOutputFormat:format};const effectiveOptions={...options,command,commandOptions:resolvedCommandOptions};const service=resolveOutputService(effectiveResult,nativeOutput,effectiveOptions,format);if(service.rendered!==null){setActiveCommandResultOmitted(effectiveResult);return service.rendered}const outputResult=service.result;propagateContextUsageServingReceipt(effectiveResult,outputResult);const projectedOutputResult=command==="test"?projectLinkedTestEvidence(outputResult,options.lean===true):outputResult;const intentOutputResult=attachReadOutputContracts(command,resolvedCommandOptions,projectedOutputResult);if(isReadOutputBudgetExceeded(intentOutputResult)){process.exitCode||=EXIT_CODE.USAGE}let{structuredDeliveryPreserved}=service;const renderResolvedOutput=value=>{if(format==="toon"){const markdownDefault=renderDefaultMarkdownResult(value);if(markdownDefault!==null)return markdownDefault}const rendererOverride=nativeOutput?{rendered:null}:runActiveRendererOverride(format,value);if(rendererOverride.rendered!==null){structuredDeliveryPreserved=false;return rendererOverride.rendered.endsWith("\n")?rendererOverride.rendered:`${rendererOverride.rendered}
@@ -1,5 +1,7 @@
1
1
  /** Supported explicit classifications for intentional telemetry delivery. */
2
2
  export declare const PM_TELEMETRY_SOURCE_CONTEXT_VALUES: readonly ["user", "automation", "test", "dogfood"];
3
+ /** Fixed core reads eligible only after runtime ownership has been established. */
4
+ export declare const TELEMETRY_SAMPLEABLE_READS: ReadonlySet<string>;
3
5
  /** Resolve explicit read sampling only for core-only invocations with no write-capable extensions. */
4
6
  export declare function resolveTelemetryReadSampleRate(command: string, noExtensions: boolean, env?: Readonly<Record<string, string | undefined>>): number;
5
7
  /** Explain process opt-outs without reading settings or creating installation identity. */
@@ -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]="f22e54f3-7ade-5af3-8344-9c133b4da8b5")}catch(e2){}})();const TRUE_VALUES=new Set(["1","true","yes","on"]);const PM_TELEMETRY_SOURCE_CONTEXT_VALUES=["user","automation","test","dogfood"];const SOURCE_CONTEXTS=new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);const SAMPLEABLE_READS=new Set(["stats","ops stats","list","get","next","context","activity","aggregate"]);function resolveTelemetryReadSampleRate(command,noExtensions,env=process.env){const raw=env.PM_TELEMETRY_READ_SAMPLE_RATE?.trim();if(!raw||!noExtensions||!SAMPLEABLE_READS.has(command))return 1;const rate=Number(raw);return Number.isFinite(rate)&&rate>0&&rate<=1?rate:1}function telemetryEnvironmentFlag(key,env){return TRUE_VALUES.has((env[key]??"").trim().toLowerCase())}function resolveTelemetryEnvironmentPolicy(env=process.env){const doNotTrack=telemetryEnvironmentFlag("DO_NOT_TRACK",env);const override=(env.PM_TELEMETRY_SOURCE_CONTEXT??"").trim().toLowerCase();const inferredTest=typeof env.VITEST==="string"||typeof env.VITEST_WORKER_ID==="string"||(env.NODE_ENV??"").trim().toLowerCase()==="test";const testSuppressed=inferredTest&&!SOURCE_CONTEXTS.has(override)&&!telemetryEnvironmentFlag("PM_TELEMETRY_SEND_TEST_EVENTS",env);return{telemetry_disabled:doNotTrack||testSuppressed||telemetryEnvironmentFlag("PM_TELEMETRY_DISABLED",env)||telemetryEnvironmentFlag("PM_NO_TELEMETRY",env),do_not_track:doNotTrack,test_suppressed:testSuppressed}}export{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,resolveTelemetryEnvironmentPolicy,resolveTelemetryReadSampleRate};
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]="c4fba032-7cda-53a2-b518-fa13a60a76d5")}catch(e2){}})();const TRUE_VALUES=new Set(["1","true","yes","on"]);const PM_TELEMETRY_SOURCE_CONTEXT_VALUES=["user","automation","test","dogfood"];const SOURCE_CONTEXTS=new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);const TELEMETRY_SAMPLEABLE_READS=new Set(["stats","ops stats","list","get","next","context","activity","aggregate"]);function resolveTelemetryReadSampleRate(command,noExtensions,env=process.env){const raw=env.PM_TELEMETRY_READ_SAMPLE_RATE?.trim();if(!raw||!noExtensions||!TELEMETRY_SAMPLEABLE_READS.has(command))return 1;const rate=Number(raw);return Number.isFinite(rate)&&rate>0&&rate<=1?rate:1}function telemetryEnvironmentFlag(key,env){return TRUE_VALUES.has((env[key]??"").trim().toLowerCase())}function resolveTelemetryEnvironmentPolicy(env=process.env){const doNotTrack=telemetryEnvironmentFlag("DO_NOT_TRACK",env);const override=(env.PM_TELEMETRY_SOURCE_CONTEXT??"").trim().toLowerCase();const inferredTest=typeof env.VITEST==="string"||typeof env.VITEST_WORKER_ID==="string"||(env.NODE_ENV??"").trim().toLowerCase()==="test";const testSuppressed=inferredTest&&!SOURCE_CONTEXTS.has(override)&&!telemetryEnvironmentFlag("PM_TELEMETRY_SEND_TEST_EVENTS",env);return{telemetry_disabled:doNotTrack||testSuppressed||telemetryEnvironmentFlag("PM_TELEMETRY_DISABLED",env)||telemetryEnvironmentFlag("PM_NO_TELEMETRY",env),do_not_track:doNotTrack,test_suppressed:testSuppressed}}export{PM_TELEMETRY_SOURCE_CONTEXT_VALUES,TELEMETRY_SAMPLEABLE_READS,resolveTelemetryEnvironmentPolicy,resolveTelemetryReadSampleRate};
2
2
  //# sourceMappingURL=policy.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Retain the first ten reads of each command per UTC minute, then sample the
3
+ * nth read at (10/n)^2. Expected retained successes stay below twenty per
4
+ * command per minute; this is a statistical bound, not a hard delivery cap.
5
+ * Explicit rates bypass automatic state. Corrupt or inaccessible state retains
6
+ * the invocation. Failures must override the returned probability at finish.
7
+ */
8
+ export declare function resolveAutomaticReadSampleRate(globalPmRoot: string, command: string, coreReadOwned: boolean, env?: Readonly<Record<string, string | undefined>>, now?: number): Promise<number>;
@@ -0,0 +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]="9d949852-abfe-5fbd-88c5-5da0cfbaf7de")}catch(e2){}})();import path from"node:path";import{readFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{resolveTelemetryReadSampleRate,TELEMETRY_SAMPLEABLE_READS}from"./policy.js";async function resolveAutomaticReadSampleRate(globalPmRoot,command,coreReadOwned,env=process.env,now=Date.now()){if(!coreReadOwned||!TELEMETRY_SAMPLEABLE_READS.has(command))return 1;if(env.PM_TELEMETRY_READ_SAMPLE_RATE!==void 0){return resolveTelemetryReadSampleRate(command,true,env)}try{const statePath=path.join(globalPmRoot,"runtime","telemetry","read-sampling.json");const minute=Math.floor(now/6e4);const counts=parseReadCounts(await readFileIfExists(statePath),minute);const ordinal=Math.min(Number.MAX_SAFE_INTEGER,(counts[command]??0)+1);counts[command]=ordinal;await writeFileAtomic(statePath,`${JSON.stringify({minute,counts})}
2
+ `);return Math.min(1,(10/ordinal)**2)}catch{return 1}}function parseReadCounts(raw,minute){const counts={};let previous;try{previous=JSON.parse(raw??"null")}catch{return counts}if(typeof previous!=="object"||previous===null||!("minute"in previous)||previous.minute!==minute||!("counts"in previous)||typeof previous.counts!=="object"||previous.counts===null)return counts;for(const[key,value]of Object.entries(previous.counts)){if(TELEMETRY_SAMPLEABLE_READS.has(key)&&typeof value==="number"&&Number.isSafeInteger(value)&&value>=0)counts[key]=value}return counts}export{resolveAutomaticReadSampleRate};
3
+ //# sourceMappingURL=read-sampling.js.map
@@ -51,7 +51,7 @@ interface PendingOtelSpan {
51
51
  }
52
52
  type TelemetryCaptureLevel = "minimal" | "redacted" | "max";
53
53
  type TelemetrySourceContext = (typeof PM_TELEMETRY_SOURCE_CONTEXT_VALUES)[number];
54
- type TelemetrySourceContextSource = "inferred" | "env_override";
54
+ type TelemetrySourceContextSource = "inferred" | "env_override" | "env_override_rejected";
55
55
  interface ResolvedTelemetrySourceContext {
56
56
  source_context: TelemetrySourceContext;
57
57
  source_context_source: TelemetrySourceContextSource;
@@ -72,7 +72,7 @@ export interface ActiveTelemetryCommand {
72
72
  pm_version: string;
73
73
  /** Value that configures or reports source context for this contract. */
74
74
  source_context: TelemetrySourceContext;
75
- /** Value that configures or reports source context source for this contract. */
75
+ /** Whether attribution was inferred, explicitly accepted, or inferred after rejecting an override without retaining its value. */
76
76
  source_context_source: TelemetrySourceContextSource;
77
77
  /** Value that configures or reports installation id for this contract. */
78
78
  installation_id: string;
@@ -177,14 +177,19 @@ declare function parseBooleanTrueLike(value: string | undefined): boolean;
177
177
  declare function resolveTelemetryHttpTimeoutMs(): number;
178
178
  /** POST a JSON payload with one total timeout that covers DNS, connection, TLS, and response completion. */
179
179
  declare function postTelemetryJson(endpoint: string, headers: Record<string, string>, body: string): Promise<number>;
180
+ /** Use a trimmed package version when provided, falling back to 0.0.0 for an unknown producer version. */
180
181
  declare function normalizePmVersion(value: string | undefined): string;
182
+ /** Trim a supplied diagnostic code and omit missing or whitespace-only codes from event payloads. */
181
183
  declare function normalizeTelemetryErrorCode(value: string | undefined): string | undefined;
184
+ /** Preserve finite non-negative integer exit codes; otherwise derive zero for success and one for failure. */
182
185
  declare function normalizeTelemetryExitCode(exitCode: number | undefined, ok: boolean): number;
186
+ /** Omit categories for successful outcomes; preserve explicit failure categories or derive them from a stable error code. */
183
187
  declare function normalizeTelemetryErrorCategory(params: {
184
188
  ok: boolean;
185
189
  errorCode?: string;
186
190
  errorCategory?: TelemetryErrorCategory;
187
191
  }): TelemetryErrorCategory | undefined;
192
+ /** Resolve explicit attribution and explain rejected input without retaining its value. */
188
193
  declare function resolveTelemetrySourceContext(globalOptions: GlobalOptions): ResolvedTelemetrySourceContext;
189
194
  /**
190
195
  * Builds privacy-bounded author and agent dimensions for a telemetry payload.
@@ -225,6 +230,7 @@ declare function buildOtelSpanRequest(activeCommand: ActiveTelemetryCommand, out
225
230
  } | null;
226
231
  /** Build a bounded, capture-level-sanitized result preview. Omit undefined object values as JSON does so optional fields cannot prevent completion telemetry. */
227
232
  declare function summarizeResult(result: unknown, captureLevel?: Exclude<TelemetryCaptureLevel, "minimal">): Record<string, unknown>;
233
+ /** Build invocation metadata for the selected capture level; minimal capture retains digests while richer levels include sanitized inputs and hashed runtime context. */
228
234
  declare function buildCommandStartPayload(params: {
229
235
  captureLevel: TelemetryCaptureLevel;
230
236
  context: TelemetryCommandContext;
@@ -234,6 +240,7 @@ declare function buildCommandStartPayload(params: {
234
240
  cwdHash: string;
235
241
  installationId: string;
236
242
  }): Record<string, unknown>;
243
+ /** Build completion diagnostics with sanitized errors and failure fingerprints; minimal capture omits start timestamps and result previews. */
237
244
  declare function buildCommandFinishPayload(params: {
238
245
  captureLevel: TelemetryCaptureLevel;
239
246
  pmVersion: string;
@@ -250,6 +257,7 @@ declare function buildCommandFinishPayload(params: {
250
257
  commandResolution: TelemetryCommandResolution;
251
258
  resolutionStage: TelemetryResolutionStage;
252
259
  }): Record<string, unknown>;
260
+ /** Build error diagnostics at the selected capture level, hashing attempted inputs and redacting error text even in minimal mode. */
253
261
  declare function buildCommandErrorPayload(params: {
254
262
  captureLevel: TelemetryCaptureLevel;
255
263
  pmVersion: string;
@@ -268,43 +276,62 @@ declare function buildCommandErrorPayload(params: {
268
276
  errorCategory: TelemetryErrorCategory;
269
277
  exitCode: number;
270
278
  }): Record<string, unknown>;
279
+ /** Append an event as an independent queue transaction; compound capture transactions use the private writer while already holding the mutex. */
271
280
  declare function enqueueTelemetryEvent(globalPmRoot: string, event: TelemetryEvent): Promise<void>;
281
+ /** Recover well-shaped event envelopes from JSONL while discarding malformed lines so one corrupt record cannot strand delivery. */
272
282
  declare function parseQueueLines(raw: string): QueuedTelemetryEvent[];
283
+ /** Allow immediate retry when scheduling metadata is absent or malformed; otherwise compare its timestamp with the current time. */
273
284
  declare function isDueForRetryAt(nextAttemptAfter: string | undefined): boolean;
285
+ /** Apply the shared due-time policy to an event envelope without altering its retry metadata. */
274
286
  declare function isDueForRetry(entry: QueuedTelemetryEvent): boolean;
287
+ /** Convert a finite retention duration to a cutoff using at least one whole day; invalid durations fall back to one day. */
275
288
  declare function retentionCutoffMs(retentionDays: number): number;
289
+ /** Expire only events with a valid occurrence timestamp before the cutoff; unknown dates do not establish expiration. */
276
290
  declare function isExpiredQueueEntry(entry: QueuedTelemetryEvent, cutoffMs: number): boolean;
291
+ /** Preserve event order while removing oversized, expired, and attempt-exhausted envelopes; return the retained snapshot and removal count. */
277
292
  declare function pruneExpiredQueueEntries(entries: QueuedTelemetryEvent[], retentionDays: number): {
278
293
  entries: QueuedTelemetryEvent[];
279
294
  prunedCount: number;
280
295
  };
296
+ /** Atomically replace the event snapshot with bounded retries for transient filesystem failures; mutation callers must hold the queue mutex. */
281
297
  declare function rewriteQueue(globalPmRoot: string, entries: QueuedTelemetryEvent[]): Promise<void>;
298
+ /** Recognize only access, busy, and permission filesystem codes as transient atomic-rewrite failures. */
282
299
  declare function isRetryableQueueRewriteError(error: unknown): boolean;
300
+ /** Yield for the requested retry delay without synchronously blocking the process. */
283
301
  declare function sleep(milliseconds: number): Promise<void>;
284
- /** Append a built OTLP span request to the bounded pending-spans queue. The detached flush worker drains and POSTs these so the foreground command never performs OTLP network I/O (GH-209). Best effort: a write failure never blocks the command, and the span is simply not exported. */
302
+ /** Serialize an independent pending-span append; compound completion capture calls the private writer under its existing queue transaction. */
285
303
  declare function enqueuePendingOtelSpan(globalPmRoot: string, request: {
286
304
  endpoint: string;
287
305
  payload: unknown;
288
306
  }): Promise<void>;
307
+ /** Recover valid pending span envelopes from JSONL, skip malformed rows, and assign stable content-derived IDs to legacy entries for reconciliation. */
289
308
  declare function parsePendingOtelSpanLines(raw: string): PendingOtelSpan[];
309
+ /** Compare valid enqueue timestamps with the retention cutoff; retain unknown or malformed dates rather than inventing an age. */
290
310
  declare function isExpiredPendingOtelSpan(entry: PendingOtelSpan, cutoffMs: number): boolean;
311
+ /** Drop oversized, expired, and attempt-exhausted spans, then keep the newest entries within the pending-span cap and report every removal. */
291
312
  declare function prunePendingOtelSpans(entries: PendingOtelSpan[], retentionDays: number): {
292
313
  entries: PendingOtelSpan[];
293
314
  prunedCount: number;
294
315
  };
316
+ /** Atomically replace the span snapshot, retrying transient filesystem contention; callers coordinate mutations with the queue mutex. */
295
317
  declare function rewritePendingOtelSpans(globalPmRoot: string, entries: PendingOtelSpan[]): Promise<void>;
296
- /** Drain the pending OTLP span queue and POST due spans to their traces endpoint. Runs only inside the flush worker (detached child) or the inline test path, so the foreground command never makes OTLP network calls. Failures increment per-span attempts with backoff and are retried by a later flush; runtime state records OTLP export diagnostics for `pm health` (GH-205). */
297
318
  /** Re-read the spans queue under the mutation serializer and rewrite it with the processed spans removed/updated by id, preserving any spans a concurrent foreground process appended during the (network) flush window. `succeededIds` are dropped; `failedUpdates` patch attempts/next_attempt_after by id; all other (incl. newly-appended) entries are retained, then pruned. Returns the count of spans left in the queue. Mirrors removeFlushedEntriesFromCurrentQueue. */
298
319
  declare function reconcilePendingOtelSpansAfterFlush(globalPmRoot: string, retentionDays: number, succeededIds: ReadonlySet<string>, failedUpdates: ReadonlyMap<string, {
299
320
  attempts: number;
300
321
  next_attempt_after: string;
301
322
  }>): Promise<number>;
323
+ /** POST due spans outside the mutation mutex, then reconcile successes and retry metadata against the current queue; publish export diagnostics for health inspection. */
302
324
  declare function flushPendingOtelSpans(globalPmRoot: string, retentionDays: number): Promise<void>;
303
325
  /** Flush both telemetry artifacts under the same worker invocation: the event ingest queue and the pending OTLP span queue. Used by the detached flush worker and the inline (test) path so OTLP export always happens off the foreground command's critical path. */
304
326
  declare function flushTelemetryArtifacts(globalPmRoot: string, endpoint: string, retentionDays: number): Promise<void>;
305
- declare function withQueueMutation<T>(operation: () => Promise<T>): Promise<T>;
327
+ export { withQueueMutation as withTelemetryQueueMutation };
328
+ /** Serialize complete queue transactions across processes. The per-acquisition wait defaults to five seconds for maintenance; foreground capture supplies a shorter budget. PM_LOCK_WAIT_MS remains an explicit override. Never hold the lock during network I/O. */
329
+ declare function withQueueMutation<T>(operation: () => Promise<T>, globalPmRoot?: string, waitMs?: number): Promise<T>;
330
+ /** Read the current event snapshot, treating a missing or blank queue as empty and dropping malformed records through the shared parser. */
306
331
  declare function readCurrentQueueEntries(globalPmRoot: string): Promise<QueuedTelemetryEvent[]>;
332
+ /** Remove acknowledged event IDs and expired entries from a fresh locked snapshot, returning the retained queue including intervening appends. */
307
333
  declare function removeFlushedEntriesFromCurrentQueue(globalPmRoot: string, flushedIds: ReadonlySet<string>, retentionDays: number): Promise<QueuedTelemetryEvent[]>;
334
+ /** Send one due event batch without holding the mutation mutex, then reconcile its result against the current queue and record delivery diagnostics. */
308
335
  declare function flushQueue(globalPmRoot: string, endpoint: string, retentionDays: number): Promise<void>;
309
336
  declare function acquireTelemetryFlushLock(globalPmRoot: string): Promise<boolean>;
310
337
  declare function isFreshDirectoryLock(lockPath: string, staleMs: number): boolean;
@@ -385,9 +412,9 @@ declare function flushQueueWithProcessLock(globalPmRoot: string, endpoint: strin
385
412
  declare function scheduleTelemetryFlush(globalPmRoot: string, endpoint: string, retentionDays: number): void;
386
413
  /** Best-effort drain of event and span queues when both process consent and persisted settings permit delivery. */
387
414
  export declare function flushTelemetryQueueNow(globalPmRoot?: string): Promise<void>;
388
- /** Begin a consent-permitted invocation, deferring sampled core reads until their outcome determines pair retention. */
415
+ /** Atomically validate consent, initialize identity, and capture an invocation; defer sampled reads until their outcome determines pair retention and schedule delivery after releasing the mutex. */
389
416
  export declare function startTelemetryCommand(context: TelemetryCommandContext): Promise<ActiveTelemetryCommand | null>;
390
- /** Complete an invocation after rechecking consent, retaining every failed read and weighting selected successful pairs. */
417
+ /** Complete an invocation only while process consent, saved consent, and its installation identity still agree; retain failed reads and weight selected successful pairs. */
391
418
  export declare function finishTelemetryCommand(activeCommand: ActiveTelemetryCommand | null, outcome: TelemetryCommandOutcome): Promise<void>;
392
- /** Record an unsampled, sanitized command error without creating identity or queue state when process consent forbids capture. */
419
+ /** Atomically validate consent and append a sanitized command error with its installation identity; schedule delivery only after releasing the queue mutex. */
393
420
  export declare function emitTelemetryErrorEvent(context: TelemetryErrorEventContext): Promise<void>;