@unbrained/pm-cli 2026.11.4 → 2026.11.5

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 (219) hide show
  1. package/.agents/skills/HARNESS_COMPATIBILITY.md +1 -1
  2. package/.agents/skills/README.md +14 -14
  3. package/.agents/skills/pm-developer/SKILL.md +16 -16
  4. package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +14 -14
  5. package/.agents/skills/pm-developer/references/SCRIPTING_COMPOSITION.md +10 -10
  6. package/.agents/skills/pm-extensions/SKILL.md +13 -13
  7. package/.agents/skills/pm-extensions/references/AUTHORING.md +12 -12
  8. package/.agents/skills/pm-sdk/SKILL.md +27 -27
  9. package/.agents/skills/pm-sdk/references/SURFACE_MAP.md +32 -32
  10. package/.agents/skills/pm-test-audit/references/AUDIT.md +1 -1
  11. package/.agents/skills/pm-user/SKILL.md +35 -35
  12. package/.claude-plugin/marketplace.json +1 -1
  13. package/AGENTS.md +9 -9
  14. package/CHANGELOG.md +9 -0
  15. package/README.md +13 -13
  16. package/dist/cli/register-setup.js +1 -1
  17. package/dist/cli-bundle/bundle-manifest.json +1 -1
  18. package/dist/cli-bundle/chunks/chunk-2RPORE7M.js +31 -0
  19. package/dist/cli-bundle/chunks/{chunk-NPEDFOVQ.js → chunk-335BZ75D.js} +2 -2
  20. package/dist/cli-bundle/chunks/chunk-5GWEY4P6.js +122 -0
  21. package/dist/cli-bundle/chunks/chunk-6VRX2CM7.js +2 -0
  22. package/dist/cli-bundle/chunks/{chunk-7PGNAHNW.js → chunk-7DEKAXVA.js} +2 -2
  23. package/dist/cli-bundle/chunks/{chunk-3OXQGGRD.js → chunk-7ZRCYESH.js} +42 -41
  24. package/dist/cli-bundle/chunks/{chunk-BWAXA6S4.js → chunk-AUEKTX7V.js} +2 -2
  25. package/dist/cli-bundle/chunks/{chunk-SRDO2NJU.js → chunk-D7KYPRK4.js} +2 -2
  26. package/dist/cli-bundle/chunks/{chunk-ODMJ3HIB.js → chunk-DAX3AOFI.js} +2 -2
  27. package/dist/cli-bundle/chunks/{chunk-L4BKTPJ6.js → chunk-F6NDMKZ4.js} +2 -2
  28. package/dist/cli-bundle/chunks/{chunk-T56MB6SF.js → chunk-FRNMQM45.js} +2 -2
  29. package/dist/cli-bundle/chunks/{chunk-5S6RT5LX.js → chunk-HNGLDMSZ.js} +3 -3
  30. package/dist/cli-bundle/chunks/{chunk-QN7VCOUU.js → chunk-HRCMORE7.js} +2 -2
  31. package/dist/cli-bundle/chunks/{chunk-BK2XAQVC.js → chunk-HRFGFIYU.js} +2 -2
  32. package/dist/cli-bundle/chunks/{chunk-CERNIZLB.js → chunk-JI2GDE4I.js} +42 -42
  33. package/dist/cli-bundle/chunks/{chunk-6T2V3UIK.js → chunk-LS3GI3H4.js} +53 -53
  34. package/dist/cli-bundle/chunks/chunk-OH6WQ7VT.js +3 -0
  35. package/dist/cli-bundle/chunks/{chunk-BRIPGUAO.js → chunk-OJDMJT7Y.js} +2 -2
  36. package/dist/cli-bundle/chunks/{chunk-7RCI7AAA.js → chunk-S4LPZ4TN.js} +2 -2
  37. package/dist/cli-bundle/chunks/{chunk-AQ5UHHQS.js → chunk-UEGXWXUZ.js} +2 -2
  38. package/dist/cli-bundle/chunks/{chunk-5BVZ32G7.js → chunk-XLSHFYXZ.js} +2 -2
  39. package/dist/cli-bundle/chunks/{chunk-2GW662DP.js → chunk-YKXATU2G.js} +2 -2
  40. package/dist/cli-bundle/chunks/{item-revision-UAZOBP2Q.js → item-revision-OJJVPQY7.js} +2 -2
  41. package/dist/cli-bundle/chunks/item-transaction-QEPBUCMY.js +2 -0
  42. package/dist/cli-bundle/chunks/{mutation-admission-QZQI2NN5.js → mutation-admission-INMM3HHG.js} +2 -2
  43. package/dist/cli-bundle/chunks/{register-list-query-P3NOKQUA.js → register-list-query-5Y5JKWU5.js} +2 -2
  44. package/dist/cli-bundle/chunks/{register-mutation-A6I5K5N6.js → register-mutation-WC7OSQID.js} +2 -2
  45. package/dist/cli-bundle/chunks/{register-operations-SPKB3TNM.js → register-operations-PO63DBZH.js} +2 -2
  46. package/dist/cli-bundle/chunks/register-setup-RRFOS7IT.js +2 -0
  47. package/dist/cli-bundle/chunks/{stage-L3T725DS.js → stage-E3MMV4TV.js} +2 -2
  48. package/dist/cli-bundle/focused-chunks/chunk-5PMJOJCZ.js +44 -0
  49. package/dist/cli-bundle/focused-chunks/{chunk-TFYTTDAK.js → chunk-7KK66ISG.js} +2 -2
  50. package/dist/cli-bundle/focused-chunks/{chunk-Y5GOUUYJ.js → chunk-AHWJPZSJ.js} +2 -2
  51. package/dist/cli-bundle/focused-chunks/{chunk-C7UX2ZI3.js → chunk-C6P6HPCX.js} +2 -2
  52. package/dist/cli-bundle/focused-chunks/{chunk-Q4OIRSKL.js → chunk-CPMSL4HS.js} +2 -2
  53. package/dist/cli-bundle/focused-chunks/chunk-CZM75DE3.js +2 -0
  54. package/dist/cli-bundle/focused-chunks/{chunk-CO2DNPH7.js → chunk-D2TBEBNW.js} +2 -2
  55. package/dist/cli-bundle/focused-chunks/chunk-E56OXRYH.js +2 -0
  56. package/dist/cli-bundle/focused-chunks/{chunk-FXFDVM5O.js → chunk-F62XGAAY.js} +2 -2
  57. package/dist/cli-bundle/focused-chunks/chunk-G4QP365K.js +2 -0
  58. package/dist/cli-bundle/focused-chunks/{chunk-J7M52SCZ.js → chunk-G5PJCR7R.js} +2 -2
  59. package/dist/cli-bundle/focused-chunks/chunk-GS3JC5UU.js +23 -0
  60. package/dist/cli-bundle/focused-chunks/{chunk-W3CSX6GI.js → chunk-LW64TINU.js} +2 -2
  61. package/dist/cli-bundle/focused-chunks/{chunk-MEJKELWC.js → chunk-M6V7UMWL.js} +3 -3
  62. package/dist/cli-bundle/focused-chunks/{chunk-CXTDEQ3N.js → chunk-MC7IE7D7.js} +2 -2
  63. package/dist/cli-bundle/focused-chunks/chunk-MG7C3JUY.js +2 -0
  64. package/dist/cli-bundle/focused-chunks/{chunk-QEVJ3Y67.js → chunk-MK4HV4JO.js} +2 -2
  65. package/dist/cli-bundle/focused-chunks/{chunk-A2246ZM7.js → chunk-NQ7GYFOX.js} +54 -54
  66. package/dist/cli-bundle/focused-chunks/chunk-O7EI33NP.js +91 -0
  67. package/dist/cli-bundle/focused-chunks/{chunk-FFO7RBLN.js → chunk-RFTJZ5VB.js} +2 -2
  68. package/dist/cli-bundle/focused-chunks/{chunk-PNPYQDHU.js → chunk-SNOXXRSJ.js} +2 -2
  69. package/dist/cli-bundle/focused-chunks/{chunk-JQS7TYQ6.js → chunk-UPJUTP2V.js} +2 -2
  70. package/dist/cli-bundle/focused-chunks/{chunk-SDLIUZEL.js → chunk-VWWTIX5L.js} +2 -2
  71. package/dist/cli-bundle/focused-chunks/{chunk-J6FDCAMH.js → chunk-XHOBYCVE.js} +2 -2
  72. package/dist/cli-bundle/focused-chunks/{chunk-J3YOATXR.js → chunk-YMGB2O4E.js} +25 -24
  73. package/dist/cli-bundle/focused-chunks/{item-revision-L6GVT42D.js → item-revision-CTDO4H3I.js} +2 -2
  74. package/dist/cli-bundle/focused-chunks/{item-transaction-GYGP264N.js → item-transaction-AEAYVVHA.js} +2 -2
  75. package/dist/cli-bundle/focused-chunks/{mutation-admission-UWTH56OD.js → mutation-admission-4WM7TNHZ.js} +2 -2
  76. package/dist/cli-bundle/focused-chunks/{stage-WRSNJ7VI.js → stage-WV7QXR4C.js} +2 -2
  77. package/dist/cli-bundle/main.js +2 -2
  78. package/dist/cli-bundle/sdk-authoring.js +1 -1
  79. package/dist/cli-bundle/sdk-contracts.js +1 -1
  80. package/dist/cli-bundle/sdk-core.js +1 -1
  81. package/dist/cli-bundle/sdk-governance.js +1 -1
  82. package/dist/cli-bundle/sdk-graph.js +1 -1
  83. package/dist/cli-bundle/sdk-merge.js +57 -57
  84. package/dist/cli-bundle/sdk-query.js +1 -1
  85. package/dist/cli-bundle/sdk-runtime.js +1 -1
  86. package/dist/cli-bundle/sdk-testing.js +1 -1
  87. package/dist/cli-bundle/sdk.js +9 -9
  88. package/dist/core/config/positional-value.d.ts +6 -0
  89. package/dist/core/config/positional-value.js +1 -1
  90. package/dist/core/item/literal-mutation-input.d.ts +17 -0
  91. package/dist/core/item/literal-mutation-input.js +1 -1
  92. package/dist/core/item/parent-reference-policy.d.ts +8 -4
  93. package/dist/core/item/parent-reference-policy.js +1 -1
  94. package/dist/core/item/sprint-release-format.d.ts +2 -1
  95. package/dist/core/item/sprint-release-format.js +1 -1
  96. package/dist/core/output/mutation-projection.js +1 -1
  97. package/dist/core/store/item-mutation-precondition.d.ts +3 -1
  98. package/dist/core/store/item-mutation-precondition.js +1 -1
  99. package/dist/core/store/item-store.js +1 -1
  100. package/dist/core/store/settings.d.ts +14 -0
  101. package/dist/core/store/settings.js +5 -4
  102. package/dist/core/telemetry/policy.d.ts +27 -1
  103. package/dist/core/telemetry/policy.js +1 -1
  104. package/dist/core/telemetry/runtime.d.ts +18 -7
  105. package/dist/core/telemetry/runtime.js +4 -4
  106. package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +8 -5
  107. package/dist/sdk/cli-contracts.d.ts +1 -1
  108. package/dist/sdk/cli-contracts.js +1 -1
  109. package/dist/sdk/config.d.ts +2 -2
  110. package/dist/sdk/config.js +1 -1
  111. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  112. package/dist/sdk/governance/health.d.ts +2 -2
  113. package/dist/sdk/governance/health.js +2 -2
  114. package/dist/sdk/index.d.ts +4 -2
  115. package/dist/sdk/index.js +1 -1
  116. package/dist/sdk/init.d.ts +4 -4
  117. package/dist/sdk/init.js +8 -8
  118. package/dist/sdk/lifecycle/claim.d.ts +4 -0
  119. package/dist/sdk/lifecycle/claim.js +1 -1
  120. package/dist/sdk/lifecycle/close.d.ts +10 -0
  121. package/dist/sdk/lifecycle/close.js +1 -1
  122. package/dist/sdk/lifecycle/create.d.ts +7 -5
  123. package/dist/sdk/lifecycle/create.js +1 -1
  124. package/dist/sdk/lifecycle/shared-unset-fields.d.ts +628 -4
  125. package/dist/sdk/lifecycle/shared-unset-fields.js +1 -1
  126. package/dist/sdk/lifecycle/update.d.ts +5 -4
  127. package/dist/sdk/lifecycle/update.js +2 -2
  128. package/dist/sdk/public-surface.json +1 -1
  129. package/dist/sdk/runtime/actions.js +1 -1
  130. package/dist/sdk/runtime/mutation-value-validation.js +1 -1
  131. package/dist/sdk/runtime-input.js +1 -1
  132. package/dist/sdk/runtime-primitives.d.ts +1 -0
  133. package/dist/sdk/runtime-primitives.js +1 -1
  134. package/dist/sdk/telemetry.d.ts +1 -1
  135. package/dist/sdk/telemetry.js +2 -2
  136. package/docs/AGENT_GUIDE.md +48 -48
  137. package/docs/AGENT_OUTPUT_ENCODINGS.md +20 -20
  138. package/docs/ASSURANCE.md +10 -10
  139. package/docs/BOUNDED_CONTEXT_READS.md +3 -3
  140. package/docs/CLAUDE_CODE_PLUGIN.md +1 -1
  141. package/docs/CLI_GRAMMAR.md +2 -2
  142. package/docs/COMMANDS.md +56 -35
  143. package/docs/COMMAND_NAMESPACES.md +1 -1
  144. package/docs/CONFIGURATION.md +82 -71
  145. package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +2 -2
  146. package/docs/CONTEXT_INTEGRITY_CONTRACTS.md +5 -5
  147. package/docs/CORPUS_SHAPES.md +1 -1
  148. package/docs/DEPENDENCY_KIND_CONTRACT.md +6 -6
  149. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +5 -5
  150. package/docs/ECOSYSTEM_PLANNING_REVIEW.md +3 -3
  151. package/docs/EXTENSION_AUTHOR_CONTRACTS.md +4 -4
  152. package/docs/HISTORY_ATTESTATION.md +1 -1
  153. package/docs/HISTORY_MAINTENANCE.md +1 -1
  154. package/docs/LIFECYCLE_COMMANDS.md +1 -1
  155. package/docs/MCP_2026_07_28.md +16 -16
  156. package/docs/MCP_2026_07_28_CONFORMANCE.md +19 -19
  157. package/docs/MCP_REMOTE_TRANSPORT_SECURITY.md +22 -22
  158. package/docs/MCP_SKILLS_AND_APPS.md +1 -1
  159. package/docs/MERGE_SAFETY.md +6 -6
  160. package/docs/MUTATION_INTEGRITY.md +5 -5
  161. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +14 -14
  162. package/docs/PACKED_FIRST_RUN.md +1 -1
  163. package/docs/QUICKSTART.md +10 -10
  164. package/docs/README.md +21 -21
  165. package/docs/READ_OUTPUT_CONTRACTS.md +9 -9
  166. package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +1 -1
  167. package/docs/RELEASING.md +19 -10
  168. package/docs/SCRIPTING.md +10 -10
  169. package/docs/SDK.md +74 -38
  170. package/docs/SDK_ARTIFACT_OUTPUT.md +1 -1
  171. package/docs/SDK_PRIMITIVE_INVENTORY.md +2 -2
  172. package/docs/SELF_DESCRIBING_CONTEXT_CONTRACTS.md +7 -7
  173. package/docs/TESTING.md +1 -1
  174. package/docs/WORKFLOW_POLICIES.md +2 -2
  175. package/docs/WORKSPACE_POSITION_AND_LIFECYCLE.md +8 -8
  176. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +1 -1
  177. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
  178. package/docs/generated/FLAG_LEXICON_BUDGETS.md +1 -1
  179. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +1 -1
  180. package/docs/performance/cli-transport-overhead.md +7 -7
  181. package/marketplace.json +1 -1
  182. package/package.json +1 -1
  183. package/packages/pm-beads/package.json +1 -1
  184. package/packages/pm-calendar/package.json +1 -1
  185. package/packages/pm-command-kit/README.md +5 -5
  186. package/packages/pm-command-kit/package.json +1 -1
  187. package/packages/pm-digital-twin/GAP_REPORT.md +16 -16
  188. package/packages/pm-digital-twin/package.json +1 -1
  189. package/packages/pm-governance-audit/package.json +1 -1
  190. package/packages/pm-guide-shell/package.json +1 -1
  191. package/packages/pm-kanban/README.md +1 -1
  192. package/packages/pm-kanban/package.json +1 -1
  193. package/packages/pm-lifecycle-hooks/package.json +1 -1
  194. package/packages/pm-linked-test-adapters/package.json +1 -1
  195. package/packages/pm-search-advanced/package.json +1 -1
  196. package/packages/pm-templates/package.json +1 -1
  197. package/packages/pm-todos/package.json +1 -1
  198. package/packages/pm-vcs/GAP_REPORT.md +1 -1
  199. package/packages/pm-vcs/package.json +1 -1
  200. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  201. package/plugins/pm-claude/README.md +6 -6
  202. package/plugins/pm-claude/package.json +1 -1
  203. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  204. package/plugins/pm-codex/package.json +1 -1
  205. package/plugins/pm-codex/plugin.json +1 -1
  206. package/runtime-dependencies.json +1 -1
  207. package/dist/cli-bundle/chunks/chunk-5Z6LWFDL.js +0 -31
  208. package/dist/cli-bundle/chunks/chunk-DSCFJTHB.js +0 -122
  209. package/dist/cli-bundle/chunks/chunk-QQHMNUZT.js +0 -2
  210. package/dist/cli-bundle/chunks/chunk-TX2W6G37.js +0 -3
  211. package/dist/cli-bundle/chunks/item-transaction-N5F4LXYV.js +0 -2
  212. package/dist/cli-bundle/chunks/register-setup-ZZRHJ4IS.js +0 -2
  213. package/dist/cli-bundle/focused-chunks/chunk-5NGNO54M.js +0 -44
  214. package/dist/cli-bundle/focused-chunks/chunk-B6U44WPW.js +0 -2
  215. package/dist/cli-bundle/focused-chunks/chunk-BAW3DGQO.js +0 -91
  216. package/dist/cli-bundle/focused-chunks/chunk-BHNY3KPJ.js +0 -2
  217. package/dist/cli-bundle/focused-chunks/chunk-CBG67HUP.js +0 -23
  218. package/dist/cli-bundle/focused-chunks/chunk-FEPE2CE4.js +0 -2
  219. package/dist/cli-bundle/focused-chunks/chunk-PMKR4MJI.js +0 -2
@@ -59,7 +59,7 @@ ok:boolean;
59
59
  path:string;
60
60
  /** Value that configures or reports target for this contract. */
61
61
  target:InitTargetResolution;
