@unbrained/pm-cli 2026.10.3 → 2026.10.4

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 (98) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +17 -2
  3. package/dist/cli/error-guidance.js +1 -1
  4. package/dist/cli/runtime/invocation-options.js +1 -1
  5. package/dist/cli/runtime/selection.js +1 -1
  6. package/dist/cli/runtime-compatibility-boundary.d.ts +1 -1
  7. package/dist/cli/runtime-compatibility-boundary.js +3 -3
  8. package/dist/cli-bundle/bundle-manifest.json +154 -154
  9. package/dist/cli-bundle/chunks/{chunk-YCBGZF3T.js → chunk-7CE2DJMA.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-6ST3SCQ6.js → chunk-7UVXKI7K.js} +2 -2
  11. package/dist/cli-bundle/chunks/{chunk-H2DZW6I6.js → chunk-D7Z2ZMJL.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-44UGMMQ6.js → chunk-GZMWISWW.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-KP7NBQK3.js → chunk-J52QIRRZ.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-3AF2R3Y6.js → chunk-JDKD3WGG.js} +6 -6
  15. package/dist/cli-bundle/chunks/chunk-JQ7DW663.js +2 -0
  16. package/dist/cli-bundle/chunks/{chunk-MKXBCBAN.js → chunk-QXIDOOWT.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-5XKF5SQV.js → chunk-SMKHR6BM.js} +49 -49
  18. package/dist/cli-bundle/chunks/{chunk-FW5LJXQY.js → chunk-V3U77H3V.js} +28 -28
  19. package/dist/cli-bundle/chunks/{chunk-YDWKGUQU.js → chunk-XZDWAYJC.js} +2 -2
  20. package/dist/cli-bundle/chunks/{chunk-QPKQKSQU.js → chunk-Y6VRBTP3.js} +71 -71
  21. package/dist/cli-bundle/chunks/{chunk-6Z4IV2MC.js → chunk-YAAFYFS4.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-list-query-DYCGUQEW.js → register-list-query-QBGXO5JJ.js} +2 -2
  23. package/dist/cli-bundle/chunks/{register-mutation-5PT3NW3A.js → register-mutation-53ZLT4RX.js} +2 -2
  24. package/dist/cli-bundle/chunks/{register-operations-QDDQOAAV.js → register-operations-OBK2FXUU.js} +2 -2
  25. package/dist/cli-bundle/chunks/{register-setup-BBX67YMA.js → register-setup-HM3OCBH2.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/{chunk-FKK2HI3S.js → chunk-2JFYR56O.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/{chunk-UTRSM3ZK.js → chunk-32EVUSS4.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-DBD4W4QP.js → chunk-467EW5RL.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-WAJNX4RN.js → chunk-5GUSO2P4.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-GMYUNHST.js → chunk-6XBRADQQ.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/{chunk-EJN7DY3B.js → chunk-7O4NUJVO.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-E754JDLY.js → chunk-CURTIIQT.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-4FFPGNCJ.js → chunk-IJUWEEEB.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-XRSCIYHR.js → chunk-JCVMOSWQ.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-ZIXFMIUL.js → chunk-JMJK2L4Z.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-WCY6HRZO.js → chunk-KG3H4UZZ.js} +14 -14
  37. package/dist/cli-bundle/focused-chunks/{chunk-VVWYI2X7.js → chunk-MHQ2XICU.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-3BIYG72P.js → chunk-Q6DJ5DFQ.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/{chunk-73DA7ISY.js → chunk-RJV6QVJE.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-HIA2ZF64.js → chunk-ZE2JZ7R6.js} +11 -11
  41. package/dist/cli-bundle/focused-chunks/chunk-ZLEN4HZD.js +165 -0
  42. package/dist/cli-bundle/main.js +22 -22
  43. package/dist/cli-bundle/sdk-authoring.js +1 -1
  44. package/dist/cli-bundle/sdk-contracts.js +1 -1
  45. package/dist/cli-bundle/sdk-core.js +22 -22
  46. package/dist/cli-bundle/sdk-governance.js +1 -1
  47. package/dist/cli-bundle/sdk-graph.js +1 -1
  48. package/dist/cli-bundle/sdk-merge.js +11 -11
  49. package/dist/cli-bundle/sdk-query.js +1 -1
  50. package/dist/cli-bundle/sdk-runtime.js +1 -1
  51. package/dist/cli-bundle/sdk-testing.js +1 -1
  52. package/dist/cli-bundle/sdk.js +1 -1
  53. package/dist/core/extensions/extension-types.d.ts +8 -1
  54. package/dist/core/extensions/extension-types.js +1 -1
  55. package/dist/core/shared/time.js +1 -1
  56. package/dist/core/store/settings.d.ts +11 -2
  57. package/dist/core/store/settings.js +2 -2
  58. package/dist/sdk/agent/subcommand-recovery.js +1 -1
  59. package/dist/sdk/cli-bootstrap.js +1 -1
  60. package/dist/sdk/context-intent-contracts.js +1 -1
  61. package/dist/sdk/extension-command-context.js +1 -1
  62. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  63. package/dist/sdk/item-transaction.js +1 -1
  64. package/dist/sdk/lifecycle/recurrence-parsers.js +1 -1
  65. package/dist/sdk/lifecycle/task-composition.js +1 -1
  66. package/dist/sdk/output-projection.js +1 -1
  67. package/dist/sdk/public-surface.json +1 -1
  68. package/dist/sdk/query/get.js +1 -1
  69. package/dist/sdk/query/search-pagination.d.ts +1 -1
  70. package/dist/sdk/query/search-pagination.js +1 -1
  71. package/dist/sdk/test/workspace-snapshot.js +1 -1
  72. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +25 -0
  73. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +23 -0
  74. package/docs/SDK_AUDITED_MUTATIONS.md +35 -0
  75. package/docs/TESTING.md +8 -0
  76. package/docs/ecosystem-review-2026-09-28.json +2864 -3157
  77. package/marketplace.json +2 -2
  78. package/package.json +1 -1
  79. package/packages/pm-beads/package.json +1 -1
  80. package/packages/pm-calendar/package.json +1 -1
  81. package/packages/pm-command-kit/package.json +1 -1
  82. package/packages/pm-digital-twin/package.json +1 -1
  83. package/packages/pm-governance-audit/package.json +1 -1
  84. package/packages/pm-guide-shell/package.json +1 -1
  85. package/packages/pm-kanban/package.json +1 -1
  86. package/packages/pm-lifecycle-hooks/package.json +1 -1
  87. package/packages/pm-linked-test-adapters/package.json +1 -1
  88. package/packages/pm-search-advanced/package.json +1 -1
  89. package/packages/pm-templates/package.json +1 -1
  90. package/packages/pm-todos/package.json +1 -1
  91. package/packages/pm-vcs/package.json +1 -1
  92. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  93. package/plugins/pm-claude/package.json +2 -2
  94. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  95. package/plugins/pm-codex/package.json +2 -2
  96. package/plugins/pm-codex/plugin.json +1 -1
  97. package/dist/cli-bundle/chunks/chunk-H7CXQBGQ.js +0 -2
  98. package/dist/cli-bundle/focused-chunks/chunk-YC32ZSLS.js +0 -165
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="33c1e75c-e348-5ab1-933f-2f7b6394fe40")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{getActiveExtensionRegistrations,toItemRecord,resolveItemTypeRegistry,resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,TYPE_TO_FOLDER,PmCliError,buildItemNotFoundError,listAllItemMetadataLight,locateItem,readLocatedItem,getHistoryPath,resolvePmRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{readHistoryEntries}from"../history-read.js";import{renderPmCommand}from"../command-line.js";import{recordContextUsageTouches}from"../context-usage.js";import{buildItemChildrenRollup}from"../item-children.js";import{buildItemSchedule}from"../item-schedule.js";import{getItemAt}from"../history-read.js";import{parseIntegerLimit}from"./parsers.js";import{runList}from"./list.js";import{registerOutputMaterialFieldGroups}from"../output-projection.js";import{GET_DEPTH_VALUES,listGetProjectionFields}from"./projection-contracts.js";import{GET_DEPTH_VALUES as GET_DEPTH_VALUES2,listGetProjectionFields as listGetProjectionFields2}from"./projection-contracts.js";const AUTOMATIC_CHILD_ROLLUP_TYPES=new Set(["epic","feature","milestone","plan"]);const BUILTIN_ITEM_TYPES=new Set(Object.keys(TYPE_TO_FOLDER).map(type=>type.toLowerCase()));function itemCollectionCounts(item){const lengths=Object.fromEntries(["comments","notes","learnings","files","tests","docs","reminders","events"].map(key=>[key,item[key]?.length??0]));return lengths}function itemMaterialFieldGroups(item,body,children){const collectionCounts=itemCollectionCounts(item);return[...body.length>0?["body"]:[],...Object.entries(collectionCounts).flatMap(([name,count])=>count>0?[name]:[]),...collectionCounts.files+collectionCounts.tests+collectionCounts.docs>0?["linked"]:[],...children===void 0?["children"]:children.count>0?["children"]:[],...typeof item.assignee==="string"&&item.assignee.trim().length>0?["claim_state"]:[],...buildItemSchedule(item)?["schedule"]:[]]}function shouldAutoIncludeGetChildren(itemType){const normalizedType=itemType.trim().toLowerCase();return normalizedType.length>0&&(AUTOMATIC_CHILD_ROLLUP_TYPES.has(normalizedType)||!BUILTIN_ITEM_TYPES.has(normalizedType))}function toClaimHistoryContext(entry){return{ts:entry.ts,author:entry.author,message:entry.message??null}}function resolveClaimStateContext(assigneeValue,history){const assignee=assigneeValue?.trim();const normalizedAssignee=assignee&&assignee.length>0?assignee:null;const lastClaim=[...history].reverse().find(entry=>entry.op==="claim");const lastRelease=[...history].reverse().find(entry=>entry.op==="release");return{claimed:normalizedAssignee!==null,assignee:normalizedAssignee,last_claim:lastClaim?toClaimHistoryContext(lastClaim):null,last_release:lastRelease?toClaimHistoryContext(lastRelease):null}}function parseGetDepth(raw){if(raw===void 0||raw.trim().length===0){return"standard"}const normalized=raw.trim().toLowerCase();if(normalized==="full"){return"deep"}if(GET_DEPTH_VALUES.includes(normalized)){return normalized}throw new PmCliError("Get --depth must be one of brief|standard|deep|full",EXIT_CODE.USAGE)}function projectItemForDepth(item,depth){const collectionCounts=itemCollectionCounts(item);if(depth==="deep"){return{...item,comments:item.comments??[],notes:item.notes??[],learnings:item.learnings??[],files:item.files??[],tests:item.tests??[],docs:item.docs??[],reminders:item.reminders??[],events:item.events??[],notes_count:collectionCounts.notes,tests_count:collectionCounts.tests,collection_counts:collectionCounts}}const{comments:_comments,notes:_notes,learnings:_learnings,files:_files,tests:_tests,docs:_docs,reminders:_reminders,events:_events,...projected}=item;return{...projected,notes_count:item.notes?.length??0,tests_count:item.tests?.length??0,collection_counts:collectionCounts}}function parseGetFields(raw){if(raw===void 0){return null}const fields=raw.split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0);if(fields.length===0){throw new PmCliError("Get --fields requires a comma-separated list of field names",EXIT_CODE.USAGE)}return fields}function normalizeGetField(field){return field.startsWith("item.")?field.slice("item.".length):field}function validateGetFields(fields,runtimeMetadataKeys,id){if(fields===null){return}const allowedValues=listGetProjectionFields(runtimeMetadataKeys);const allowed=new Set(allowedValues);const unknown=fields.filter(field=>{const normalized=normalizeGetField(field);return!allowed.has(field)&&!allowed.has(normalized)});if(unknown.length>0){const suggestedRetryArguments=["get",id,"--fields",fields.filter(field=>!unknown.includes(field)).join(",")||"id,title,status"];throw new PmCliError(`Unknown get --fields value(s): ${unknown.join(", ")}`,EXIT_CODE.USAGE,{code:"unknown_field_projection",examples:["pm get <id> --fields id,title,status,type,updated_at","pm get <id> --fields id,title,claim_state","pm get <id> --fields id,title,body,linked.files"],recovery:{allowed_values:allowedValues,suggested_retry:renderPmCommand(suggestedRetryArguments),suggested_retry_args:suggestedRetryArguments}})}}const EMPTY_PROJECTED_COLLECTION_FIELDS=new Set(["comments","notes","learnings","files","tests","test_runs","docs","reminders","events","dependencies","plan_steps","plan_decisions","plan_discoveries","plan_validation"]);function projectedMetadataValue(source,counts,field){if(Object.hasOwn(counts,field))return counts[field];if(source[field]!==void 0)return source[field];return EMPTY_PROJECTED_COLLECTION_FIELDS.has(field)?[]:void 0}function projectItemForFields(item,fields){const source=toItemRecord(item);const omittedCounts={notes_count:item.notes?.length??0,tests_count:item.tests?.length??0,collection_counts:itemCollectionCounts(item)};const projected={id:item.id};for(const field of fields){const normalized=normalizeGetField(field);if(normalized==="body"||normalized==="linked"||normalized.startsWith("linked.")||normalized==="claim_state"||normalized.startsWith("claim_state.")||normalized==="children"||normalized.startsWith("children.")||normalized==="schedule"||normalized.startsWith("schedule.")){continue}projected[normalized]=projectedMetadataValue(source,omittedCounts,normalized)}return projected}function fieldsInclude(fields,name){return fields?.some(field=>field===name||field===`item.${name}`)??false}function fieldsIncludeRoot(fields,name){return fields.some(field=>{const normalized=normalizeGetField(field);return normalized===name||normalized.startsWith(`${name}.`)})}function resolveGetProjection(options,id){if(options.full&&(options.fields!==void 0||options.depth!==void 0)){throw new PmCliError("Get projection options are mutually exclusive; remove the extra projection flag and retry.",EXIT_CODE.USAGE,{code:"projection_options_mutually_exclusive",recovery:{suggested_retry:renderPmCommand(["get",id,"--full"]),suggested_retry_args:["get",id,"--full"]}})}if(options.tree!==true&&options.treeDepth!==void 0){throw new PmCliError("Get --tree-depth requires --tree",EXIT_CODE.USAGE)}if(options.at!==void 0&&options.tree===true){throw new PmCliError("Get --at cannot be combined with --tree because workspace-level historical projections are not yet indexed.",EXIT_CODE.USAGE)}return{depth:options.full?"deep":parseGetDepth(options.depth),full:options.full===true||options.depth?.trim().toLowerCase()==="full",treeDepth:options.tree===true?parseIntegerLimit(options.treeDepth,"--tree-depth"):void 0,fields:parseGetFields(options.fields),fieldProjection:options.fields!==void 0}}async function loadGetItemContext(id,global2,at){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());if(at!==void 0){const historical=await getItemAt(id,at,{pmRoot:global2.path});return{pmRoot,settings,typeToFolder:typeRegistry.type_to_folder,locatedId:historical.document.metadata.id,metadata:historical.document.metadata,body:historical.document.body,historical}}const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);if(!located){throw await buildItemNotFoundError(pmRoot,id,settings.id_prefix,typeRegistry.type_to_folder)}const loaded=await readLocatedItem(located,{schema:settings.schema});return{pmRoot,settings,typeToFolder:typeRegistry.type_to_folder,locatedId:located.id,metadata:loaded.document.metadata,body:loaded.document.body}}function validateGetProjectionFields(fields,settings,historical,id){const runtimeMetadataKeys=resolveRuntimeFieldRegistry(settings.schema).definitions.map(field=>field.metadata_key);validateGetFields(fields,runtimeMetadataKeys,id);if(historical&&fieldsIncludeRoot(fields??[],"children")){throw new PmCliError("Get --at cannot project children because workspace-level historical relationships are not yet indexed.",EXIT_CODE.USAGE)}}function shouldIncludeGetField(params){const{fieldProjection,depth,fields,field}=params;if(fieldProjection){if(field==="body"||field==="linked"){return fieldsInclude(fields,field)}return fieldsIncludeRoot(fields,field)}return depth!=="brief"}async function resolveGetClaimState(context,includeClaimState){if(!includeClaimState){return void 0}const historyPath=getHistoryPath(context.pmRoot,context.locatedId);const history=await readHistoryEntries(historyPath,context.locatedId);return resolveClaimStateContext(context.metadata.assignee,context.historical?history.slice(0,context.historical.target.historyIndex+1):history)}function attachGetLinked(result,context,fields,includeLinked){const includeLinkedFiles=includeLinked||fieldsInclude(fields,"linked.files");const includeLinkedTests=includeLinked||fieldsInclude(fields,"linked.tests");const includeLinkedDocs=includeLinked||fieldsInclude(fields,"linked.docs");if(!includeLinked&&!includeLinkedFiles&&!includeLinkedTests&&!includeLinkedDocs){return}result.linked={files:includeLinkedFiles?context.metadata.files??[]:[],tests:includeLinkedTests?context.metadata.tests??[]:[],docs:includeLinkedDocs?context.metadata.docs??[]:[]}}async function buildGetChildrenRollup(context,includeChildren){if(!includeChildren){return void 0}const statusRegistry=resolveRuntimeStatusRegistry(context.settings.schema);const corpus=await listAllItemMetadataLight(context.pmRoot,context.settings.item_format,context.typeToFolder,void 0,context.settings.schema);return buildItemChildrenRollup(context.locatedId,corpus,statusRegistry)}function attachGetSchedule(result,context,fields,includeSchedule){if(!includeSchedule){return}const schedule=buildItemSchedule(context.metadata);if(!schedule){return}if(fields===null||fieldsInclude(fields,"schedule")){result.schedule=schedule;return}result.schedule=Object.fromEntries(Object.entries(schedule).filter(([key])=>fields.some(field=>normalizeGetField(field)===`schedule.${key}`)))}async function buildGetTree(context,options,treeDepth,global2){if(options.tree!==true){return void 0}const subtree=await runList(void 0,{parent:context.locatedId,tree:true,treeDepth:treeDepth===void 0?void 0:String(treeDepth),full:true},global2);return{root_id:context.locatedId,root_title:context.metadata.title,depth_limit:treeDepth??null,count:subtree.count,items:subtree.items.map(entry=>toItemRecord(entry))}}async function runGet(id,global2,options={}){const projection=resolveGetProjection(options,id);const context=await loadGetItemContext(id,global2,options.at);validateGetProjectionFields(projection.fields,context.settings,context.historical!==void 0,context.locatedId);const includeBody=shouldIncludeGetField({...projection,field:"body"});const includeLinked=shouldIncludeGetField({...projection,field:"linked"});const includeClaimState=shouldIncludeGetField({...projection,field:"claim_state"});const includeChildren=context.historical===void 0&&(projection.fieldProjection?fieldsIncludeRoot(projection.fields,"children"):projection.depth==="deep"&&(projection.full||shouldAutoIncludeGetChildren(context.metadata.type)));const includeSchedule=projection.fieldProjection?fieldsIncludeRoot(projection.fields,"schedule"):projection.depth!=="brief";const claimState=await resolveGetClaimState(context,includeClaimState);const result={item:projection.fieldProjection?projectItemForFields(context.metadata,projection.fields):projectItemForDepth(context.metadata,projection.depth)};if(includeBody){result.item.body=context.body}attachGetLinked(result,context,projection.fields,includeLinked);if(claimState){result.claim_state=claimState}attachGetSchedule(result,context,projection.fields,includeSchedule);const children=await buildGetChildrenRollup(context,includeChildren);if(children!==void 0){result.children=children}const tree=await buildGetTree(context,options,projection.treeDepth,global2);if(tree!==void 0){result.tree=tree}if(context.historical){result.reconstructed=true;result.as_of_version=context.historical.as_of_version;result.as_of_timestamp=context.historical.as_of_timestamp}if(context.historical===void 0){try{await recordContextUsageTouches({pmRoot:context.pmRoot,author:resolveAuthor(void 0,context.settings.author_default),itemIds:[context.locatedId],intent:"get"})}catch{}}registerOutputMaterialFieldGroups(result,itemMaterialFieldGroups(context.metadata,context.body,children));return result}const _testOnlyGetCommand={shouldAutoIncludeGetChildren};export{GET_DEPTH_VALUES2 as GET_DEPTH_VALUES,_testOnlyGetCommand,listGetProjectionFields2 as listGetProjectionFields,runGet};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="deaedc1c-6f20-568e-bed6-970d43fb98dc")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{getActiveExtensionRegistrations,toItemRecord,resolveItemTypeRegistry,resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,TYPE_TO_FOLDER,PmCliError,buildItemNotFoundError,listAllItemMetadataLight,locateItem,readLocatedItem,getHistoryPath,resolvePmRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{readHistoryEntries}from"../history-read.js";import{renderPmCommand}from"../command-line.js";import{recordContextUsageTouches}from"../context-usage.js";import{buildItemChildrenRollup}from"../item-children.js";import{buildItemSchedule}from"../item-schedule.js";import{getItemAt}from"../history-read.js";import{parseIntegerLimit}from"./parsers.js";import{runList}from"./list.js";import{registerOutputMaterialFieldGroups}from"../output-projection.js";import{GET_DEPTH_VALUES,listGetProjectionFields}from"./projection-contracts.js";import{GET_DEPTH_VALUES as GET_DEPTH_VALUES2,listGetProjectionFields as listGetProjectionFields2}from"./projection-contracts.js";const AUTOMATIC_CHILD_ROLLUP_TYPES=new Set(["epic","feature","milestone","plan"]);const BUILTIN_ITEM_TYPES=new Set(Object.keys(TYPE_TO_FOLDER).map(type=>type.toLowerCase()));function itemCollectionCounts(item){const lengths=Object.fromEntries(["comments","notes","learnings","files","tests","docs","reminders","events"].map(key=>[key,item[key]?.length??0]));return lengths}function itemMaterialFieldGroups(item,body,children){const collectionCounts=itemCollectionCounts(item);return[...body.length>0?["body"]:[],...Object.entries(collectionCounts).flatMap(([name,count])=>count>0?[name]:[]),...collectionCounts.files+collectionCounts.tests+collectionCounts.docs>0?["linked"]:[],...children===void 0?["children"]:children.count>0?["children"]:[],...typeof item.assignee==="string"&&item.assignee.trim().length>0?["claim_state"]:[],...buildItemSchedule(item)?["schedule"]:[]]}function shouldAutoIncludeGetChildren(itemType){const normalizedType=itemType.trim().toLowerCase();return normalizedType.length>0&&(AUTOMATIC_CHILD_ROLLUP_TYPES.has(normalizedType)||!BUILTIN_ITEM_TYPES.has(normalizedType))}function toClaimHistoryContext(entry){return{ts:entry.ts,author:entry.author,message:entry.message??null}}function resolveClaimStateContext(assigneeValue,history){const assignee=assigneeValue?.trim();const normalizedAssignee=assignee&&assignee.length>0?assignee:null;const lastClaim=[...history].reverse().find(entry=>entry.op==="claim");const lastRelease=[...history].reverse().find(entry=>entry.op==="release");return{claimed:normalizedAssignee!==null,assignee:normalizedAssignee,last_claim:lastClaim?toClaimHistoryContext(lastClaim):null,last_release:lastRelease?toClaimHistoryContext(lastRelease):null}}function parseGetDepth(raw){if(raw===void 0||raw.trim().length===0){return"standard"}const normalized=raw.trim().toLowerCase();if(normalized==="full"){return"deep"}if(GET_DEPTH_VALUES.includes(normalized)){return normalized}throw new PmCliError("Get --depth must be one of brief|standard|deep|full",EXIT_CODE.USAGE,{field:"depth",value:raw,recovery:{allowed_values:[...GET_DEPTH_VALUES,"full"]}})}function projectItemForDepth(item,depth){const collectionCounts=itemCollectionCounts(item);if(depth==="deep"){return{...item,comments:item.comments??[],notes:item.notes??[],learnings:item.learnings??[],files:item.files??[],tests:item.tests??[],docs:item.docs??[],reminders:item.reminders??[],events:item.events??[],notes_count:collectionCounts.notes,tests_count:collectionCounts.tests,collection_counts:collectionCounts}}const{comments:_comments,notes:_notes,learnings:_learnings,files:_files,tests:_tests,docs:_docs,reminders:_reminders,events:_events,...projected}=item;return{...projected,notes_count:item.notes?.length??0,tests_count:item.tests?.length??0,collection_counts:collectionCounts}}function parseGetFields(raw){if(raw===void 0){return null}const fields=raw.split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0);if(fields.length===0){throw new PmCliError("Get --fields requires a comma-separated list of field names",EXIT_CODE.USAGE)}return fields}function normalizeGetField(field){return field.startsWith("item.")?field.slice("item.".length):field}function validateGetFields(fields,runtimeMetadataKeys,id){if(fields===null){return}const allowedValues=listGetProjectionFields(runtimeMetadataKeys);const allowed=new Set(allowedValues);const unknown=fields.filter(field=>{const normalized=normalizeGetField(field);return!allowed.has(field)&&!allowed.has(normalized)});if(unknown.length>0){const suggestedRetryArguments=["get",id,"--fields",fields.filter(field=>!unknown.includes(field)).join(",")||"id,title,status"];throw new PmCliError(`Unknown get --fields value(s): ${unknown.join(", ")}`,EXIT_CODE.USAGE,{code:"unknown_field_projection",examples:["pm get <id> --fields id,title,status,type,updated_at","pm get <id> --fields id,title,claim_state","pm get <id> --fields id,title,body,linked.files"],recovery:{allowed_values:allowedValues,suggested_retry:renderPmCommand(suggestedRetryArguments),suggested_retry_args:suggestedRetryArguments}})}}const EMPTY_PROJECTED_COLLECTION_FIELDS=new Set(["comments","notes","learnings","files","tests","test_runs","docs","reminders","events","dependencies","plan_steps","plan_decisions","plan_discoveries","plan_validation"]);function projectedMetadataValue(source,counts,field){if(Object.hasOwn(counts,field))return counts[field];if(source[field]!==void 0)return source[field];return EMPTY_PROJECTED_COLLECTION_FIELDS.has(field)?[]:void 0}function projectItemForFields(item,fields){const source=toItemRecord(item);const omittedCounts={notes_count:item.notes?.length??0,tests_count:item.tests?.length??0,collection_counts:itemCollectionCounts(item)};const projected={id:item.id};for(const field of fields){const normalized=normalizeGetField(field);if(normalized==="body"||normalized==="linked"||normalized.startsWith("linked.")||normalized==="claim_state"||normalized.startsWith("claim_state.")||normalized==="children"||normalized.startsWith("children.")||normalized==="schedule"||normalized.startsWith("schedule.")){continue}projected[normalized]=projectedMetadataValue(source,omittedCounts,normalized)}return projected}function fieldsInclude(fields,name){return fields?.some(field=>field===name||field===`item.${name}`)??false}function fieldsIncludeRoot(fields,name){return fields.some(field=>{const normalized=normalizeGetField(field);return normalized===name||normalized.startsWith(`${name}.`)})}function resolveGetProjection(options,id){if(options.full&&(options.fields!==void 0||options.depth!==void 0)){throw new PmCliError("Get projection options are mutually exclusive; remove the extra projection flag and retry.",EXIT_CODE.USAGE,{code:"projection_options_mutually_exclusive",flag:"--full",recovery:{suggested_retry:renderPmCommand(["get",id,"--full"]),suggested_retry_args:["get",id,"--full"]}})}if(options.tree!==true&&options.treeDepth!==void 0){throw new PmCliError("Get --tree-depth requires --tree",EXIT_CODE.USAGE)}if(options.at!==void 0&&options.tree===true){throw new PmCliError("Get --at cannot be combined with --tree because workspace-level historical projections are not yet indexed.",EXIT_CODE.USAGE)}return{depth:options.full?"deep":parseGetDepth(options.depth),full:options.full===true||options.depth?.trim().toLowerCase()==="full",treeDepth:options.tree===true?parseIntegerLimit(options.treeDepth,"--tree-depth"):void 0,fields:parseGetFields(options.fields),fieldProjection:options.fields!==void 0}}async function loadGetItemContext(id,global2,at){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());if(at!==void 0){const historical=await getItemAt(id,at,{pmRoot:global2.path});return{pmRoot,settings,typeToFolder:typeRegistry.type_to_folder,locatedId:historical.document.metadata.id,metadata:historical.document.metadata,body:historical.document.body,historical}}const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);if(!located){throw await buildItemNotFoundError(pmRoot,id,settings.id_prefix,typeRegistry.type_to_folder)}const loaded=await readLocatedItem(located,{schema:settings.schema});return{pmRoot,settings,typeToFolder:typeRegistry.type_to_folder,locatedId:located.id,metadata:loaded.document.metadata,body:loaded.document.body}}function validateGetProjectionFields(fields,settings,historical,id){const runtimeMetadataKeys=resolveRuntimeFieldRegistry(settings.schema).definitions.map(field=>field.metadata_key);validateGetFields(fields,runtimeMetadataKeys,id);if(historical&&fieldsIncludeRoot(fields??[],"children")){throw new PmCliError("Get --at cannot project children because workspace-level historical relationships are not yet indexed.",EXIT_CODE.USAGE)}}function shouldIncludeGetField(params){const{fieldProjection,depth,fields,field}=params;if(fieldProjection){if(field==="body"||field==="linked"){return fieldsInclude(fields,field)}return fieldsIncludeRoot(fields,field)}return depth!=="brief"}async function resolveGetClaimState(context,includeClaimState){if(!includeClaimState){return void 0}const historyPath=getHistoryPath(context.pmRoot,context.locatedId);const history=await readHistoryEntries(historyPath,context.locatedId);return resolveClaimStateContext(context.metadata.assignee,context.historical?history.slice(0,context.historical.target.historyIndex+1):history)}function attachGetLinked(result,context,fields,includeLinked){const includeLinkedFiles=includeLinked||fieldsInclude(fields,"linked.files");const includeLinkedTests=includeLinked||fieldsInclude(fields,"linked.tests");const includeLinkedDocs=includeLinked||fieldsInclude(fields,"linked.docs");if(!includeLinked&&!includeLinkedFiles&&!includeLinkedTests&&!includeLinkedDocs){return}result.linked={files:includeLinkedFiles?context.metadata.files??[]:[],tests:includeLinkedTests?context.metadata.tests??[]:[],docs:includeLinkedDocs?context.metadata.docs??[]:[]}}async function buildGetChildrenRollup(context,includeChildren){if(!includeChildren){return void 0}const statusRegistry=resolveRuntimeStatusRegistry(context.settings.schema);const corpus=await listAllItemMetadataLight(context.pmRoot,context.settings.item_format,context.typeToFolder,void 0,context.settings.schema);return buildItemChildrenRollup(context.locatedId,corpus,statusRegistry)}function attachGetSchedule(result,context,fields,includeSchedule){if(!includeSchedule){return}const schedule=buildItemSchedule(context.metadata);if(!schedule){return}if(fields===null||fieldsInclude(fields,"schedule")){result.schedule=schedule;return}result.schedule=Object.fromEntries(Object.entries(schedule).filter(([key])=>fields.some(field=>normalizeGetField(field)===`schedule.${key}`)))}async function buildGetTree(context,options,treeDepth,global2){if(options.tree!==true){return void 0}const subtree=await runList(void 0,{parent:context.locatedId,tree:true,treeDepth:treeDepth===void 0?void 0:String(treeDepth),full:true},global2);return{root_id:context.locatedId,root_title:context.metadata.title,depth_limit:treeDepth??null,count:subtree.count,items:subtree.items.map(entry=>toItemRecord(entry))}}async function runGet(id,global2,options={}){const projection=resolveGetProjection(options,id);const context=await loadGetItemContext(id,global2,options.at);validateGetProjectionFields(projection.fields,context.settings,context.historical!==void 0,context.locatedId);const includeBody=shouldIncludeGetField({...projection,field:"body"});const includeLinked=shouldIncludeGetField({...projection,field:"linked"});const includeClaimState=shouldIncludeGetField({...projection,field:"claim_state"});const includeChildren=context.historical===void 0&&(projection.fieldProjection?fieldsIncludeRoot(projection.fields,"children"):projection.depth==="deep"&&(projection.full||shouldAutoIncludeGetChildren(context.metadata.type)));const includeSchedule=projection.fieldProjection?fieldsIncludeRoot(projection.fields,"schedule"):projection.depth!=="brief";const claimState=await resolveGetClaimState(context,includeClaimState);const result={item:projection.fieldProjection?projectItemForFields(context.metadata,projection.fields):projectItemForDepth(context.metadata,projection.depth)};if(includeBody){result.item.body=context.body}attachGetLinked(result,context,projection.fields,includeLinked);if(claimState){result.claim_state=claimState}attachGetSchedule(result,context,projection.fields,includeSchedule);const children=await buildGetChildrenRollup(context,includeChildren);if(children!==void 0){result.children=children}const tree=await buildGetTree(context,options,projection.treeDepth,global2);if(tree!==void 0){result.tree=tree}if(context.historical){result.reconstructed=true;result.as_of_version=context.historical.as_of_version;result.as_of_timestamp=context.historical.as_of_timestamp}if(context.historical===void 0){try{await recordContextUsageTouches({pmRoot:context.pmRoot,author:resolveAuthor(void 0,context.settings.author_default),itemIds:[context.locatedId],intent:"get"})}catch{}}registerOutputMaterialFieldGroups(result,itemMaterialFieldGroups(context.metadata,context.body,children));return result}const _testOnlyGetCommand={shouldAutoIncludeGetChildren};export{GET_DEPTH_VALUES2 as GET_DEPTH_VALUES,_testOnlyGetCommand,listGetProjectionFields2 as listGetProjectionFields,runGet};
2
2
  //# sourceMappingURL=get.js.map
