@unbrained/pm-cli 2026.10.25 → 2026.10.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +28 -0
- package/dist/cli/error-guidance.d.ts +5 -0
- package/dist/cli/error-guidance.js +2 -2
- package/dist/cli/register-mutation.js +2 -2
- package/dist/cli-bundle/bundle-manifest.json +1 -1
- package/dist/cli-bundle/chunks/{chunk-O3ZTGRIH.js → chunk-25MTQAHX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TLMXSYJA.js → chunk-57YPOOED.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4GD6QOP6.js → chunk-7UDQAINZ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-LNKPH2DD.js → chunk-ER7RLJW5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YCCGZHOR.js → chunk-MWCG25PO.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-444VPGQT.js → chunk-N6FTEILW.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-FNZT4BTE.js → chunk-NGKTROAO.js} +86 -86
- package/dist/cli-bundle/chunks/chunk-OCDRHIVQ.js +6 -0
- package/dist/cli-bundle/chunks/{chunk-3CYXE6BV.js → chunk-ONC4BBQP.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RQKDANP7.js → chunk-OUDR2HWR.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-RD6UW3MW.js → chunk-T7T4WLUY.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-MVJGGCGQ.js → chunk-TGOG5BFM.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-UF6EXZSP.js +2 -0
- package/dist/cli-bundle/chunks/chunk-VS2IIV3F.js +128 -0
- package/dist/cli-bundle/chunks/chunk-XAIR53QZ.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-VAEB6IUQ.js → chunk-Y42DYMZX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-EYCVAAIP.js → chunk-YJBIPNDL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UI3FD3DW.js → chunk-Z35XAHUN.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-7C3GCLOO.js → chunk-ZLVFUZI4.js} +27 -27
- package/dist/cli-bundle/chunks/{chunk-7T3H24HN.js → chunk-ZT64RDMF.js} +2 -2
- package/dist/cli-bundle/chunks/{indexed-receipt-blobs-47I6KKDO.js → indexed-receipt-blobs-NWQIDTH7.js} +2 -2
- package/dist/cli-bundle/chunks/{mutation-admission-747C6IUR.js → mutation-admission-VTNV6JV2.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-COST6KRV.js → register-list-query-LZDWUZS4.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-M2A7PH42.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-S4LKLUBJ.js → register-operations-E7P2JTXM.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-3ITZXPOL.js → register-setup-DOV7KGSH.js} +2 -2
- package/dist/cli-bundle/chunks/{settlement-hook-5IVCF6ZY.js → settlement-hook-SVD6CO7U.js} +2 -2
- package/dist/cli-bundle/chunks/{stage-3UUIYROS.js → stage-LYLEOAQB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-HMYDUEQK.js → chunk-226XKW3W.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-ABMNYWV6.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3M5FZCMC.js → chunk-ADSBGYLW.js} +8 -8
- package/dist/cli-bundle/focused-chunks/{chunk-22727JYL.js → chunk-B266DDBJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-Y4JHHY24.js → chunk-BH7RE2ZY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-BL77VCRB.js +22 -0
- package/dist/cli-bundle/focused-chunks/{chunk-77NU7NPN.js → chunk-CSCZYSNZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-URWYYJ7K.js → chunk-D5YQ4KAE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ZYCOMRFT.js → chunk-E5C24MCV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-74KC7FUQ.js → chunk-I7H3XF25.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-IF6C43IP.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-KERJNFXY.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-46KDJH3K.js → chunk-KTXU5WU6.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-NE27VCU7.js +91 -0
- package/dist/cli-bundle/focused-chunks/{chunk-NI5SG2M2.js → chunk-NFN2P4TW.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-NC5HUGHU.js → chunk-NLZUI234.js} +4 -4
- package/dist/cli-bundle/focused-chunks/chunk-PK5FJIVA.js +12 -0
- package/dist/cli-bundle/focused-chunks/{chunk-LWJ2X75I.js → chunk-UHWTPOM4.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-B5JOVH5F.js → chunk-UP765R2V.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-U6HXIF6G.js → chunk-WDWHUJQW.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-7DEZT4JN.js → chunk-YQKLKRMW.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-YTEC2EPM.js +3 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3FM75SBJ.js → chunk-YW5GHQN2.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{indexed-receipt-blobs-YCLN2ZZG.js → indexed-receipt-blobs-YFDNGHCM.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{mutation-admission-BQBQXILV.js → mutation-admission-L42E3U5U.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{settlement-hook-XVS6P2XI.js → settlement-hook-3CADO4XZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{stage-VSIL4MTZ.js → stage-TUQHWU7N.js} +2 -2
- package/dist/cli-bundle/main.js +4 -4
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +23 -23
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +57 -57
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +9 -9
- package/dist/core/extensions/extension-types.d.ts +3 -0
- package/dist/core/extensions/extension-types.js +1 -1
- package/dist/core/output/mutation-projection.js +1 -1
- package/dist/core/policy/workflow-policy-store.js +1 -1
- package/dist/core/shared/errors.d.ts +9 -0
- package/dist/core/shared/errors.js +1 -1
- package/dist/core/shared/secret-rules.d.ts +17 -0
- package/dist/core/shared/secret-rules.js +2 -1
- package/dist/core/store/item-mutation-precondition.d.ts +8 -0
- package/dist/core/store/item-mutation-precondition.js +1 -1
- package/dist/core/store/item-store.js +1 -1
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1
- package/dist/sdk/cli-contracts/completeness.js +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -1
- package/dist/sdk/cli-contracts/registration-helpers.d.ts +1 -1
- package/dist/sdk/cli-contracts/registration-helpers.js +1 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +4 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -1
- package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1
- package/dist/sdk/context-signal-store.js +2 -2
- package/dist/sdk/core.d.ts +1 -1
- package/dist/sdk/core.js +1 -1
- package/dist/sdk/extension-command-context.js +2 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
- package/dist/sdk/index.d.ts +2 -1
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/item-transaction.js +1 -1
- package/dist/sdk/lifecycle/close-many.d.ts +3 -0
- package/dist/sdk/lifecycle/close-many.js +1 -1
- package/dist/sdk/lifecycle/close.d.ts +3 -1
- package/dist/sdk/lifecycle/close.js +1 -1
- package/dist/sdk/lifecycle/create.d.ts +2 -0
- package/dist/sdk/lifecycle/create.js +1 -1
- package/dist/sdk/lifecycle/plan.d.ts +2 -0
- package/dist/sdk/lifecycle/plan.js +1 -1
- package/dist/sdk/lifecycle/restore.js +1 -1
- package/dist/sdk/lifecycle-policy.d.ts +11 -0
- package/dist/sdk/lifecycle-policy.js +1 -1
- package/dist/sdk/mutation-guard.d.ts +6 -1
- package/dist/sdk/mutation-guard.js +1 -1
- package/dist/sdk/output/fit-envelope.d.ts +98 -0
- package/dist/sdk/output/fit-envelope.js +2 -0
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query.d.ts +1 -0
- package/dist/sdk/query.js +1 -1
- package/dist/sdk/read-output-session.d.ts +1 -1
- package/dist/sdk/read-output-session.js +1 -1
- package/dist/sdk/runtime-input.js +1 -1
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +1 -1
- package/dist/sdk/runtime.d.ts +2 -2
- package/dist/sdk/runtime.js +1 -1
- package/dist/sdk/scheduling-shortcuts.d.ts +2 -0
- package/dist/sdk/scheduling-shortcuts.js +1 -1
- package/dist/sdk/workspace-transaction.d.ts +3 -1
- package/dist/sdk/workspace-transaction.js +2 -2
- package/docs/COMMANDS.md +2 -1
- package/docs/MUTATION_INTEGRITY.md +33 -0
- package/docs/QUALITY_EVIDENCE.md +9 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +55 -1
- package/docs/SDK.md +88 -6
- package/docs/WORKFLOW_POLICIES.md +14 -1
- package/docs/agent-task-token-baseline.json +1 -1
- package/docs/agent-task-transcripts.json +1 -1
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +4 -3
- package/marketplace.json +1 -1
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/extensions/calendar/shortcuts.ts +2 -2
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/package.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/package.json +1 -1
- package/plugins/pm-codex/plugin.json +1 -1
- package/runtime-dependencies.json +1 -1
- package/dist/cli-bundle/chunks/chunk-5ZPT67NJ.js +0 -127
- package/dist/cli-bundle/chunks/chunk-HMJSFWHK.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RLXK2S7P.js +0 -2
- package/dist/cli-bundle/chunks/chunk-XYLBOXSH.js +0 -6
- package/dist/cli-bundle/chunks/register-mutation-JZVVJUHY.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-5LBZR6YW.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-IVLIUPVV.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-KIIGME23.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-MT5TYMEU.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-QH5KMIYZ.js +0 -91
- package/dist/cli-bundle/focused-chunks/chunk-W7MCCFYV.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-WMPDY5ZU.js +0 -21
|
@@ -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]="ce212ffb-1f13-5893-9690-31dbb4e0de13")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{normalizeItemFormatVersion,requiredItemFormatVersion}from"../../core/item/item-format-version.js";import{assertProjectRuntimeFormatGuard}from"../environment/project-runtime-compatibility.js";import{enforceWorkflowMutation}from"../../core/policy/workflow-policy-store.js";import jsonPatch from"fast-json-patch";import fs from"node:fs/promises";import{readLocatedItemSnapshot}from"../../core/store/item-store.js";import{readHistorySnapshot}from"../../core/history/read.js";import{verifyHistoryRewriteNoDrift}from"../../core/history/history-rewrite.js";import{resolveHistorySubject}from"../history/subject.js";import{historyVersionOffset}from"../../core/history/version-address.js";import{writeFileAtomic,appendHistoryEntry,createHistoryEntry,replayToCanonicalItemDocument,replayToItemDocument,toReplayDocument,enforceHistoryStreamPolicyForItem,canonicalDocument,serializeItemDocument,resolveItemTypeRegistry,acquireLockLease,EXIT_CODE,PmCliError,nowIso,getActiveExtensionRegistrations,projectAfterCommandItemSnapshot,recordAfterCommandAffectedItem,runActiveOnWriteHooks,runActiveBeforeMutationHooks,createMutationGuardSdk,getItemPath,resolvePmRoot,resolveWorkspaceRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{applyHistoryPatch,ensureMaterializedHistoryTarget as ensureMaterializedRestoreTarget,extractPatchFailureContext,replayHistoryToTarget as replayToTarget,resolveHistoryTarget}from"../history-read.js";import{acquireItemMetadataDerivedIndexLock,refreshItemMetadataDerivedIndex}from"../item-metadata-index.js";async function readRestoreItem(located,settings,history){const snapshot=await readLocatedItemSnapshot(located,{schema:settings.schema});return snapshot.error===null?{raw:snapshot.raw,document:snapshot.document}:{raw:snapshot.raw,document:replayCurrentDocument(history),recovered:!0}}function ensureReplayTarget(target,history){return resolveHistoryTarget(target,history,{errorSubject:"restore",allowFutureTimestamp:!0})}function replayCurrentDocument(history){const currentReplay=replayToTarget(history,history.length-1);return Object.keys(currentReplay.metadata).length===0?{metadata:{},body:currentReplay.body}:canonicalDocument(replayToItemDocument(currentReplay))}async function resolveRestoreSubject(pmRoot,id,settings,typeToFolder){const subject=await resolveHistorySubject(pmRoot,id,settings,typeToFolder),historyPolicy=subject.located?await enforceHistoryStreamPolicyForItem({pmRoot,settings,itemId:subject.id,commandLabel:"restore"}):{warnings:[]};return{...subject,historyPolicyWarnings:historyPolicy.warnings}}function changedFields(beforeDocument,afterDocument){const beforeReplay=toReplayDocument(beforeDocument),afterReplay=toReplayDocument(afterDocument),patch=jsonPatch.compare(beforeReplay,afterReplay),fields=new Set;for(const op of patch){if(op.path==="/body"||op.path.startsWith("/body/")){fields.add("body");continue}const segment=op.path.replace(/^\/(?:metadata|front_matter)\/?/,"").split("/")[0];fields.add(segment.replaceAll("~1","/").replaceAll("~0","~"))}return Array.from(fields).sort((a,b)=>a.localeCompare(b))}async function loadRestoreStateUnderLock(params){const verified=await verifyHistoryRewriteNoDrift({pmRoot:params.pmRoot,subject:params.subject,settings:params.settings,typeRegistry:params.typeRegistry,historyRawBeforeLock:params.historyRawBeforeLock,currentItemRawBeforeLock:params.currentItemRawBeforeLock,operation:"restore",readItem:located=>readRestoreItem(located,params.settings,params.history)});return{loadedItemUnderLock:verified.loadedItemUnderLock,existingItemPath:verified.locatedUnderLock?.itemPath??null}}function resolveRestoreCurrentState(loadedItemUnderLock,history){return loadedItemUnderLock?{document:loadedItemUnderLock.document,originalRaw:loadedItemUnderLock.raw}:{document:replayCurrentDocument(history),originalRaw:null}}function collectRestoreOwnershipWarnings(params){const assigned=params.document.metadata.assignee?.trim();if(!(assigned&&assigned!==params.author&&!params.force))return[];if(params.enforcement==="strict")throw new PmCliError(`Item ${params.resolvedId} is assigned to ${assigned}. Use --force to override.`,EXIT_CODE.CONFLICT);return params.enforcement==="warn"?[`ownership_warning:assignee_conflict:${params.resolvedId}:${assigned}`]:[]}async function restorePreviousItemAfterHistoryFailure(params){if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null&¶ms.restoredItemPath!==params.existingItemPath){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw),await fs.rm(params.restoredItemPath,{force:!0});return}if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw);return}await fs.rm(params.restoredItemPath,{force:!0})}async function runRestoreWriteHooks(params){return[...await runActiveOnWriteHooks({path:params.restoredItemPath,scope:"project",op:"restore",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]}),...await runActiveOnWriteHooks({path:params.historyPath,scope:"project",op:"restore:history",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]})]}async function runRestore(id,target,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),subject=await resolveRestoreSubject(pmRoot,id,settings,typeRegistry.type_to_folder),resolvedId=subject.id,{raw:historyRawBeforeLock,entries:history}=await readHistorySnapshot(subject.historyPath,resolvedId);if(history.length===0)throw new PmCliError(`No history exists for ${resolvedId}; restore is unavailable.`,EXIT_CODE.NOT_FOUND);const resolvedTarget=ensureReplayTarget(target,history),replayDocument=ensureMaterializedRestoreTarget(replayToTarget(history,resolvedTarget.historyIndex),resolvedTarget),restoredDocument=replayToCanonicalItemDocument(replayDocument,{schema:settings.schema});if(restoredDocument.metadata.id!==resolvedId)throw new PmCliError(`Restore target resolved to item ${restoredDocument.metadata.id}, expected ${resolvedId}.`,EXIT_CODE.GENERIC_FAILURE);const currentItemRawBeforeLock=(subject.located?await readRestoreItem(subject.located,settings,history):null)?.raw??null,author=resolveAuthor(options.author,settings.author_default),lease=await acquireLockLease(pmRoot,resolvedId,settings.locks.ttl_seconds,author,!!options.force,settings.governance.force_required_for_stale_lock,settings.locks.wait_ms,{waitPolicy:"progress"}),releaseLock=lease.release;try{const{loadedItemUnderLock,existingItemPath}=await loadRestoreStateUnderLock({pmRoot,subject,settings,typeRegistry,historyRawBeforeLock,currentItemRawBeforeLock,history}),itemFormat="toon",currentState=resolveRestoreCurrentState(loadedItemUnderLock,history);restoredDocument.metadata.pm_format_version=normalizeItemFormatVersion(Math.max(requiredItemFormatVersion(restoredDocument.metadata),requiredItemFormatVersion(currentState.document.metadata))),assertProjectRuntimeFormatGuard(resolveWorkspaceRoot(pmRoot),requiredItemFormatVersion(restoredDocument.metadata));const ownershipWarnings=collectRestoreOwnershipWarnings({document:currentState.document,author,force:options.force,enforcement:settings.governance.ownership_enforcement,resolvedId}),restoreChangedFields=changedFields(currentState.document,restoredDocument),workflowPolicy=await enforceWorkflowMutation({pmRoot,settings,operation:"restore",author,before:currentState.document,after:restoredDocument});await runActiveBeforeMutationHooks({pm_root:pmRoot,operation:"restore",before:currentState.document,after:restoredDocument,changed_fields:restoreChangedFields,sdk:createMutationGuardSdk({pmRoot,settings,typeToFolder:typeRegistry.type_to_folder})});const serializedRestore=serializeItemDocument(restoredDocument,{format:itemFormat,schema:settings.schema}),restoredItemPath=getItemPath(pmRoot,restoredDocument.metadata.type,resolvedId,itemFormat,typeRegistry.type_to_folder),derivedIndexWarnings=await lease.fence(async()=>{const releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(pmRoot,author);let derivedIndexWarnings2;try{await writeFileAtomic(restoredItemPath,serializedRestore),existingItemPath&&restoredItemPath!==existingItemPath&&await fs.rm(existingItemPath);const historyEntry=createHistoryEntry({nowIso:nowIso(),author,op:"restore",before:currentState.document,after:restoredDocument,message:options.message,context:workflowPolicy.decisions.length===0?void 0:{workflow_policies:workflowPolicy.decisions}});try{await appendHistoryEntry(subject.historyPath,historyEntry)}catch(error){throw await restorePreviousItemAfterHistoryFailure({existingItemPath,resolvedOriginalRaw:currentState.originalRaw,restoredItemPath}),error}derivedIndexWarnings2=await refreshItemMetadataDerivedIndex({pmRoot,preferredFormat:settings.item_format,typeToFolder:typeRegistry.type_to_folder,schema:settings.schema,itemPath:restoredItemPath,previousItemPath:existingItemPath??void 0,document:restoredDocument})}finally{await releaseDerivedIndexLock()}return derivedIndexWarnings2}),hookWarnings=await runRestoreWriteHooks({restoredItemPath,historyPath:subject.historyPath,before:currentState.document,after:restoredDocument});recordAfterCommandAffectedItem({id:restoredDocument.metadata.id,op:"restore",item_type:restoredDocument.metadata.type,previous_status:currentState.document.metadata.status,status:restoredDocument.metadata.status,previous:projectAfterCommandItemSnapshot(currentState.document.metadata,restoreChangedFields),current:projectAfterCommandItemSnapshot(restoredDocument.metadata,restoreChangedFields),changed_fields:restoreChangedFields});const targetEntry=history[resolvedTarget.historyIndex],offset=historyVersionOffset(history,!0);return{item:restoredDocument.metadata,restored_from:{kind:resolvedTarget.kind,target:resolvedTarget.raw,history_index:resolvedTarget.historyIndex+1,version:offset===null?null:offset+resolvedTarget.historyIndex+1,entry_ts:targetEntry.ts,entry_op:targetEntry.op},changed_fields:restoreChangedFields,warnings:[...workflowPolicy.warnings,...loadedItemUnderLock?.recovered?["restore_unreadable_item_recovered"]:[],...subject.historyPolicyWarnings,...ownershipWarnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}const _testOnlyRestoreCommand={applyHistoryPatch,changedFields,ensureMaterializedRestoreTarget,ensureReplayTarget,extractPatchFailureContext,replayCurrentDocument,replayToTarget,resolveRestoreSubject};export{_testOnlyRestoreCommand,runRestore};
|
|
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]="f3145f17-e911-571b-9da3-f014e6fdde1c")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{normalizeItemFormatVersion,requiredItemFormatVersion}from"../../core/item/item-format-version.js";import{assertProjectRuntimeFormatGuard}from"../environment/project-runtime-compatibility.js";import{enforceWorkflowMutation}from"../../core/policy/workflow-policy-store.js";import jsonPatch from"fast-json-patch";import fs from"node:fs/promises";import{readLocatedItemSnapshot}from"../../core/store/item-store.js";import{assertItemMutationPreconditions}from"../../core/store/item-mutation-precondition.js";import{readHistorySnapshot}from"../../core/history/read.js";import{verifyHistoryRewriteNoDrift}from"../../core/history/history-rewrite.js";import{resolveHistorySubject}from"../history/subject.js";import{historyVersionOffset}from"../../core/history/version-address.js";import{writeFileAtomic,appendHistoryEntry,createHistoryEntry,replayToCanonicalItemDocument,replayToItemDocument,toReplayDocument,enforceHistoryStreamPolicyForItem,canonicalDocument,serializeItemDocument,resolveItemTypeRegistry,acquireLockLease,EXIT_CODE,PmCliError,nowIso,getActiveExtensionRegistrations,projectAfterCommandItemSnapshot,recordAfterCommandAffectedItem,runActiveOnWriteHooks,runActiveBeforeMutationHooks,createMutationGuardSdk,getItemPath,resolvePmRoot,resolveWorkspaceRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{applyHistoryPatch,ensureMaterializedHistoryTarget as ensureMaterializedRestoreTarget,extractPatchFailureContext,replayHistoryToTarget as replayToTarget,resolveHistoryTarget}from"../history-read.js";import{acquireItemMetadataDerivedIndexLock,refreshItemMetadataDerivedIndex}from"../item-metadata-index.js";async function readRestoreItem(located,settings,history){const snapshot=await readLocatedItemSnapshot(located,{schema:settings.schema});return snapshot.error===null?{raw:snapshot.raw,document:snapshot.document}:{raw:snapshot.raw,document:replayCurrentDocument(history),recovered:!0}}function ensureReplayTarget(target,history){return resolveHistoryTarget(target,history,{errorSubject:"restore",allowFutureTimestamp:!0})}function replayCurrentDocument(history){const currentReplay=replayToTarget(history,history.length-1);return Object.keys(currentReplay.metadata).length===0?{metadata:{},body:currentReplay.body}:canonicalDocument(replayToItemDocument(currentReplay))}async function resolveRestoreSubject(pmRoot,id,settings,typeToFolder){const subject=await resolveHistorySubject(pmRoot,id,settings,typeToFolder),historyPolicy=subject.located?await enforceHistoryStreamPolicyForItem({pmRoot,settings,itemId:subject.id,commandLabel:"restore"}):{warnings:[]};return{...subject,historyPolicyWarnings:historyPolicy.warnings}}function changedFields(beforeDocument,afterDocument){const beforeReplay=toReplayDocument(beforeDocument),afterReplay=toReplayDocument(afterDocument),patch=jsonPatch.compare(beforeReplay,afterReplay),fields=new Set;for(const op of patch){if(op.path==="/body"||op.path.startsWith("/body/")){fields.add("body");continue}const segment=op.path.replace(/^\/(?:metadata|front_matter)\/?/,"").split("/")[0];fields.add(segment.replaceAll("~1","/").replaceAll("~0","~"))}return Array.from(fields).sort((a,b)=>a.localeCompare(b))}async function loadRestoreStateUnderLock(params){const verified=await verifyHistoryRewriteNoDrift({pmRoot:params.pmRoot,subject:params.subject,settings:params.settings,typeRegistry:params.typeRegistry,historyRawBeforeLock:params.historyRawBeforeLock,currentItemRawBeforeLock:params.currentItemRawBeforeLock,operation:"restore",readItem:located=>readRestoreItem(located,params.settings,params.history)});return{loadedItemUnderLock:verified.loadedItemUnderLock,existingItemPath:verified.locatedUnderLock?.itemPath??null}}function resolveRestoreCurrentState(loadedItemUnderLock,history){return loadedItemUnderLock?{document:loadedItemUnderLock.document,originalRaw:loadedItemUnderLock.raw}:{document:replayCurrentDocument(history),originalRaw:null}}function collectRestoreOwnershipWarnings(params){const assigned=params.document.metadata.assignee?.trim();if(!(assigned&&assigned!==params.author&&!params.force))return[];if(params.enforcement==="strict")throw new PmCliError(`Item ${params.resolvedId} is assigned to ${assigned}. Use --force to override.`,EXIT_CODE.CONFLICT);return params.enforcement==="warn"?[`ownership_warning:assignee_conflict:${params.resolvedId}:${assigned}`]:[]}async function restorePreviousItemAfterHistoryFailure(params){if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null&¶ms.restoredItemPath!==params.existingItemPath){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw),await fs.rm(params.restoredItemPath,{force:!0});return}if(params.existingItemPath&¶ms.resolvedOriginalRaw!==null){await writeFileAtomic(params.existingItemPath,params.resolvedOriginalRaw);return}await fs.rm(params.restoredItemPath,{force:!0})}async function runRestoreWriteHooks(params){return[...await runActiveOnWriteHooks({path:params.restoredItemPath,scope:"project",op:"restore",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]}),...await runActiveOnWriteHooks({path:params.historyPath,scope:"project",op:"restore:history",item_id:params.after.metadata.id,item_type:params.after.metadata.type,before:params.before,after:params.after,changed_fields:["restored"]})]}async function runRestore(id,target,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),subject=await resolveRestoreSubject(pmRoot,id,settings,typeRegistry.type_to_folder),resolvedId=subject.id,{raw:historyRawBeforeLock,entries:history}=await readHistorySnapshot(subject.historyPath,resolvedId);if(history.length===0)throw new PmCliError(`No history exists for ${resolvedId}; restore is unavailable.`,EXIT_CODE.NOT_FOUND);const resolvedTarget=ensureReplayTarget(target,history),replayDocument=ensureMaterializedRestoreTarget(replayToTarget(history,resolvedTarget.historyIndex),resolvedTarget),restoredDocument=replayToCanonicalItemDocument(replayDocument,{schema:settings.schema});if(restoredDocument.metadata.id!==resolvedId)throw new PmCliError(`Restore target resolved to item ${restoredDocument.metadata.id}, expected ${resolvedId}.`,EXIT_CODE.GENERIC_FAILURE);const currentItemRawBeforeLock=(subject.located?await readRestoreItem(subject.located,settings,history):null)?.raw??null,author=resolveAuthor(options.author,settings.author_default),lease=await acquireLockLease(pmRoot,resolvedId,settings.locks.ttl_seconds,author,!!options.force,settings.governance.force_required_for_stale_lock,settings.locks.wait_ms,{waitPolicy:"progress"}),releaseLock=lease.release;try{const{loadedItemUnderLock,existingItemPath}=await loadRestoreStateUnderLock({pmRoot,subject,settings,typeRegistry,historyRawBeforeLock,currentItemRawBeforeLock,history}),itemFormat="toon",currentState=resolveRestoreCurrentState(loadedItemUnderLock,history);assertItemMutationPreconditions(pmRoot,currentState.document),restoredDocument.metadata.pm_format_version=normalizeItemFormatVersion(Math.max(requiredItemFormatVersion(restoredDocument.metadata),requiredItemFormatVersion(currentState.document.metadata))),assertProjectRuntimeFormatGuard(resolveWorkspaceRoot(pmRoot),requiredItemFormatVersion(restoredDocument.metadata));const ownershipWarnings=collectRestoreOwnershipWarnings({document:currentState.document,author,force:options.force,enforcement:settings.governance.ownership_enforcement,resolvedId}),restoreChangedFields=changedFields(currentState.document,restoredDocument),workflowPolicy=await enforceWorkflowMutation({pmRoot,settings,operation:"restore",author,before:currentState.document,after:restoredDocument});await runActiveBeforeMutationHooks({pm_root:pmRoot,operation:"restore",before:currentState.document,after:restoredDocument,changed_fields:restoreChangedFields,sdk:createMutationGuardSdk({pmRoot,settings,typeToFolder:typeRegistry.type_to_folder})});const serializedRestore=serializeItemDocument(restoredDocument,{format:itemFormat,schema:settings.schema}),restoredItemPath=getItemPath(pmRoot,restoredDocument.metadata.type,resolvedId,itemFormat,typeRegistry.type_to_folder),derivedIndexWarnings=await lease.fence(async()=>{const releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(pmRoot,author);let derivedIndexWarnings2;try{await writeFileAtomic(restoredItemPath,serializedRestore),existingItemPath&&restoredItemPath!==existingItemPath&&await fs.rm(existingItemPath);const historyEntry=createHistoryEntry({nowIso:nowIso(),author,op:"restore",before:currentState.document,after:restoredDocument,message:options.message,context:workflowPolicy.decisions.length===0?void 0:{workflow_policies:workflowPolicy.decisions}});try{await appendHistoryEntry(subject.historyPath,historyEntry)}catch(error){throw await restorePreviousItemAfterHistoryFailure({existingItemPath,resolvedOriginalRaw:currentState.originalRaw,restoredItemPath}),error}derivedIndexWarnings2=await refreshItemMetadataDerivedIndex({pmRoot,preferredFormat:settings.item_format,typeToFolder:typeRegistry.type_to_folder,schema:settings.schema,itemPath:restoredItemPath,previousItemPath:existingItemPath??void 0,document:restoredDocument})}finally{await releaseDerivedIndexLock()}return derivedIndexWarnings2}),hookWarnings=await runRestoreWriteHooks({restoredItemPath,historyPath:subject.historyPath,before:currentState.document,after:restoredDocument});recordAfterCommandAffectedItem({id:restoredDocument.metadata.id,op:"restore",item_type:restoredDocument.metadata.type,previous_status:currentState.document.metadata.status,status:restoredDocument.metadata.status,previous:projectAfterCommandItemSnapshot(currentState.document.metadata,restoreChangedFields),current:projectAfterCommandItemSnapshot(restoredDocument.metadata,restoreChangedFields),changed_fields:restoreChangedFields});const targetEntry=history[resolvedTarget.historyIndex],offset=historyVersionOffset(history,!0);return{item:restoredDocument.metadata,restored_from:{kind:resolvedTarget.kind,target:resolvedTarget.raw,history_index:resolvedTarget.historyIndex+1,version:offset===null?null:offset+resolvedTarget.historyIndex+1,entry_ts:targetEntry.ts,entry_op:targetEntry.op},changed_fields:restoreChangedFields,warnings:[...workflowPolicy.warnings,...loadedItemUnderLock?.recovered?["restore_unreadable_item_recovered"]:[],...subject.historyPolicyWarnings,...ownershipWarnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}const _testOnlyRestoreCommand={applyHistoryPatch,changedFields,ensureMaterializedRestoreTarget,ensureReplayTarget,extractPatchFailureContext,replayCurrentDocument,replayToTarget,resolveRestoreSubject};export{_testOnlyRestoreCommand,runRestore};
|
|
2
2
|
//# sourceMappingURL=restore.js.map
|
|
@@ -33,6 +33,8 @@ lifecyclePolicy?:Partial<TerminalTransitionPolicy>;
|
|
|
33
33
|
}
|
|
34
34
|
/** Result returned by the public close-item operation. */
|
|
35
35
|
export interface CloseOperationResult {
|
|
36
|
+
/** Completion timestamp and the input that supplied it for this close event. */
|
|
37
|
+
completion?:CloseCompletionReceipt;
|
|
36
38
|
/** Closed item projected as a stable record. */
|
|
37
39
|
item:Record<string,unknown>;
|
|
38
40
|
/** Metadata fields changed by the transition. */
|
|
@@ -42,6 +44,15 @@ follow_up?:CloseEvidenceFollowUp;
|
|
|
42
44
|
/** Validation and lifecycle policy receipts. */
|
|
43
45
|
warnings:string[];
|
|
44
46
|
}
|
|
47
|
+
/** Per-close completion provenance, also sealed into the immutable close event. */
|
|
48
|
+
export interface CloseCompletionReceipt {
|
|
49
|
+
/** Actual persisted completed_at value. */
|
|
50
|
+
timestamp:string;
|
|
51
|
+
/** Caller assertion, preserved metadata, or inferred tracker close time. */
|
|
52
|
+
source:"asserted" | "existing" | "close_time";
|
|
53
|
+
/** Actionable correction guidance when completion was inferred. */
|
|
54
|
+
hint?:string;
|
|
55
|
+
}
|
|
45
56
|
/** Optional evidence completion after a successful, durable close. */
|
|
46
57
|
export interface CloseEvidenceFollowUp {
|
|
47
58
|
/** Close succeeded; this guidance does not request another close attempt. */
|
|
@@ -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]="
|
|
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]="1430dcf8-9363-556d-aa33-184cea5421f9")}catch{}})();import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";const DEFAULT_TERMINAL_TRANSITION_POLICY=Object.freeze({requireCloseReason:!0,orderingEdges:"preserve"});function resolveTerminalReason(input){const candidates=[{source:"explicit",value:input.explicit},{source:"duplicate",value:input.duplicateOf===void 0?void 0:`Duplicate of ${input.duplicateOf}`},{source:"resolution",value:input.resolution},{source:"message",value:input.message}];for(const candidate of candidates){const normalized=candidate.value?.trim();if(normalized)return{closeReason:normalized,source:candidate.source}}return{source:"none"}}function requireTerminalReason(input,required){return requireTerminalReasonWithRecovery(input,required,{operation:"close"})}function requireTerminalReasonWithRecovery(input,required,recovery){const resolution=resolveTerminalReason(input);if(!required||resolution.closeReason!==void 0)return resolution;const examples=recovery.operation==="create"?[`pm create --title "<title>" --type <type> --status ${recovery.status??"closed"} --close-reason "<closing summary>"`,`pm create --title "<title>" --type <type> --status ${recovery.status??"closed"} --resolution "<resolution summary>"`,"pm create --stdin-json < item.json"]:['pm close <id> "Done: <what changed and why>"','pm close <id> --reason "<closing summary>"','pm close <id> -m "<closing summary>"',"pm close <id> --duplicate-of <canonical-id>"];throw new PmCliError("Close reason text is required because governance.require_close_reason is enabled",EXIT_CODE.USAGE,{code:"close_reason_required",required:"Provide an author-controlled closing summary as the reason, message, resolution, or duplicate target.",why:"governance.require_close_reason is enabled, so tools must not invent immutable closure evidence.",examples,nextSteps:[`Re-run the ${recovery.operation} operation with a closing summary.`,"To stop requiring reasons, run: pm config set governance-require-close-reason --policy disabled"]})}function applyTerminalOrderingPolicy(metadata,policy){const previousBlockedBy=typeof metadata.blocked_by=="string"?metadata.blocked_by.trim():"",hadBlockedBy=metadata.blocked_by!==void 0,dependencies=metadata.dependencies??[],predecessorEdges=dependencies.filter(dependency=>dependency.kind==="blocked_by"),hadBlockedReason=metadata.blocked_reason!==void 0,changedFields=[];if(hadBlockedBy&&(delete metadata.blocked_by,changedFields.push("blocked_by")),hadBlockedReason&&(delete metadata.blocked_reason,changedFields.push("blocked_reason")),policy.orderingEdges==="remove"&&predecessorEdges.length>0){const removed=new Set(predecessorEdges),retained=dependencies.filter(dependency=>!removed.has(dependency));retained.length>0?metadata.dependencies=retained:delete metadata.dependencies,changedFields.push("dependencies")}if(policy.orderingEdges==="remove")return{changedFields,warnings:[...previousBlockedBy?[`closed_cleared_blocked_by:${metadata.id}:${previousBlockedBy}`]:[],...predecessorEdges.length>0?[`closed_removed_predecessors:${metadata.id}:${predecessorEdges.map(edge=>edge.id).join(",")}`,`closed_removed_predecessors_count:${metadata.id}:${predecessorEdges.length}`]:[]]};const blockerIds=[...new Set([...previousBlockedBy?[previousBlockedBy]:[],...predecessorEdges.map(dependency=>dependency.id)])];return blockerIds.length===0?{changedFields,warnings:[]}:{changedFields,warnings:[`closed_preserved_predecessors:${metadata.id}:${blockerIds.join(",")}`]}}export{DEFAULT_TERMINAL_TRANSITION_POLICY,applyTerminalOrderingPolicy,requireTerminalReason,requireTerminalReasonWithRecovery,resolveTerminalReason};
|
|
2
2
|
//# sourceMappingURL=lifecycle-policy.js.map
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Provides SDK-first pre-write provenance and secret-detection guardrails for
|
|
5
5
|
* CLI, MCP, and package-owned mutation dispatchers.
|
|
6
6
|
*/
|
|
7
|
-
import { SECRET_RULES } from "../core/shared/secret-rules.js";
|
|
7
|
+
import { SECRET_RULES,type SecretNormalizationKind } from "../core/shared/secret-rules.js";
|
|
8
|
+
export type { SecretNormalizationKind } from "../core/shared/secret-rules.js";
|
|
8
9
|
/** Configurable handling mode for credential-shaped mutation content. */
|
|
9
10
|
export type SecretGuardMode = "off" | "advise" | "block";
|
|
10
11
|
/** Settings consumed by the shared mutation guard. */
|
|
@@ -22,6 +23,10 @@ export interface SecretGuardFinding {
|
|
|
22
23
|
rule:(typeof SECRET_RULES)[number]["mutationRule"];
|
|
23
24
|
/** Object path or argument index containing the match. */
|
|
24
25
|
path:string;
|
|
26
|
+
/** Detection-only transformations, without original or decoded coordinate values. */
|
|
27
|
+
normalizations?:SecretNormalizationKind[];
|
|
28
|
+
/** Remaining encoded input exceeded the finite inspection envelope and requires explicit review. */
|
|
29
|
+
normalization_incomplete?:true;
|
|
25
30
|
}
|
|
26
31
|
/** Result of a non-blocking or bypassed mutation guard evaluation. */
|
|
27
32
|
export interface MutationGuardResult {
|
|
@@ -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]="
|
|
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]="d6059407-bf03-5ae8-8b01-e3e7c5b28030")}catch{}})();import{SECRET_RULES,findSecretRuleMatches}from"../core/shared/secret-rules.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";const PM_MUTATION_ACTION_CONTRACTS=[{action:"append",history_scope:"item"},{action:"claim",history_scope:"item"},{action:"close",history_scope:"item"},{action:"close-many",history_scope:"item"},{action:"close-task",history_scope:"item"},{action:"comments",history_scope:"conditional"},{action:"config",history_scope:"conditional"},{action:"copy",history_scope:"item"},{action:"create",history_scope:"item"},{action:"delete",history_scope:"item"},{action:"deps",history_scope:"conditional"},{action:"discover",history_scope:"item"},{action:"docs",history_scope:"conditional"},{action:"files",history_scope:"conditional"},{action:"focus",history_scope:"conditional"},{action:"gc",history_scope:"conditional"},{action:"history-compact",history_scope:"history"},{action:"history-author-acknowledge",history_scope:"workspace"},{action:"history-redact",history_scope:"history"},{action:"history-repair",history_scope:"history"},{action:"init",history_scope:"workspace"},{action:"install",history_scope:"conditional"},{action:"learnings",history_scope:"conditional"},{action:"notes",history_scope:"conditional"},{action:"package",history_scope:"conditional"},{action:"pause-task",history_scope:"item"},{action:"plan",history_scope:"conditional"},{action:"profile",history_scope:"conditional"},{action:"release",history_scope:"item"},{action:"restore",history_scope:"item"},{action:"schema",history_scope:"conditional"},{action:"start-task",history_scope:"item"},{action:"templates",history_scope:"conditional"},{action:"test",history_scope:"conditional"},{action:"test-all",history_scope:"conditional"},{action:"update",history_scope:"item"},{action:"update-many",history_scope:"item"},{action:"upgrade",history_scope:"conditional"}],MUTATION_ACTION_CONTRACTS_BY_NAME=new Map(PM_MUTATION_ACTION_CONTRACTS.map(contract=>[contract.action,contract]));function stringLeaves(value,path="$",seen=new WeakSet){return typeof value=="string"?[{path,value}]:typeof value!="object"||value===null?[]:seen.has(value)?[]:(seen.add(value),Array.isArray(value)?value.flatMap((entry,index)=>stringLeaves(entry,`${path}[${index}]`,seen)):Object.entries(value).flatMap(([key,entry])=>stringLeaves(entry,`${path}.${key}`,seen)))}function preflightRuleMatch(rule,value){const matches=findSecretRuleMatches(rule,value),first=matches.next().value;if(!first||rule.mutationRule!=="absolute_home_path"||first.normalization_incomplete)return first;for(const later of matches)if(later.normalization_incomplete)return{...first,normalizations:[...new Set([first.normalizations,later.normalizations].flatMap(kinds=>kinds??[]))],normalization_incomplete:!0};return first}function scanMutationSecrets(payload){const findings=[];for(const leaf of stringLeaves(payload))for(const rule of SECRET_RULES){const match=preflightRuleMatch(rule,leaf.value);if(match){const finding={rule:rule.mutationRule,path:leaf.path};match.normalizations&&(finding.normalizations=match.normalizations),match.normalization_incomplete&&(finding.normalization_incomplete=!0),findings.push(finding)}}return findings.filter((finding,index,all)=>all.findIndex(candidate=>candidate.rule===finding.rule&&candidate.path===finding.path)===index)}function evaluateMutationGuard(options){const author=options.author.trim()||"unknown";if(options.settings.require_attributed_author&&author.toLowerCase()==="unknown")throw new PmCliError("Mutation author is required by workspace policy.",EXIT_CODE.USAGE,{code:"mutation_author_required",required:"Pass --author <id>, set PM_AUTHOR, or configure author_default.",nextSteps:["Retry with --author <stable-agent-id>.","Set PM_AUTHOR for this agent session."]});if(options.settings.secret_guard==="off")return{author,findings:[],warnings:[],override_applied:!1};let findings;try{findings=scanMutationSecrets(options.payload)}catch{return{author,findings:[],warnings:["secret_guard_scan_failed_open"],override_applied:!1}}if(findings.length===0)return{author,findings,warnings:[],override_applied:!1};const ruleSummary=[...new Set(findings.map(finding=>finding.rule))].sort().join(",");if(options.settings.secret_guard==="block"&&options.force!==!0)throw new PmCliError(`Mutation blocked by secret guard (${ruleSummary}). No detected value was logged.`,EXIT_CODE.CONFLICT,{code:"mutation_secret_guard_blocked",required:"Remove the credential-shaped content or retry with --force after explicit review.",nextSteps:["Replace the value with a secret-manager reference.","Use pm history-redact if equivalent content already entered history."],recovery:{recovery_mode:"compact",attempted_command:"pm <mutation> [REDACTED]",normalized_args:["[REDACTED]"],suggested_retry:"Remove credential-shaped content, then retry the mutation."}});return{author,findings,warnings:[`secret_guard_detected:${findings.length}:rules=${ruleSummary}`,...options.settings.secret_guard==="block"&&options.force===!0?["secret_guard_force_override"]:[]],override_applied:options.settings.secret_guard==="block"&&options.force===!0}}function isMutationAction(action){return MUTATION_ACTION_CONTRACTS_BY_NAME.has(action.trim().toLowerCase())}function listMutationActions(){return[...MUTATION_ACTION_CONTRACTS_BY_NAME.keys()].sort((left,right)=>left.localeCompare(right))}function getMutationActionContract(action){return MUTATION_ACTION_CONTRACTS_BY_NAME.get(action.trim().toLowerCase())}export{PM_MUTATION_ACTION_CONTRACTS,evaluateMutationGuard,getMutationActionContract,isMutationAction,listMutationActions,scanMutationSecrets};
|
|
2
2
|
//# sourceMappingURL=mutation-guard.js.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Deterministic admission policy; neither policy reorders or splits rows. */
|
|
2
|
+
export type OutputEnvelopeFitPolicy = "prefix" | "skip";
|
|
3
|
+
/** SDK-owned receipt included in every measured envelope as output_fit. */
|
|
4
|
+
export interface OutputEnvelopeFitReceipt {
|
|
5
|
+
/** Receipt schema version. */
|
|
6
|
+
version:1;
|
|
7
|
+
/** Admission policy applied in caller order. */
|
|
8
|
+
policy:OutputEnvelopeFitPolicy;
|
|
9
|
+
/** Number of rows offered before fitting. */
|
|
10
|
+
total_candidates:number;
|
|
11
|
+
/** Original positions of the retained rows. */
|
|
12
|
+
included_indices:readonly number[];
|
|
13
|
+
/** Number of whole rows withheld by the policy. */
|
|
14
|
+
omitted_count:number;
|
|
15
|
+
/** Binding ceiling in the caller's token estimator units. */
|
|
16
|
+
token_budget:number;
|
|
17
|
+
/** Greatest complete-envelope estimate across all required renderers. */
|
|
18
|
+
estimated_tokens:number;
|
|
19
|
+
/** Greatest UTF-8 byte count across all required renderers. */
|
|
20
|
+
output_bytes:number;
|
|
21
|
+
}
|
|
22
|
+
/** Envelope with the reserved, SDK-owned accounting and omission receipt. */
|
|
23
|
+
export type FittedOutputEnvelope<Envelope> = Omit<Envelope,"output_fit"> & {
|
|
24
|
+
/** Self-accounting receipt, including its own bytes and framing. */
|
|
25
|
+
readonly output_fit:Readonly<OutputEnvelopeFitReceipt>;
|
|
26
|
+
};
|
|
27
|
+
/** One complete rendering, ready to emit without reserializing or reframing. */
|
|
28
|
+
export interface OutputEnvelopeRendering {
|
|
29
|
+
/** Caller-selected transport identity. */
|
|
30
|
+
name:string;
|
|
31
|
+
/** Complete output, including any caller-supplied newline or framing. */
|
|
32
|
+
text:string;
|
|
33
|
+
/** UTF-8 bytes of text, including the receipt. */
|
|
34
|
+
bytes:number;
|
|
35
|
+
/** Estimate of text under the selected estimator. */
|
|
36
|
+
estimated_tokens:number;
|
|
37
|
+
}
|
|
38
|
+
/** Actual fitting work, kept outside the measured output to avoid self-counting. */
|
|
39
|
+
export interface OutputEnvelopeFitWork {
|
|
40
|
+
/** Candidate admission trials performed, excluding the minimum envelope. */
|
|
41
|
+
evaluated_candidates:number;
|
|
42
|
+
/** Renderer calls across all fixed-point passes and admission trials. */
|
|
43
|
+
render_calls:number;
|
|
44
|
+
/** Hard ceiling on renderer calls. */
|
|
45
|
+
max_render_calls:number;
|
|
46
|
+
}
|
|
47
|
+
/** Explicit failure to produce a verified packet; no oversized output is returned. */
|
|
48
|
+
export declare class OutputEnvelopeFitError extends RangeError {
|
|
49
|
+
/** Stable refusal reason suitable for package-specific error translation. */
|
|
50
|
+
readonly code:"output_envelope_infeasible" | "output_envelope_work_limit" | "output_envelope_unstable";
|
|
51
|
+
/** Work completed before refusal. */
|
|
52
|
+
readonly work:Readonly<OutputEnvelopeFitWork>;
|
|
53
|
+
/** Measured minimum-envelope estimate when the budget is infeasible. */
|
|
54
|
+
readonly minimum_tokens:number | undefined;
|
|
55
|
+
/** Capture immutable refusal evidence without serializing caller data. */
|
|
56
|
+
constructor(code:OutputEnvelopeFitError["code"],work:OutputEnvelopeFitWork,minimumTokens?:number);
|
|
57
|
+
}
|
|
58
|
+
/** Caller-owned envelope construction, renderers and finite work controls. */
|
|
59
|
+
export interface FitOutputEnvelopeOptions<Row,Envelope extends Record<string,unknown>> {
|
|
60
|
+
/** Maximum complete-envelope estimate accepted by every required renderer. */
|
|
61
|
+
tokenBudget:number;
|
|
62
|
+
/** Preserve a prefix by default; skip may retain later smaller rows. */
|
|
63
|
+
policy?:OutputEnvelopeFitPolicy;
|
|
64
|
+
/** Construct mandatory domain metadata; output_fit is reserved and overwritten by the SDK. Must be pure and deterministic. */
|
|
65
|
+
buildEnvelope:(rows:readonly Row[],receipt:Readonly<OutputEnvelopeFitReceipt>) => Envelope;
|
|
66
|
+
/** Nonempty set of pure deterministic renderers, including all output framing. */
|
|
67
|
+
renderers:Readonly<Record<string,(envelope:FittedOutputEnvelope<Envelope>) => string>>;
|
|
68
|
+
/** Estimate the exact rendered text; defaults to ceil(UTF-8 bytes / 4). Stronger estimators may be supplied. */
|
|
69
|
+
estimateTokens?:(text:string) => number;
|
|
70
|
+
/** Hard renderer-call ceiling; defaults to 10,000. */
|
|
71
|
+
maxRenderCalls?:number;
|
|
72
|
+
/** Fixed-point pass ceiling per admission trial; defaults to 16. */
|
|
73
|
+
maxStabilizationPasses?:number;
|
|
74
|
+
}
|
|
75
|
+
/** Verified envelope and cached renderings; work is diagnostic, not emitted packet data. */
|
|
76
|
+
export interface OutputEnvelopeFitResult<Row,Envelope> {
|
|
77
|
+
/** Whole caller rows retained in original order. */
|
|
78
|
+
rows:readonly Row[];
|
|
79
|
+
/** Domain metadata plus the exact measured receipt. */
|
|
80
|
+
envelope:FittedOutputEnvelope<Envelope>;
|
|
81
|
+
/** Cached complete outputs; every rendering satisfies the budget. */
|
|
82
|
+
renderings:readonly OutputEnvelopeRendering[];
|
|
83
|
+
/** True only when all candidates were retained. */
|
|
84
|
+
complete:boolean;
|
|
85
|
+
/** Actual bounded fitting work. */
|
|
86
|
+
work:Readonly<OutputEnvelopeFitWork>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Fit whole ordered rows against every required complete rendering. First prove
|
|
90
|
+
* the empty mandatory envelope fits, then admit rows under prefix or skip
|
|
91
|
+
* policy. No monotonic-size assumption or binary search is used. Callbacks
|
|
92
|
+
* must be pure and return promptly; call/pass ceilings bound SDK fitting work,
|
|
93
|
+
* not arbitrary callback execution time. Emit the cached renderings directly.
|
|
94
|
+
*
|
|
95
|
+
* @throws {OutputEnvelopeFitError} When the minimum envelope is too large,
|
|
96
|
+
* accounting fails to stabilize, or the renderer-call ceiling is exhausted.
|
|
97
|
+
*/
|
|
98
|
+
export declare function fitOutputEnvelope<Row,Envelope extends Record<string,unknown>>(candidates:readonly Row[],options:FitOutputEnvelopeOptions<Row,Envelope>):OutputEnvelopeFitResult<Row,Envelope>;
|
|
@@ -0,0 +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]="f698608a-2f39-5972-b24b-93287af6b373")}catch{}})();import{estimatePmOutputTokens}from"../cli-contracts/agent-output-contracts.js";class OutputEnvelopeFitError extends RangeError{code;work;minimum_tokens;constructor(code,work,minimumTokens){super(code),this.name="OutputEnvelopeFitError",this.code=code,this.work=Object.freeze({...work}),this.minimum_tokens=minimumTokens}}function assertPositiveInteger(value,name){if(!Number.isSafeInteger(value)||value<1)throw new RangeError(`${name} must be a positive safe integer`)}function renderEnvelope(envelope,renderers,estimateTokens,work){return renderers.map(([name,render])=>{if(work.render_calls>=work.max_render_calls)throw new OutputEnvelopeFitError("output_envelope_work_limit",work);work.render_calls+=1;const text=render(envelope);if(typeof text!="string")throw new TypeError("Envelope renderers must return strings");const estimatedTokens=estimateTokens(text);if(!Number.isSafeInteger(estimatedTokens)||estimatedTokens<0)throw new RangeError("Envelope token estimates must be non-negative safe integers");return{name,text,bytes:Buffer.byteLength(text,"utf8"),estimated_tokens:estimatedTokens}})}function stabilizeEnvelope(rows,initial,options,work){let receipt=initial;const renderers=Object.entries(options.renderers),estimateTokens=options.estimateTokens??(text=>estimatePmOutputTokens(Buffer.byteLength(text,"utf8")));for(let pass=0;pass<(options.maxStabilizationPasses??16);pass+=1){const frozenReceipt=Object.freeze({...receipt}),envelope={...options.buildEnvelope(rows,frozenReceipt),output_fit:frozenReceipt},renderings=renderEnvelope(envelope,renderers,estimateTokens,work),bytes=Math.max(...renderings.map(rendering=>rendering.bytes)),tokens=Math.max(...renderings.map(rendering=>rendering.estimated_tokens));if(bytes===receipt.output_bytes&&tokens===receipt.estimated_tokens)return{envelope,renderings};receipt={...receipt,output_bytes:bytes,estimated_tokens:tokens}}throw new OutputEnvelopeFitError("output_envelope_unstable",work)}function fitOutputEnvelope(candidates,options){assertPositiveInteger(options.tokenBudget,"tokenBudget"),assertPositiveInteger(options.maxRenderCalls??1e4,"maxRenderCalls"),assertPositiveInteger(options.maxStabilizationPasses??16,"maxStabilizationPasses");const policy=options.policy??"prefix";if(policy!=="prefix"&&policy!=="skip")throw new TypeError("Unknown output envelope fit policy");if(Object.entries(options.renderers).length===0||Object.entries(options.renderers).some(([name,render])=>!name.trim()||typeof render!="function"))throw new TypeError("Envelope fitting requires named callable renderers");const work={evaluated_candidates:0,render_calls:0,max_render_calls:options.maxRenderCalls??1e4};let rows=[],included=[];const receiptFor=indices=>({version:1,policy,total_candidates:candidates.length,included_indices:Object.freeze([...indices]),omitted_count:candidates.length-indices.length,token_budget:options.tokenBudget,estimated_tokens:0,output_bytes:0});let fitted=stabilizeEnvelope(rows,receiptFor(included),options,work);if(fitted.envelope.output_fit.estimated_tokens>options.tokenBudget)throw new OutputEnvelopeFitError("output_envelope_infeasible",work,fitted.envelope.output_fit.estimated_tokens);for(const[index,candidate]of candidates.entries()){work.evaluated_candidates+=1;const trialRows=[...rows,candidate],trialIndices=[...included,index],trial=stabilizeEnvelope(trialRows,receiptFor(trialIndices),options,work);if(trial.envelope.output_fit.estimated_tokens<=options.tokenBudget)rows=trialRows,included=trialIndices,fitted=trial;else if(policy==="prefix")break}return{rows,...fitted,complete:rows.length===candidates.length,work:Object.freeze({...work})}}export{OutputEnvelopeFitError,fitOutputEnvelope};
|
|
2
|
+
//# sourceMappingURL=fit-envelope.js.map
|