62
- /** Value that configures or reports settings for this contract. */
62
+ /** The tracker settings, with telemetry consent and capture level from the global profile, which the runtime reads (GH-1660). */
63
63
  settings:PmSettings;
64
64
  /** Value that configures or reports created dirs for this contract. */
65
65
  created_dirs:string[];
@@ -147,7 +147,7 @@ ok:boolean;
147
147
  path:string;
148
148
  /** Governance policy selected for this workspace. */
149
149
  governance_preset:GovernancePreset;
150
- /** Project telemetry consent and capture level. */
150
+ /** Telemetry consent and capture level from the global profile, which the runtime reads. */
151
151
  telemetry:string;
152
152
  /** Number of created directories and schema files. */
153
153
  created_count:number;
@@ -203,10 +203,10 @@ declare function summarizeInstalledPackages(result:ExtensionCommandResult):InitI
203
203
  declare function registerInitTypePreset(pmRoot:string,settings:PmSettings,preset:InitTypePresetName):Promise<InitRegisteredTypePresetSummary>;
204
204
  declare function isLikelyWorkspaceRoot(candidate:string):Promise<boolean>;
205
205
  declare function assertExplicitTrackerPathIsNotWorkspaceRoot(pmRoot:string,explicitTrackerTarget:boolean,force:boolean):Promise<void>;