@@ -5,7 +5,7 @@ export declare function createSearchCursorFingerprint(options: {
5
5
  query: string;
6
6
  mode: SearchMode;
7
7
  searchOptions: SearchOptions;
8
- /** Resolved tracker scope when invoked by the query runtime. */
8
+ /** Tracker scope, resolved before hashing so callers share native path identity. */
9
9
  pmRoot?: string;
10
10
  }): string;
11
11
  /** Page ranked search hits without coupling cursor mechanics to search scoring. */
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="18c21143-96a8-5031-b288-42f6188f8821")}catch(e2){}})();import{createQueryFingerprint,paginateQueryRows,selectCursorSemanticOptions}from"../pagination.js";import{SEARCH_FLAG_CONTRACTS}from"../cli-contracts/flag-contracts.js";function createSearchCursorFingerprint(options){return createQueryFingerprint("search",{pmRoot:options.pmRoot,query:options.query.trim(),mode:options.mode,options:selectCursorSemanticOptions(options.searchOptions,SEARCH_FLAG_CONTRACTS)})}function resolveSearchPage(options){const page=paginateQueryRows(options.sorted,{cursor:options.searchOptions.after,fingerprint:createSearchCursorFingerprint(options),limit:options.limit,readId:hit=>hit.item.id});return{limited:page.rows,pageExtras:{applied_limit:options.limit,...page.has_more?{has_more:true,truncated:true}:{},...page.next_cursor?{next_cursor:page.next_cursor}:{}}}}export{createSearchCursorFingerprint,resolveSearchPage};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1c634b84-b239-5b9f-be64-b1c8e03fc25b")}catch(e2){}})();import{createQueryFingerprint,paginateQueryRows,selectCursorSemanticOptions}from"../pagination.js";import path from"node:path";import{SEARCH_FLAG_CONTRACTS}from"../cli-contracts/flag-contracts.js";function createSearchCursorFingerprint(options){return createQueryFingerprint("search",{pmRoot:options.pmRoot===void 0?void 0:path.resolve(options.pmRoot),query:options.query.trim(),mode:options.mode,options:selectCursorSemanticOptions(options.searchOptions,SEARCH_FLAG_CONTRACTS)})}function resolveSearchPage(options){const page=paginateQueryRows(options.sorted,{cursor:options.searchOptions.after,fingerprint:createSearchCursorFingerprint(options),limit:options.limit,readId:hit=>hit.item.id});return{limited:page.rows,pageExtras:{applied_limit:options.limit,...page.has_more?{has_more:true,truncated:true}:{},...page.next_cursor?{next_cursor:page.next_cursor}:{}}}}export{createSearchCursorFingerprint,resolveSearchPage};
2
2
  //# sourceMappingURL=search-pagination.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d4e00fbd-12c7-5863-a197-0c71d4e406ec")}catch(e2){}})();import{cp,lstat,mkdir,readlink,realpath,stat,symlink}from"node:fs/promises";import path from"node:path";import{isFileMissingError}from"../../core/fs/fs-utils.js";const EXCLUDED_SEGMENTS=new Set([".agents",".git",".nyc_output",".turbo","coverage"]);function hasExcludedSegment(relative){return relative.split(path.sep).some(segment=>EXCLUDED_SEGMENTS.has(segment.toLowerCase()))}function isOutsideWorkspace(relative){return relative===".."||relative.startsWith(`..${path.sep}`)||path.isAbsolute(relative)}async function resolveLinkTarget(target){const missing=[];let ancestor=target;while(path.dirname(ancestor)!==ancestor){try{return path.join(await realpath(ancestor),...missing)}catch(error){if(!isFileMissingError(error))throw error;missing.unshift(path.basename(ancestor));ancestor=path.dirname(ancestor)}}return path.join(await realpath(ancestor),...missing)}async function resolveSnapshotTarget(target,sourceRoot,dependencyRoots){const relative=path.relative(sourceRoot,await resolveLinkTarget(target));if(!isOutsideWorkspace(relative))return relative;const suffix=[];let ancestor=target;while(path.dirname(ancestor)!==ancestor){const physicalAncestor=await resolveLinkTarget(ancestor);const dependency=dependencyRoots.find(([,root])=>root===physicalAncestor);if(dependency)return path.join(dependency[0],...suffix);suffix.unshift(path.basename(ancestor));ancestor=path.dirname(ancestor)}return relative}async function seedLinkedTestWorkspaceSnapshot(sourceRoot,snapshotRoot){const dependencyRoots=[];const sourceLinks=[];const resolvedSourceRoot=await realpath(sourceRoot);const resolvedSnapshotRoot=await resolveLinkTarget(path.resolve(snapshotRoot));if(![path.relative(resolvedSourceRoot,resolvedSnapshotRoot),path.relative(resolvedSnapshotRoot,resolvedSourceRoot)].every(isOutsideWorkspace)){throw new Error("Snapshot destination must be disjoint from the source workspace; choose a temporary root outside the checkout.")}await mkdir(path.dirname(snapshotRoot),{recursive:true});await cp(resolvedSourceRoot,snapshotRoot,{recursive:true,force:true,async filter(source){const relative=path.relative(resolvedSourceRoot,source);if(!relative)return true;if(hasExcludedSegment(relative))return false;if(path.basename(source).toLowerCase()==="node_modules"){if((await stat(source,{throwIfNoEntry:false}))?.isDirectory()){const target=await resolveLinkTarget(source);const targetRelative=path.relative(resolvedSourceRoot,target);if(!isOutsideWorkspace(path.relative(target,resolvedSourceRoot))||!isOutsideWorkspace(targetRelative)&&(hasExcludedSegment(targetRelative)||!targetRelative.split(path.sep).some(segment=>segment.toLowerCase()==="node_modules"))){throw new Error(`Dependency symlink must target an included dependency directory or external installation: ${relative}`)}dependencyRoots.push([relative,target])}return false}if(!(await lstat(source)).isSymbolicLink())return true;sourceLinks.push([relative,path.resolve(path.dirname(source),await readlink(source)),(await stat(source,{throwIfNoEntry:false}))?.isDirectory()?"junction":"file"]);return false}});for(const[relative]of dependencyRoots){await symlink(path.resolve(resolvedSourceRoot,relative),path.join(snapshotRoot,relative),"junction")}for(const[relative,target,type]of sourceLinks){const targetRelative=await resolveSnapshotTarget(target,resolvedSourceRoot,dependencyRoots);if(isOutsideWorkspace(targetRelative)||hasExcludedSegment(targetRelative)){throw new Error(`Source symlink must target included workspace source: ${relative}`)}await symlink(path.resolve(snapshotRoot,targetRelative),path.join(snapshotRoot,relative),type)}}export{seedLinkedTestWorkspaceSnapshot};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="50a9baf9-931e-5822-a71a-122398a94b8c")}catch(e2){}})();import{cp,lstat,mkdir,readlink,realpath,stat,symlink}from"node:fs/promises";import path from"node:path";import{isFileMissingError}from"../../core/fs/fs-utils.js";const EXCLUDED_SEGMENTS=new Set([".agents",".git",".nyc_output",".turbo","coverage"]);function hasExcludedSegment(relative){return relative.split(path.sep).some(segment=>EXCLUDED_SEGMENTS.has(segment.toLowerCase()))}function isOutsideWorkspace(relative){return relative===".."||relative.startsWith(`..${path.sep}`)||path.isAbsolute(relative)}async function statSnapshotTarget(source){try{return await stat(source)}catch(error){if(!isFileMissingError(error))throw error;return void 0}}async function resolveLinkTarget(target){const missing=[];let ancestor=target;while(path.dirname(ancestor)!==ancestor){try{return path.join(await realpath(ancestor),...missing)}catch(error){if(!isFileMissingError(error))throw error;missing.unshift(path.basename(ancestor));ancestor=path.dirname(ancestor)}}return path.join(await realpath(ancestor),...missing)}async function resolveSnapshotTarget(target,sourceRoot,dependencyRoots){const relative=path.relative(sourceRoot,await resolveLinkTarget(target));if(!isOutsideWorkspace(relative))return relative;const suffix=[];let ancestor=target;while(path.dirname(ancestor)!==ancestor){const physicalAncestor=await resolveLinkTarget(ancestor);const dependency=dependencyRoots.find(([,root])=>root===physicalAncestor);if(dependency)return path.join(dependency[0],...suffix);suffix.unshift(path.basename(ancestor));ancestor=path.dirname(ancestor)}return relative}async function seedLinkedTestWorkspaceSnapshot(sourceRoot,snapshotRoot){const dependencyRoots=[];const sourceLinks=[];const resolvedSourceRoot=await realpath(sourceRoot);const resolvedSnapshotRoot=await resolveLinkTarget(path.resolve(snapshotRoot));if(![path.relative(resolvedSourceRoot,resolvedSnapshotRoot),path.relative(resolvedSnapshotRoot,resolvedSourceRoot)].every(isOutsideWorkspace)){throw new Error("Snapshot destination must be disjoint from the source workspace; choose a temporary root outside the checkout.")}await mkdir(path.dirname(snapshotRoot),{recursive:true});await cp(resolvedSourceRoot,snapshotRoot,{recursive:true,force:true,async filter(source){const relative=path.relative(resolvedSourceRoot,source);if(!relative)return true;if(hasExcludedSegment(relative))return false;if(path.basename(source).toLowerCase()==="node_modules"){if((await statSnapshotTarget(source))?.isDirectory()){const target=await resolveLinkTarget(source);const targetRelative=path.relative(resolvedSourceRoot,target);if(!isOutsideWorkspace(path.relative(target,resolvedSourceRoot))||!isOutsideWorkspace(targetRelative)&&(hasExcludedSegment(targetRelative)||!targetRelative.split(path.sep).some(segment=>segment.toLowerCase()==="node_modules"))){throw new Error(`Dependency symlink must target an included dependency directory or external installation: ${relative}`)}dependencyRoots.push([relative,target])}return false}if(!(await lstat(source)).isSymbolicLink())return true;sourceLinks.push([relative,path.resolve(path.dirname(source),await readlink(source)),(await statSnapshotTarget(source))?.isDirectory()?"junction":"file"]);return false}});for(const[relative]of dependencyRoots){await symlink(path.resolve(resolvedSourceRoot,relative),path.join(snapshotRoot,relative),"junction")}for(const[relative,target,type]of sourceLinks){const targetRelative=await resolveSnapshotTarget(target,resolvedSourceRoot,dependencyRoots);if(isOutsideWorkspace(targetRelative)||hasExcludedSegment(targetRelative)){throw new Error(`Source symlink must target included workspace source: ${relative}`)}await symlink(path.resolve(snapshotRoot,targetRelative),path.join(snapshotRoot,relative),type)}}export{seedLinkedTestWorkspaceSnapshot};