206
- declare function runInitWizard(initialPrefix:string,telemetryDefault:boolean):Promise<{
206
+ declare function runInitWizard(initialPrefix:string,telemetryDefault:boolean | undefined):Promise<{
207
207
  prefix:string;
208
208
  preset:BuiltinGovernancePreset;
209
- telemetry_enabled:boolean;
209
+ telemetry_enabled:boolean | undefined;
210
210
  }>;
211
211
  declare function buildInitNextSteps(params:{
212
212
  installBundledPackages:boolean;
package/dist/sdk/init.js CHANGED
@@ -1,17 +1,17 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ffab1407-659d-5bc4-95ff-5efe52baf522")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import readline from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import{getActiveExtensionRegistrations,runActiveOnWriteHooks}from"../core/extensions/index.js";import{pathExists,readFileIfExists}from"../core/fs/fs-utils.js";import{writeWorkspaceJsonWithHistory}from"../core/history/workspace-history.js";import{normalizePrefix}from"../core/item/id.js";import{resolveItemTypeRegistry}from"../core/item/type-registry.js";import{DEFAULT_RUNTIME_SCHEMA_FILE_PATHS,ensureRuntimeSchemaFileScaffold,filePathForSchemaSection,normalizeRuntimeSchemaSettings}from"../core/schema/runtime-schema.js";import{parseItemTypesFile,serializeItemTypesFile,upsertItemType}from"../core/schema/item-types-file.js";import{normalizeTypePresetName,resolveTypePresetDefinitions,TYPE_PRESET_NAMES}from"../core/schema/type-presets.js";import{EXIT_CODE,GOVERNANCE_PRESET_DEFAULTS,PM_REQUIRED_SUBDIRS,SETTINGS_DEFAULTS}from"../core/shared/constants.js";import{readAuthorEnvironment,resolveAuthor}from"../core/shared/author.js";import{PmCliError}from"../core/shared/errors.js";import{resolvePmRoot}from"../core/store/paths.js";import{readSettings,writeSettings}from"../core/store/settings.js";import{ensurePmGitignore}from"./workspace.js";import{renderPmCommand}from"./command-line.js";import{runExtension}from"./extension.js";import{INIT_AGENT_GUIDANCE_MODE_VALUES,runInitAgentGuidance}from"./init-agent-guidance.js";import{findGitWorkspaceRoot,installMergeFence}from"./merge/install.js";const INIT_INVOCATION_CWD=Symbol.for("pm.sdk.init-invocation-cwd");function summarizeInitResult(result,display=!1){if(display){const warnings=result.warnings.filter(warning=>!/^(?:already_exists:|updated:|registered_type_preset:)/u.test(warning)),guidanceSteps=warnings.includes("agent_guidance:missing_non_interactive")?result.next_steps.filter(step=>step.includes("--agent-guidance")):[];return{ok:result.ok,path:result.path,governance_preset:result.governance_preset,telemetry:`${result.settings.telemetry.enabled?"enabled":"disabled"} (${result.settings.telemetry.capture_level})`,created_count:result.created_dirs.length,next_steps:[...guidanceSteps,...result.next_steps.filter(step=>!guidanceSteps.includes(step))].slice(0,3),...warnings.length>0?{warnings:warnings.join("; ")}:{},details:`${renderPmCommand(["--pm-path",result.path,"init","--verbose"])} for full setup details and notices (or --json)`}}return{ok:result.ok,path:result.path,target:result.target,id_prefix:result.settings.id_prefix,governance_preset:result.governance_preset,telemetry:{enabled:result.settings.telemetry.enabled,capture_level:result.settings.telemetry.capture_level},output_format:result.settings.output.default_format,created_dirs_count:result.created_dirs.length,created_dirs:result.created_dirs,warnings:result.warnings,wizard_used:result.wizard_used,...result.registered_type_preset?{registered_type_preset:result.registered_type_preset}:{},...result.installed_packages?{installed_packages:result.installed_packages}:{},next_steps:result.next_steps,agent_guidance:result.agent_guidance,hint:"Re-run with --verbose for the full settings tree."}}const _testOnly={normalizeInitGovernancePreset,normalizeInitTypePreset,normalizeOptionalInitAuthor,normalizeInitAgentGuidanceMode,isPathLikeInitTarget,resolveInitInvocation,resolveInitPrefixInput,parseYesNoChoice,applyGovernancePreset,runInitWizard,setInitReadlineFactoryForTests,summarizeInstalledPackages,buildInitNextSteps,registerInitTypePreset,assertExplicitTrackerPathIsNotWorkspaceRoot,isLikelyWorkspaceRoot,installInitMergeFence};let createInitReadlineInterface=()=>readline.createInterface({input,output});function setInitReadlineFactoryForTests(factory){createInitReadlineInterface=factory??(()=>readline.createInterface({input,output}))}function cloneDefaults(){return structuredClone(SETTINGS_DEFAULTS)}const BUILTIN_GOVERNANCE_PRESETS=["minimal","default","strict"];function normalizeInitGovernancePreset(rawValue){if(rawValue===void 0)return;const normalized=rawValue.trim().toLowerCase().replaceAll("-","_");if(normalized.length===0)throw new PmCliError("--preset must not be empty",EXIT_CODE.USAGE);if(normalized==="minimal"||normalized==="default"||normalized==="strict")return normalized;if(normalized==="lite"||normalized==="minimum")return"minimal";throw new PmCliError(`Invalid --preset value "${rawValue}". Allowed: ${BUILTIN_GOVERNANCE_PRESETS.join(", ")}`,EXIT_CODE.USAGE)}function normalizeInitTypePreset(rawValue){if(rawValue!==void 0){if(rawValue.trim().length===0)throw new PmCliError("--type-preset must not be empty",EXIT_CODE.USAGE);try{return normalizeTypePresetName(rawValue)}catch{throw new PmCliError(`Invalid --type-preset value "${rawValue}". Allowed: ${TYPE_PRESET_NAMES.join(", ")}`,EXIT_CODE.USAGE)}}}function normalizeOptionalInitAuthor(rawValue){if(rawValue===void 0)return;const normalized=rawValue.trim();if(normalized.length===0)throw new PmCliError("--author must not be empty",EXIT_CODE.USAGE);return normalized}function isPathLikeInitTarget(rawValue){if(rawValue===void 0)return!1;const trimmed=rawValue.trim();return trimmed.length===0?!1:path.isAbsolute(trimmed)||/^[a-z]:/iu.test(trimmed)||trimmed.startsWith(".")||trimmed.includes("/")||trimmed.includes("\\")}function resolveInitInvocation(cwd,global2,prefixArg,workspaceArg){const normalizedWorkspace=workspaceArg?.trim();if(workspaceArg!==void 0&&normalizedWorkspace?.length===0)throw new PmCliError("--workspace must not be empty",EXIT_CODE.USAGE);if(normalizedWorkspace!==void 0){if(global2.path!==void 0||isPathLikeInitTarget(prefixArg))throw new PmCliError("--workspace cannot be combined with --pm-path/--path or a path-like positional target.",EXIT_CODE.USAGE);const workspaceRoot=path.resolve(cwd,normalizedWorkspace),pmRoot2=path.join(workspaceRoot,".agents","pm");return{pmRoot:pmRoot2,prefixArg,target:{mode:"workspace-path",tracker_root:pmRoot2,workspace_root:workspaceRoot}}}if(global2.path===void 0&&isPathLikeInitTarget(prefixArg)){const positionalTarget=path.resolve(cwd,prefixArg.trim());return{pmRoot:positionalTarget,prefixArg:void 0,target:{mode:"tracker-path",tracker_root:positionalTarget}}}const pmRoot=resolvePmRoot(cwd,global2.path),currentTrackerRoot=path.join(path.resolve(cwd),".agents","pm"),discoveredWorkspaceRoot=path.dirname(path.dirname(pmRoot)),discovery=path.resolve(pmRoot)===currentTrackerRoot?"current":"ancestor";return{pmRoot,prefixArg,target:global2.path===void 0?{mode:"workspace-discovery",tracker_root:pmRoot,workspace_root:discoveredWorkspaceRoot,discovery,requested_cwd:path.resolve(cwd),...discovery==="ancestor"?{suggested_current_tracker_root:currentTrackerRoot}:{}}:{mode:"tracker-path",tracker_root:pmRoot}}}function resolveInitPrefixInput(positionalPrefix,flaggedPrefix){if(flaggedPrefix===void 0)return positionalPrefix;if(flaggedPrefix.trim().length===0)throw new PmCliError("--id-prefix must not be empty",EXIT_CODE.USAGE);if(isPathLikeInitTarget(flaggedPrefix))throw new PmCliError(`--id-prefix accepts an item ID prefix, not a tracker path: "${flaggedPrefix}".`,EXIT_CODE.USAGE,{code:"init_id_prefix_path_like",required:"Pass the tracker path positionally or with the global --path option.",examples:[`pm init ${flaggedPrefix}`,`pm --path ${flaggedPrefix} init`]});if(positionalPrefix!==void 0&&normalizePrefix(positionalPrefix)!==normalizePrefix(flaggedPrefix))throw new PmCliError(`Conflicting id prefixes: positional "${positionalPrefix}" and --id-prefix "${flaggedPrefix}".`,EXIT_CODE.USAGE,{code:"init_id_prefix_conflict",required:"Use either the positional id prefix or --id-prefix with one value.",examples:[`pm init ${normalizePrefix(positionalPrefix)}`,`pm init --id-prefix ${normalizePrefix(flaggedPrefix)}`]});return flaggedPrefix}function normalizeInitAgentGuidanceMode(rawValue){if(rawValue===void 0)return"ask";const normalized=rawValue.trim().toLowerCase().replaceAll("-","_");if(normalized.length===0)throw new PmCliError("--agent-guidance must not be empty",EXIT_CODE.USAGE);if(normalized==="ask"||normalized==="add"||normalized==="skip"||normalized==="status")return normalized;throw new PmCliError(`Invalid --agent-guidance value "${rawValue}". Allowed: ${INIT_AGENT_GUIDANCE_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseYesNoChoice(answer,currentDefault){const normalized=answer.trim().toLowerCase();return normalized.length===0?currentDefault:normalized==="y"||normalized==="yes"?!0:normalized==="n"||normalized==="no"?!1:currentDefault}function applyGovernancePreset(settings,preset){const knobs=GOVERNANCE_PRESET_DEFAULTS[preset];settings.governance={preset,...knobs},settings.validation.parent_reference=knobs.parent_reference,settings.validation.metadata_profile=knobs.metadata_profile}function isInstalledPackageEntry(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function summarizeInstalledPackages(result){const details=result.details;return{installed_all:details.installed_all===!0,installed_count:typeof details.installed_count=="number"?details.installed_count:0,packages:Array.isArray(details.packages)?details.packages.filter(isInstalledPackageEntry).map(entry=>({alias:typeof entry.alias=="string"?entry.alias:"",ok:entry.ok===!0})):[]}}async function registerInitTypePreset(pmRoot,settings,preset){const schema=normalizeRuntimeSchemaSettings(settings.schema),typesPath=filePathForSchemaSection(pmRoot,schema.files.types,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.types);let nextFile=parseItemTypesFile(await readFileIfExists(typesPath));const registered=[],updated=[];for(const normalized of resolveTypePresetDefinitions(preset)){const upsert=upsertItemType(nextFile,normalized);nextFile=upsert.file,(upsert.replaced?updated:registered).push(upsert.definition.name)}return await writeWorkspaceJsonWithHistory({pmRoot,filePath:typesPath,raw:serializeItemTypesFile(nextFile),op:"init:type-preset",author:resolveAuthor(void 0,settings.author_default),lockTtlSeconds:settings.locks.ttl_seconds,lockWaitMs:settings.locks.wait_ms}),{name:preset,registered,updated,file:typesPath}}async function isLikelyWorkspaceRoot(candidate){const indicators=[".git","package.json","pnpm-workspace.yaml","AGENTS.md",path.join(".agents","pm")];for(const indicator of indicators)if(await pathExists(path.join(candidate,indicator)))return!0;return!1}async function assertExplicitTrackerPathIsNotWorkspaceRoot(pmRoot,explicitTrackerTarget,force){if(!explicitTrackerTarget||force||await pathExists(path.join(pmRoot,"settings.json"))||!await isLikelyWorkspaceRoot(pmRoot))return;const nestedTracker=path.join(pmRoot,".agents","pm");throw new PmCliError(`Refusing to initialize tracker files directly in workspace root "${pmRoot}".`,EXIT_CODE.USAGE,{code:"workspace_root_pm_path",type:"urn:pm-cli:error:workspace_root_pm_path",why:"Path-like init targets and --pm-path/--path point at the tracker storage directory itself, not the repository workspace. Point at .agents/pm, use --workspace, or pass --force if you intentionally want root-level tracker files.",examples:[`pm --pm-path ${nestedTracker} init --yes`,"pm init --yes",`pm --pm-path ${pmRoot} init --yes --force`],nextSteps:["Use --pm-path <repo>/.agents/pm for repository-local tracker storage.","Use PM_PATH only for sandboxed tests or explicit tracker roots.","Pass --force only when root-level tracker files are intentional."],recovery:{next_best_command:`pm --pm-path ${nestedTracker} init --yes`}})}async function ensureInitDirectories(pmRoot,subdirs){const createdDirs=[],warnings=[];for(const subdir of subdirs){const target=subdir?path.join(pmRoot,subdir):pmRoot,existed=await pathExists(target);await fs.mkdir(target,{recursive:!0}),existed?warnings.push(`already_exists:${target}`):createdDirs.push(target),warnings.push(...await runActiveOnWriteHooks({path:target,scope:"project",op:"init:ensure_dir"}))}return{createdDirs,warnings}}async function runInitWizard(initialPrefix,telemetryDefault){const rl=createInitReadlineInterface();try{output.write(`pm init setup wizard (agent-optimized)
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0bfdfae5-a153-5cc1-9946-aa2ef215aa85")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import readline from"node:readline/promises";import{stdin as input,stdout as output}from"node:process";import{getActiveExtensionRegistrations,runActiveOnWriteHooks}from"../core/extensions/index.js";import{pathExists,readFileIfExists}from"../core/fs/fs-utils.js";import{writeWorkspaceJsonWithHistory}from"../core/history/workspace-history.js";import{normalizePrefix}from"../core/item/id.js";import{resolveItemTypeRegistry}from"../core/item/type-registry.js";import{DEFAULT_RUNTIME_SCHEMA_FILE_PATHS,ensureRuntimeSchemaFileScaffold,filePathForSchemaSection,normalizeRuntimeSchemaSettings}from"../core/schema/runtime-schema.js";import{parseItemTypesFile,serializeItemTypesFile,upsertItemType}from"../core/schema/item-types-file.js";import{normalizeTypePresetName,resolveTypePresetDefinitions,TYPE_PRESET_NAMES}from"../core/schema/type-presets.js";import{EXIT_CODE,GOVERNANCE_PRESET_DEFAULTS,PM_REQUIRED_SUBDIRS,SETTINGS_DEFAULTS}from"../core/shared/constants.js";import{readAuthorEnvironment,resolveAuthor}from"../core/shared/author.js";import{PmCliError}from"../core/shared/errors.js";import{resolveGlobalPmRoot,resolvePmRoot}from"../core/store/paths.js";import{resolveTelemetryEnvironmentPolicy}from"../core/telemetry/policy.js";import{isSettingsReadFallback,readSettings,writeSettings}from"../core/store/settings.js";import{ensurePmGitignore}from"./workspace.js";import{renderPmCommand}from"./command-line.js";import{runExtension}from"./extension.js";import{INIT_AGENT_GUIDANCE_MODE_VALUES,runInitAgentGuidance}from"./init-agent-guidance.js";import{findGitWorkspaceRoot,installMergeFence}from"./merge/install.js";const INIT_INVOCATION_CWD=Symbol.for("pm.sdk.init-invocation-cwd");function summarizeInitResult(result,display=!1){if(display){const warnings=result.warnings.filter(warning=>!/^(?:already_exists:|updated:|registered_type_preset:)/u.test(warning)),guidanceSteps=warnings.includes("agent_guidance:missing_non_interactive")?result.next_steps.filter(step=>step.includes("--agent-guidance")):[];return{ok:result.ok,path:result.path,governance_preset:result.governance_preset,telemetry:`${result.settings.telemetry.enabled?"enabled":"disabled"} (${result.settings.telemetry.capture_level})`,created_count:result.created_dirs.length,next_steps:[...guidanceSteps,...result.next_steps.filter(step=>!guidanceSteps.includes(step))].slice(0,3),...warnings.length>0?{warnings:warnings.join("; ")}:{},details:`${renderPmCommand(["--pm-path",result.path,"init","--verbose"])} for full setup details and notices (or --json)`}}return{ok:result.ok,path:result.path,target:result.target,id_prefix:result.settings.id_prefix,governance_preset:result.governance_preset,telemetry:{enabled:result.settings.telemetry.enabled,capture_level:result.settings.telemetry.capture_level},output_format:result.settings.output.default_format,created_dirs_count:result.created_dirs.length,created_dirs:result.created_dirs,warnings:result.warnings,wizard_used:result.wizard_used,...result.registered_type_preset?{registered_type_preset:result.registered_type_preset}:{},...result.installed_packages?{installed_packages:result.installed_packages}:{},next_steps:result.next_steps,agent_guidance:result.agent_guidance,hint:"Re-run with --verbose for the full settings tree."}}const _testOnly={normalizeInitGovernancePreset,normalizeInitTypePreset,normalizeOptionalInitAuthor,normalizeInitAgentGuidanceMode,isPathLikeInitTarget,resolveInitInvocation,resolveInitPrefixInput,parseYesNoChoice,applyGovernancePreset,runInitWizard,setInitReadlineFactoryForTests,summarizeInstalledPackages,buildInitNextSteps,registerInitTypePreset,assertExplicitTrackerPathIsNotWorkspaceRoot,isLikelyWorkspaceRoot,installInitMergeFence};let createInitReadlineInterface=()=>readline.createInterface({input,output});function setInitReadlineFactoryForTests(factory){createInitReadlineInterface=factory??(()=>readline.createInterface({input,output}))}function cloneDefaults(){return structuredClone(SETTINGS_DEFAULTS)}const BUILTIN_GOVERNANCE_PRESETS=["minimal","default","strict"];function normalizeInitGovernancePreset(rawValue){if(rawValue===void 0)return;const normalized=rawValue.trim().toLowerCase().replaceAll("-","_");if(normalized.length===0)throw new PmCliError("--preset must not be empty",EXIT_CODE.USAGE);if(normalized==="minimal"||normalized==="default"||normalized==="strict")return normalized;if(normalized==="lite"||normalized==="minimum")return"minimal";throw new PmCliError(`Invalid --preset value "${rawValue}". Allowed: ${BUILTIN_GOVERNANCE_PRESETS.join(", ")}`,EXIT_CODE.USAGE)}function normalizeInitTypePreset(rawValue){if(rawValue!==void 0){if(rawValue.trim().length===0)throw new PmCliError("--type-preset must not be empty",EXIT_CODE.USAGE);try{return normalizeTypePresetName(rawValue)}catch{throw new PmCliError(`Invalid --type-preset value "${rawValue}". Allowed: ${TYPE_PRESET_NAMES.join(", ")}`,EXIT_CODE.USAGE)}}}function normalizeOptionalInitAuthor(rawValue){if(rawValue===void 0)return;const normalized=rawValue.trim();if(normalized.length===0)throw new PmCliError("--author must not be empty",EXIT_CODE.USAGE);return normalized}function isPathLikeInitTarget(rawValue){if(rawValue===void 0)return!1;const trimmed=rawValue.trim();return trimmed.length===0?!1:path.isAbsolute(trimmed)||/^[a-z]:/iu.test(trimmed)||trimmed.startsWith(".")||trimmed.includes("/")||trimmed.includes("\\")}function resolveInitInvocation(cwd,global2,prefixArg,workspaceArg){const normalizedWorkspace=workspaceArg?.trim();if(workspaceArg!==void 0&&normalizedWorkspace?.length===0)throw new PmCliError("--workspace must not be empty",EXIT_CODE.USAGE);if(normalizedWorkspace!==void 0){if(global2.path!==void 0||isPathLikeInitTarget(prefixArg))throw new PmCliError("--workspace cannot be combined with --pm-path/--path or a path-like positional target.",EXIT_CODE.USAGE);const workspaceRoot=path.resolve(cwd,normalizedWorkspace),pmRoot2=path.join(workspaceRoot,".agents","pm");return{pmRoot:pmRoot2,prefixArg,target:{mode:"workspace-path",tracker_root:pmRoot2,workspace_root:workspaceRoot}}}if(global2.path===void 0&&isPathLikeInitTarget(prefixArg)){const positionalTarget=path.resolve(cwd,prefixArg.trim());return{pmRoot:positionalTarget,prefixArg:void 0,target:{mode:"tracker-path",tracker_root:positionalTarget}}}const pmRoot=resolvePmRoot(cwd,global2.path),currentTrackerRoot=path.join(path.resolve(cwd),".agents","pm"),discoveredWorkspaceRoot=path.dirname(path.dirname(pmRoot)),discovery=path.resolve(pmRoot)===currentTrackerRoot?"current":"ancestor";return{pmRoot,prefixArg,target:global2.path===void 0?{mode:"workspace-discovery",tracker_root:pmRoot,workspace_root:discoveredWorkspaceRoot,discovery,requested_cwd:path.resolve(cwd),...discovery==="ancestor"?{suggested_current_tracker_root:currentTrackerRoot}:{}}:{mode:"tracker-path",tracker_root:pmRoot}}}function resolveInitPrefixInput(positionalPrefix,flaggedPrefix){if(flaggedPrefix===void 0)return positionalPrefix;if(flaggedPrefix.trim().length===0)throw new PmCliError("--id-prefix must not be empty",EXIT_CODE.USAGE);if(isPathLikeInitTarget(flaggedPrefix))throw new PmCliError(`--id-prefix accepts an item ID prefix, not a tracker path: "${flaggedPrefix}".`,EXIT_CODE.USAGE,{code:"init_id_prefix_path_like",required:"Pass the tracker path positionally or with the global --path option.",examples:[`pm init ${flaggedPrefix}`,`pm --path ${flaggedPrefix} init`]});if(positionalPrefix!==void 0&&normalizePrefix(positionalPrefix)!==normalizePrefix(flaggedPrefix))throw new PmCliError(`Conflicting id prefixes: positional "${positionalPrefix}" and --id-prefix "${flaggedPrefix}".`,EXIT_CODE.USAGE,{code:"init_id_prefix_conflict",required:"Use either the positional id prefix or --id-prefix with one value.",examples:[`pm init ${normalizePrefix(positionalPrefix)}`,`pm init --id-prefix ${normalizePrefix(flaggedPrefix)}`]});return flaggedPrefix}function normalizeInitAgentGuidanceMode(rawValue){if(rawValue===void 0)return"ask";const normalized=rawValue.trim().toLowerCase().replaceAll("-","_");if(normalized.length===0)throw new PmCliError("--agent-guidance must not be empty",EXIT_CODE.USAGE);if(normalized==="ask"||normalized==="add"||normalized==="skip"||normalized==="status")return normalized;throw new PmCliError(`Invalid --agent-guidance value "${rawValue}". Allowed: ${INIT_AGENT_GUIDANCE_MODE_VALUES.join(", ")}`,EXIT_CODE.USAGE)}function parseYesNoChoice(answer,currentDefault){const normalized=answer.trim().toLowerCase();return normalized.length===0?currentDefault:normalized==="y"||normalized==="yes"?!0:normalized==="n"||normalized==="no"?!1:currentDefault}function applyGovernancePreset(settings,preset){const knobs=GOVERNANCE_PRESET_DEFAULTS[preset];settings.governance={preset,...knobs},settings.validation.parent_reference=knobs.parent_reference,settings.validation.metadata_profile=knobs.metadata_profile}function isInstalledPackageEntry(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function summarizeInstalledPackages(result){const details=result.details;return{installed_all:details.installed_all===!0,installed_count:typeof details.installed_count=="number"?details.installed_count:0,packages:Array.isArray(details.packages)?details.packages.filter(isInstalledPackageEntry).map(entry=>({alias:typeof entry.alias=="string"?entry.alias:"",ok:entry.ok===!0})):[]}}async function registerInitTypePreset(pmRoot,settings,preset){const schema=normalizeRuntimeSchemaSettings(settings.schema),typesPath=filePathForSchemaSection(pmRoot,schema.files.types,DEFAULT_RUNTIME_SCHEMA_FILE_PATHS.types);let nextFile=parseItemTypesFile(await readFileIfExists(typesPath));const registered=[],updated=[];for(const normalized of resolveTypePresetDefinitions(preset)){const upsert=upsertItemType(nextFile,normalized);nextFile=upsert.file,(upsert.replaced?updated:registered).push(upsert.definition.name)}return await writeWorkspaceJsonWithHistory({pmRoot,filePath:typesPath,raw:serializeItemTypesFile(nextFile),op:"init:type-preset",author:resolveAuthor(void 0,settings.author_default),lockTtlSeconds:settings.locks.ttl_seconds,lockWaitMs:settings.locks.wait_ms}),{name:preset,registered,updated,file:typesPath}}async function isLikelyWorkspaceRoot(candidate){const indicators=[".git","package.json","pnpm-workspace.yaml","AGENTS.md",path.join(".agents","pm")];for(const indicator of indicators)if(await pathExists(path.join(candidate,indicator)))return!0;return!1}async function assertExplicitTrackerPathIsNotWorkspaceRoot(pmRoot,explicitTrackerTarget,force){if(!explicitTrackerTarget||force||await pathExists(path.join(pmRoot,"settings.json"))||!await isLikelyWorkspaceRoot(pmRoot))return;const nestedTracker=path.join(pmRoot,".agents","pm");throw new PmCliError(`Refusing to initialize tracker files directly in workspace root "${pmRoot}".`,EXIT_CODE.USAGE,{code:"workspace_root_pm_path",type:"urn:pm-cli:error:workspace_root_pm_path",why:"Path-like init targets and --pm-path/--path point at the tracker storage directory itself, not the repository workspace. Point at .agents/pm, use --workspace, or pass --force if you intentionally want root-level tracker files.",examples:[`pm --pm-path ${nestedTracker} init --yes`,"pm init --yes",`pm --pm-path ${pmRoot} init --yes --force`],nextSteps:["Use --pm-path <repo>/.agents/pm for repository-local tracker storage.","Use PM_PATH only for sandboxed tests or explicit tracker roots.","Pass --force only when root-level tracker files are intentional."],recovery:{next_best_command:`pm --pm-path ${nestedTracker} init --yes`}})}async function ensureInitDirectories(pmRoot,subdirs){const createdDirs=[],warnings=[];for(const subdir of subdirs){const target=subdir?path.join(pmRoot,subdir):pmRoot,existed=await pathExists(target);await fs.mkdir(target,{recursive:!0}),existed?warnings.push(`already_exists:${target}`):createdDirs.push(target),warnings.push(...await runActiveOnWriteHooks({path:target,scope:"project",op:"init:ensure_dir"}))}return{createdDirs,warnings}}async function runInitWizard(initialPrefix,telemetryDefault){const rl=createInitReadlineInterface(),steps=telemetryDefault===void 0?2:3;try{output.write(`pm init setup wizard (agent-optimized)
2
2
  `),output.write(`This walkthrough is non-destructive and each choice can be changed later with pm config.
3
3
 
4
- `),output.write(`1/3 Item ID prefix
4
+ `),output.write(`1/${steps} Item ID prefix
5
5
  `),output.write(`Prefix is prepended to generated IDs (for example pm-a1b2).
6
6
  `);const prefixAnswer=await rl.question(`Item ID prefix [${initialPrefix}]: `),resolvedPrefix=prefixAnswer.trim().length>0?normalizePrefix(prefixAnswer):initialPrefix;output.write(`
7
- 2/3 Governance preset
7
+ 2/${steps} Governance preset
8
8
  `),output.write(`minimal: no ownership blocking, progressive create defaults, close validation off.
9
9
  `),output.write(`default: ownership conflict warnings, progressive create defaults, close validation warn.
10
10
  `),output.write(`strict: ownership blocking, strict create defaults, close validation strict.
11
11
  `);const presetAnswer=await rl.question("Governance preset [minimal/default/strict] (default: minimal): "),presetChoice=presetAnswer.trim().length>0?presetAnswer.trim():"minimal";let resolvedPreset="minimal";try{resolvedPreset=normalizeInitGovernancePreset(presetChoice)}catch{output.write(`Unrecognized governance preset "${presetChoice}"; using minimal.
12
- `)}output.write(`
13
- 3/3 Project telemetry
14
- `),output.write(`Telemetry helps improve reliability and can be disabled anytime via pm config.
15
- `);const telemetryLabel=telemetryDefault?"Y/n":"y/N",telemetryAnswer=await rl.question(`Enable telemetry for this project? [${telemetryLabel}] `),telemetryEnabled=parseYesNoChoice(telemetryAnswer,telemetryDefault);return output.write(`
16
- `),{prefix:resolvedPrefix,preset:resolvedPreset,telemetry_enabled:telemetryEnabled}}finally{rl.close()}}function normalizeInitCommandOptions(options){return{presetFromOption:normalizeInitGovernancePreset(options.preset),useDefaults:options.defaults===!0,authorFromOption:normalizeOptionalInitAuthor(options.author),installBundledPackages:options.withPackages===!0,agentGuidanceMode:normalizeInitAgentGuidanceMode(options.agentGuidance),typePreset:normalizeInitTypePreset(options.typePreset)}}function collectExistingSettingsPendingChanges(params){const pendingChanges=[];return params.prefixArg!==void 0&&params.settings.id_prefix!==params.normalizedPrefix&&pendingChanges.push("id_prefix"),params.presetFromOption!==void 0&&params.settings.governance.preset!==params.presetFromOption&&pendingChanges.push("governance_preset"),params.authorFromOption!==void 0&&params.settings.author_default!==params.authorFromOption&&pendingChanges.push("author_default"),pendingChanges}function assertExistingSettingsUpdateAllowed(settingsPath,pendingChanges,force,target){if(pendingChanges.length===0||force)return;const ancestorDiscovery=target.discovery==="ancestor";throw new PmCliError(`${ancestorDiscovery?`No tracker exists in ${target.requested_cwd}; pm init found an ancestor tracker at ${target.tracker_root}. `:""}Refusing to update existing tracker settings at ${settingsPath} without --force.`,EXIT_CODE.USAGE,{code:"init_existing_settings_requires_force",type:"urn:pm-cli:error:init_existing_settings_requires_force",required:`--force for ${pendingChanges.join(", ")}`,why:ancestorDiscovery?"Ancestor discovery is useful for normal commands, but init must make the selected existing workspace explicit before changing its identity or policy settings.":"pm init is safe to rerun, but changing id prefix, governance preset, or default author on an existing tracker can corrupt long-lived project context when an agent meant to initialize a sandbox path.",resolved_path:target.tracker_root,requested_path:target.requested_cwd,suggested_path:target.suggested_current_tracker_root,examples:["pm init --yes","pm init ./sandbox-pm --yes",...ancestorDiscovery?['pm init <name> --yes --pm-path "$PWD/.agents/pm"']:[],"pm init acme --yes --force"],nextSteps:[...ancestorDiscovery?['To create a new tracker in the current directory, rerun with --pm-path "$PWD/.agents/pm".']:[],"If you meant to initialize a sandbox tracker, pass a path-like positional such as ./sandbox-pm or /tmp/pm-test.","If you intentionally want to rewrite this existing tracker's init-managed settings, rerun with --force."]})}function applyExistingSettingsUpdates(params){let changed=!1;return params.prefixArg!==void 0&&params.settings.id_prefix!==params.normalizedPrefix&&(params.settings.id_prefix=params.normalizedPrefix,params.warnings.push(`updated:id_prefix:${params.normalizedPrefix}`),changed=!0),params.presetFromOption!==void 0&&params.settings.governance.preset!==params.presetFromOption&&(applyGovernancePreset(params.settings,params.presetFromOption),params.warnings.push(`updated:governance_preset:${params.presetFromOption}`),changed=!0),params.authorFromOption!==void 0&&params.settings.author_default!==params.authorFromOption&&(params.settings.author_default=params.authorFromOption,params.warnings.push(`updated:author_default:${params.authorFromOption}`),changed=!0),changed}async function loadExistingInitSettings(params){const settings=await readSettings(params.pmRoot);params.warnings.push(`already_exists:${params.settingsPath}`);const pendingChanges=collectExistingSettingsPendingChanges({settings,normalizedPrefix:params.normalizedPrefix,prefixArg:params.prefixArg,presetFromOption:params.normalizedOptions.presetFromOption,authorFromOption:params.normalizedOptions.authorFromOption});return assertExistingSettingsUpdateAllowed(params.settingsPath,pendingChanges,params.options.force===!0,params.target),applyExistingSettingsUpdates({settings,normalizedPrefix:params.normalizedPrefix,prefixArg:params.prefixArg,presetFromOption:params.normalizedOptions.presetFromOption,authorFromOption:params.normalizedOptions.authorFromOption,warnings:params.warnings})&&await writeSettings(params.pmRoot,settings),{settings,normalizedPrefix:params.normalizedPrefix,chosenPreset:params.normalizedOptions.presetFromOption,wizardUsed:!1}}async function createNewInitSettings(params){let normalizedPrefix=params.normalizedPrefix,chosenPreset=params.normalizedOptions.presetFromOption,chosenTelemetryEnabled,wizardUsed=!1;if(params.normalizedOptions.presetFromOption===void 0&&!params.normalizedOptions.useDefaults&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0){const wizardChoices=await runInitWizard(normalizedPrefix,SETTINGS_DEFAULTS.telemetry.enabled);normalizedPrefix=wizardChoices.prefix,chosenPreset=wizardChoices.preset,chosenTelemetryEnabled=wizardChoices.telemetry_enabled,wizardUsed=!0}const effectivePreset=chosenPreset??"minimal",settings=cloneDefaults();settings.id_prefix=normalizedPrefix,applyGovernancePreset(settings,effectivePreset);const environmentAuthor=readAuthorEnvironment()?.trim()||void 0;return settings.author_default=params.normalizedOptions.authorFromOption??environmentAuthor??"",chosenTelemetryEnabled!==void 0&&(settings.telemetry.enabled=chosenTelemetryEnabled,settings.telemetry.first_run_prompt_completed=!0),await writeSettings(params.pmRoot,settings),{settings,normalizedPrefix,chosenPreset,wizardUsed}}async function resolveInitSettings(params){return params.settingsExists?await loadExistingInitSettings(params):await createNewInitSettings({pmRoot:params.pmRoot,normalizedPrefix:params.normalizedPrefix,normalizedOptions:params.normalizedOptions})}async function applyInitAgentGuidance(params){const agentGuidanceResult=await runInitAgentGuidance({pm_root:params.pmRoot,cwd:params.cwd,mode:params.agentGuidanceMode,interactive:process.stdin.isTTY===!0&&process.stdout.isTTY===!0,settings:params.settings});return params.warnings.push(...agentGuidanceResult.warnings),agentGuidanceResult.settings_changed&&await writeSettings(params.pmRoot,params.settings),{...agentGuidanceResult.summary,next_steps:agentGuidanceResult.next_steps}}async function ensureInitRuntimeSchemaFiles(pmRoot,settings){const createdDirs=[],warnings=[],runtimeSchemaScaffold=await ensureRuntimeSchemaFileScaffold(pmRoot,settings.schema);for(const createdPath of runtimeSchemaScaffold.created_paths)createdDirs.push(createdPath),warnings.push(...await runActiveOnWriteHooks({path:createdPath,scope:"project",op:"init:runtime_schema_file"}));return{createdDirs,warnings}}async function maybeRegisterInitTypePreset(params){if(params.typePreset===void 0)return;const registeredTypePreset=await registerInitTypePreset(params.pmRoot,params.settings,params.typePreset);return params.warnings.push(`registered_type_preset:${params.typePreset}`),params.warnings.push(...await runActiveOnWriteHooks({path:registeredTypePreset.file,scope:"project",op:"init:type_preset"})),registeredTypePreset}async function ensureInitTypeDirectories(params){const customTypeFolders=resolveItemTypeRegistry(params.settings,getActiveExtensionRegistrations()).folders.filter(folder=>!PM_REQUIRED_SUBDIRS.includes(folder)),scaffold=await ensureInitDirectories(params.pmRoot,customTypeFolders);params.createdDirs.push(...scaffold.createdDirs),params.warnings.push(...scaffold.warnings)}function resolveInitWorkspaceRoot(target){const trackerRoot=path.resolve(target.tracker_root),agentsRoot=path.dirname(trackerRoot);return path.basename(trackerRoot)==="pm"&&path.basename(agentsRoot)===".agents"?path.dirname(agentsRoot):target.workspace_root}async function maybeInstallInitBundledPackages(installBundledPackages,global2,pmRoot,warnings){if(!installBundledPackages)return;const packageInstallResult=await runExtension("all",{install:!0,project:!0},{...global2,path:pmRoot});warnings.push(...packageInstallResult.warnings);const installedPackages=summarizeInstalledPackages(packageInstallResult),failedAliases=installedPackages.packages.filter(entry=>!entry.ok).map(entry=>entry.alias);if(!installedPackages.installed_all||failedAliases.length>0)throw new PmCliError(`pm init --with-packages did not install all bundled packages successfully${failedAliases.length>0?`: ${failedAliases.join(", ")}`:"."}`,EXIT_CODE.GENERIC_FAILURE);return installedPackages}function buildInitNextSteps(params){const pmCommand=args=>renderPmCommand([...params.target.mode==="workspace-discovery"?[]:["--pm-path",params.target.tracker_root],...args]),nextSteps=[`Create your first item: ${pmCommand(["create","--type","Task","--title","<title>"])}`,`List active items: ${pmCommand(["list"])}`,`Get agent-friendly project context: ${pmCommand(["context"])}`];params.installBundledPackages?nextSteps.push(`Explore newly-available commands: ${pmCommand(["cal"])}, ${pmCommand(["templates"])}, ${pmCommand(["guide"])}`):(nextSteps.push(`Add optional packages for richer workflows: ${pmCommand(["install","calendar","--project"])}, ${pmCommand(["install","templates","--project"])}, ${pmCommand(["install","guide-shell","--project"])}`),nextSteps.push(`Or install everything bundled: ${pmCommand(["init","--with-packages"])} (idempotent on re-run)`)),params.registeredTypePreset&&nextSteps.push(`Inspect registered preset types: ${pmCommand(["schema","list"])}, ${pmCommand(["schema","show",params.registeredTypePreset.registered[0]??params.registeredTypePreset.updated[0]])}`),nextSteps.push("Supported agent harnesses are attributed automatically; use --author or PM_AUTHOR only when an explicit identity override is required.");for(const guidanceNextStep of params.agentGuidanceNextSteps){const scopedGuidance=params.target.mode==="workspace-discovery"?guidanceNextStep:guidanceNextStep.replace(/\bpm (?=[a-z])/g,()=>`${pmCommand([])} `);nextSteps.includes(scopedGuidance)||nextSteps.push(scopedGuidance)}return nextSteps}async function installInitMergeFence(pmRoot,gitWorkspaceRoot,warnings,install=installMergeFence){if(gitWorkspaceRoot===null){warnings.push("merge_fence_skipped:not_git_repository:run pm merge install after moving the tracker into a Git repository");return}try{const mergeFence=await install({pmRoot,workspaceRoot:gitWorkspaceRoot});mergeFence.gitattributes.changed&&warnings.push(`updated:merge_fence:${mergeFence.gitattributes.path}`)}catch(error){if(!(error instanceof PmCliError))throw error;warnings.push(`merge_fence_skipped:install_failed:${error.context.code??"pm_error"}:${error.message}:run pm merge install after resolving the Git repository error`)}}async function ensureInitWorkspaceGitignore(workspaceRoot,pmRoot,agentGuidanceMode,warnings){if(workspaceRoot==null||agentGuidanceMode==="status")return;const gitignore=await ensurePmGitignore(workspaceRoot,{pmRoot});gitignore.changed&&warnings.push(`updated:gitignore:${gitignore.path}`)}async function runInit(prefixArg,global2,options={}){const invocationCwd=global2[INIT_INVOCATION_CWD],cwd=typeof invocationCwd=="string"?invocationCwd:process.cwd(),invocation=resolveInitInvocation(cwd,global2,prefixArg,options.workspace),pmRoot=invocation.pmRoot;prefixArg=resolveInitPrefixInput(invocation.prefixArg,options.idPrefix);const normalizedOptions=normalizeInitCommandOptions(options);await assertExplicitTrackerPathIsNotWorkspaceRoot(pmRoot,invocation.target.mode==="tracker-path",options.force===!0);const createdDirs=[],warnings=[],settingsPath=path.join(pmRoot,"settings.json"),settingsExists=await pathExists(settingsPath);let settingsResolution;settingsExists&&(settingsResolution=await resolveInitSettings({pmRoot,settingsPath,settingsExists,normalizedPrefix:normalizePrefix(prefixArg),prefixArg,options,normalizedOptions,warnings,target:invocation.target}));const baseDirs=await ensureInitDirectories(pmRoot,PM_REQUIRED_SUBDIRS);createdDirs.push(...baseDirs.createdDirs),warnings.push(...baseDirs.warnings),settingsResolution??=await resolveInitSettings({pmRoot,settingsPath,settingsExists,normalizedPrefix:normalizePrefix(prefixArg),prefixArg,options,normalizedOptions,warnings,target:invocation.target});let{settings}=settingsResolution;const configuredWorkspaceRoot=resolveInitWorkspaceRoot(invocation.target),gitWorkspaceRoot=await findGitWorkspaceRoot(configuredWorkspaceRoot??path.dirname(pmRoot)),workspaceRoot=configuredWorkspaceRoot??gitWorkspaceRoot,agentGuidance=await applyInitAgentGuidance({pmRoot,cwd:workspaceRoot??cwd,agentGuidanceMode:normalizedOptions.agentGuidanceMode,settings,warnings}),schemaFiles=await ensureInitRuntimeSchemaFiles(pmRoot,settings);createdDirs.push(...schemaFiles.createdDirs),warnings.push(...schemaFiles.warnings);const registeredTypePreset=await maybeRegisterInitTypePreset({pmRoot,settings,typePreset:normalizedOptions.typePreset,warnings});registeredTypePreset&&(settings=await readSettings(pmRoot)),await ensureInitTypeDirectories({pmRoot,settings,createdDirs,warnings}),await ensureInitWorkspaceGitignore(workspaceRoot,pmRoot,normalizedOptions.agentGuidanceMode,warnings),!settingsExists&&options.mergeFence!==!1&&normalizedOptions.agentGuidanceMode!=="status"&&await installInitMergeFence(pmRoot,gitWorkspaceRoot,warnings);const installedPackages=await maybeInstallInitBundledPackages(normalizedOptions.installBundledPackages,global2,pmRoot,warnings),nextSteps=buildInitNextSteps({installBundledPackages:normalizedOptions.installBundledPackages,registeredTypePreset,agentGuidanceNextSteps:agentGuidance.next_steps,target:invocation.target});return{ok:!0,path:pmRoot,target:invocation.target,settings,created_dirs:createdDirs,warnings,governance_preset:settings.governance.preset,wizard_used:settingsResolution.wizardUsed,...registeredTypePreset?{registered_type_preset:registeredTypePreset}:{},...installedPackages?{installed_packages:installedPackages}:{},next_steps:nextSteps,agent_guidance:agentGuidance}}export{INIT_INVOCATION_CWD,_testOnly,runInit,summarizeInitResult};
12
+ `)}let telemetryEnabled;if(telemetryDefault!==void 0){output.write(`
13
+ 3/3 Telemetry
14
+ `),output.write(`Telemetry helps improve reliability. The choice applies to this CLI install; change it with pm config global set telemetry-tracking.
15
+ `);const telemetryAnswer=await rl.question(`Enable telemetry for this CLI install? [${telemetryDefault?"Y/n":"y/N"}] `);telemetryEnabled=parseYesNoChoice(telemetryAnswer,telemetryDefault)}return output.write(`
16
+ `),{prefix:resolvedPrefix,preset:resolvedPreset,telemetry_enabled:telemetryEnabled}}finally{rl.close()}}function normalizeInitCommandOptions(options){return{presetFromOption:normalizeInitGovernancePreset(options.preset),useDefaults:options.defaults===!0,authorFromOption:normalizeOptionalInitAuthor(options.author),installBundledPackages:options.withPackages===!0,agentGuidanceMode:normalizeInitAgentGuidanceMode(options.agentGuidance),typePreset:normalizeInitTypePreset(options.typePreset)}}function collectExistingSettingsPendingChanges(params){const pendingChanges=[];return params.prefixArg!==void 0&&params.settings.id_prefix!==params.normalizedPrefix&&pendingChanges.push("id_prefix"),params.presetFromOption!==void 0&&params.settings.governance.preset!==params.presetFromOption&&pendingChanges.push("governance_preset"),params.authorFromOption!==void 0&&params.settings.author_default!==params.authorFromOption&&pendingChanges.push("author_default"),pendingChanges}function assertExistingSettingsUpdateAllowed(settingsPath,pendingChanges,force,target){if(pendingChanges.length===0||force)return;const ancestorDiscovery=target.discovery==="ancestor";throw new PmCliError(`${ancestorDiscovery?`No tracker exists in ${target.requested_cwd}; pm init found an ancestor tracker at ${target.tracker_root}. `:""}Refusing to update existing tracker settings at ${settingsPath} without --force.`,EXIT_CODE.USAGE,{code:"init_existing_settings_requires_force",type:"urn:pm-cli:error:init_existing_settings_requires_force",required:`--force for ${pendingChanges.join(", ")}`,why:ancestorDiscovery?"Ancestor discovery is useful for normal commands, but init must make the selected existing workspace explicit before changing its identity or policy settings.":"pm init is safe to rerun, but changing id prefix, governance preset, or default author on an existing tracker can corrupt long-lived project context when an agent meant to initialize a sandbox path.",resolved_path:target.tracker_root,requested_path:target.requested_cwd,suggested_path:target.suggested_current_tracker_root,examples:["pm init --yes","pm init ./sandbox-pm --yes",...ancestorDiscovery?['pm init <name> --yes --pm-path "$PWD/.agents/pm"']:[],"pm init acme --yes --force"],nextSteps:[...ancestorDiscovery?['To create a new tracker in the current directory, rerun with --pm-path "$PWD/.agents/pm".']:[],"If you meant to initialize a sandbox tracker, pass a path-like positional such as ./sandbox-pm or /tmp/pm-test.","If you intentionally want to rewrite this existing tracker's init-managed settings, rerun with --force."]})}function applyExistingSettingsUpdates(params){let changed=!1;return params.prefixArg!==void 0&&params.settings.id_prefix!==params.normalizedPrefix&&(params.settings.id_prefix=params.normalizedPrefix,params.warnings.push(`updated:id_prefix:${params.normalizedPrefix}`),changed=!0),params.presetFromOption!==void 0&&params.settings.governance.preset!==params.presetFromOption&&(applyGovernancePreset(params.settings,params.presetFromOption),params.warnings.push(`updated:governance_preset:${params.presetFromOption}`),changed=!0),params.authorFromOption!==void 0&&params.settings.author_default!==params.authorFromOption&&(params.settings.author_default=params.authorFromOption,params.warnings.push(`updated:author_default:${params.authorFromOption}`),changed=!0),changed}async function loadExistingInitSettings(params){const settings=await readSettings(params.pmRoot);params.warnings.push(`already_exists:${params.settingsPath}`);const pendingChanges=collectExistingSettingsPendingChanges({settings,normalizedPrefix:params.normalizedPrefix,prefixArg:params.prefixArg,presetFromOption:params.normalizedOptions.presetFromOption,authorFromOption:params.normalizedOptions.authorFromOption});return assertExistingSettingsUpdateAllowed(params.settingsPath,pendingChanges,params.options.force===!0,params.target),applyExistingSettingsUpdates({settings,normalizedPrefix:params.normalizedPrefix,prefixArg:params.prefixArg,presetFromOption:params.normalizedOptions.presetFromOption,authorFromOption:params.normalizedOptions.authorFromOption,warnings:params.warnings})&&await writeSettings(params.pmRoot,settings),{settings,normalizedPrefix:params.normalizedPrefix,chosenPreset:params.normalizedOptions.presetFromOption,wizardUsed:!1}}async function createNewInitSettings(params){let normalizedPrefix=params.normalizedPrefix,chosenPreset=params.normalizedOptions.presetFromOption,chosenTelemetryEnabled,wizardUsed=!1;if(params.normalizedOptions.presetFromOption===void 0&&!params.normalizedOptions.useDefaults&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0){const wizardChoices=await runInitWizard(normalizedPrefix,await resolveWizardTelemetryDefault());normalizedPrefix=wizardChoices.prefix,chosenPreset=wizardChoices.preset,chosenTelemetryEnabled=wizardChoices.telemetry_enabled,wizardUsed=!0}const effectivePreset=chosenPreset??"minimal",settings=cloneDefaults();settings.id_prefix=normalizedPrefix,applyGovernancePreset(settings,effectivePreset);const environmentAuthor=readAuthorEnvironment()?.trim()||void 0;settings.author_default=params.normalizedOptions.authorFromOption??environmentAuthor??"";const writeOptions=initSettingsWriteOptions(params.pmRoot);return chosenTelemetryEnabled!==void 0&&(settings.telemetry.enabled=chosenTelemetryEnabled,settings.telemetry.first_run_prompt_completed=!0),await writeSettings(params.pmRoot,settings,void 0,writeOptions),chosenTelemetryEnabled!==void 0&&writeOptions.omitSections&&await persistGlobalTelemetryConsent(chosenTelemetryEnabled,params.warnings),{settings,normalizedPrefix,chosenPreset,wizardUsed}}function initSettingsWriteOptions(pmRoot){return path.resolve(pmRoot)===path.resolve(resolveGlobalPmRoot(process.cwd()))?{}:{omitSections:["telemetry"]}}async function resolveWizardTelemetryDefault(){const global2=await readSettings(resolveGlobalPmRoot(process.cwd()));if(!(resolveTelemetryEnvironmentPolicy().telemetry_disabled||global2.telemetry.first_run_prompt_completed||isSettingsReadFallback(global2)))return global2.telemetry.enabled}async function persistGlobalTelemetryConsent(enabled,warnings){const globalPmRoot=resolveGlobalPmRoot(process.cwd()),global2=await readSettings(globalPmRoot);if(isSettingsReadFallback(global2)){warnings.push("telemetry_consent_not_recorded:global_settings_unreadable");return}let kept=!1;global2.telemetry.enabled=enabled,global2.telemetry.first_run_prompt_completed=!0,await writeSettings(globalPmRoot,global2,"telemetry:first_run_prompt",{skipIfStored:stored=>kept=stored.telemetry?.first_run_prompt_completed===!0}),kept&&warnings.push("telemetry_consent_kept:recorded_while_prompting")}async function withGlobalTelemetry(settings){const{telemetry}=await readSettings(resolveGlobalPmRoot(process.cwd()));return{...settings,telemetry:{...settings.telemetry,enabled:telemetry.enabled,first_run_prompt_completed:telemetry.first_run_prompt_completed,capture_level:telemetry.capture_level}}}async function resolveInitSettings(params){return params.settingsExists?await loadExistingInitSettings(params):await createNewInitSettings({pmRoot:params.pmRoot,normalizedPrefix:params.normalizedPrefix,normalizedOptions:params.normalizedOptions,warnings:params.warnings})}async function applyInitAgentGuidance(params){const agentGuidanceResult=await runInitAgentGuidance({pm_root:params.pmRoot,cwd:params.cwd,mode:params.agentGuidanceMode,interactive:process.stdin.isTTY===!0&&process.stdout.isTTY===!0,settings:params.settings});return params.warnings.push(...agentGuidanceResult.warnings),agentGuidanceResult.settings_changed&&await writeSettings(params.pmRoot,params.settings,void 0,initSettingsWriteOptions(params.pmRoot)),{...agentGuidanceResult.summary,next_steps:agentGuidanceResult.next_steps}}async function ensureInitRuntimeSchemaFiles(pmRoot,settings){const createdDirs=[],warnings=[],runtimeSchemaScaffold=await ensureRuntimeSchemaFileScaffold(pmRoot,settings.schema);for(const createdPath of runtimeSchemaScaffold.created_paths)createdDirs.push(createdPath),warnings.push(...await runActiveOnWriteHooks({path:createdPath,scope:"project",op:"init:runtime_schema_file"}));return{createdDirs,warnings}}async function maybeRegisterInitTypePreset(params){if(params.typePreset===void 0)return;const registeredTypePreset=await registerInitTypePreset(params.pmRoot,params.settings,params.typePreset);return params.warnings.push(`registered_type_preset:${params.typePreset}`),params.warnings.push(...await runActiveOnWriteHooks({path:registeredTypePreset.file,scope:"project",op:"init:type_preset"})),registeredTypePreset}async function ensureInitTypeDirectories(params){const customTypeFolders=resolveItemTypeRegistry(params.settings,getActiveExtensionRegistrations()).folders.filter(folder=>!PM_REQUIRED_SUBDIRS.includes(folder)),scaffold=await ensureInitDirectories(params.pmRoot,customTypeFolders);params.createdDirs.push(...scaffold.createdDirs),params.warnings.push(...scaffold.warnings)}function resolveInitWorkspaceRoot(target){const trackerRoot=path.resolve(target.tracker_root),agentsRoot=path.dirname(trackerRoot);return path.basename(trackerRoot)==="pm"&&path.basename(agentsRoot)===".agents"?path.dirname(agentsRoot):target.workspace_root}async function maybeInstallInitBundledPackages(installBundledPackages,global2,pmRoot,warnings){if(!installBundledPackages)return;const packageInstallResult=await runExtension("all",{install:!0,project:!0},{...global2,path:pmRoot});warnings.push(...packageInstallResult.warnings);const installedPackages=summarizeInstalledPackages(packageInstallResult),failedAliases=installedPackages.packages.filter(entry=>!entry.ok).map(entry=>entry.alias);if(!installedPackages.installed_all||failedAliases.length>0)throw new PmCliError(`pm init --with-packages did not install all bundled packages successfully${failedAliases.length>0?`: ${failedAliases.join(", ")}`:"."}`,EXIT_CODE.GENERIC_FAILURE);return installedPackages}function buildInitNextSteps(params){const pmCommand=args=>renderPmCommand([...params.target.mode==="workspace-discovery"?[]:["--pm-path",params.target.tracker_root],...args]),nextSteps=[`Create your first item: ${pmCommand(["create","--type","Task","--title","<title>"])}`,`List active items: ${pmCommand(["list"])}`,`Get agent-friendly project context: ${pmCommand(["context"])}`];params.installBundledPackages?nextSteps.push(`Explore newly-available commands: ${pmCommand(["cal"])}, ${pmCommand(["templates"])}, ${pmCommand(["guide"])}`):(nextSteps.push(`Add optional packages for richer workflows: ${pmCommand(["install","calendar","--project"])}, ${pmCommand(["install","templates","--project"])}, ${pmCommand(["install","guide-shell","--project"])}`),nextSteps.push(`Or install everything bundled: ${pmCommand(["init","--with-packages"])} (idempotent on re-run)`)),params.registeredTypePreset&&nextSteps.push(`Inspect registered preset types: ${pmCommand(["schema","list"])}, ${pmCommand(["schema","show",params.registeredTypePreset.registered[0]??params.registeredTypePreset.updated[0]])}`),nextSteps.push("Supported agent harnesses are attributed automatically; use --author or PM_AUTHOR only when an explicit identity override is required.");for(const guidanceNextStep of params.agentGuidanceNextSteps){const scopedGuidance=params.target.mode==="workspace-discovery"?guidanceNextStep:guidanceNextStep.replace(/\bpm (?=[a-z])/g,()=>`${pmCommand([])} `);nextSteps.includes(scopedGuidance)||nextSteps.push(scopedGuidance)}return nextSteps}async function installInitMergeFence(pmRoot,gitWorkspaceRoot,warnings,install=installMergeFence){if(gitWorkspaceRoot===null){warnings.push("merge_fence_skipped:not_git_repository:run pm merge install after moving the tracker into a Git repository");return}try{const mergeFence=await install({pmRoot,workspaceRoot:gitWorkspaceRoot});mergeFence.gitattributes.changed&&warnings.push(`updated:merge_fence:${mergeFence.gitattributes.path}`)}catch(error){if(!(error instanceof PmCliError))throw error;warnings.push(`merge_fence_skipped:install_failed:${error.context.code??"pm_error"}:${error.message}:run pm merge install after resolving the Git repository error`)}}async function ensureInitWorkspaceGitignore(workspaceRoot,pmRoot,agentGuidanceMode,warnings){if(workspaceRoot==null||agentGuidanceMode==="status")return;const gitignore=await ensurePmGitignore(workspaceRoot,{pmRoot});gitignore.changed&&warnings.push(`updated:gitignore:${gitignore.path}`)}async function runInit(prefixArg,global2,options={}){const invocationCwd=global2[INIT_INVOCATION_CWD],cwd=typeof invocationCwd=="string"?invocationCwd:process.cwd(),invocation=resolveInitInvocation(cwd,global2,prefixArg,options.workspace),pmRoot=invocation.pmRoot;prefixArg=resolveInitPrefixInput(invocation.prefixArg,options.idPrefix);const normalizedOptions=normalizeInitCommandOptions(options);await assertExplicitTrackerPathIsNotWorkspaceRoot(pmRoot,invocation.target.mode==="tracker-path",options.force===!0);const createdDirs=[],warnings=[],settingsPath=path.join(pmRoot,"settings.json"),settingsExists=await pathExists(settingsPath);let settingsResolution;settingsExists&&(settingsResolution=await resolveInitSettings({pmRoot,settingsPath,settingsExists,normalizedPrefix:normalizePrefix(prefixArg),prefixArg,options,normalizedOptions,warnings,target:invocation.target}));const baseDirs=await ensureInitDirectories(pmRoot,PM_REQUIRED_SUBDIRS);createdDirs.push(...baseDirs.createdDirs),warnings.push(...baseDirs.warnings),settingsResolution??=await resolveInitSettings({pmRoot,settingsPath,settingsExists,normalizedPrefix:normalizePrefix(prefixArg),prefixArg,options,normalizedOptions,warnings,target:invocation.target});let{settings}=settingsResolution;const configuredWorkspaceRoot=resolveInitWorkspaceRoot(invocation.target),gitWorkspaceRoot=await findGitWorkspaceRoot(configuredWorkspaceRoot??path.dirname(pmRoot)),workspaceRoot=configuredWorkspaceRoot??gitWorkspaceRoot,agentGuidance=await applyInitAgentGuidance({pmRoot,cwd:workspaceRoot??cwd,agentGuidanceMode:normalizedOptions.agentGuidanceMode,settings,warnings}),schemaFiles=await ensureInitRuntimeSchemaFiles(pmRoot,settings);createdDirs.push(...schemaFiles.createdDirs),warnings.push(...schemaFiles.warnings);const registeredTypePreset=await maybeRegisterInitTypePreset({pmRoot,settings,typePreset:normalizedOptions.typePreset,warnings});registeredTypePreset&&(settings=await readSettings(pmRoot)),await ensureInitTypeDirectories({pmRoot,settings,createdDirs,warnings}),await ensureInitWorkspaceGitignore(workspaceRoot,pmRoot,normalizedOptions.agentGuidanceMode,warnings),!settingsExists&&options.mergeFence!==!1&&normalizedOptions.agentGuidanceMode!=="status"&&await installInitMergeFence(pmRoot,gitWorkspaceRoot,warnings);const installedPackages=await maybeInstallInitBundledPackages(normalizedOptions.installBundledPackages,global2,pmRoot,warnings),nextSteps=buildInitNextSteps({installBundledPackages:normalizedOptions.installBundledPackages,registeredTypePreset,agentGuidanceNextSteps:agentGuidance.next_steps,target:invocation.target});return{ok:!0,path:pmRoot,target:invocation.target,settings:await withGlobalTelemetry(settings),created_dirs:createdDirs,warnings,governance_preset:settings.governance.preset,wizard_used:settingsResolution.wizardUsed,...registeredTypePreset?{registered_type_preset:registeredTypePreset}:{},...installedPackages?{installed_packages:installedPackages}:{},next_steps:nextSteps,agent_guidance:agentGuidance}}export{INIT_INVOCATION_CWD,_testOnly,runInit,summarizeInitResult};
17
17
  //# sourceMappingURL=init.js.map
@@ -38,6 +38,8 @@ available:true;
38
38
  recommendation:NextRecommendation;
39
39
  /** Value that configures or reports attempts for this contract. */
40
40
  attempts:number;
41
+ /** Earlier candidates skipped because a declared blocker refused their start; nothing was written to them. */
42
+ start_refused?:string[];
41
43
  }
42
44
  /** Non-error empty result returned when an if-available candidate walk is exhausted. */
43
45
  export interface ClaimNextUnavailableResult {
@@ -57,6 +59,8 @@ skipped:true;
57
59
  recommendation:null;
58
60
  /** Number of ranked candidates attempted. */
59
61
  attempts:number;
62
+ /** Candidates skipped because a declared blocker refused their start; nothing was written to them. */
63
+ start_refused?:string[];
60
64
  /** Stable machine-readable exhaustion warning. */
61
65
  warnings:[typeof NO_AVAILABLE_NEXT_ITEM_CODE];
62
66
  }
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4021f6b1-2156-5057-b41c-b1c8847aca7a")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{resolveRuntimeStatusRegistry,statusIsTerminal,EXIT_CODE,PmCliError,toItemRecord,mutateItem,resolvePmRoot,readSettings,resolveAuthor,resolveClaimPrincipal,normalizeStatusForRegistry}from"../runtime-primitives.js";import{wrapOwnershipConflict}from"../annotations.js";import{resolveItemOwnershipConflict}from"../ownership-source.js";import{applyReleaseHandoff,resolveReleaseHandoff}from"./release-handoff.js";import{enforceTypeWorkflowTransition}from"./workflow-transition.js";import{admitExplicitStartClaim,admitStartTransition}from"./start-blockers.js";import{resolveTypeWorkflows}from"../../core/schema/type-workflows.js";import{resolveStartTaskInProgressStatus}from"../start-task-status.js";import{runNext}from"../query/next.js";import{recordClaimSemanticAttribution,recordReleaseSemanticAttribution}from"../context/semantic-session-attribution.js";const NO_AVAILABLE_NEXT_ITEM_CODE="no_available_next_item";function isAlreadyClaimedError(error){if(!(error instanceof Error)||error.name!=="PmCliError")return!1;const context=error.context;return typeof context=="object"&&context!==null&&"code"in context&&context.code==="already_claimed_by"}async function runClaim(id,force,global2,options={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),statusRegistry=resolveRuntimeStatusRegistry(settings.schema),author=resolveAuthor(options.author,settings.author_default),claimPrincipal=resolveClaimPrincipal(author);let previousAssignee=null,skipped=!1,startEvidence={};const mutationWarnings=[],result=await mutateItem({pmRoot,settings,id,op:"claim",author,message:options.message,force,skipNoop:!0,async mutate(document){const currentAssigneeText=document.metadata.assignee??"",currentClaimPrincipal=document.metadata.claim_principal?.trim()||currentAssigneeText;if(previousAssignee=currentAssigneeText.trim().length>0?currentAssigneeText:null,statusIsTerminal(document.metadata.status,statusRegistry)&&!force)throw new PmCliError(`Cannot claim terminal item ${document.metadata.id} without --force`,EXIT_CODE.CONFLICT);if(previousAssignee!==null&&currentClaimPrincipal!==claimPrincipal){if(options.ifAvailable===!0)return skipped=!0,mutationWarnings.push(`claim_skipped_held_by:${previousAssignee}`),{changedFields:[]};if(!force){const ownership2=await resolveItemOwnershipConflict(pmRoot,document.metadata.id,currentAssigneeText);throw new PmCliError(`Item ${document.metadata.id} is already ${ownership2.phrase}. Use --force to take over, or --if-available to skip without failing.`,EXIT_CODE.CONFLICT,{code:"already_claimed_by",item_id:document.metadata.id,claimed_by:ownership2.holder,claimed_at:ownership2.since,claim_source:ownership2.source,why:"Claim is an atomic test-and-set so parallel agents never proceed believing they own the same item.",nextSteps:["Run pm next to pick a different unclaimed item.","Re-run with --if-available to treat a held item as a no-op skip.","Re-run with --force only when taking over the item is coordinated."]})}mutationWarnings.push(`claim_takeover:${previousAssignee}->${author}`)}const ownership={assignee:author,claim_principal:claimPrincipal},changedFields=["assignee","claim_principal"].filter(field=>document.metadata[field]!==ownership[field]);Object.assign(document.metadata,ownership);const fromStatus=document.metadata.status,{changedFields:startedFields,warnings:startWarnings,...started}=applyClaimStart(document.metadata,options.start===!0,settings,statusRegistry);return startWarnings.push(...await claimStartWarnings({pmRoot,settings,metadata:document.metadata,fromStatus,registry:statusRegistry,force,start:options.start===!0})),startEvidence=started,mutationWarnings.push(...startWarnings),{changedFields:[...changedFields,...startedFields],warnings:mutationWarnings}}});return skipped||mutationWarnings.push(...await recordClaimAttributionAfterCommit({pmRoot,settings,principal:claimPrincipal,itemId:result.item.id})),{item:toItemRecord(result.item),changed_fields:result.changedFields,claimed_by:skipped&&previousAssignee!==null?previousAssignee:author,previous_assignee:previousAssignee,forced:force,...skipped?{skipped:!0}:{},...mutationWarnings.length>0?{warnings:mutationWarnings}:{},...startEvidence}}const CLAIM_ATTRIBUTION_UNRECORDED_WARNING="claim_semantic_attribution_unrecorded";async function recordClaimAttributionAfterCommit(params){try{return await recordClaimSemanticAttribution(params),[]}catch{return[CLAIM_ATTRIBUTION_UNRECORDED_WARNING]}}function requireClaimTarget(id,next,start=!1){const startSuffix=start?" --start":"";if(!next&&!id)throw new PmCliError(start?"pm claim --start needs an item id, or --next to start the next available item":"Specify an item id or pass --next",EXIT_CODE.USAGE,{code:"missing_required_argument",field:"id",required:"Pass an item id, or --next to select the next available item.",nextSteps:[`Retry as pm claim <id>${startSuffix}, or pm claim --next${startSuffix}.`]});if(next&&id)throw new PmCliError("Specify either an item id or --next, not both",EXIT_CODE.USAGE,{code:"ambiguous_option_combination",required:"Pass either an item id or --next.",nextSteps:[`Retry as pm claim ${id}${startSuffix} to claim that item, or drop the id to select with --next.`]})}async function claimStartWarnings(params){return params.start?admitStartTransition(params):admitExplicitStartClaim(params)}function applyClaimStart(metadata,start,settings,registry){if(!start)return{changedFields:[],warnings:[]};if(statusIsTerminal(metadata.status,registry))throw new PmCliError(`Cannot start terminal item ${metadata.id}; reopen it with pm item reopen before starting it`,EXIT_CODE.CONFLICT,{code:"terminal_state_conflict",item_id:metadata.id,why:"Starting work moves an active item into progress; a terminal item must be reopened so its recurrence evidence is recorded.",nextSteps:[`Run pm item reopen ${metadata.id} "<reason>", then pm claim ${metadata.id} --start.`]});const startStatus=resolveStartTaskInProgressStatus(registry),enforcement=settings.governance.workflow_enforcement??"off",warning=enforceTypeWorkflowTransition({enforcement,typeWorkflows:enforcement==="off"?[]:resolveTypeWorkflows(settings.schema),statusRegistry:registry,typeName:metadata.type,fromStatus:metadata.status,toStatus:startStatus}),receipt={from_status:metadata.status,to_status:startStatus},changedFields=metadata.status===startStatus?[]:["status"];return metadata.status=startStatus,{start:receipt,changedFields,warnings:warning?[warning]:[]}}async function runClaimNext(force,global2,options={},nextOptions={}){const maxAttempts=parseClaimNextAttempts(options.maxAttempts),settings=await readSettings(resolvePmRoot(process.cwd(),global2.path)),claimOptions={...options,author:resolveAuthor(options.author,settings.author_default)},next=await runNext({...nextOptions,callerAuthor:claimOptions.author,limit:String(maxAttempts)},global2),recommendations=[next.recommended,...next.ready].filter(entry=>entry!==null).map(entry=>({...entry,reasons:"reasons"in entry?entry.reasons:["ranked ready candidate"]}));return claimNextFromRecommendations(recommendations.slice(0,maxAttempts),force,global2,claimOptions)}function parseClaimNextAttempts(raw){if(raw===void 0)return 10;const parsed=Number(raw);if(!Number.isSafeInteger(parsed)||parsed<1||parsed>100)throw new PmCliError("--max-attempts must be an integer from 1 to 100",EXIT_CODE.USAGE);return parsed}async function claimNextFromRecommendations(recommendations,force,global2,options={},claimRunner=runClaim){let attempts=0;for(const recommendation of recommendations){attempts+=1;try{const claimed=await claimRunner(recommendation.id,force,global2,options),result={...claimed,recommendation,attempts,available:!0};if(!claimed.skipped)return result}catch(error){if(!isAlreadyClaimedError(error))throw error}}if(options.ifAvailable===!0)return{available:!1,item:null,claimed_by:resolveAuthor(options.author,""),previous_assignee:null,forced:force,skipped:!0,recommendation:null,attempts,warnings:[NO_AVAILABLE_NEXT_ITEM_CODE]};const noCandidatesMatched=attempts===0;throw new PmCliError(noCandidatesMatched?"No actionable items matched the selection filters":"No actionable item remained available to claim",noCandidatesMatched?EXIT_CODE.NOT_FOUND:EXIT_CODE.CONFLICT,{code:NO_AVAILABLE_NEXT_ITEM_CODE,why:noCandidatesMatched?"No ready items matched the specified filters or selection criteria.":"Every ranked candidate was claimed by another agent before this atomic selection completed.",nextSteps:[noCandidatesMatched?"Verify the filters or run pm next to inspect all ready work.":"Run pm claim --next again to refresh the ranked candidate set."]})}async function runRelease(id,force,global2,options={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),author=resolveAuthor(options.author,settings.author_default),claimPrincipal=resolveClaimPrincipal(author),ownershipReleaseBypass=options.ownershipReleaseBypass===!0;let previousAssignee=null;const statusRegistry=resolveRuntimeStatusRegistry(settings.schema),handoffStatus=resolveReleaseHandoff(options,statusRegistry);if(handoffStatus!==void 0&&ownershipReleaseBypass)throw new PmCliError("Ownership-release bypass only clears ownership; it cannot change a handoff status.",EXIT_CODE.USAGE);let handoff,result;try{result=await mutateItem({pmRoot,settings,id,op:"release",author,message:options.message,force,bypassAssigneeConflict:ownershipReleaseBypass,mutate(document){previousAssignee=document.metadata.assignee??null;const transition=handoffStatus===void 0?void 0:applyReleaseHandoff(document.metadata,handoffStatus,settings,statusRegistry,options.message);return handoff=transition?.receipt,!previousAssignee&&!document.metadata.claim_principal?{changedFields:[]}:(delete document.metadata.assignee,delete document.metadata.claim_principal,{changedFields:["assignee","claim_principal",...transition?.changedFields??[]],warnings:transition?.warnings})}})}catch(error){wrapOwnershipConflict(error,{required:"For approved non-owner handoffs, prefer the ownership-release bypass before considering --force.",examples:['pm release pm-a1b2 --author "reviewer" --force'],nextSteps:["Use the package-provided ownership-release bypass for handoffs that only clear assignee metadata.","Use --force only when an explicit override is approved for broader ownership conflicts."]})}await recordReleaseSemanticAttribution({pmRoot,principal:claimPrincipal,itemId:result.item.id});const stillInProgress=normalizeStatusForRegistry(result.item.status,statusRegistry)===normalizeStatusForRegistry(statusRegistry.in_progress_status,statusRegistry);return{item:toItemRecord(result.item),released_by:author,changed_fields:result.changedFields,previous_assignee:previousAssignee,forced:force,...handoff===void 0?{}:{handoff},...result.warnings.length>0||stillInProgress?{warnings:[...result.warnings,...stillInProgress?["released_unclaimed_in_progress"]:[]]}:{},...stillInProgress?{suggestions:[`${result.item.id} remains ${result.item.status} and unclaimed. If work is paused, run pm release ${result.item.id} --pause to move it to ${statusRegistry.open_status}.`]}:{}}}export{CLAIM_ATTRIBUTION_UNRECORDED_WARNING,NO_AVAILABLE_NEXT_ITEM_CODE,applyClaimStart,claimNextFromRecommendations,isAlreadyClaimedError,parseClaimNextAttempts,requireClaimTarget,runClaim,runClaimNext,runRelease};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8893eba1-595b-5f31-9496-e8debc63a27c")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{resolveRuntimeStatusRegistry,statusIsTerminal,EXIT_CODE,PmCliError,toItemRecord,mutateItem,resolvePmRoot,readSettings,resolveAuthor,resolveClaimPrincipal,normalizeStatusForRegistry}from"../runtime-primitives.js";import{wrapOwnershipConflict}from"../annotations.js";import{resolveItemOwnershipConflict}from"../ownership-source.js";import{applyReleaseHandoff,resolveReleaseHandoff}from"./release-handoff.js";import{enforceTypeWorkflowTransition}from"./workflow-transition.js";import{admitExplicitStartClaim,admitStartTransition,START_BLOCKED_REFUSAL_CODE}from"./start-blockers.js";import{resolveTypeWorkflows}from"../../core/schema/type-workflows.js";import{resolveStartTaskInProgressStatus}from"../start-task-status.js";import{runNext}from"../query/next.js";import{recordClaimSemanticAttribution,recordReleaseSemanticAttribution}from"../context/semantic-session-attribution.js";const NO_AVAILABLE_NEXT_ITEM_CODE="no_available_next_item";function hasRefusalCode(error,code){if(!(error instanceof Error)||error.name!=="PmCliError")return!1;const context=error.context;return typeof context=="object"&&context!==null&&"code"in context&&context.code===code}function isAlreadyClaimedError(error){return hasRefusalCode(error,"already_claimed_by")}async function runClaim(id,force,global2,options={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),statusRegistry=resolveRuntimeStatusRegistry(settings.schema),author=resolveAuthor(options.author,settings.author_default),claimPrincipal=resolveClaimPrincipal(author);let previousAssignee=null,skipped=!1,startEvidence={};const mutationWarnings=[],result=await mutateItem({pmRoot,settings,id,op:"claim",author,message:options.message,force,skipNoop:!0,async mutate(document){const currentAssigneeText=document.metadata.assignee??"",currentClaimPrincipal=document.metadata.claim_principal?.trim()||currentAssigneeText;if(previousAssignee=currentAssigneeText.trim().length>0?currentAssigneeText:null,statusIsTerminal(document.metadata.status,statusRegistry)&&!force)throw new PmCliError(`Cannot claim terminal item ${document.metadata.id} without --force`,EXIT_CODE.CONFLICT);if(previousAssignee!==null&&currentClaimPrincipal!==claimPrincipal){if(options.ifAvailable===!0)return skipped=!0,mutationWarnings.push(`claim_skipped_held_by:${previousAssignee}`),{changedFields:[]};if(!force){const ownership2=await resolveItemOwnershipConflict(pmRoot,document.metadata.id,currentAssigneeText);throw new PmCliError(`Item ${document.metadata.id} is already ${ownership2.phrase}. Use --force to take over, or --if-available to skip without failing.`,EXIT_CODE.CONFLICT,{code:"already_claimed_by",item_id:document.metadata.id,claimed_by:ownership2.holder,claimed_at:ownership2.since,claim_source:ownership2.source,why:"Claim is an atomic test-and-set so parallel agents never proceed believing they own the same item.",nextSteps:["Run pm next to pick a different unclaimed item.","Re-run with --if-available to treat a held item as a no-op skip.","Re-run with --force only when taking over the item is coordinated."]})}mutationWarnings.push(`claim_takeover:${previousAssignee}->${author}`)}const ownership={assignee:author,claim_principal:claimPrincipal},changedFields=["assignee","claim_principal"].filter(field=>document.metadata[field]!==ownership[field]);Object.assign(document.metadata,ownership);const fromStatus=document.metadata.status,{changedFields:startedFields,warnings:startWarnings,...started}=applyClaimStart(document.metadata,options.start===!0,settings,statusRegistry);return startWarnings.push(...await claimStartWarnings({pmRoot,settings,metadata:document.metadata,fromStatus,registry:statusRegistry,force,start:options.start===!0})),startEvidence=started,mutationWarnings.push(...startWarnings),{changedFields:[...changedFields,...startedFields],warnings:mutationWarnings}}});return skipped||mutationWarnings.push(...await recordClaimAttributionAfterCommit({pmRoot,settings,principal:claimPrincipal,itemId:result.item.id})),{item:toItemRecord(result.item),changed_fields:result.changedFields,claimed_by:skipped&&previousAssignee!==null?previousAssignee:author,previous_assignee:previousAssignee,forced:force,...skipped?{skipped:!0}:{},...mutationWarnings.length>0?{warnings:mutationWarnings}:{},...startEvidence}}const CLAIM_ATTRIBUTION_UNRECORDED_WARNING="claim_semantic_attribution_unrecorded";async function recordClaimAttributionAfterCommit(params){try{return await recordClaimSemanticAttribution(params),[]}catch{return[CLAIM_ATTRIBUTION_UNRECORDED_WARNING]}}function requireClaimTarget(id,next,start=!1){const startSuffix=start?" --start":"";if(!next&&!id)throw new PmCliError(start?"pm claim --start needs an item id, or --next to start the next available item":"Specify an item id or pass --next",EXIT_CODE.USAGE,{code:"missing_required_argument",field:"id",required:"Pass an item id, or --next to select the next available item.",nextSteps:[`Retry as pm claim <id>${startSuffix}, or pm claim --next${startSuffix}.`]});if(next&&id)throw new PmCliError("Specify either an item id or --next, not both",EXIT_CODE.USAGE,{code:"ambiguous_option_combination",required:"Pass either an item id or --next.",nextSteps:[`Retry as pm claim ${id}${startSuffix} to claim that item, or drop the id to select with --next.`]})}async function claimStartWarnings(params){return params.start?admitStartTransition(params):admitExplicitStartClaim(params)}function applyClaimStart(metadata,start,settings,registry){if(!start)return{changedFields:[],warnings:[]};if(statusIsTerminal(metadata.status,registry))throw new PmCliError(`Cannot start terminal item ${metadata.id}; reopen it with pm item reopen before starting it`,EXIT_CODE.CONFLICT,{code:"terminal_state_conflict",item_id:metadata.id,why:"Starting work moves an active item into progress; a terminal item must be reopened so its recurrence evidence is recorded.",nextSteps:[`Run pm item reopen ${metadata.id} "<reason>", then pm claim ${metadata.id} --start.`]});const startStatus=resolveStartTaskInProgressStatus(registry),enforcement=settings.governance.workflow_enforcement??"off",warning=enforceTypeWorkflowTransition({enforcement,typeWorkflows:enforcement==="off"?[]:resolveTypeWorkflows(settings.schema),statusRegistry:registry,typeName:metadata.type,fromStatus:metadata.status,toStatus:startStatus}),receipt={from_status:metadata.status,to_status:startStatus},changedFields=metadata.status===startStatus?[]:["status"];return metadata.status=startStatus,{start:receipt,changedFields,warnings:warning?[warning]:[]}}async function runClaimNext(force,global2,options={},nextOptions={}){const maxAttempts=parseClaimNextAttempts(options.maxAttempts),settings=await readSettings(resolvePmRoot(process.cwd(),global2.path)),claimOptions={...options,author:resolveAuthor(options.author,settings.author_default)},next=await runNext({...nextOptions,callerAuthor:claimOptions.author,limit:String(maxAttempts)},global2),recommendations=[next.recommended,...next.ready].filter(entry=>entry!==null).map(entry=>({...entry,reasons:"reasons"in entry?entry.reasons:["ranked ready candidate"]}));return claimNextFromRecommendations(recommendations.slice(0,maxAttempts),force,global2,claimOptions)}function parseClaimNextAttempts(raw){if(raw===void 0)return 10;const parsed=Number(raw);if(!Number.isSafeInteger(parsed)||parsed<1||parsed>100)throw new PmCliError("--max-attempts must be an integer from 1 to 100",EXIT_CODE.USAGE);return parsed}async function claimNextFromRecommendations(recommendations,force,global2,options={},claimRunner=runClaim){let attempts=0;const startRefused=[],refusals=()=>startRefused.length>0?{start_refused:[...startRefused]}:{};for(const recommendation of recommendations){attempts+=1;try{const claimed=await claimRunner(recommendation.id,force,global2,options),result={...claimed,recommendation,attempts,available:!0,...refusals()};if(!claimed.skipped)return result}catch(error){if(hasRefusalCode(error,START_BLOCKED_REFUSAL_CODE)){startRefused.push(recommendation.id);continue}if(!isAlreadyClaimedError(error))throw error}}if(options.ifAvailable===!0)return{available:!1,item:null,claimed_by:resolveAuthor(options.author,""),previous_assignee:null,forced:force,skipped:!0,recommendation:null,attempts,...refusals(),warnings:[NO_AVAILABLE_NEXT_ITEM_CODE]};throw noAvailableNextItemError(attempts,startRefused,options.start===!0)}function noAvailableNextItemError(attempts,startRefused,start){const noCandidatesMatched=attempts===0;let why="Every ranked candidate was claimed by another agent before this atomic selection completed.";return noCandidatesMatched?why="No ready items matched the specified filters or selection criteria.":startRefused.length>0&&(why=`${startRefused.length} of ${attempts} attempted candidates refused their start because a declared blocker is open (${startRefused.join(", ")}), and nothing was written to them; ${startRefused.length===attempts?"no other candidate was attempted":"every other attempted candidate was claimed by another agent"}.`),new PmCliError(noCandidatesMatched?"No actionable items matched the selection filters":"No actionable item remained available to claim",noCandidatesMatched?EXIT_CODE.NOT_FOUND:EXIT_CODE.CONFLICT,{code:NO_AVAILABLE_NEXT_ITEM_CODE,why,nextSteps:[noCandidatesMatched?"Verify the filters or run pm next to inspect all ready work.":`Run pm claim --next${start?" --start":""} again, with the same filters, to refresh the ranked candidate set.`],...startRefused.length>0?{details:{start_refused:[...startRefused]}}:{}})}async function runRelease(id,force,global2,options={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),author=resolveAuthor(options.author,settings.author_default),claimPrincipal=resolveClaimPrincipal(author),ownershipReleaseBypass=options.ownershipReleaseBypass===!0;let previousAssignee=null;const statusRegistry=resolveRuntimeStatusRegistry(settings.schema),handoffStatus=resolveReleaseHandoff(options,statusRegistry);if(handoffStatus!==void 0&&ownershipReleaseBypass)throw new PmCliError("Ownership-release bypass only clears ownership; it cannot change a handoff status.",EXIT_CODE.USAGE);let handoff,result;try{result=await mutateItem({pmRoot,settings,id,op:"release",author,message:options.message,force,bypassAssigneeConflict:ownershipReleaseBypass,mutate(document){previousAssignee=document.metadata.assignee??null;const transition=handoffStatus===void 0?void 0:applyReleaseHandoff(document.metadata,handoffStatus,settings,statusRegistry,options.message);return handoff=transition?.receipt,!previousAssignee&&!document.metadata.claim_principal?{changedFields:[]}:(delete document.metadata.assignee,delete document.metadata.claim_principal,{changedFields:["assignee","claim_principal",...transition?.changedFields??[]],warnings:transition?.warnings})}})}catch(error){wrapOwnershipConflict(error,{required:"For approved non-owner handoffs, prefer the ownership-release bypass before considering --force.",examples:['pm release pm-a1b2 --author "reviewer" --force'],nextSteps:["Use the package-provided ownership-release bypass for handoffs that only clear assignee metadata.","Use --force only when an explicit override is approved for broader ownership conflicts."]})}await recordReleaseSemanticAttribution({pmRoot,principal:claimPrincipal,itemId:result.item.id});const stillInProgress=normalizeStatusForRegistry(result.item.status,statusRegistry)===normalizeStatusForRegistry(statusRegistry.in_progress_status,statusRegistry);return{item:toItemRecord(result.item),released_by:author,changed_fields:result.changedFields,previous_assignee:previousAssignee,forced:force,...handoff===void 0?{}:{handoff},...result.warnings.length>0||stillInProgress?{warnings:[...result.warnings,...stillInProgress?["released_unclaimed_in_progress"]:[]]}:{},...stillInProgress?{suggestions:[`${result.item.id} remains ${result.item.status} and unclaimed. If work is paused, run pm release ${result.item.id} --pause to move it to ${statusRegistry.open_status}.`]}:{}}}export{CLAIM_ATTRIBUTION_UNRECORDED_WARNING,NO_AVAILABLE_NEXT_ITEM_CODE,applyClaimStart,claimNextFromRecommendations,isAlreadyClaimedError,parseClaimNextAttempts,requireClaimTarget,runClaim,runClaimNext,runRelease};
2
2
  //# sourceMappingURL=claim.js.map