2
2
  //# sourceMappingURL=workspace-snapshot.js.map
@@ -67,6 +67,31 @@ remains complete and `recovery.suggested_retry_args` is atomic: the projector
67
67
  either retains the executable argv or removes the recovery rather than slicing
68
68
  it into a dead command.
69
69
 
70
+ Enum, date, get-depth, and minimum intent-budget validation producers attach the failed metadata
71
+ `field` and supplied `value` to `PmCliError.context`; closed domains also attach
72
+ the complete legal values, including the accepted `full` depth alias. CLI
73
+ attribution normalizes camelCase and snake_case fields to an actually supplied
74
+ canonical flag, so `tokenBudget` identifies `--token-budget`. Explicit flag
75
+ metadata retains its spelling. Argument order and unrelated valid flags cannot
76
+ become the refusal owner. The error-context `value` is text, including the
77
+ textual representation of numeric SDK inputs. Compound projection conflicts
78
+ identify their flag without inventing a rejected scalar. Missing items identify
79
+ the `id` operand.
80
+ When the producer cannot identify a field or value, the diagnostic retains the
81
+ command surface and omits the unknown scalar. Policy evidence takes precedence
82
+ over syntactic attribution. Tracked by [pm-gh1365](../.agents/pm/issues/pm-gh1365.toon).
83
+
84
+ `--json` and `--output-format json` (including `--output-format=json`) select
85
+ JSON on stderr for parser and execution errors as well as successful output.
86
+ The canonical `--output-format` selector wins when combined with `--json`, so
87
+ `--output-format toon --json` retains text diagnostics. Exit codes are unchanged.
88
+ The executable's project-runtime compatibility warnings and refusals use that
89
+ same SDK selector, including repeated formats and the `--` terminator. A JSON
90
+ stale-read warning is emitted after successful dispatch; a failed read emits its
91
+ typed error alone so stderr remains one JSON value. Text warnings retain their
92
+ pre-dispatch presentation.
93
+ Tracked by [pm-gh1366](../.agents/pm/issues/pm-gh1366.toon).
94
+
70
95
  The deterministic ladder is:
71
96
 
72
97
  1. full diagnostic;
@@ -232,6 +232,29 @@ activity limits so the built-in orientation declaration remains feasible on a
232
232
  large tracker. All five intent commands accept the same
233
233
  `--token-budget` override. Explicit `--depth` and `--limit` controls still win.
234
234
 
235
+ Context omission instructions request the named section, for example
236
+ `--section files`, so they can be appended while retaining `--for handoff` or
237
+ `--for orient`. An explicit depth suppresses the intent's default section subset;
238
+ an explicit section remains authoritative at any depth. Workspace memory that
239
+ is already present is never reported as omitted. The original filters and token
240
+ budget remain binding; an oversized restoration reports its remaining budget
241
+ constraint. Tracked by [pm-gh1367](../.agents/pm/issues/pm-gh1367.toon).
242
+
243
+ For namespaced commands, options supplied on an ancestor apply only when the
244
+ selected leaf declares them. `context --tag urgent next` forwards the tag;
245
+ a leaf-supplied limit takes precedence. `context next --depth deep` and
246
+ `context --depth deep next` fail with `unknown_option`, because `next` does not
247
+ declare a depth projection. Inspect the leaf's help before applying context
248
+ controls to it. Tracked by [pm-gh1368](../.agents/pm/issues/pm-gh1368.toon).
249
+
250
+ Ownership compositions use the resolved canonical item ID in every stage and
251
+ the root receipt, including short-ID invocations. Default CLI/MCP start, pause,
252
+ and close receipts expose the final status and aggregate changed-field count
253
+ without repeating item bodies. `--full-changed-fields` and typed SDK methods
254
+ retain complete constituent results. A failed later step reports the canonical
255
+ item and prior durable mutation without implying rollback.
256
+ Tracked by [pm-gh1369](../.agents/pm/issues/pm-gh1369.toon).
257
+
235
258
  If a selected result exceeds its budget, long explanatory strings compact