@@ -2,6 +2,7 @@ import { type ItemRevisionConflictRowFields } from "./item-revision.js";
2
2
  import { type GlobalOptions } from "../runtime-primitives.js";
3
3
  import { collectBlockedByIds } from "../actionability.js";
4
4
  import { type CloseOperationOptions,type CloseOperationResult,type CloseEvidenceFollowUp,type CloseCompletionReceipt } from "../lifecycle-policy.js";
5
+ import type { PmCliErrorDetails,PmCliErrorDetailValue } from "../../core/shared/errors.js";
5
6
  /** Compatibility options for command-shaped close consumers. */
6
7
  export interface CloseCommandOptions {
7
8
  /** Mutation author. */
@@ -36,6 +37,13 @@ follow_up?:CloseEvidenceFollowUp;
36
37
  /** Validation and lifecycle receipts. */
37
38
  warnings:string[];
38
39
  }
40
+ /**
41
+ * Trim the merged post-close details until the error host renders them whole:
42
+ * other failures first, then the revision change evidence, then pending ids
43
+ * (one always stays). Each dropped entry is counted in its list's omitted
44
+ * field, so a reader knows the list is partial.
45
+ */
46
+ declare function fitPostCloseDetails(details:Record<string,PmCliErrorDetailValue>):PmCliErrorDetails;
39
47
  /** A guarded dependent whose auto-unblock refused after a bulk row's close committed. */
40
48
  export type DependentRevisionConflict = ItemRevisionConflictRowFields & {
41
49
  item_id:string;
@@ -53,8 +61,10 @@ dependent_revision_conflict:DependentRevisionConflict;
53
61
  /** Public contract for test only close command, shared by SDK and presentation-layer consumers. */
54
62
  export declare const _testOnlyCloseCommand:{
55
63
  blockedByIds:typeof collectBlockedByIds;
64
+ fitPostCloseDetails:typeof fitPostCloseDetails;
56
65
  };
57
66
  /** Close one item through the SDK-owned lifecycle transaction and policy. */
58
67
  export declare function closeItem(id:string,closeReasonText:string | undefined,options:CloseOperationOptions,global:GlobalOptions):Promise<CloseOperationResult>;
59
68
  /** Compatibility command-shaped wrapper over the SDK-owned close operation. */
60
69
  export declare function runClose(id:string,closeReasonText:string | undefined,options:CloseCommandOptions,global:GlobalOptions):Promise<CloseResult>;
70
+ export {};
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0912c0d0-66d6-5e13-b663-91844378a79a")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isItemRevisionConflict,itemRevisionConflictRowFields}from"./item-revision.js";import{toErrorMessage}from"../runtime-primitives.js";import{toItemRecord,isTerminalStatus,resolveItemTypeRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,PmCliError,buildItemNotFoundError,listAllItemMetadataLight,locateItem,readLocatedItem,mutateItem,resolvePmRoot,readSettings,resolveAuthor,resolveIsoOrRelative,shouldCompletePlanOnClose,getActiveExtensionRegistrations}from"../runtime-primitives.js";import{collectBlockedByIds,indexBlockedByIds}from"../actionability.js";import{applyTerminalOrderingPolicy,requireTerminalReason}from"../lifecycle-policy.js";import{nowIso}from"../../core/shared/time.js";import{renderPmCommand,resolvePmCommandScopeArgs}from"../command-line.js";import{mutateItemWithHistoryContextResolver}from"../../core/store/item-store.js";const CLOSE_VALIDATION_FIELDS=[{key:"resolution",label:"resolution (--resolution)"},{key:"expected_result",label:"expected_result (--expected-result)"},{key:"actual_result",label:"actual_result (--actual-result)"}];function parseValidateCloseMode(raw){if(raw===void 0)return;const normalized=raw.trim().toLowerCase();if(normalized.length===0||normalized==="warn")return"warn";if(normalized==="off"||normalized==="none"||normalized==="disabled")return"off";if(normalized==="strict")return"strict";throw new PmCliError(`Invalid --validate-close mode "${raw}" (expected "off", "warn", or "strict")`,EXIT_CODE.USAGE)}function findMissingCloseValidationFields(itemMetadata){const missing=[];for(const field of CLOSE_VALIDATION_FIELDS){const rawValue=itemMetadata[field.key];(typeof rawValue!="string"||rawValue.trim().length===0)&&missing.push(field)}return missing}function closeEvidenceRecovery(metadata,commandScope,options={}){const missing=findMissingCloseValidationFields(metadata);if(missing.length===0)return;const values={resolution:options.resolution,expected_result:options.expectedResult,actual_result:options.actualResult},missingFlags=missing.map(field=>`--${field.key.replaceAll("_","-")}`),args=[...commandScope,"update",metadata.id,...missing.flatMap((field,index)=>[missingFlags[index],values[field.key]?.trim()||"<value>"])];return{missing:missingFlags,suggested_retry:renderPmCommand(args),suggested_retry_args:args}}async function duplicateChainReferencesClosingItem(loadItemById,initialDuplicateOf,closingId){const visited=new Set;let current=initialDuplicateOf;for(;typeof current=="string"&&current.trim().length>0;){const currentId=current.trim();if(currentId===closingId)return!0;if(visited.has(currentId))return!1;visited.add(currentId),current=(await loadItemById(currentId))?.duplicate_of}return!1}function shouldApplyDuplicateFallback(value){return typeof value!="string"||value.trim().length===0}async function assertDuplicateTargetExists(pmRoot,settings,duplicateOf,closingId){const rawTarget=duplicateOf?.trim();if(!rawTarget)return;if(rawTarget===closingId)throw new PmCliError("An item cannot be closed as a duplicate of itself.",EXIT_CODE.USAGE,{code:"duplicate_target_self",why:"--duplicate-of must identify the canonical item that should remain open or already represent the work."});const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),itemCache=new Map,loadItemById=async id=>{if(itemCache.has(id))return itemCache.get(id)??null;const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);if(!located)return itemCache.set(id,null),null;const{document}=await readLocatedItem(located,{schema:settings.schema});return itemCache.set(id,document.metadata),document.metadata},target=await loadItemById(rawTarget);if(!target)throw new PmCliError(`Duplicate target "${rawTarget}" was not found. Create or locate the canonical item first.`,EXIT_CODE.USAGE,{code:"duplicate_target_missing",why:"Duplicate closure should point at a real canonical pm item so future dedupe and changelog tooling can trace the relationship.",examples:[`pm close ${closingId} "Duplicate of ${rawTarget}" --duplicate-of ${rawTarget}`],nextSteps:["Run pm search/list to find the canonical item, then retry with --duplicate-of <id>."]});if(await duplicateChainReferencesClosingItem(loadItemById,target.duplicate_of,closingId))throw new PmCliError(`Circular duplicate reference detected. Target "${rawTarget}" points back to "${closingId}".`,EXIT_CODE.USAGE,{code:"duplicate_target_circular",why:"Circular duplicate relationships create loops for dedupe and status propagation tooling.",nextSteps:["Choose the existing canonical item, or clear the target duplicate_of metadata before closing this item as a duplicate."]});if(typeof target.duplicate_of=="string"&&target.duplicate_of.trim().length>0)throw new PmCliError(`Duplicate target "${rawTarget}" is already marked as a duplicate of "${target.duplicate_of.trim()}".`,EXIT_CODE.USAGE,{code:"duplicate_target_is_duplicate",why:"Duplicate closure should point directly at the canonical item, not another duplicate.",examples:[`pm close ${closingId} "Duplicate of ${target.duplicate_of.trim()}" --duplicate-of ${target.duplicate_of.trim()}`],nextSteps:["Use the canonical item referenced by duplicate_of as the --duplicate-of target."]});return target.id}function findActiveChildIds(items,parentId,statusRegistry){return items.filter(item=>item.parent===parentId&&!isTerminalStatus(item.status,statusRegistry)).map(item=>item.id).sort((left,right)=>left.localeCompare(right))}function findAutoUnblockCandidates(items,closedId,statusRegistry){const itemsById=new Map(items.map(item=>[item.id.trim().toLowerCase(),item])),blockerIdsByItem=indexBlockedByIds(items),normalizedClosedId=closedId.trim().toLowerCase(),blockedStatuses=statusRegistry.blocked_statuses;return items.filter(item=>blockedStatuses.has(item.status)).map(item=>({item,blockerIds:blockerIdsByItem.get(item.id.trim().toLowerCase())})).filter(({blockerIds})=>blockerIds.includes(normalizedClosedId)).filter(({blockerIds})=>blockerIds.every(blockerId=>{if(blockerId===normalizedClosedId)return!0;const blocker=itemsById.get(blockerId);return blocker!==void 0&&isTerminalStatus(blocker.status,statusRegistry)})).map(({item,blockerIds})=>({id:item.id,blocker_ids:blockerIds})).sort((left,right)=>left.id.localeCompare(right.id))}async function autoUnblockResolvedDependents(pmRoot,settings,items,closedId,author,statusRegistry){const candidates=findAutoUnblockCandidates(items,closedId,statusRegistry),warnings=[],unblockedIds=[];let conflict;for(const candidate of candidates)try{const unblocked=await mutateItem({pmRoot,settings,id:candidate.id,op:"update",author,message:`Auto-unblocked after blocker ${closedId} closed`,mutate(document){const dependencies=document.metadata.dependencies??[],remainingDependencies=dependencies.filter(dependency=>{const dependencyId=dependency.id.trim().toLowerCase();return dependency.kind!=="blocked_by"||!candidate.blocker_ids.includes(dependencyId)});document.metadata.status=statusRegistry.open_status,delete document.metadata.blocked_by,delete document.metadata.blocked_reason,document.metadata.unblock_note=`Auto-unblocked after blocker ${closedId} closed; all blockers resolved (${candidate.blocker_ids.join(", ")}).`,remainingDependencies.length>0?document.metadata.dependencies=remainingDependencies:delete document.metadata.dependencies;const changedFields=["status","blocked_by","blocked_reason","unblock_note"];return remainingDependencies.length!==dependencies.length&&changedFields.push("dependencies"),{changedFields}}});warnings.push(`auto_unblocked:${unblocked.item.id}:resolved_blockers=${candidate.blocker_ids.join(",")}`),unblockedIds.push(unblocked.item.id)}catch(error){conflict===void 0&&isItemRevisionConflict(error)&&(conflict=error);const reason=error instanceof Error?error.message.replace(/\s+/g," ").trim():"unknown";warnings.push(`auto_unblock_failed:${candidate.id}:${reason}`)}if(conflict!==void 0)throw new PmCliError(`${closedId} was closed, but auto-unblocking ${String(conflict.context.item_id)} was refused. ${conflict.message}`,conflict.exitCode,{...conflict.context,side_effects:[{path:`history/${closedId}.jsonl`,op:"close"},...unblockedIds.map(id=>({path:`history/${id}.jsonl`,op:"update"}))]});return warnings}async function committedCloseDependentConflict(error,id,pmRoot){if(!isItemRevisionConflict(error)||!error.context.side_effects?.some(effect=>`${effect.op}:${effect.path}`==`close:history/${id}.jsonl`))return;const dependent=String(error.context.item_id);return{warnings:[...error.context.side_effects.filter(effect=>effect.op==="update").map(effect=>effect.path.slice(8,-6)).map(unblockedId=>`auto_unblocked:${unblockedId}`),`auto_unblock_refused:${dependent}:item_revision_conflict`],dependent_revision_conflict:{item_id:dependent,error:toErrorMessage(error),...await itemRevisionConflictRowFields(error,pmRoot)}}}function applyInlineCloseFields(metadata,options){const changedFields=[],inlineCloseFields=[{option:options.resolution,key:"resolution"},{option:options.expectedResult,key:"expected_result"},{option:options.actualResult,key:"actual_result"}];for(const{option,key}of inlineCloseFields){if(typeof option!="string")continue;const trimmed=option.trim();trimmed.length!==0&&(metadata[key]=trimmed,changedFields.push(key))}return changedFields}function applyDuplicateCloseMetadata(metadata,duplicateOf){if(duplicateOf===void 0)return[];metadata.duplicate_of=duplicateOf;const duplicateFallbackFields=[],fallbackValues=[{key:"resolution",value:`Duplicate of ${duplicateOf}`},{key:"expected_result",value:`Canonical item ${duplicateOf} tracks the work.`},{key:"actual_result",value:`Closed as duplicate of ${duplicateOf}.`}];for(const{key,value}of fallbackValues)shouldApplyDuplicateFallback(metadata[key])&&(metadata[key]=value,duplicateFallbackFields.push(key));return duplicateFallbackFields}function collectCloseValidationWarnings(metadata,validateCloseMode,activeChildIds,commandScope){const warnings=[];if(validateCloseMode!=="off"){const missingFields=findMissingCloseValidationFields(metadata);if(missingFields.length>0){const missingLabels=missingFields.map(field=>field.label);if(validateCloseMode==="strict"){const missingFlags=missingFields.map(field=>`--${field.key.replaceAll("_","-")}`),updateTokens=[...commandScope,"update",metadata.id,...missingFlags.flatMap(flag=>[flag,"<value>"])];throw new PmCliError(`Cannot close item ${metadata.id}: missing ${missingLabels.join(", ")}. Populate fields or use --validate-close warn.`,EXIT_CODE.USAGE,{code:"close_validation_missing_fields",recovery:{missing:missingFlags,suggested_retry:renderPmCommand(updateTokens),suggested_retry_args:updateTokens},nextSteps:["Run the suggested pm update, then retry the original pm close invocation.","Use --validate-close warn only when governance permits an evidenced exception."]})}warnings.push(`close_validation_missing_fields:${metadata.id}:${missingLabels.join(",")}`)}if(activeChildIds.length>0){if(validateCloseMode==="strict")throw new PmCliError(`Cannot close item ${metadata.id}: active child items remain open (${activeChildIds.join(", ")}). Close, cancel, or re-parent them first, or use --validate-close warn.`,EXIT_CODE.USAGE);warnings.push(`close_validation_active_children:${metadata.id}:${activeChildIds.join(",")}`)}return warnings}return activeChildIds.length>0&&warnings.push(`closed_with_active_children:${metadata.id}:${activeChildIds.join(",")}`),warnings}function applyCloseReason(metadata,closeReason){return closeReason!==void 0?(metadata.close_reason=closeReason,["close_reason"]):[]}function clearCloseAssignee(metadata){const cleared=["assignee","claim_principal"].filter(key=>metadata[key]!==void 0);for(const key of cleared)delete metadata[key];return[...cleared]}function mutateCloseMetadata(metadata,context){if(isTerminalStatus(metadata.status,context.statusRegistry)&&!context.force)throw new PmCliError(`Item ${metadata.id} is already terminal; use pm update to append acceptance evidence, or --force only for an intentional repeat closure.`,EXIT_CODE.CONFLICT,{recovery:closeEvidenceRecovery(metadata,context.commandScope,context.options)});const inlineChangedFields=applyInlineCloseFields(metadata,context.options),duplicateFallbackFields=applyDuplicateCloseMetadata(metadata,context.duplicateOf),mutationWarnings=collectCloseValidationWarnings(metadata,context.validateCloseMode,context.activeChildIds,context.commandScope);metadata.status=context.statusRegistry.close_status,metadata.closed_at=context.closedAt;const shouldWriteCompletedAt=context.options.completedAt!==void 0||metadata.completed_at===void 0;shouldWriteCompletedAt&&(metadata.completed_at=context.completedAt);const changedFields=["status","closed_at",...shouldWriteCompletedAt?["completed_at"]:[],...applyCloseReason(metadata,context.closeReason),...inlineChangedFields];if(shouldCompletePlanOnClose(metadata)&&(metadata.plan_mode="completed",changedFields.push("plan_mode")),context.duplicateOf!==void 0){changedFields.push("duplicate_of");for(const key of duplicateFallbackFields)changedFields.includes(key)||changedFields.push(key)}changedFields.push(...clearCloseAssignee(metadata));const blockerCleanup=applyTerminalOrderingPolicy(metadata,context.lifecyclePolicy);return changedFields.push(...blockerCleanup.changedFields),mutationWarnings.push(...blockerCleanup.warnings),{changedFields,...mutationWarnings.length>0?{warnings:mutationWarnings}:{}}}const _testOnlyCloseCommand={blockedByIds:collectBlockedByIds};async function closeItem(id,closeReasonText,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path),commandScope=resolvePmCommandScopeArgs(global2);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),statusRegistry=resolveRuntimeStatusRegistry(settings.schema),author=resolveAuthor(options.author,settings.author_default),typeToFolder=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()).type_to_folder,located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeToFolder);if(!located)throw await buildItemNotFoundError(pmRoot,id,settings.id_prefix,typeToFolder);const duplicateOf=await assertDuplicateTargetExists(pmRoot,settings,options.duplicateOf,located.id),lifecyclePolicy={requireCloseReason:options.lifecyclePolicy?.requireCloseReason??settings.governance.require_close_reason,orderingEdges:options.lifecyclePolicy?.orderingEdges??"preserve"},closeReason=requireTerminalReason({explicit:closeReasonText,duplicateOf,resolution:options.resolution,message:options.message},lifecyclePolicy.requireCloseReason).closeReason,validateCloseMode=parseValidateCloseMode(options.validateClose)??settings.governance.close_validation_default,trackerItems=await listAllItemMetadataLight(pmRoot,settings.item_format,typeToFolder,void 0,settings.schema),activeChildIds=findActiveChildIds(trackerItems,located.id,statusRegistry),closedAt=nowIso(),completedAt=options.completedAt===void 0?closedAt:resolveIsoOrRelative(options.completedAt,new Date(closedAt),"completed-at");let completion={timestamp:completedAt,source:options.completedAt===void 0?"close_time":"asserted",...options.completedAt===void 0?{hint:`completed_at defaults to the close time. If work finished earlier, correct it with ${renderPmCommand([...commandScope,"update",located.id,"--completed-at","<ISO>"])}.`}:{}};const result=await mutateItemWithHistoryContextResolver({pmRoot,settings,id:located.id,op:"close",author,message:options.message,force:options.force,resolveHistoryContext:()=>({completion:{timestamp:completion.timestamp,source:completion.source}}),mutate(document){return options.completedAt===void 0&&document.metadata.completed_at!==void 0&&(completion={timestamp:document.metadata.completed_at,source:"existing"}),mutateCloseMetadata(document.metadata,{pmRoot,commandScope,statusRegistry,force:options.force,options,duplicateOf,validateCloseMode,activeChildIds,closeReason,closedAt,completedAt,lifecyclePolicy})}}),evidence=validateCloseMode==="warn"?closeEvidenceRecovery(result.item,commandScope):void 0;return{item:toItemRecord(result.item),changed_fields:result.changedFields,...evidence?{follow_up:{kind:"complete_close_evidence",missing:evidence.missing,suggested_command:evidence.suggested_retry,suggested_command_args:evidence.suggested_retry_args}}:{},warnings:[...result.warnings,...await autoUnblockResolvedDependents(pmRoot,settings,trackerItems,located.id,author,statusRegistry)],completion}}function runClose(id,closeReasonText,options,global2){return closeItem(id,closeReasonText,options,global2)}export{_testOnlyCloseCommand,closeItem,committedCloseDependentConflict,runClose};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1ae551f9-53e5-5f63-a6a2-231a40c61c62")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{enrichItemRevisionConflict,isItemRevisionConflict,itemRevisionConflictRowFields}from"./item-revision.js";import{toErrorMessage}from"../runtime-primitives.js";import{toItemRecord,isTerminalStatus,resolveItemTypeRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,PmCliError,buildItemNotFoundError,listAllItemMetadataLight,locateItem,readLocatedItem,mutateItem,resolvePmRoot,readSettings,resolveAuthor,resolveIsoOrRelative,shouldCompletePlanOnClose,getActiveExtensionRegistrations}from"../runtime-primitives.js";import{collectBlockedByIds,indexBlockedByIds}from"../actionability.js";import{applyTerminalOrderingPolicy,requireTerminalReason}from"../lifecycle-policy.js";import{nowIso}from"../../core/shared/time.js";import{isPmCliErrorDetails}from"../../core/shared/error-details.js";import{unicodeSafePrefix}from"../../core/shared/text-normalization.js";import{renderPmCommand,resolvePmCommandScopeArgs}from"../command-line.js";import{mutateItemWithHistoryContextResolver}from"../../core/store/item-store.js";const CLOSE_VALIDATION_FIELDS=[{key:"resolution",label:"resolution (--resolution)"},{key:"expected_result",label:"expected_result (--expected-result)"},{key:"actual_result",label:"actual_result (--actual-result)"}];function parseValidateCloseMode(raw){if(raw===void 0)return;const normalized=raw.trim().toLowerCase();if(normalized.length===0||normalized==="warn")return"warn";if(normalized==="off"||normalized==="none"||normalized==="disabled")return"off";if(normalized==="strict")return"strict";throw new PmCliError(`Invalid --validate-close mode "${raw}" (expected "off", "warn", or "strict")`,EXIT_CODE.USAGE)}function findMissingCloseValidationFields(itemMetadata){const missing=[];for(const field of CLOSE_VALIDATION_FIELDS){const rawValue=itemMetadata[field.key];(typeof rawValue!="string"||rawValue.trim().length===0)&&missing.push(field)}return missing}function closeEvidenceRecovery(metadata,commandScope,options={}){const missing=findMissingCloseValidationFields(metadata);if(missing.length===0)return;const values={resolution:options.resolution,expected_result:options.expectedResult,actual_result:options.actualResult},missingFlags=missing.map(field=>`--${field.key.replaceAll("_","-")}`),args=[...commandScope,"update",metadata.id,...missing.flatMap((field,index)=>[missingFlags[index],values[field.key]?.trim()||"<value>"])];return{missing:missingFlags,suggested_retry:renderPmCommand(args),suggested_retry_args:args}}async function duplicateChainReferencesClosingItem(loadItemById,initialDuplicateOf,closingId){const visited=new Set;let current=initialDuplicateOf;for(;typeof current=="string"&&current.trim().length>0;){const currentId=current.trim();if(currentId===closingId)return!0;if(visited.has(currentId))return!1;visited.add(currentId),current=(await loadItemById(currentId))?.duplicate_of}return!1}function shouldApplyDuplicateFallback(value){return typeof value!="string"||value.trim().length===0}async function assertDuplicateTargetExists(pmRoot,settings,duplicateOf,closingId){const rawTarget=duplicateOf?.trim();if(!rawTarget)return;if(rawTarget===closingId)throw new PmCliError("An item cannot be closed as a duplicate of itself.",EXIT_CODE.USAGE,{code:"duplicate_target_self",why:"--duplicate-of must identify the canonical item that should remain open or already represent the work."});const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),itemCache=new Map,loadItemById=async id=>{if(itemCache.has(id))return itemCache.get(id)??null;const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);if(!located)return itemCache.set(id,null),null;const{document}=await readLocatedItem(located,{schema:settings.schema});return itemCache.set(id,document.metadata),document.metadata},target=await loadItemById(rawTarget);if(!target)throw new PmCliError(`Duplicate target "${rawTarget}" was not found. Create or locate the canonical item first.`,EXIT_CODE.USAGE,{code:"duplicate_target_missing",why:"Duplicate closure should point at a real canonical pm item so future dedupe and changelog tooling can trace the relationship.",examples:[`pm close ${closingId} "Duplicate of ${rawTarget}" --duplicate-of ${rawTarget}`],nextSteps:["Run pm search/list to find the canonical item, then retry with --duplicate-of <id>."]});if(await duplicateChainReferencesClosingItem(loadItemById,target.duplicate_of,closingId))throw new PmCliError(`Circular duplicate reference detected. Target "${rawTarget}" points back to "${closingId}".`,EXIT_CODE.USAGE,{code:"duplicate_target_circular",why:"Circular duplicate relationships create loops for dedupe and status propagation tooling.",nextSteps:["Choose the existing canonical item, or clear the target duplicate_of metadata before closing this item as a duplicate."]});if(typeof target.duplicate_of=="string"&&target.duplicate_of.trim().length>0)throw new PmCliError(`Duplicate target "${rawTarget}" is already marked as a duplicate of "${target.duplicate_of.trim()}".`,EXIT_CODE.USAGE,{code:"duplicate_target_is_duplicate",why:"Duplicate closure should point directly at the canonical item, not another duplicate.",examples:[`pm close ${closingId} "Duplicate of ${target.duplicate_of.trim()}" --duplicate-of ${target.duplicate_of.trim()}`],nextSteps:["Use the canonical item referenced by duplicate_of as the --duplicate-of target."]});return target.id}function findActiveChildIds(items,parentId,statusRegistry){return items.filter(item=>item.parent===parentId&&!isTerminalStatus(item.status,statusRegistry)).map(item=>item.id).sort((left,right)=>left.localeCompare(right))}function findAutoUnblockCandidates(items,closedId,statusRegistry){const itemsById=new Map(items.map(item=>[item.id.trim().toLowerCase(),item])),blockerIdsByItem=indexBlockedByIds(items),normalizedClosedId=closedId.trim().toLowerCase(),blockedStatuses=statusRegistry.blocked_statuses;return items.filter(item=>blockedStatuses.has(item.status)).map(item=>({item,blockerIds:blockerIdsByItem.get(item.id.trim().toLowerCase())})).filter(({blockerIds})=>blockerIds.includes(normalizedClosedId)).filter(({blockerIds})=>blockerIds.every(blockerId=>{if(blockerId===normalizedClosedId)return!0;const blocker=itemsById.get(blockerId);return blocker!==void 0&&isTerminalStatus(blocker.status,statusRegistry)})).map(({item,blockerIds})=>({id:item.id,blocker_ids:blockerIds})).sort((left,right)=>left.id.localeCompare(right.id))}async function autoUnblockResolvedDependents(pmRoot,settings,items,closedId,author,statusRegistry,commandScope){const candidates=findAutoUnblockCandidates(items,closedId,statusRegistry),warnings=[],unblockedIds=[],conflictIds=[],failed=[];let conflict;for(const candidate of candidates)try{const unblocked=await mutateItem({pmRoot,settings,id:candidate.id,op:"update",author,message:`Auto-unblocked after blocker ${closedId} closed`,mutate(document){const dependencies=document.metadata.dependencies??[],remainingDependencies=dependencies.filter(dependency=>{const dependencyId=dependency.id.trim().toLowerCase();return dependency.kind!=="blocked_by"||!candidate.blocker_ids.includes(dependencyId)});document.metadata.status=statusRegistry.open_status,delete document.metadata.blocked_by,delete document.metadata.blocked_reason,document.metadata.unblock_note=`Auto-unblocked after blocker ${closedId} closed; all blockers resolved (${candidate.blocker_ids.join(", ")}).`,remainingDependencies.length>0?document.metadata.dependencies=remainingDependencies:delete document.metadata.dependencies;const changedFields=["status","blocked_by","blocked_reason","unblock_note"];return remainingDependencies.length!==dependencies.length&&changedFields.push("dependencies"),{changedFields}}});warnings.push(`auto_unblocked:${unblocked.item.id}:resolved_blockers=${candidate.blocker_ids.join(",")}`),unblockedIds.push(unblocked.item.id)}catch(error){const reason=error instanceof Error?error.message.replace(/\s+/g," ").trim():"unknown";isItemRevisionConflict(error)?(conflict??=error,conflictIds.push(candidate.id)):failed.push({id:candidate.id,reason}),warnings.push(`auto_unblock_failed:${candidate.id}:${reason}`)}if(conflict!==void 0){const enriched=await enrichItemRevisionConflict(conflict,pmRoot),blockedStatuses=[...statusRegistry.blocked_statuses].sort().join(",");throw postCloseDependentConflict(enriched,{closedId,unblockedIds,conflictIds,failed,openStatus:statusRegistry.open_status,blockedStatuses,commandScope})}return warnings}const POST_CLOSE_REPORT_LIMIT=10,POST_CLOSE_STEP_LIMIT=20,POST_CLOSE_DETAIL_TRIMS=[{list:"auto_unblock_failed",omitted:"auto_unblock_failed_omitted",floor:0},{list:"changes_since",omitted:"changes_since_omitted",floor:0},{list:"pending_unblock",omitted:"pending_unblock_omitted",floor:1}];function fitPostCloseDetails(details){for(const trim of POST_CLOSE_DETAIL_TRIMS){const list=details[trim.list];if(Array.isArray(list))for(;list.length>trim.floor&&!isPmCliErrorDetails(details);)list.pop(),Reflect.set(details,trim.omitted,Number(details[trim.omitted])+1)}return details}function boundedIdList(ids){const omitted=ids.length-POST_CLOSE_REPORT_LIMIT;return`${ids.slice(0,POST_CLOSE_REPORT_LIMIT).join(", ")}${omitted>0?`, and ${omitted} more`:""}`}function postCloseDependentConflict(conflict,fanOut){const{closedId,conflictIds,failed,commandScope}=fanOut,dependent=String(conflict.context.item_id),unblock=id=>renderPmCommand([...commandScope,"update",id,"--status",fanOut.openStatus,"--unset","blocked_by","--unset","blocked_reason","--expect-hash",`${id}=<item_hash>`]),reported=failed.slice(0,POST_CLOSE_REPORT_LIMIT).map(entry=>({id:entry.id,reason:unicodeSafePrefix(entry.reason,160)})),otherFailures=failed.length===0?"":` Auto-unblocking also failed for ${boundedIdList(failed.map(entry=>entry.id))}; details.auto_unblock_failed gives the reasons it kept (auto_unblock_failed_omitted counts the rest; their get step shows the item). Fix that cause before unblocking it.`,discovery=renderPmCommand([...commandScope,"list","--status",fanOut.blockedStatuses,"--fields","id,title,blocked_by,dependencies","--limit","200"]),allSteps=[...conflictIds.slice(0,POST_CLOSE_REPORT_LIMIT).flatMap(id=>[renderPmCommand([...commandScope,"get",id,"--json"]),unblock(id)]),...reported.map(entry=>renderPmCommand([...commandScope,"get",entry.id,"--json"]))],truncated=conflictIds.length>POST_CLOSE_REPORT_LIMIT||failed.length>POST_CLOSE_REPORT_LIMIT||allSteps.length>POST_CLOSE_STEP_LIMIT,steps=allSteps.slice(0,truncated?POST_CLOSE_STEP_LIMIT-1:POST_CLOSE_STEP_LIMIT);return new PmCliError(`${closedId} was closed, but auto-unblocking ${dependent} was refused. ${conflict.message}`,conflict.exitCode,{...conflict.context,required:`The close of ${closedId} is complete; do not retry it. Only unblocking ${conflictIds.length===1?dependent:`the guarded dependents it refused (${boundedIdList(conflictIds)})`} remains: re-read each one (pm get <id> --json reports item_hash), check that every blocker it declares is resolved, then unblock it with ${unblock(dependent)}${conflictIds.length===1?"":" for each id"}.${otherFailures}${truncated?` This refusal does not list a step for every dependent left blocked; list them with ${discovery}, and while it reports has_more, continue with --after <next_cursor>.`:""}`,nextSteps:truncated?[...steps,discovery]:steps,details:fitPostCloseDetails({...structuredClone(conflict.context.details),pending_unblock:conflictIds.slice(0,POST_CLOSE_REPORT_LIMIT),pending_unblock_omitted:Math.max(0,conflictIds.length-POST_CLOSE_REPORT_LIMIT),auto_unblock_failed:reported,auto_unblock_failed_omitted:Math.max(0,failed.length-POST_CLOSE_REPORT_LIMIT)}),side_effects:[{path:`history/${closedId}.jsonl`,op:"close"},...fanOut.unblockedIds.map(id=>({path:`history/${id}.jsonl`,op:"update"}))]})}async function committedCloseDependentConflict(error,id,pmRoot){if(!isItemRevisionConflict(error)||!error.context.side_effects?.some(effect=>`${effect.op}:${effect.path}`==`close:history/${id}.jsonl`))return;const dependent=String(error.context.item_id);return{warnings:[...error.context.side_effects.filter(effect=>effect.op==="update").map(effect=>effect.path.slice(8,-6)).map(unblockedId=>`auto_unblocked:${unblockedId}`),`auto_unblock_refused:${dependent}:item_revision_conflict`],dependent_revision_conflict:{item_id:dependent,error:toErrorMessage(error),...await itemRevisionConflictRowFields(error,pmRoot)}}}function applyInlineCloseFields(metadata,options){const changedFields=[],inlineCloseFields=[{option:options.resolution,key:"resolution"},{option:options.expectedResult,key:"expected_result"},{option:options.actualResult,key:"actual_result"}];for(const{option,key}of inlineCloseFields){if(typeof option!="string")continue;const trimmed=option.trim();trimmed.length!==0&&(metadata[key]=trimmed,changedFields.push(key))}return changedFields}function applyDuplicateCloseMetadata(metadata,duplicateOf){if(duplicateOf===void 0)return[];metadata.duplicate_of=duplicateOf;const duplicateFallbackFields=[],fallbackValues=[{key:"resolution",value:`Duplicate of ${duplicateOf}`},{key:"expected_result",value:`Canonical item ${duplicateOf} tracks the work.`},{key:"actual_result",value:`Closed as duplicate of ${duplicateOf}.`}];for(const{key,value}of fallbackValues)shouldApplyDuplicateFallback(metadata[key])&&(metadata[key]=value,duplicateFallbackFields.push(key));return duplicateFallbackFields}function collectCloseValidationWarnings(metadata,validateCloseMode,activeChildIds,commandScope){const warnings=[];if(validateCloseMode!=="off"){const missingFields=findMissingCloseValidationFields(metadata);if(missingFields.length>0){const missingLabels=missingFields.map(field=>field.label);if(validateCloseMode==="strict"){const missingFlags=missingFields.map(field=>`--${field.key.replaceAll("_","-")}`),updateTokens=[...commandScope,"update",metadata.id,...missingFlags.flatMap(flag=>[flag,"<value>"])];throw new PmCliError(`Cannot close item ${metadata.id}: missing ${missingLabels.join(", ")}. Populate fields or use --validate-close warn.`,EXIT_CODE.USAGE,{code:"close_validation_missing_fields",recovery:{missing:missingFlags,suggested_retry:renderPmCommand(updateTokens),suggested_retry_args:updateTokens},nextSteps:["Run the suggested pm update, then retry the original pm close invocation.","Use --validate-close warn only when governance permits an evidenced exception."]})}warnings.push(`close_validation_missing_fields:${metadata.id}:${missingLabels.join(",")}`)}if(activeChildIds.length>0){if(validateCloseMode==="strict")throw new PmCliError(`Cannot close item ${metadata.id}: active child items remain open (${activeChildIds.join(", ")}). Close, cancel, or re-parent them first, or use --validate-close warn.`,EXIT_CODE.USAGE);warnings.push(`close_validation_active_children:${metadata.id}:${activeChildIds.join(",")}`)}return warnings}return activeChildIds.length>0&&warnings.push(`closed_with_active_children:${metadata.id}:${activeChildIds.join(",")}`),warnings}function applyCloseReason(metadata,closeReason){return closeReason!==void 0?(metadata.close_reason=closeReason,["close_reason"]):[]}function clearCloseAssignee(metadata){const cleared=["assignee","claim_principal"].filter(key=>metadata[key]!==void 0);for(const key of cleared)delete metadata[key];return[...cleared]}function mutateCloseMetadata(metadata,context){if(isTerminalStatus(metadata.status,context.statusRegistry)&&!context.force)throw new PmCliError(`Item ${metadata.id} is already terminal; use pm update to append acceptance evidence, or --force only for an intentional repeat closure.`,EXIT_CODE.CONFLICT,{recovery:closeEvidenceRecovery(metadata,context.commandScope,context.options)});const inlineChangedFields=applyInlineCloseFields(metadata,context.options),duplicateFallbackFields=applyDuplicateCloseMetadata(metadata,context.duplicateOf),mutationWarnings=collectCloseValidationWarnings(metadata,context.validateCloseMode,context.activeChildIds,context.commandScope);metadata.status=context.statusRegistry.close_status,metadata.closed_at=context.closedAt;const shouldWriteCompletedAt=context.options.completedAt!==void 0||metadata.completed_at===void 0;shouldWriteCompletedAt&&(metadata.completed_at=context.completedAt);const changedFields=["status","closed_at",...shouldWriteCompletedAt?["completed_at"]:[],...applyCloseReason(metadata,context.closeReason),...inlineChangedFields];if(shouldCompletePlanOnClose(metadata)&&(metadata.plan_mode="completed",changedFields.push("plan_mode")),context.duplicateOf!==void 0){changedFields.push("duplicate_of");for(const key of duplicateFallbackFields)changedFields.includes(key)||changedFields.push(key)}changedFields.push(...clearCloseAssignee(metadata));const blockerCleanup=applyTerminalOrderingPolicy(metadata,context.lifecyclePolicy);return changedFields.push(...blockerCleanup.changedFields),mutationWarnings.push(...blockerCleanup.warnings),{changedFields,...mutationWarnings.length>0?{warnings:mutationWarnings}:{}}}const _testOnlyCloseCommand={blockedByIds:collectBlockedByIds,fitPostCloseDetails};async function closeItem(id,closeReasonText,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path),commandScope=resolvePmCommandScopeArgs(global2);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),statusRegistry=resolveRuntimeStatusRegistry(settings.schema),author=resolveAuthor(options.author,settings.author_default),typeToFolder=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()).type_to_folder,located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeToFolder);if(!located)throw await buildItemNotFoundError(pmRoot,id,settings.id_prefix,typeToFolder);const duplicateOf=await assertDuplicateTargetExists(pmRoot,settings,options.duplicateOf,located.id),lifecyclePolicy={requireCloseReason:options.lifecyclePolicy?.requireCloseReason??settings.governance.require_close_reason,orderingEdges:options.lifecyclePolicy?.orderingEdges??"preserve"},closeReason=requireTerminalReason({explicit:closeReasonText,duplicateOf,resolution:options.resolution,message:options.message},lifecyclePolicy.requireCloseReason).closeReason,validateCloseMode=parseValidateCloseMode(options.validateClose)??settings.governance.close_validation_default,trackerItems=await listAllItemMetadataLight(pmRoot,settings.item_format,typeToFolder,void 0,settings.schema),activeChildIds=findActiveChildIds(trackerItems,located.id,statusRegistry),closedAt=nowIso(),completedAt=options.completedAt===void 0?closedAt:resolveIsoOrRelative(options.completedAt,new Date(closedAt),"completed-at");let completion={timestamp:completedAt,source:options.completedAt===void 0?"close_time":"asserted",...options.completedAt===void 0?{hint:`completed_at defaults to the close time. If work finished earlier, correct it with ${renderPmCommand([...commandScope,"update",located.id,"--completed-at","<ISO>"])}.`}:{}};const result=await mutateItemWithHistoryContextResolver({pmRoot,settings,id:located.id,op:"close",author,message:options.message,force:options.force,resolveHistoryContext:()=>({completion:{timestamp:completion.timestamp,source:completion.source}}),mutate(document){return options.completedAt===void 0&&document.metadata.completed_at!==void 0&&(completion={timestamp:document.metadata.completed_at,source:"existing"}),mutateCloseMetadata(document.metadata,{pmRoot,commandScope,statusRegistry,force:options.force,options,duplicateOf,validateCloseMode,activeChildIds,closeReason,closedAt,completedAt,lifecyclePolicy})}}),evidence=validateCloseMode==="warn"?closeEvidenceRecovery(result.item,commandScope):void 0;return{item:toItemRecord(result.item),changed_fields:result.changedFields,...evidence?{follow_up:{kind:"complete_close_evidence",missing:evidence.missing,suggested_command:evidence.suggested_retry,suggested_command_args:evidence.suggested_retry_args}}:{},warnings:[...result.warnings,...await autoUnblockResolvedDependents(pmRoot,settings,trackerItems,located.id,author,statusRegistry,commandScope)],completion}}function runClose(id,closeReasonText,options,global2){return closeItem(id,closeReasonText,options,global2)}export{_testOnlyCloseCommand,closeItem,committedCloseDependentConflict,runClose};
2
2
  //# sourceMappingURL=close.js.map