236
259
  first, followed by deterministic root-row reduction that retains at least one
237
260
  useful row and reports `budget_row_compaction`. Only a result whose minimum
@@ -3,6 +3,7 @@
3
3
  The extension settings contract is tracked by
4
4
  [pm-wtqltn](../.agents/pm/issues/pm-wtqltn.toon). Full-item JSON annotation
5
5
  integrity is tracked by [pm-2589e6](../.agents/pm/issues/pm-2589e6.toon).
6
+ Canonical previews are tracked by [pm-2sef82](../.agents/pm/features/pm-2sef82.toon).
6
7
 
7
8
  ## Extension settings
8
9
 
@@ -36,10 +37,44 @@ the same operation ID can then be used for the real mutation. A normal return
36
37
  also reports `changed` and `dry_run`. Invalid results fail before writing, and
37
38
  a history-append failure restores the previous settings bytes. The callback
38
39
  must derive its complete next settings object from the locked `current` value.
40
+ The callback receives normalized inline settings with defaults and preset knobs
41
+ even when the source file is sparse. Returning that tree unchanged retains the
42
+ original source bytes, including unknown fields, without creating an audit event.
43
+ Changed writes apply known-setting changes to the captured source through the
44
+ standard serializer, preserving sparse omissions and unrecognized fields in
45
+ unchanged containers for forward compatibility. Those fields remain outside the
46
+ typed callback and canonical preview. Replacing an array replaces its complete
47
+ contents, as in normal settings writes. Present legacy values are canonicalized
48
+ on a changed write; an identity no-op still retains the original bytes.
49
+ The host also validates the final serialized bytes before committing, so a
50
+ proposal that changes while being serialized cannot persist invalid settings.
39
51
  The host applies the standard settings serializer, including legacy format