@@ -1,6 +1,8 @@
1
+ import { type MutationInputAudience } from "../../core/item/literal-mutation-input.js";
1
2
  import { type ResolvedItemTypeDefinition,type RuntimeFieldRegistry,type GlobalOptions } from "../runtime-primitives.js";
2
3
  import { type SimilarityAdvisory } from "../similarity.js";
3
4
  import { type LifecycleTransitionSuggestion } from "./lifecycle-transitions.js";
5
+ import { type CreateNullClearableOptionKey,type WithNullClears } from "./shared-unset-fields.js";
4
6
  import type { MutationMetadataCommandOptions,SharedLinkedResourceClearOptions,SharedLinkedResourceOptions } from "./mutation-command-options.js";
5
7
  import type { Comment,Dependency,ItemMetadata,LinkedDoc,LinkedFile,LinkedTest,LogNote } from "../../types/index.js";
6
8
  /** Documents the create command options payload exchanged by command, SDK, and package integrations. */
@@ -43,8 +45,8 @@ allowDuplicate?:boolean;
43
45
  inheritFocus?:boolean;
44
46
  [key:string]:unknown;
45
47
  }
46
- /** Presentation-neutral input accepted by the SDK-owned create operation. */
47
- export type CreateOperationOptions = CreateCommandOptions;
48
+ /** Presentation-neutral input accepted by the SDK-owned create operation; clearable fields also accept `null`. */
49
+ export type CreateOperationOptions = WithNullClears<CreateCommandOptions,CreateNullClearableOptionKey>;
48
50
  /** Documents the create result payload exchanged by command, SDK, and package integrations. */
49
51
  export interface CreateResult {
50
52
  /** Value that configures or reports item for this contract. */
@@ -107,14 +109,14 @@ declare function createExampleTokensForFlag(flag:string,typeName:string,openStat
107
109
  /** Build a runnable option shape for one configured type, expressing empty required collections with explicit clear flags. */
108
110
  declare function buildTypeSpecificCreateExample(typeDefinition:ResolvedItemTypeDefinition,missingCreateFlags:string[],missingTypeOptionKeys:string[],openStatus:string):string;
109
111
  /** Require a trimmed option value while preserving title-specific recovery guidance. */
110
- export declare function requireStringOption(value:string | undefined,flag:string):string;
111
- declare function mergeCreateOptionsWithTemplate(templateOptions:Record<string,unknown>,explicitOptions:CreateCommandOptions):CreateCommandOptions;
112
+ export declare function requireStringOption(value:string | undefined,flag:string,audience?:MutationInputAudience):string;
113
+ declare function mergeCreateOptionsWithTemplate(templateOptions:Record<string,unknown>,explicitOptions:CreateCommandOptions,runtimeFieldRegistry?:RuntimeFieldRegistry):CreateCommandOptions;
112
114
  declare function normalizeExtensionCommandPath(command:string):string;
113
115
  declare function hasTemplatesShowHandler():boolean;
114
116
  declare function readTemplateOptionsFromRuntimeResult(result:unknown,templateName:string):Record<string,string | string[] | number | boolean>;
115
117
  declare function loadCreateTemplateOptionsFromRuntime(templateName:string,global:GlobalOptions,pmRoot:string):Promise<Record<string,string | string[] | number | boolean>>;
116
118
  /** Implements run create for the public runtime surface of this module. */
117
- export declare function runCreate(options:CreateCommandOptions,global:GlobalOptions):Promise<CreateResult>;
119
+ export declare function runCreate(input:CreateOperationOptions,global:GlobalOptions):Promise<CreateResult>;
118
120
  /** Public contract for test only create command, shared by SDK and presentation-layer consumers. */
119
121
  export declare const _testOnlyCreateCommand:{
120
122
  buildHistoryMessage:typeof buildHistoryMessage;