40
52
  coercion and collection-name sanitization, and runs active `onWrite` hooks
41
53
  after a changed write.
42
54
 
55
+ Request `includePreview: true` to receive an optional `preview` settings tree
56
+ alongside the receipt. The host resolves it from the exact serialized bytes
57
+ inside the audit lock, using the same defaults and governance presets as normal
58
+ settings reads. A named `minimal` preset therefore reports ownership `none`
59
+ even if the callback proposed `strict`. Custom presets retain their configured
60
+ knobs. Legacy formats and collection names reflect their canonical persisted
61
+ values. This tree describes inline settings before optional file-backed schema
62
+ overlays; it does not load or create those files.
63
+
64
+ Use `dryRun: true, includePreview: true` to inspect the result before applying
65
+ the same operation. A fresh no-op also includes its canonical tree. An idempotent
66
+ replay omits `preview`: the original callback is not re-executed, and later
67
+ settings changes cannot reconstruct its historical proposal. Receipts remain
68
+ three booleans when the option is absent. Direct SDK dry runs read configuration
69
+ without executing read hooks, scaffolding optional schemas, or populating the
70
+ hydrated settings cache. Mutation callbacks should only derive settings and
71
+ avoid external side effects.
72
+
73
+ For an extension that requires previews, set its manifest `pm_min_version` to
74
+ a published host release containing this option. Check for `preview` on a fresh
75
+ dry-run operation before applying settings, while allowing replay receipts to
76
+ omit it as described above.
77
+
43
78
  ## Full-item JSON updates
44
79
 
45
80
  `pm update <id> --stdin-json` accepts a full item read document. New comments,
package/docs/TESTING.md CHANGED
@@ -575,6 +575,14 @@ pm test <item-id> --run --workspace-context snapshot --override-linked-workspace
575
575
  must be physically disjoint; overlapping roots fail before copying with a
576
576
  diagnostic directing the caller to a temporary root outside the checkout.
577
577
 
578
+ Snapshot target probes treat only `ENOENT` as absence and propagate other
579
+ filesystem failures. They use explicit error handling so Node 22 and older
580
+ Node 24 releases retain the same dangling-link behavior; the async `stat`
581
+ `throwIfNoEntry` option was added in
582
+ [Node 24.15](https://nodejs.org/download/release/v24.20.0/docs/api/fs.html#fspromisesstatpath-options).
583
+ The real filesystem and CLI snapshot suite runs in the required Node 22
584
+ telemetry regression job and native Windows regression job before merge.
585
+
578
586
  The real-filesystem regression for this contract is tracked by
579
587
  [pm-5iwfkj](../.agents/pm/issues/pm-5iwfkj.toon).
580
588