@unbrained/pm-cli 2026.9.15 → 2026.9.17
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 +2 -2
- package/CHANGELOG.md +58 -0
- package/dist/cli/error-guidance.d.ts +1 -1
- package/dist/cli/error-guidance.js +1 -1
- package/dist/cli/register-setup.js +1 -1
- package/dist/cli-bundle/bundle-manifest.json +149 -149
- package/dist/cli-bundle/chunks/{chunk-3RB6Z7XE.js → chunk-5ZY4WE3F.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UKLOSZV6.js → chunk-C3MFMGCR.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WLJJ4MAU.js → chunk-CPFBDM53.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YMMLKKEP.js → chunk-DN2RIHRN.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5P5PYCZX.js → chunk-E67MIO3Z.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3AHONKLL.js → chunk-G2IJF244.js} +48 -48
- package/dist/cli-bundle/chunks/{chunk-RM2OGG65.js → chunk-LD2FH2YE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RKPUO75B.js → chunk-Q6KPZGMP.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-Y2P3DSSO.js → chunk-T526C5DX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-BOZ4HVYL.js → chunk-UF75LUAK.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-J4DRE3WN.js → chunk-UJSB6NO6.js} +76 -76
- package/dist/cli-bundle/chunks/{chunk-WDF7PP4P.js → chunk-YZXB4XGA.js} +4 -4
- package/dist/cli-bundle/chunks/{register-list-query-IWSPNFFD.js → register-list-query-ISM35VIX.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-3DVF4R64.js → register-mutation-KHMBJJS6.js} +2 -2
- package/dist/cli-bundle/chunks/{register-operations-LXP3MECQ.js → register-operations-HHDROJD6.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-KFQSNBDX.js → register-setup-YAURJMY5.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-533DCWPY.js → chunk-267N774W.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ZHX3433X.js → chunk-5FSGN4MP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-BMATJLPT.js → chunk-5KYHDFDN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-SHF57M2H.js → chunk-7S7XWMXC.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-AXDAIBT3.js → chunk-7ZC4CKOX.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-JKJYXCT6.js → chunk-BFUXTNZU.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-PBJC2ZNA.js → chunk-G4TKJZ4A.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ZOE2NSJB.js → chunk-GKSAMNBG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-63YRRGKX.js → chunk-IVWUQE7T.js} +51 -51
- package/dist/cli-bundle/focused-chunks/{chunk-6C3CUU2G.js → chunk-JZSLDLR4.js} +20 -20
- package/dist/cli-bundle/focused-chunks/{chunk-YBQTVE5S.js → chunk-LNM3BS45.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-5SBU4QDC.js → chunk-NOK652OP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-OGGF2RBL.js → chunk-OCTTDZOU.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-MD7ADLME.js → chunk-OWDDVMAP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-UACMCSCC.js → chunk-WUMGGQYN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-4YTDKIPF.js → chunk-Z4PWEIMX.js} +21 -21
- package/dist/cli-bundle/main.js +11 -10
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +2 -2
- 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 +40 -40
- 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 +2 -2
- package/dist/core/diagnostics/remediation.js +1 -1
- package/dist/core/store/tracker-preflight.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/init.d.ts +22 -1
- package/dist/sdk/init.js +1 -1
- package/dist/sdk/merge/install.js +2 -2
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/read-output-budget.d.ts +2 -0
- package/dist/sdk/read-output-budget.js +1 -1
- package/dist/sdk/read-output-contracts.d.ts +4 -0
- package/dist/sdk/read-output-contracts.js +1 -1
- package/docs/MERGE_SAFETY.md +13 -2
- package/docs/PACKED_FIRST_RUN.md +46 -0
- package/docs/QUICKSTART.md +16 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +14 -0
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +6 -3
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- 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-codex/.codex-plugin/plugin.json +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { PmReadOutputReceipt } from "./read-output-contracts.js";
|
|
2
|
+
/** Project a standard item read to brief depth, preserving metadata and disclosing every removed section. */
|
|
3
|
+
export declare function projectReadOutputItemToBrief(command: string, options: Record<string, unknown>, result: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
2
4
|
/** Input to the deterministic finite-retry recommendation contract. */
|
|
3
5
|
export interface PmReadOutputRecoveryBudgetInput {
|
|
4
6
|
/** Ceiling that already bound and truncated the response. */
|
|
@@ -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]="
|
|
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]="0699d81a-43d0-5c33-a0c5-c415ebe90566")}catch(e2){}})();import{formatBuiltInOutput}from"../core/output/output.js";import{countReadOutputRows,readOutputBudgetCollections}from"./read-output-rows.js";const MAX_ESTIMATE_ITERATIONS=8;const MAX_COMPACTION_ITERATIONS=64;const RECOVERY_MARGIN_NUMERATOR=5;const RECOVERY_MARGIN_DENOMINATOR=4;const RECOVERY_ROUNDING_TOKENS=100;function projectReadOutputItemToBrief(command,options,result){if(command!=="get"||!isRecord(result.item)||["fields","outputInclude","output_include","outputCursor","output_cursor"].some(key=>options[key]!==void 0)||options.full===true||options.tree===true||options.depth!==void 0&&options.depth!=="standard")return void 0;const item=result.item;const sections=["linked","claim_state","schedule"];const omitted=sections.filter(key=>Object.hasOwn(result,key));const projected=Object.fromEntries(Object.entries(result).filter(([key])=>!sections.includes(key)));projected.item=Object.fromEntries(Object.entries(item).filter(([key])=>key!=="body"));if(Object.hasOwn(item,"body"))omitted.push("body");const previous=isRecord(result.omission_receipt)&&Array.isArray(result.omission_receipt.omitted_field_groups)?result.omission_receipt.omitted_field_groups:[];const groups=[...previous,...omitted.map(name=>({name,restore_with:`--fields ${name}`}))];projected.omission_receipt={has_omissions:groups.length>0,omitted_field_group_count:groups.length,omitted_field_groups:groups};return projected}function resolveReadOutputRecoveryBudget(input){const binding=Math.trunc(input.effective_budget_tokens);const measured=Math.trunc(input.measured_result_tokens);if(!Number.isSafeInteger(binding)||binding<=0||!Number.isSafeInteger(measured)||measured<=0){return{output_budget:"unbounded",recovery_budget_multiplier:null,rule_version:"v1"}}const baseline=Math.max(binding+1,measured);const withMargin=Math.ceil(baseline*RECOVERY_MARGIN_NUMERATOR/RECOVERY_MARGIN_DENOMINATOR);const rounded=Math.ceil(withMargin/RECOVERY_ROUNDING_TOKENS)*RECOVERY_ROUNDING_TOKENS;if(!Number.isSafeInteger(rounded)){return{output_budget:"unbounded",recovery_budget_multiplier:null,rule_version:"v1"}}return{output_budget:rounded,recovery_budget_multiplier:rounded/binding,rule_version:"v1"}}function estimateReadOutputTokens(result,format){const rendered=format===void 0?JSON.stringify(result):formatBuiltInOutput(result,format);return Math.ceil(Buffer.byteLength(rendered,"utf8")/4)}function isRecord(value){return value!==null&&typeof value==="object"&&!Array.isArray(value)}function compactStrings(value,state){if(typeof value==="string"){if(value.length<=240)return value;state.compacted=true;return`${value.slice(0,240)}\u2026`}if(Array.isArray(value)){return value.map(entry=>compactStrings(entry,state))}if(!isRecord(value))return value;return Object.fromEntries(Object.entries(value).map(([key,entry])=>[key,compactStrings(entry,state)]))}function updateReadOutputReceiptEstimate(result,receipt,format){let estimate=receipt.estimated_tokens;for(let iteration=0;iteration<MAX_ESTIMATE_ITERATIONS;iteration+=1){receipt.estimated_tokens=estimate;const measured=estimateReadOutputTokens(result,format);if(measured===estimate)return;estimate=measured}receipt.estimated_tokens=estimate}function compactRowsToBudget(result,receipt,budget,minimumRowsByPath,format){for(let iteration=0;iteration<MAX_COMPACTION_ITERATIONS;iteration+=1){updateReadOutputReceiptEstimate(result,receipt,format);if(receipt.estimated_tokens<=budget)return;const candidate=readOutputBudgetCollections(result).filter(collection=>{const length=Array.isArray(collection.value)?collection.value.length:Object.keys(collection.value).length;return length>Math.max(1,minimumRowsByPath.get(collection.path)??0)}).map(collection=>({collection,length:Array.isArray(collection.value)?collection.value.length:Object.keys(collection.value).length})).sort((left,right)=>right.length-left.length||left.collection.path.localeCompare(right.collection.path))[0]?.collection;if(!candidate)return;const minimumRows=Math.max(1,minimumRowsByPath.get(candidate.path)??0);if(Array.isArray(candidate.value)){candidate.value.splice(-Math.min(candidate.value.length-minimumRows,Math.max(1,Math.ceil(candidate.value.length/2))))}else{const keys=Object.keys(candidate.value);for(const key of keys.slice(-Math.min(keys.length-minimumRows,Math.max(1,Math.ceil(keys.length/2))))){delete candidate.value[key]}}receipt.rows_compacted=true;receipt.compacted_row_paths=[...new Set([...receipt.compacted_row_paths??[],candidate.path])].sort((left,right)=>left.localeCompare(right));result.has_more=true;result.truncated=true;if(typeof result.count==="number"){result.count=countReadOutputRows(result)}}}function compactReadOutputToBudget(result,receipt,budget,minimumRowsByPath=new Map,format){const stringCompactionState={compacted:false};const compacted=compactStrings(result,stringCompactionState);receipt.strings_compacted=stringCompactionState.compacted;compacted.read_output=receipt;compactRowsToBudget(compacted,receipt,budget,minimumRowsByPath,format);updateReadOutputReceiptEstimate(compacted,receipt,format);return compacted}export{compactReadOutputToBudget,estimateReadOutputTokens,projectReadOutputItemToBrief,resolveReadOutputRecoveryBudget,updateReadOutputReceiptEstimate};
|
|
2
2
|
//# sourceMappingURL=read-output-budget.js.map
|
|
@@ -129,6 +129,10 @@ export interface PmReadOutputReceipt {
|
|
|
129
129
|
result_omitted: boolean;
|
|
130
130
|
/** Estimated tokens in the useful result immediately before whole-result omission. */
|
|
131
131
|
omitted_result_estimated_tokens?: number;
|
|
132
|
+
/** Detail depth selected before destructive string or row compaction. */
|
|
133
|
+
applied_depth?: "brief";
|
|
134
|
+
/** Binding constraint that selected the smaller detail projection. */
|
|
135
|
+
degradation_reason?: "output_budget_reached";
|
|
132
136
|
}
|
|
133
137
|
/** Machine-readable explanation of budget-driven row degradation. */
|
|
134
138
|
export interface PmReadOutputTruncationDisclosure {
|
|
@@ -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]="8e488707-02ae-54ce-b30b-24371975b98e")}catch(e2){}})();import{resolvePmHistoryOperation}from"./cli-contracts/command-aliases.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{compactReadOutputToBudget,estimateReadOutputTokens,resolveReadOutputRecoveryBudget,updateReadOutputReceiptEstimate}from"./read-output-budget.js";import{resolveReadOutputRecoveryBudget as resolveReadOutputRecoveryBudget2}from"./read-output-budget.js";import{resolvePmCommandOutputBudget}from"./cli-contracts/agent-output-contracts.js";import{boundReadOutputRows,countReadOutputRows,mapReadOutputRows,readOutputBudgetCollections,readOutputContinuationRowCollections,readOutputRowPaths}from"./read-output-rows.js";import{applyReadOutputContinuation,decodeReadOutputContinuationCursor,encodeReadOutputContinuationCursor,prioritizeAssuranceAssertions,readOutputCollectionFingerprint}from"./read-output/continuation.js";import{decodeReadOutputContinuationCursor as decodeReadOutputContinuationCursor2,encodeReadOutputContinuationCursor as encodeReadOutputContinuationCursor2,PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES,readOutputCollectionFingerprint as readOutputCollectionFingerprint2}from"./read-output/continuation.js";import{applyReadOutputSessionReferences,attachReadOutputSessionReceipt,parseReadOutputSession,readOutputSessionRemainingTokens}from"./read-output-session.js";import{decodeQueryCursorEnvelope,encodeQueryCursor}from"./pagination.js";const PM_READ_OUTPUT_DIMENSIONS=["include","amount","cost","encoding"];const PM_READ_OUTPUT_SURFACES=["list","context","search","get","next","health","deps","graph","history","activity","validate","events","contracts","comments","notes","files","docs","stats","aggregate","duplicates","package-catalog","package-manage","comments-audit","assurance"];const READ_OUTPUT_PRECEDENCE=["canonical","legacy","intent","default"];const CANONICAL_OPTIONS={include:"--output-include",amount:"--output-limit",cost:"--output-budget",encoding:"--output-format"};const READ_OUTPUT_INVOCATION_PROVENANCE=Symbol.for("pm.readOutputInvocationProvenance");const PM_READ_OUTPUT_OPTION_FLAGS=Object.freeze(PM_READ_OUTPUT_DIMENSIONS.map(dimension=>CANONICAL_OPTIONS[dimension]));const PM_READ_OUTPUT_COMPOSITION_OPTION_FLAGS=Object.freeze(["--output-session","--output-cursor","--output-row-contract"]);const LEGACY_FLAGS_BY_COMMAND={list:{include:["--brief","--compact","--fields","--full"],amount:["--after","--limit","--no-truncate"],cost:["--token-budget"],encoding:["--format","--stream"]},context:{include:["--fields","--section"],amount:["--after","--depth","--limit"],cost:["--token-budget"],encoding:["--format"]},search:{include:["--compact","--fields","--full"],amount:["--after","--limit"],cost:["--token-budget"],encoding:["--format"]},get:{include:["--fields","--full"],amount:["--depth"],cost:["--token-budget"],encoding:["--format"]},next:{amount:["--blocked-limit","--limit"],cost:["--token-budget"],encoding:["--format"]},health:{include:["--brief","--check-only","--full","--summary"]},deps:{include:["--collapse","--full","--summary"],amount:["--edge-limit","--max-depth","--node-limit"],cost:["--token-budget"],encoding:["--format"]},graph:{include:["--full","--summary"],amount:["--after","--limit","--max-depth","--max-paths"]},history:{include:["--compact","--full"],amount:["--limit"],encoding:["--format"]},activity:{include:["--compact","--full"],amount:["--limit","--unbounded"],encoding:["--stream"]},validate:{include:["--counts","--full"]},events:{include:["--full"],amount:["--limit"],encoding:["--follow"]},contracts:{include:["--full","--summary"]},comments:{amount:["--limit"]},notes:{amount:["--limit"]},files:{amount:["--limit","--no-truncate","--offset"]},docs:{},stats:{},aggregate:{},duplicates:{amount:["--limit"]},"package-catalog":{},"package-manage":{},"comments-audit":{},assurance:{}};const VALUE_BEARING_INCLUDE_ALIASES=new Set(["--collapse","--fields","--section"]);const BEHAVIOR_PRESERVING_MIGRATION_HINTS=Object.freeze({"--after":"--after retains cursor-position semantics; use --output-limit <n> separately to bound returned rows.","--check-only":"--check-only retains health side-effect semantics; --output-include does not suppress vector refresh.","--collapse":"--collapse retains dependency grouping semantics; --output-include does not replace it.","--depth":"--depth retains traversal or detail-depth semantics; --output-limit does not replace it.","--follow":"--follow retains event-tail semantics; --output-format does not enable following.","--max-depth":"--max-depth retains graph traversal-depth semantics; --output-limit does not replace it.","--max-paths":"--max-paths retains graph path-search semantics; use --output-limit separately to bound returned rows.","--no-truncate":"--no-truncate is a compatibility alias; prefer --output-limit unbounded.","--offset":"--offset retains positional pagination semantics; use --output-limit separately to bound returned rows.","--stream":"--stream retains command streaming semantics; --output-format selects only static result encoding.","--unbounded":"--unbounded is a compatibility alias; prefer --output-limit unbounded."});function flagSelector(flag){return flag.slice(2).replaceAll("-","_")}function migrationHint(flag,dimension){const behaviorHint=BEHAVIOR_PRESERVING_MIGRATION_HINTS[flag];if(behaviorHint!==void 0)return behaviorHint;const suffix=dimension==="include"?VALUE_BEARING_INCLUDE_ALIASES.has(flag)?"<csv>":flagSelector(flag):dimension==="amount"?"<n>":dimension==="cost"?"<tokens>":"<toon|json>";return`${flag} is a compatibility alias; prefer ${CANONICAL_OPTIONS[dimension]} ${suffix}.`}function buildSurfaceContract(command){const legacy=LEGACY_FLAGS_BY_COMMAND[command];const dimensions=Object.freeze(Object.fromEntries(PM_READ_OUTPUT_DIMENSIONS.map(dimension=>[dimension,Object.freeze({dimension,canonical_option:CANONICAL_OPTIONS[dimension],applicable:true,inapplicable_reason:null,legacy_aliases:Object.freeze((legacy[dimension]??[]).map(flag=>Object.freeze({flag,semantics:BEHAVIOR_PRESERVING_MIGRATION_HINTS[flag]===void 0?"replacement":"behavior_preserving",migration_hint:migrationHint(flag,dimension),visibility:"hidden_alias"})))})])));return Object.freeze({command,dimensions,precedence:READ_OUTPUT_PRECEDENCE,budget_retention_policy:command==="assurance"?"verdict_priority":"ordered_prefix",projection_modes:Object.freeze([...readOutputIncludeModeOptions(command).keys()])})}const PM_READ_OUTPUT_SURFACE_CONTRACTS=Object.freeze(PM_READ_OUTPUT_SURFACES.map(buildSurfaceContract));const SURFACE_CONTRACT_BY_COMMAND=new Map(PM_READ_OUTPUT_SURFACE_CONTRACTS.map(contract=>[contract.command,contract]));function resolveReadOutputSurface(command,options={}){const normalizedCommand=resolvePmHistoryOperation(command.trim().toLowerCase());const packageMode=normalizedCommand==="package catalog"||normalizedCommand==="packages catalog"||normalizedCommand==="package-catalog"||(normalizedCommand==="package"||normalizedCommand==="packages"||normalizedCommand==="extension")&&(options.catalog===true||options.target==="catalog"||options.action==="catalog");const root=packageMode?"package-catalog":normalizedCommand==="package manage"||normalizedCommand==="package-manage"?"package-manage":normalizedCommand.split(" ")[0];const normalized=root.startsWith("list-")?"list":root==="ctx"?"context":root;return PM_READ_OUTPUT_SURFACES.includes(normalized)?normalized:void 0}const CANONICAL_OPTION_KEYS=["outputInclude","output_include","outputLimit","output_limit","outputBudget","output_budget","outputFormat","output_format","outputSession","output_session","outputCursor","output_cursor","outputRowContract","output_row_contract"];const HYBRID_READ_MUTATION_KEYS={comments:["add","body","stdin","file","edit","delete"],notes:["add","addJson","stdin","file","edit","delete"],files:["add","addGlob","remove","migrate","apply","note"],docs:["add","addGlob","remove","migrate","note"],"package-catalog":["activate","adopt","adoptAll","deactivate","doctor","init","install","manage","migrate","reload","scaffold","uninstall"]};function hasCanonicalReadOutputOptions(options){return CANONICAL_OPTION_KEYS.some(key=>options[key]!==void 0)}const READ_OUTPUT_VALUE_VALIDATORS=[{keys:["outputInclude","output_include"],valid:value=>stringList(value)!==void 0,message:"--output-include requires at least one comma-separated field or section."},{keys:["outputLimit","output_limit"],valid:value=>value==="unbounded"||positiveInteger(value)!==void 0,message:"--output-limit must be a positive integer or unbounded."},{keys:["outputBudget","output_budget"],valid:value=>value==="unbounded"||positiveInteger(value)!==void 0,message:"--output-budget must be a positive integer or unbounded."},{keys:["outputFormat","output_format"],valid:value=>value==="toon"||value==="json",message:"--output-format must be toon or json."},{keys:["outputSession","output_session"],valid:value=>{parseReadOutputSession(value);return true},message:"--output-session must be a valid session-state object."},{keys:["outputCursor","output_cursor"],valid:value=>typeof value==="string"&&value.trim().length>0,message:"--output-cursor requires a non-empty continuation cursor."}];function validateReadOutputOptions(command,options){if(!hasCanonicalReadOutputOptions(options))return;const normalizedCommand=resolveReadOutputSurface(command,options);if(!normalizedCommand){throw new PmCliError(`Universal output controls apply only to read commands; ${command||"this command"} is not a read surface.`,EXIT_CODE.USAGE)}if((HYBRID_READ_MUTATION_KEYS[normalizedCommand]??[]).some(key=>options[key]!==void 0&&options[key]!==false)){throw new PmCliError(`Universal output controls cannot be combined with a ${normalizedCommand} mutation.`,EXIT_CODE.USAGE)}for(const validator of READ_OUTPUT_VALUE_VALIDATORS){const value=validator.keys.map(key=>options[key]).find(entry=>entry!==void 0);if(value!==void 0&&!validator.valid(value)){throw new PmCliError(validator.message,EXIT_CODE.USAGE)}}}function readOutputIncludeModeOptions(command){const surface=resolveReadOutputSurface(command);if(!surface)return new Map;return new Map((LEGACY_FLAGS_BY_COMMAND[surface].include??[]).filter(flag=>!VALUE_BEARING_INCLUDE_ALIASES.has(flag)&&BEHAVIOR_PRESERVING_MIGRATION_HINTS[flag]===void 0).map(flag=>[flagSelector(flag),optionKey(flag)]))}function applyReadOutputIncludeModes(command,includeValue,commandOptions){const requested=stringList(includeValue)??[];const modeOptions=readOutputIncludeModeOptions(command);const selectors=[];const modes=[];const optionsWithProvenance=commandOptions;const existingProvenance=optionsWithProvenance[READ_OUTPUT_INVOCATION_PROVENANCE];const canonicalModes=new Set(existingProvenance?.canonical_include_modes??[]);const explicitLegacyAliases=new Set(existingProvenance?.explicit_legacy_aliases??[]);for(const token of requested){const option=modeOptions.get(token);if(option===void 0){selectors.push(token);continue}const legacyFlag=`--${token.replaceAll("_","-")}`;if(isRequestedOption(readOption(commandOptions,legacyFlag))){explicitLegacyAliases.add(legacyFlag)}commandOptions[option]=true;modes.push(token);canonicalModes.add(token)}const forwardedGetFieldSelectors=resolveReadOutputSurface(command)==="get"?selectors.filter(selector=>selector!=="item"):[];const forwardedGetFields=forwardedGetFieldSelectors.length>0;if(forwardedGetFields){commandOptions.fields=[...new Set([...stringList(commandOptions.fields)??[],...forwardedGetFieldSelectors])].join(",");canonicalModes.add("fields")}if(modes.length>0||forwardedGetFields){optionsWithProvenance[READ_OUTPUT_INVOCATION_PROVENANCE]={canonical_include_modes:[...canonicalModes],explicit_legacy_aliases:[...explicitLegacyAliases],...existingProvenance?.cli_invocation_observed===true?{cli_invocation_observed:true}:{}}}return{selectors,modes}}function normalizeReadOutputIncludeModeOptions(command,options){const include=options.outputInclude??options.output_include;if(include===void 0)return;const{selectors,modes}=applyReadOutputIncludeModes(command,include,options);if(modes.length===0)return;const residual=selectors.length>0?selectors.join(","):void 0;options.outputInclude=residual;if(Object.hasOwn(options,"output_include")){options.output_include=residual}}function optionKey(flag){return flag.slice(2).replace(/-([a-z])/gu,(_,character)=>character.toUpperCase())}function readOption(options,flag){const key=optionKey(flag);if(Object.hasOwn(options,key))return options[key];const snakeKey=flag.slice(2).replaceAll("-","_");if(Object.hasOwn(options,snakeKey))return options[snakeKey];if(flag==="--no-truncate"&&options.truncate===false)return true;return void 0}function isRequestedOption(value){return value!==void 0&&value!==false&&value!==null}function stringList(value){const values=Array.isArray(value)?value:[value];const normalized=values.flatMap(entry=>typeof entry==="string"?entry.split(","):[]).map(entry=>entry.trim()).filter(Boolean);return normalized.length>0?[...new Set(normalized)]:void 0}function positiveInteger(value){const parsed=typeof value==="number"?value:typeof value==="string"&&/^\d+$/u.test(value.trim())?Number(value):Number.NaN;return Number.isSafeInteger(parsed)&&parsed>0?parsed:void 0}function resolveLegacyDimension(contract,options,usable,ignore){for(const alias of contract.legacy_aliases){if(ignore(alias.flag))continue;const value=readOption(options,alias.flag);const candidate={value,flag:alias.flag};if(isRequestedOption(value)&&usable(candidate))return candidate}return void 0}function resolveIncludeValue(canonical,legacy){const canonicalList=stringList(canonical);if(canonicalList)return{source:"canonical",value:canonicalList};if(!legacy)return void 0;return{source:"legacy",value:stringList(legacy.value)??[flagSelector(legacy.flag)]}}function resolveAmountValue(canonical,legacy){if(canonical==="unbounded"){return{source:"canonical",value:"unbounded"}}const canonicalLimit=positiveInteger(canonical);if(canonicalLimit!==void 0){return{source:"canonical",value:canonicalLimit}}if(!legacy)return void 0;if(legacy.flag==="--no-truncate"||legacy.flag==="--unbounded"){return{source:"legacy",value:"unbounded"}}const legacyLimit=positiveInteger(legacy.value);return legacyLimit===void 0?void 0:{source:"legacy",value:legacyLimit}}function resolveCostValue(canonical,legacy){if(canonical==="unbounded"){return{source:"canonical",value:"unbounded"}}const canonicalBudget=positiveInteger(canonical);if(canonicalBudget!==void 0){return{source:"canonical",value:canonicalBudget}}if(!legacy)return void 0;const legacyBudget=positiveInteger(legacy.value);return legacyBudget===void 0?void 0:{source:"legacy",value:legacyBudget}}function resolveEncodingValue(canonical,legacy){if(canonical==="json"||canonical==="toon"){return{source:"canonical",value:canonical}}if(!legacy)return void 0;if(legacy.flag==="--stream"||legacy.flag==="--follow"){return{source:"legacy",value:"stream"}}return legacy.value==="json"||legacy.value==="toon"?{source:"legacy",value:legacy.value}:void 0}function shouldIgnoreReadOutputLegacyAlias(provenance,dimension,flag){if(!provenance)return false;const explicitLegacyAliases=new Set(provenance.explicit_legacy_aliases);if(provenance.cli_invocation_observed===true){return!explicitLegacyAliases.has(flag)}const forwardedIncludeAliases=new Set(provenance.canonical_include_modes.map(mode=>`--${mode.replaceAll("_","-")}`));return dimension==="include"&&forwardedIncludeAliases.has(flag)&&!explicitLegacyAliases.has(flag)}function hasCompleteReadOutputIntent(command,legacyByDimension,provenance){const root=command.trim().toLowerCase().replaceAll(/\s+/gu," ").split(" ")[0];return root==="list-all"||legacyByDimension.amount?.flag==="--no-truncate"||legacyByDimension.include?.flag==="--full"||provenance?.canonical_include_modes.includes("full")===true}function canonicalReadOutputOptionsUsed(resolvedByDimension,provenance){return PM_READ_OUTPUT_DIMENSIONS.flatMap(dimension=>resolvedByDimension[dimension]?.source==="canonical"||dimension==="include"&&(provenance?.canonical_include_modes.length??0)>0?[CANONICAL_OPTIONS[dimension]]:[])}function resolveReadOutputDimensions(command,options){const normalizedCommand=resolveReadOutputSurface(command,options);if(!normalizedCommand)return void 0;const contract=SURFACE_CONTRACT_BY_COMMAND.get(normalizedCommand);const invocationProvenance=options[READ_OUTPUT_INVOCATION_PROVENANCE];const legacyResolvers={include:candidate=>resolveIncludeValue(void 0,candidate),amount:candidate=>resolveAmountValue(void 0,candidate),cost:candidate=>resolveCostValue(void 0,candidate),encoding:candidate=>resolveEncodingValue(void 0,candidate)};const legacyByDimension=Object.fromEntries(PM_READ_OUTPUT_DIMENSIONS.map(dimension=>[dimension,resolveLegacyDimension(contract.dimensions[dimension],options,candidate=>legacyResolvers[dimension](candidate)!==void 0,flag=>shouldIgnoreReadOutputLegacyAlias(invocationProvenance,dimension,flag))]));const legacyAliasesUsed=PM_READ_OUTPUT_DIMENSIONS.flatMap(dimension=>{const resolved=legacyByDimension[dimension];return resolved?[resolved.flag]:[]});const migrationHints=PM_READ_OUTPUT_DIMENSIONS.flatMap(dimension=>{const resolved=legacyByDimension[dimension];if(!resolved)return[];const alias=contract.dimensions[dimension].legacy_aliases.find(entry=>entry.flag===resolved.flag);return[alias.migration_hint]});const encoding=resolveEncodingValue(options.outputFormat??options.output_format,legacyByDimension.encoding);const include=resolveIncludeValue(options.outputInclude??options.output_include,legacyByDimension.include);const amount=resolveAmountValue(options.outputLimit??options.output_limit,legacyByDimension.amount);const explicitCost=resolveCostValue(options.outputBudget??options.output_budget,legacyByDimension.cost);const completeResultIntent=hasCompleteReadOutputIntent(command,legacyByDimension,invocationProvenance);const budget=resolvePmCommandOutputBudget(command,{generateFallback:true});const resolvedOutputFormat=encoding?.value==="json"||options.resolvedOutputFormat==="json"?"json":"toon";const cost=explicitCost??(completeResultIntent?{source:"intent",value:"unbounded"}:{source:"default",value:budget.default_max_estimated_tokens_by_format[resolvedOutputFormat]});const resolvedByDimension={include,amount,cost,encoding};return{command:normalizedCommand,include,amount,cost,encoding,canonical_options_used:canonicalReadOutputOptionsUsed(resolvedByDimension,invocationProvenance),legacy_aliases_used:legacyAliasesUsed,migration_hints:migrationHints,precedence:READ_OUTPUT_PRECEDENCE}}function isRecord(value){return value!==null&&typeof value==="object"&&!Array.isArray(value)}const ENVELOPE_KEYS=new Set(["applied_bound","applied_limit","completeness","continuation_kind","continuation_path","continuation_contract","count","filters","has_more","next_cursor","now","omission_receipt","projection","budget_retention_policy","row_contract","sorting","total","truncated"]);const GET_STABLE_DERIVED_ITEM_SELECTORS=["collection_counts","notes_count","tests_count"];function projectRecordFields(value,selectors){const selected=new Set(selectors.map(selector=>selector.split(".")[0]));return Object.fromEntries(Object.entries(value).filter(([key])=>selected.has(key)))}function getProjectionVocabulary(result){const item=isRecord(result.item)?result.item:{};const itemFields=[...new Set([...Object.keys(item),...GET_STABLE_DERIVED_ITEM_SELECTORS.filter(key=>Object.hasOwn(item,key))])].sort((left,right)=>left.localeCompare(right));const sections=Object.keys(result).filter(key=>key!=="item"&&key!=="read_output"&&!ENVELOPE_KEYS.has(key)).sort((left,right)=>left.localeCompare(right));return{item,itemFields,sections,valid:[...itemFields,"item",...itemFields.map(field=>`item.${field}`),...sections]}}function applyGetIncludeProjection(result,selectors){const vocabulary=getProjectionVocabulary(result);const unknown=selectors.filter(selector=>!vocabulary.valid.includes(selector));if(unknown.length>0){throw new PmCliError(`Unknown --output-include selector(s) for get: ${unknown.join(", ")}. Valid selectors: ${vocabulary.valid.join(", ")}.`,EXIT_CODE.USAGE)}const fullItem=selectors.includes("item");const itemSelectors=selectors.flatMap(selector=>selector.startsWith("item.")?[selector.slice("item.".length)]:vocabulary.itemFields.includes(selector)?[selector]:[]).filter((selector,index,values)=>values.indexOf(selector)===index);if(fullItem&&itemSelectors.length>0){throw new PmCliError("--output-include cannot mix a full item with projected item fields; use item or item.<field>, not both.",EXIT_CODE.USAGE)}const selectedSections=new Set(selectors.filter(selector=>vocabulary.sections.includes(selector)));const projected=Object.fromEntries(Object.entries(result).filter(([key])=>ENVELOPE_KEYS.has(key)||selectedSections.has(key)));if(fullItem){projected.item=vocabulary.item}else if(itemSelectors.length>0){projected.item=projectRecordFields(vocabulary.item,itemSelectors)}const omittedFieldGroups=[...fullItem?[]:itemSelectors.length>0?vocabulary.itemFields.filter(field=>!itemSelectors.includes(field)).map(field=>({name:`item.${field}`,restore_with:`--output-include item.${field}`})):[{name:"item",restore_with:"--output-include item"}],...vocabulary.sections.filter(section=>!selectedSections.has(section)).map(section=>({name:section,restore_with:`--output-include ${section}`}))];const inheritedOmittedFieldGroups=isRecord(projected.omission_receipt)&&Array.isArray(projected.omission_receipt.omitted_field_groups)?projected.omission_receipt.omitted_field_groups:[];const combinedOmittedFieldGroups=[...inheritedOmittedFieldGroups,...omittedFieldGroups];projected.omission_receipt={has_omissions:combinedOmittedFieldGroups.length>0,omitted_field_group_count:combinedOmittedFieldGroups.length,omitted_field_groups:combinedOmittedFieldGroups};return projected}function countPopulatedRows(result){let populated=0;mapReadOutputRows({...result},entry=>{if(isRecord(entry)&&Object.keys(entry).length>0)populated+=1;return entry});return populated}function rejectEmptyIncludeProjection(command,original,shaped,selectors){if(countPopulatedRows(original)===0||countPopulatedRows(shaped)>0){return}const modes=[...readOutputIncludeModeOptions(command).keys()];const domain=modes.length>0?` Declared ${command} projection modes: ${modes.join(", ")}.`:` The ${command} surface declares no projection modes; name row fields instead.`;throw new PmCliError(`Unknown --output-include selector(s) for ${command}: ${selectors.join(", ")}. No selector matched any returned row field.${domain}`,EXIT_CODE.USAGE)}function applyIncludeProjection(command,result,selectors){if(command==="get"){return applyGetIncludeProjection(result,selectors)}const rows=readOutputRowPaths(result);const qualifiedRowSelectors=selectors.flatMap(selector=>rows.flatMap(rowPath=>selector.startsWith(`${rowPath}.`)?[selector.slice(rowPath.length+1)]:[]));const selectedRoot=selectors.some(selector=>Object.hasOwn(result,selector.split(".")[0])&&!rows.some(rowPath=>selector.startsWith(`${rowPath}.`)));if(rows.length>0&&(!selectedRoot||qualifiedRowSelectors.length>0)){const projected={...result};const rowSelectors=qualifiedRowSelectors.length>0?qualifiedRowSelectors:selectors;const shaped=mapReadOutputRows(projected,entry=>isRecord(entry)?projectRecordFields(entry,rowSelectors):entry);rejectEmptyIncludeProjection(command,result,shaped,rowSelectors);return shaped}return Object.fromEntries(Object.entries(result).filter(([key])=>selectors.some(selector=>selector.split(".")[0]===key)||ENVELOPE_KEYS.has(key)))}function applyAmountBound(result,amount){if(amount==="unbounded")return result;const{result:bounded,truncated}=boundReadOutputRows(result,amount);if(!truncated)return bounded;bounded.has_more=true;bounded.truncated=true;if(typeof bounded.count==="number"){bounded.count=countReadOutputRows(bounded)}bounded.applied_bound={kind:"output_limit",source:"explicit",value:amount};return bounded}function requestedDimensions(resolved){return PM_READ_OUTPUT_DIMENSIONS.filter(dimension=>resolved[dimension]!==void 0&&resolved[dimension]?.source!=="default"||resolved.canonical_options_used.includes(CANONICAL_OPTIONS[dimension]))}function readOutputMeasurementFormat(options){const format=options.resolvedOutputFormat??options.outputFormat??options.output_format??options.format;return format==="json"||format==="toon"?format:void 0}function attachReadOutputSessionContracts(result,state,receipt,format){let withSession=attachReadOutputSessionReceipt(result,state,format);for(let iteration=0;iteration<8;iteration+=1){const previousReadEstimate=receipt.estimated_tokens;const previousSessionEstimate=withSession.read_session.spent_this_call_tokens;updateReadOutputReceiptEstimate(withSession,receipt,format);withSession=attachReadOutputSessionReceipt(withSession,state,format);const sessionEstimate=withSession.read_session.spent_this_call_tokens;if(receipt.estimated_tokens===previousReadEstimate&&sessionEstimate===previousSessionEstimate){return withSession}}return withSession}function stabilizeReadOutputReceiptEstimates(result,options){if(!isRecord(result.read_output))return result;const format=readOutputMeasurementFormat(options);const receipt=result.read_output;const session=parseReadOutputSession(options.outputSession??options.output_session);if(session===void 0){updateReadOutputReceiptEstimate(result,receipt,format);return result}return attachReadOutputSessionContracts(result,session,receipt,format)}function attachValidateDiagnosticRowContract(command,result){if(command!=="validate")return result;const projection=isRecord(result.projection)?result.projection:void 0;const declaredFieldGroups=Array.isArray(projection?.declared_field_groups)?projection.declared_field_groups:[];if(!declaredFieldGroups.some(group=>isRecord(group)&&group.name==="diagnostic_rows")){return result}const diagnosticCollectionPaths=[...new Set(readOutputBudgetCollections(result).map(({path})=>path).filter(path=>/^checks\.\d+\.details\./u.test(path)))];const diagnosticRowKeys=diagnosticCollectionPaths.filter(path=>!diagnosticCollectionPaths.some(candidate=>candidate!==path&&path.startsWith(`${candidate}.`)));if(diagnosticRowKeys.length===0)return result;const existingContract=isRecord(result.row_contract)?result.row_contract:{};const existingRowKeys=Array.isArray(existingContract.row_keys)?existingContract.row_keys.filter(entry=>typeof entry==="string"):[];const existingContinuationRowKeys=Array.isArray(existingContract.continuation_row_keys)?existingContract.continuation_row_keys.filter(entry=>typeof entry==="string"):[];const rowKeys=existingRowKeys.length>0?existingRowKeys:diagnosticRowKeys;const continuationRowKeys=[...new Set(diagnosticRowKeys)];return JSON.stringify(rowKeys)===JSON.stringify(existingRowKeys)&&JSON.stringify(continuationRowKeys)===JSON.stringify(existingContinuationRowKeys)?result:{...result,row_contract:{...existingContract,row_keys:rowKeys,continuation_row_keys:continuationRowKeys,jq_selector:typeof existingContract.jq_selector==="string"?existingContract.jq_selector:".checks[].details"}}}function projectReadOutputRows(result,resolved,session,cursor){let projected={...result};if(resolved.include?.source==="canonical"){projected=applyIncludeProjection(resolved.command,projected,resolved.include.value)}if(resolved.command==="assurance"){projected=prioritizeAssuranceAssertions(projected)}projected=applyReadOutputContinuation(projected,resolved.command,cursor);if(resolved.amount?.source==="canonical"){projected=applyAmountBound(projected,resolved.amount.value)}return session===void 0?projected:applyReadOutputSessionReferences(projected,session)}function resolveBindingReadOutputBudget(resolved,session){const budgets=[...resolved.cost!==void 0&&resolved.cost.value!=="unbounded"&&(resolved.cost.source==="canonical"||resolved.cost.source==="default")?[{source:resolved.cost.source,tokens:resolved.cost.value}]:[],...session===void 0?[]:[{source:"session",tokens:readOutputSessionRemainingTokens(session)}]];return budgets.sort((left,right)=>left.tokens-right.tokens)[0]}function canonicalReadOutputReceiptFields(resolved){const canonicalOptions=resolved.canonical_options_used;return canonicalOptions&&canonicalOptions.length>0?{canonical_options_used:canonicalOptions}:{}}function omitReadOutputForBudget(resolved,requested,session,bindingBudget,omittedResultEstimatedTokens,format){const minimalReceipt={contract_version:1,command:resolved.command,requested_dimensions:requested,...bindingBudget.source==="default"?{budget_source:bindingBudget.source,budget_tokens:bindingBudget.tokens}:{},precedence:resolved.precedence,...canonicalReadOutputReceiptFields(resolved),legacy_aliases_used:[],migration_hints:[],estimated_tokens:0,within_budget:false,strings_compacted:false,rows_compacted:false,result_omitted:true,...session===void 0?{omitted_result_estimated_tokens:omittedResultEstimatedTokens}:{}};const omitted={output_budget_exceeded:{omitted_result:true,reason:"requested_budget_infeasible",restore_with:"Unbounded",recovery:{outputBudget:"unbounded"}},read_output:minimalReceipt};const boundedOmission=session===void 0?omitted:attachReadOutputSessionContracts(omitted,session,minimalReceipt,format);if(session===void 0){updateReadOutputReceiptEstimate(boundedOmission,minimalReceipt,format)}if(session!==void 0&&minimalReceipt.estimated_tokens>bindingBudget.tokens){throw new PmCliError("The remaining output-session budget cannot fit its mandatory receipts; start a new session with a larger token_budget.",EXIT_CODE.USAGE)}return boundedOmission}function canReturnReadOutputUnchanged(resolved,session,result,format){if(session!==void 0)return false;const canonicalRequestedCount=resolved.canonical_options_used.length;if(resolved.cost?.value==="unbounded"){return canonicalRequestedCount===(resolved.cost.source==="canonical"?1:0)}if(resolved.cost?.source==="legacy"&&canonicalRequestedCount===0){return true}return canonicalRequestedCount===0&&(resolved.cost===void 0||estimateReadOutputTokens(result,format)<=resolved.cost.value)}function attachReadOutputTruncationDisclosure(projected,resolved,receipt,bindingBudget,continuationCursorRebased,measuredResultTokens,collectionsBeforeBudget){if(!receipt.rows_compacted)return;const overridden=resolved.amount?.value==="unbounded"?["amount"]:[];const afterByPath=new Map(readOutputContinuationRowCollections(projected).map(collection=>[collection.path,Array.isArray(collection.value)?collection.value.length:Object.keys(collection.value).length]));const continuations=[...collectionsBeforeBudget.entries()].flatMap(([path,before])=>{const retainedRows=afterByPath.get(path);if(retainedRows>=before.rows)return[];const offset=before.baseOffset+retainedRows;return[{path,cursor:encodeReadOutputContinuationCursor({command:resolved.command,path,offset,total_rows:before.totalRows,fingerprint:before.fingerprint}),retained_rows:retainedRows,remaining_rows:before.totalRows-offset,total_rows:before.totalRows}]});const primary=continuations[0];const continuationHint=primary?"; page --output-cursor":"";const budgetHint=bindingBudget.source==="session"?`Truncated by the remaining ${bindingBudget.tokens}-token session budget; start a new output session with a larger token_budget${continuationHint}.`:`${bindingBudget.tokens}-token: raise --output-budget${continuationHint}`;receipt.migration_hints=[budgetHint,...resolved.migration_hints];const recoveryBudget=resolveReadOutputRecoveryBudget({effective_budget_tokens:bindingBudget.tokens,measured_result_tokens:measuredResultTokens});if(primary&&typeof projected.next_cursor!=="string"){projected.next_cursor=primary.cursor}projected.continuation_kind=continuationCursorRebased?"producer_cursor":primary?"output_cursor":"none";projected.output_budget_truncation={reason:"output_budget_reached",budget_source:bindingBudget.source,budget_tokens:bindingBudget.tokens,overridden_dimensions:overridden,compacted_row_paths:receipt.compacted_row_paths,continuation_cursor_rebased:continuationCursorRebased,continuation_available:continuations.length>0,recovery_budget_multiplier:primary?1:recoveryBudget.recovery_budget_multiplier,continuations,restore_with:primary?"recovery":`Retry with --output-budget ${recoveryBudget.output_budget} because no declared row collection can be continued.`,recovery:primary?{cursor:primary.cursor,cli:"--output-cursor",sdk:"outputCursor",mcp:"outputCursor"}:{cli:`--output-budget ${recoveryBudget.output_budget}`,sdk:{outputBudget:recoveryBudget.output_budget},mcp:{outputBudget:recoveryBudget.output_budget}}}}function rebaseBudgetCompactedCursor(projected,originalItemCount,cursorSource,cursorContinuesExistingPage){if(typeof cursorSource!=="string"||!Array.isArray(projected.items)){return false}const retainedCount=projected.items.length;if(retainedCount===0||retainedCount>=originalItemCount){return false}let cursor;try{cursor=decodeQueryCursorEnvelope(cursorSource)}catch{return false}const sourceIndex=cursor.after_index;if(sourceIndex===void 0)return false;const last=projected.items.at(-1);if(Object.prototype.toString.call(last)!=="[object Object]"){return false}const lastId=Reflect.get(last,"id");if(typeof lastId!=="string"||lastId.length===0)return false;const afterIndex=cursorContinuesExistingPage?sourceIndex-(originalItemCount-retainedCount):sourceIndex+retainedCount;if(afterIndex<0)return false;projected.next_cursor=encodeQueryCursor(cursor.fingerprint,lastId,afterIndex,cursor.snapshot);if(typeof projected.applied_limit==="number"){projected.applied_limit=retainedCount}return true}function captureReadOutputContinuationState(projected,command,cursor,options){const collectionsBeforeBudget=new Map(readOutputContinuationRowCollections(projected).map(collection=>{const rows=Array.isArray(collection.value)?collection.value.length:Object.keys(collection.value).length;const continued=cursor?.path===collection.path;return[collection.path,{rows,totalRows:continued?cursor.total_rows:rows,baseOffset:continued?cursor.offset:0,fingerprint:continued?cursor.fingerprint:readOutputCollectionFingerprint(collection.path,collection.value,command)}]}));const cursorContinuesExistingPage=typeof projected.next_cursor==="string";return{collectionsBeforeBudget,originalItemCount:Array.isArray(projected.items)?projected.items.length:0,cursorContinuesExistingPage,cursorSource:cursorContinuesExistingPage?projected.next_cursor:options.after}}function compactReadOutputProjection(projected,resolved,receipt,bindingBudget,session,continuationState,measuredResultTokens,format){const assuranceMinimumRows=resolved.command==="assurance"&&Array.isArray(projected.assertions)?projected.assertions.filter(row=>isRecord(row)&&row.verdict!=="pass").length:0;let targetBudget=bindingBudget.tokens;let compacted=projected;for(let iteration=0;iteration<8;iteration+=1){compacted=compactReadOutputToBudget(projected,receipt,targetBudget,assuranceMinimumRows>0?new Map([["assertions",assuranceMinimumRows]]):new Map,format);const continuationCursorRebased=rebaseBudgetCompactedCursor(compacted,continuationState.originalItemCount,continuationState.cursorSource,continuationState.cursorContinuesExistingPage);attachReadOutputTruncationDisclosure(compacted,resolved,receipt,bindingBudget,continuationCursorRebased,measuredResultTokens,continuationState.collectionsBeforeBudget);if(session!==void 0){compacted=attachReadOutputSessionContracts(compacted,session,receipt,format)}updateReadOutputReceiptEstimate(compacted,receipt,format);const overrun=receipt.estimated_tokens-bindingBudget.tokens;if(overrun<=0||targetBudget<=0)return compacted;targetBudget=Math.max(0,targetBudget-overrun)}return compacted}function applyReadOutputDimensions(command,options,result){const resolved=resolveReadOutputDimensions(command,options);if(!resolved)return result;const format=readOutputMeasurementFormat(options);const session=parseReadOutputSession(options.outputSession??options.output_session);const rawCursor=options.outputCursor??options.output_cursor;const cursor=typeof rawCursor==="string"?decodeReadOutputContinuationCursor(rawCursor):void 0;const requested=requestedDimensions(resolved);if(cursor===void 0&&canReturnReadOutputUnchanged(resolved,session,result,format)){return result}const continuationReadyResult=attachValidateDiagnosticRowContract(resolved.command,result);const bindingBudget=resolveBindingReadOutputBudget(resolved,session);let projected=projectReadOutputRows(continuationReadyResult,resolved,session,cursor);const continuationState=captureReadOutputContinuationState(projected,resolved.command,cursor,options);const receipt={contract_version:1,command:resolved.command,requested_dimensions:requested,...bindingBudget?.source==="default"?{budget_source:bindingBudget.source,budget_tokens:bindingBudget.tokens}:{},precedence:resolved.precedence,...canonicalReadOutputReceiptFields(resolved),legacy_aliases_used:resolved.legacy_aliases_used,migration_hints:resolved.migration_hints,estimated_tokens:0,within_budget:true,strings_compacted:false,rows_compacted:false,result_omitted:false};projected.read_output=receipt;projected=session===void 0?projected:attachReadOutputSessionContracts(projected,session,receipt,format);updateReadOutputReceiptEstimate(projected,receipt,format);if(bindingBudget!==void 0&&receipt.estimated_tokens>bindingBudget.tokens){const measuredResultTokens=receipt.estimated_tokens;projected=compactReadOutputProjection(projected,resolved,receipt,bindingBudget,session,continuationState,measuredResultTokens,format)}if(bindingBudget!==void 0&&receipt.estimated_tokens>bindingBudget.tokens){return omitReadOutputForBudget(resolved,requested,session,bindingBudget,receipt.estimated_tokens,format)}return projected}function isReadOutputBudgetExceeded(result){return isRecord(result)&&isRecord(result.output_budget_exceeded)&&result.output_budget_exceeded.omitted_result===true&&result.output_budget_exceeded.reason==="requested_budget_infeasible"}function resolveReadOutputEncoding(command,options){const encoding=resolveReadOutputDimensions(command,options)?.encoding;return encoding?.value==="json"||encoding?.value==="toon"?encoding.value:void 0}export{PM_READ_OUTPUT_COMPOSITION_OPTION_FLAGS,PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES,PM_READ_OUTPUT_DIMENSIONS,PM_READ_OUTPUT_OPTION_FLAGS,PM_READ_OUTPUT_SURFACES,PM_READ_OUTPUT_SURFACE_CONTRACTS,applyReadOutputDimensions,applyReadOutputIncludeModes,decodeReadOutputContinuationCursor2 as decodeReadOutputContinuationCursor,encodeReadOutputContinuationCursor2 as encodeReadOutputContinuationCursor,isReadOutputBudgetExceeded,normalizeReadOutputIncludeModeOptions,readOutputCollectionFingerprint2 as readOutputCollectionFingerprint,readOutputIncludeModeOptions,resolveReadOutputDimensions,resolveReadOutputEncoding,resolveReadOutputRecoveryBudget2 as resolveReadOutputRecoveryBudget,resolveReadOutputSurface,stabilizeReadOutputReceiptEstimates,validateReadOutputOptions};
|
|
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]="43055f93-73df-541f-b179-3cc67e4a1a03")}catch(e2){}})();import{resolvePmHistoryOperation}from"./cli-contracts/command-aliases.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{compactReadOutputToBudget,estimateReadOutputTokens,projectReadOutputItemToBrief,resolveReadOutputRecoveryBudget,updateReadOutputReceiptEstimate}from"./read-output-budget.js";import{resolveReadOutputRecoveryBudget as resolveReadOutputRecoveryBudget2}from"./read-output-budget.js";import{resolvePmCommandOutputBudget}from"./cli-contracts/agent-output-contracts.js";import{boundReadOutputRows,countReadOutputRows,mapReadOutputRows,readOutputBudgetCollections,readOutputContinuationRowCollections,readOutputRowPaths}from"./read-output-rows.js";import{applyReadOutputContinuation,decodeReadOutputContinuationCursor,encodeReadOutputContinuationCursor,prioritizeAssuranceAssertions,readOutputCollectionFingerprint}from"./read-output/continuation.js";import{decodeReadOutputContinuationCursor as decodeReadOutputContinuationCursor2,encodeReadOutputContinuationCursor as encodeReadOutputContinuationCursor2,PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES,readOutputCollectionFingerprint as readOutputCollectionFingerprint2}from"./read-output/continuation.js";import{applyReadOutputSessionReferences,attachReadOutputSessionReceipt,parseReadOutputSession,readOutputSessionRemainingTokens}from"./read-output-session.js";import{decodeQueryCursorEnvelope,encodeQueryCursor}from"./pagination.js";const PM_READ_OUTPUT_DIMENSIONS=["include","amount","cost","encoding"];const PM_READ_OUTPUT_SURFACES=["list","context","search","get","next","health","deps","graph","history","activity","validate","events","contracts","comments","notes","files","docs","stats","aggregate","duplicates","package-catalog","package-manage","comments-audit","assurance"];const READ_OUTPUT_PRECEDENCE=["canonical","legacy","intent","default"];const CANONICAL_OPTIONS={include:"--output-include",amount:"--output-limit",cost:"--output-budget",encoding:"--output-format"};const READ_OUTPUT_INVOCATION_PROVENANCE=Symbol.for("pm.readOutputInvocationProvenance");const PM_READ_OUTPUT_OPTION_FLAGS=Object.freeze(PM_READ_OUTPUT_DIMENSIONS.map(dimension=>CANONICAL_OPTIONS[dimension]));const PM_READ_OUTPUT_COMPOSITION_OPTION_FLAGS=Object.freeze(["--output-session","--output-cursor","--output-row-contract"]);const LEGACY_FLAGS_BY_COMMAND={list:{include:["--brief","--compact","--fields","--full"],amount:["--after","--limit","--no-truncate"],cost:["--token-budget"],encoding:["--format","--stream"]},context:{include:["--fields","--section"],amount:["--after","--depth","--limit"],cost:["--token-budget"],encoding:["--format"]},search:{include:["--compact","--fields","--full"],amount:["--after","--limit"],cost:["--token-budget"],encoding:["--format"]},get:{include:["--fields","--full"],amount:["--depth"],cost:["--token-budget"],encoding:["--format"]},next:{amount:["--blocked-limit","--limit"],cost:["--token-budget"],encoding:["--format"]},health:{include:["--brief","--check-only","--full","--summary"]},deps:{include:["--collapse","--full","--summary"],amount:["--edge-limit","--max-depth","--node-limit"],cost:["--token-budget"],encoding:["--format"]},graph:{include:["--full","--summary"],amount:["--after","--limit","--max-depth","--max-paths"]},history:{include:["--compact","--full"],amount:["--limit"],encoding:["--format"]},activity:{include:["--compact","--full"],amount:["--limit","--unbounded"],encoding:["--stream"]},validate:{include:["--counts","--full"]},events:{include:["--full"],amount:["--limit"],encoding:["--follow"]},contracts:{include:["--full","--summary"]},comments:{amount:["--limit"]},notes:{amount:["--limit"]},files:{amount:["--limit","--no-truncate","--offset"]},docs:{},stats:{},aggregate:{},duplicates:{amount:["--limit"]},"package-catalog":{},"package-manage":{},"comments-audit":{},assurance:{}};const VALUE_BEARING_INCLUDE_ALIASES=new Set(["--collapse","--fields","--section"]);const BEHAVIOR_PRESERVING_MIGRATION_HINTS=Object.freeze({"--after":"--after retains cursor-position semantics; use --output-limit <n> separately to bound returned rows.","--check-only":"--check-only retains health side-effect semantics; --output-include does not suppress vector refresh.","--collapse":"--collapse retains dependency grouping semantics; --output-include does not replace it.","--depth":"--depth retains traversal or detail-depth semantics; --output-limit does not replace it.","--follow":"--follow retains event-tail semantics; --output-format does not enable following.","--max-depth":"--max-depth retains graph traversal-depth semantics; --output-limit does not replace it.","--max-paths":"--max-paths retains graph path-search semantics; use --output-limit separately to bound returned rows.","--no-truncate":"--no-truncate is a compatibility alias; prefer --output-limit unbounded.","--offset":"--offset retains positional pagination semantics; use --output-limit separately to bound returned rows.","--stream":"--stream retains command streaming semantics; --output-format selects only static result encoding.","--unbounded":"--unbounded is a compatibility alias; prefer --output-limit unbounded."});function flagSelector(flag){return flag.slice(2).replaceAll("-","_")}function migrationHint(flag,dimension){const behaviorHint=BEHAVIOR_PRESERVING_MIGRATION_HINTS[flag];if(behaviorHint!==void 0)return behaviorHint;const suffix=dimension==="include"?VALUE_BEARING_INCLUDE_ALIASES.has(flag)?"<csv>":flagSelector(flag):dimension==="amount"?"<n>":dimension==="cost"?"<tokens>":"<toon|json>";return`${flag} is a compatibility alias; prefer ${CANONICAL_OPTIONS[dimension]} ${suffix}.`}function buildSurfaceContract(command){const legacy=LEGACY_FLAGS_BY_COMMAND[command];const dimensions=Object.freeze(Object.fromEntries(PM_READ_OUTPUT_DIMENSIONS.map(dimension=>[dimension,Object.freeze({dimension,canonical_option:CANONICAL_OPTIONS[dimension],applicable:true,inapplicable_reason:null,legacy_aliases:Object.freeze((legacy[dimension]??[]).map(flag=>Object.freeze({flag,semantics:BEHAVIOR_PRESERVING_MIGRATION_HINTS[flag]===void 0?"replacement":"behavior_preserving",migration_hint:migrationHint(flag,dimension),visibility:"hidden_alias"})))})])));return Object.freeze({command,dimensions,precedence:READ_OUTPUT_PRECEDENCE,budget_retention_policy:command==="assurance"?"verdict_priority":"ordered_prefix",projection_modes:Object.freeze([...readOutputIncludeModeOptions(command).keys()])})}const PM_READ_OUTPUT_SURFACE_CONTRACTS=Object.freeze(PM_READ_OUTPUT_SURFACES.map(buildSurfaceContract));const SURFACE_CONTRACT_BY_COMMAND=new Map(PM_READ_OUTPUT_SURFACE_CONTRACTS.map(contract=>[contract.command,contract]));function resolveReadOutputSurface(command,options={}){const normalizedCommand=resolvePmHistoryOperation(command.trim().toLowerCase());const packageMode=normalizedCommand==="package catalog"||normalizedCommand==="packages catalog"||normalizedCommand==="package-catalog"||(normalizedCommand==="package"||normalizedCommand==="packages"||normalizedCommand==="extension")&&(options.catalog===true||options.target==="catalog"||options.action==="catalog");const root=packageMode?"package-catalog":normalizedCommand==="package manage"||normalizedCommand==="package-manage"?"package-manage":normalizedCommand.split(" ")[0];const normalized=root.startsWith("list-")?"list":root==="ctx"?"context":root;return PM_READ_OUTPUT_SURFACES.includes(normalized)?normalized:void 0}const CANONICAL_OPTION_KEYS=["outputInclude","output_include","outputLimit","output_limit","outputBudget","output_budget","outputFormat","output_format","outputSession","output_session","outputCursor","output_cursor","outputRowContract","output_row_contract"];const HYBRID_READ_MUTATION_KEYS={comments:["add","body","stdin","file","edit","delete"],notes:["add","addJson","stdin","file","edit","delete"],files:["add","addGlob","remove","migrate","apply","note"],docs:["add","addGlob","remove","migrate","note"],"package-catalog":["activate","adopt","adoptAll","deactivate","doctor","init","install","manage","migrate","reload","scaffold","uninstall"]};function hasCanonicalReadOutputOptions(options){return CANONICAL_OPTION_KEYS.some(key=>options[key]!==void 0)}const READ_OUTPUT_VALUE_VALIDATORS=[{keys:["outputInclude","output_include"],valid:value=>stringList(value)!==void 0,message:"--output-include requires at least one comma-separated field or section."},{keys:["outputLimit","output_limit"],valid:value=>value==="unbounded"||positiveInteger(value)!==void 0,message:"--output-limit must be a positive integer or unbounded."},{keys:["outputBudget","output_budget"],valid:value=>value==="unbounded"||positiveInteger(value)!==void 0,message:"--output-budget must be a positive integer or unbounded."},{keys:["outputFormat","output_format"],valid:value=>value==="toon"||value==="json",message:"--output-format must be toon or json."},{keys:["outputSession","output_session"],valid:value=>{parseReadOutputSession(value);return true},message:"--output-session must be a valid session-state object."},{keys:["outputCursor","output_cursor"],valid:value=>typeof value==="string"&&value.trim().length>0,message:"--output-cursor requires a non-empty continuation cursor."}];function validateReadOutputOptions(command,options){if(!hasCanonicalReadOutputOptions(options))return;const normalizedCommand=resolveReadOutputSurface(command,options);if(!normalizedCommand){throw new PmCliError(`Universal output controls apply only to read commands; ${command||"this command"} is not a read surface.`,EXIT_CODE.USAGE)}if((HYBRID_READ_MUTATION_KEYS[normalizedCommand]??[]).some(key=>options[key]!==void 0&&options[key]!==false)){throw new PmCliError(`Universal output controls cannot be combined with a ${normalizedCommand} mutation.`,EXIT_CODE.USAGE)}for(const validator of READ_OUTPUT_VALUE_VALIDATORS){const value=validator.keys.map(key=>options[key]).find(entry=>entry!==void 0);if(value!==void 0&&!validator.valid(value)){throw new PmCliError(validator.message,EXIT_CODE.USAGE)}}}function readOutputIncludeModeOptions(command){const surface=resolveReadOutputSurface(command);if(!surface)return new Map;return new Map((LEGACY_FLAGS_BY_COMMAND[surface].include??[]).filter(flag=>!VALUE_BEARING_INCLUDE_ALIASES.has(flag)&&BEHAVIOR_PRESERVING_MIGRATION_HINTS[flag]===void 0).map(flag=>[flagSelector(flag),optionKey(flag)]))}function applyReadOutputIncludeModes(command,includeValue,commandOptions){const requested=stringList(includeValue)??[];const modeOptions=readOutputIncludeModeOptions(command);const selectors=[];const modes=[];const optionsWithProvenance=commandOptions;const existingProvenance=optionsWithProvenance[READ_OUTPUT_INVOCATION_PROVENANCE];const canonicalModes=new Set(existingProvenance?.canonical_include_modes??[]);const explicitLegacyAliases=new Set(existingProvenance?.explicit_legacy_aliases??[]);for(const token of requested){const option=modeOptions.get(token);if(option===void 0){selectors.push(token);continue}const legacyFlag=`--${token.replaceAll("_","-")}`;if(isRequestedOption(readOption(commandOptions,legacyFlag))){explicitLegacyAliases.add(legacyFlag)}commandOptions[option]=true;modes.push(token);canonicalModes.add(token)}const forwardedGetFieldSelectors=resolveReadOutputSurface(command)==="get"?selectors.filter(selector=>selector!=="item"):[];const forwardedGetFields=forwardedGetFieldSelectors.length>0;if(forwardedGetFields){commandOptions.fields=[...new Set([...stringList(commandOptions.fields)??[],...forwardedGetFieldSelectors])].join(",");canonicalModes.add("fields")}if(modes.length>0||forwardedGetFields){optionsWithProvenance[READ_OUTPUT_INVOCATION_PROVENANCE]={canonical_include_modes:[...canonicalModes],explicit_legacy_aliases:[...explicitLegacyAliases],...existingProvenance?.cli_invocation_observed===true?{cli_invocation_observed:true}:{}}}return{selectors,modes}}function normalizeReadOutputIncludeModeOptions(command,options){const include=options.outputInclude??options.output_include;if(include===void 0)return;const{selectors,modes}=applyReadOutputIncludeModes(command,include,options);if(modes.length===0)return;const residual=selectors.length>0?selectors.join(","):void 0;options.outputInclude=residual;if(Object.hasOwn(options,"output_include")){options.output_include=residual}}function optionKey(flag){return flag.slice(2).replace(/-([a-z])/gu,(_,character)=>character.toUpperCase())}function readOption(options,flag){const key=optionKey(flag);if(Object.hasOwn(options,key))return options[key];const snakeKey=flag.slice(2).replaceAll("-","_");if(Object.hasOwn(options,snakeKey))return options[snakeKey];if(flag==="--no-truncate"&&options.truncate===false)return true;return void 0}function isRequestedOption(value){return value!==void 0&&value!==false&&value!==null}function stringList(value){const values=Array.isArray(value)?value:[value];const normalized=values.flatMap(entry=>typeof entry==="string"?entry.split(","):[]).map(entry=>entry.trim()).filter(Boolean);return normalized.length>0?[...new Set(normalized)]:void 0}function positiveInteger(value){const parsed=typeof value==="number"?value:typeof value==="string"&&/^\d+$/u.test(value.trim())?Number(value):Number.NaN;return Number.isSafeInteger(parsed)&&parsed>0?parsed:void 0}function resolveLegacyDimension(contract,options,usable,ignore){for(const alias of contract.legacy_aliases){if(ignore(alias.flag))continue;const value=readOption(options,alias.flag);const candidate={value,flag:alias.flag};if(isRequestedOption(value)&&usable(candidate))return candidate}return void 0}function resolveIncludeValue(canonical,legacy){const canonicalList=stringList(canonical);if(canonicalList)return{source:"canonical",value:canonicalList};if(!legacy)return void 0;return{source:"legacy",value:stringList(legacy.value)??[flagSelector(legacy.flag)]}}function resolveAmountValue(canonical,legacy){if(canonical==="unbounded"){return{source:"canonical",value:"unbounded"}}const canonicalLimit=positiveInteger(canonical);if(canonicalLimit!==void 0){return{source:"canonical",value:canonicalLimit}}if(!legacy)return void 0;if(legacy.flag==="--no-truncate"||legacy.flag==="--unbounded"){return{source:"legacy",value:"unbounded"}}const legacyLimit=positiveInteger(legacy.value);return legacyLimit===void 0?void 0:{source:"legacy",value:legacyLimit}}function resolveCostValue(canonical,legacy){if(canonical==="unbounded"){return{source:"canonical",value:"unbounded"}}const canonicalBudget=positiveInteger(canonical);if(canonicalBudget!==void 0){return{source:"canonical",value:canonicalBudget}}if(!legacy)return void 0;const legacyBudget=positiveInteger(legacy.value);return legacyBudget===void 0?void 0:{source:"legacy",value:legacyBudget}}function resolveEncodingValue(canonical,legacy){if(canonical==="json"||canonical==="toon"){return{source:"canonical",value:canonical}}if(!legacy)return void 0;if(legacy.flag==="--stream"||legacy.flag==="--follow"){return{source:"legacy",value:"stream"}}return legacy.value==="json"||legacy.value==="toon"?{source:"legacy",value:legacy.value}:void 0}function shouldIgnoreReadOutputLegacyAlias(provenance,dimension,flag){if(!provenance)return false;const explicitLegacyAliases=new Set(provenance.explicit_legacy_aliases);if(provenance.cli_invocation_observed===true){return!explicitLegacyAliases.has(flag)}const forwardedIncludeAliases=new Set(provenance.canonical_include_modes.map(mode=>`--${mode.replaceAll("_","-")}`));return dimension==="include"&&forwardedIncludeAliases.has(flag)&&!explicitLegacyAliases.has(flag)}function hasCompleteReadOutputIntent(command,legacyByDimension,provenance){const root=command.trim().toLowerCase().replaceAll(/\s+/gu," ").split(" ")[0];return root==="list-all"||legacyByDimension.amount?.flag==="--no-truncate"||legacyByDimension.include?.flag==="--full"||provenance?.canonical_include_modes.includes("full")===true}function canonicalReadOutputOptionsUsed(resolvedByDimension,provenance){return PM_READ_OUTPUT_DIMENSIONS.flatMap(dimension=>resolvedByDimension[dimension]?.source==="canonical"||dimension==="include"&&(provenance?.canonical_include_modes.length??0)>0?[CANONICAL_OPTIONS[dimension]]:[])}function resolveReadOutputDimensions(command,options){const normalizedCommand=resolveReadOutputSurface(command,options);if(!normalizedCommand)return void 0;const contract=SURFACE_CONTRACT_BY_COMMAND.get(normalizedCommand);const invocationProvenance=options[READ_OUTPUT_INVOCATION_PROVENANCE];const legacyResolvers={include:candidate=>resolveIncludeValue(void 0,candidate),amount:candidate=>resolveAmountValue(void 0,candidate),cost:candidate=>resolveCostValue(void 0,candidate),encoding:candidate=>resolveEncodingValue(void 0,candidate)};const legacyByDimension=Object.fromEntries(PM_READ_OUTPUT_DIMENSIONS.map(dimension=>[dimension,resolveLegacyDimension(contract.dimensions[dimension],options,candidate=>legacyResolvers[dimension](candidate)!==void 0,flag=>shouldIgnoreReadOutputLegacyAlias(invocationProvenance,dimension,flag))]));const legacyAliasesUsed=PM_READ_OUTPUT_DIMENSIONS.flatMap(dimension=>{const resolved=legacyByDimension[dimension];return resolved?[resolved.flag]:[]});const migrationHints=PM_READ_OUTPUT_DIMENSIONS.flatMap(dimension=>{const resolved=legacyByDimension[dimension];if(!resolved)return[];const alias=contract.dimensions[dimension].legacy_aliases.find(entry=>entry.flag===resolved.flag);return[alias.migration_hint]});const encoding=resolveEncodingValue(options.outputFormat??options.output_format,legacyByDimension.encoding);const include=resolveIncludeValue(options.outputInclude??options.output_include,legacyByDimension.include);const amount=resolveAmountValue(options.outputLimit??options.output_limit,legacyByDimension.amount);const explicitCost=resolveCostValue(options.outputBudget??options.output_budget,legacyByDimension.cost);const completeResultIntent=hasCompleteReadOutputIntent(command,legacyByDimension,invocationProvenance);const budget=resolvePmCommandOutputBudget(command,{generateFallback:true});const resolvedOutputFormat=encoding?.value==="json"||options.resolvedOutputFormat==="json"?"json":"toon";const cost=explicitCost??(completeResultIntent?{source:"intent",value:"unbounded"}:{source:"default",value:budget.default_max_estimated_tokens_by_format[resolvedOutputFormat]});const resolvedByDimension={include,amount,cost,encoding};return{command:normalizedCommand,include,amount,cost,encoding,canonical_options_used:canonicalReadOutputOptionsUsed(resolvedByDimension,invocationProvenance),legacy_aliases_used:legacyAliasesUsed,migration_hints:migrationHints,precedence:READ_OUTPUT_PRECEDENCE}}function isRecord(value){return value!==null&&typeof value==="object"&&!Array.isArray(value)}const ENVELOPE_KEYS=new Set(["applied_bound","applied_limit","completeness","continuation_kind","continuation_path","continuation_contract","count","filters","has_more","next_cursor","now","omission_receipt","projection","budget_retention_policy","row_contract","sorting","total","truncated"]);const GET_STABLE_DERIVED_ITEM_SELECTORS=["collection_counts","notes_count","tests_count"];function projectRecordFields(value,selectors){const selected=new Set(selectors.map(selector=>selector.split(".")[0]));return Object.fromEntries(Object.entries(value).filter(([key])=>selected.has(key)))}function getProjectionVocabulary(result){const item=isRecord(result.item)?result.item:{};const itemFields=[...new Set([...Object.keys(item),...GET_STABLE_DERIVED_ITEM_SELECTORS.filter(key=>Object.hasOwn(item,key))])].sort((left,right)=>left.localeCompare(right));const sections=Object.keys(result).filter(key=>key!=="item"&&key!=="read_output"&&!ENVELOPE_KEYS.has(key)).sort((left,right)=>left.localeCompare(right));return{item,itemFields,sections,valid:[...itemFields,"item",...itemFields.map(field=>`item.${field}`),...sections]}}function applyGetIncludeProjection(result,selectors){const vocabulary=getProjectionVocabulary(result);const unknown=selectors.filter(selector=>!vocabulary.valid.includes(selector));if(unknown.length>0){throw new PmCliError(`Unknown --output-include selector(s) for get: ${unknown.join(", ")}. Valid selectors: ${vocabulary.valid.join(", ")}.`,EXIT_CODE.USAGE)}const fullItem=selectors.includes("item");const itemSelectors=selectors.flatMap(selector=>selector.startsWith("item.")?[selector.slice("item.".length)]:vocabulary.itemFields.includes(selector)?[selector]:[]).filter((selector,index,values)=>values.indexOf(selector)===index);if(fullItem&&itemSelectors.length>0){throw new PmCliError("--output-include cannot mix a full item with projected item fields; use item or item.<field>, not both.",EXIT_CODE.USAGE)}const selectedSections=new Set(selectors.filter(selector=>vocabulary.sections.includes(selector)));const projected=Object.fromEntries(Object.entries(result).filter(([key])=>ENVELOPE_KEYS.has(key)||selectedSections.has(key)));if(fullItem){projected.item=vocabulary.item}else if(itemSelectors.length>0){projected.item=projectRecordFields(vocabulary.item,itemSelectors)}const omittedFieldGroups=[...fullItem?[]:itemSelectors.length>0?vocabulary.itemFields.filter(field=>!itemSelectors.includes(field)).map(field=>({name:`item.${field}`,restore_with:`--output-include item.${field}`})):[{name:"item",restore_with:"--output-include item"}],...vocabulary.sections.filter(section=>!selectedSections.has(section)).map(section=>({name:section,restore_with:`--output-include ${section}`}))];const inheritedOmittedFieldGroups=isRecord(projected.omission_receipt)&&Array.isArray(projected.omission_receipt.omitted_field_groups)?projected.omission_receipt.omitted_field_groups:[];const combinedOmittedFieldGroups=[...inheritedOmittedFieldGroups,...omittedFieldGroups];projected.omission_receipt={has_omissions:combinedOmittedFieldGroups.length>0,omitted_field_group_count:combinedOmittedFieldGroups.length,omitted_field_groups:combinedOmittedFieldGroups};return projected}function countPopulatedRows(result){let populated=0;mapReadOutputRows({...result},entry=>{if(isRecord(entry)&&Object.keys(entry).length>0)populated+=1;return entry});return populated}function rejectEmptyIncludeProjection(command,original,shaped,selectors){if(countPopulatedRows(original)===0||countPopulatedRows(shaped)>0){return}const modes=[...readOutputIncludeModeOptions(command).keys()];const domain=modes.length>0?` Declared ${command} projection modes: ${modes.join(", ")}.`:` The ${command} surface declares no projection modes; name row fields instead.`;throw new PmCliError(`Unknown --output-include selector(s) for ${command}: ${selectors.join(", ")}. No selector matched any returned row field.${domain}`,EXIT_CODE.USAGE)}function applyIncludeProjection(command,result,selectors){if(command==="get"){return applyGetIncludeProjection(result,selectors)}const rows=readOutputRowPaths(result);const qualifiedRowSelectors=selectors.flatMap(selector=>rows.flatMap(rowPath=>selector.startsWith(`${rowPath}.`)?[selector.slice(rowPath.length+1)]:[]));const selectedRoot=selectors.some(selector=>Object.hasOwn(result,selector.split(".")[0])&&!rows.some(rowPath=>selector.startsWith(`${rowPath}.`)));if(rows.length>0&&(!selectedRoot||qualifiedRowSelectors.length>0)){const projected={...result};const rowSelectors=qualifiedRowSelectors.length>0?qualifiedRowSelectors:selectors;const shaped=mapReadOutputRows(projected,entry=>isRecord(entry)?projectRecordFields(entry,rowSelectors):entry);rejectEmptyIncludeProjection(command,result,shaped,rowSelectors);return shaped}return Object.fromEntries(Object.entries(result).filter(([key])=>selectors.some(selector=>selector.split(".")[0]===key)||ENVELOPE_KEYS.has(key)))}function applyAmountBound(result,amount){if(amount==="unbounded")return result;const{result:bounded,truncated}=boundReadOutputRows(result,amount);if(!truncated)return bounded;bounded.has_more=true;bounded.truncated=true;if(typeof bounded.count==="number"){bounded.count=countReadOutputRows(bounded)}bounded.applied_bound={kind:"output_limit",source:"explicit",value:amount};return bounded}function requestedDimensions(resolved){return PM_READ_OUTPUT_DIMENSIONS.filter(dimension=>resolved[dimension]!==void 0&&resolved[dimension]?.source!=="default"||resolved.canonical_options_used.includes(CANONICAL_OPTIONS[dimension]))}function readOutputMeasurementFormat(options){const format=options.resolvedOutputFormat??options.outputFormat??options.output_format??options.format;return format==="json"||format==="toon"?format:void 0}function attachReadOutputSessionContracts(result,state,receipt,format){let withSession=attachReadOutputSessionReceipt(result,state,format);for(let iteration=0;iteration<8;iteration+=1){const previousReadEstimate=receipt.estimated_tokens;const previousSessionEstimate=withSession.read_session.spent_this_call_tokens;updateReadOutputReceiptEstimate(withSession,receipt,format);withSession=attachReadOutputSessionReceipt(withSession,state,format);const sessionEstimate=withSession.read_session.spent_this_call_tokens;if(receipt.estimated_tokens===previousReadEstimate&&sessionEstimate===previousSessionEstimate){return withSession}}return withSession}function stabilizeReadOutputReceiptEstimates(result,options){if(!isRecord(result.read_output))return result;const format=readOutputMeasurementFormat(options);const receipt=result.read_output;const session=parseReadOutputSession(options.outputSession??options.output_session);if(session===void 0){updateReadOutputReceiptEstimate(result,receipt,format);return result}return attachReadOutputSessionContracts(result,session,receipt,format)}function attachValidateDiagnosticRowContract(command,result){if(command!=="validate")return result;const projection=isRecord(result.projection)?result.projection:void 0;const declaredFieldGroups=Array.isArray(projection?.declared_field_groups)?projection.declared_field_groups:[];if(!declaredFieldGroups.some(group=>isRecord(group)&&group.name==="diagnostic_rows")){return result}const diagnosticCollectionPaths=[...new Set(readOutputBudgetCollections(result).map(({path})=>path).filter(path=>/^checks\.\d+\.details\./u.test(path)))];const diagnosticRowKeys=diagnosticCollectionPaths.filter(path=>!diagnosticCollectionPaths.some(candidate=>candidate!==path&&path.startsWith(`${candidate}.`)));if(diagnosticRowKeys.length===0)return result;const existingContract=isRecord(result.row_contract)?result.row_contract:{};const existingRowKeys=Array.isArray(existingContract.row_keys)?existingContract.row_keys.filter(entry=>typeof entry==="string"):[];const existingContinuationRowKeys=Array.isArray(existingContract.continuation_row_keys)?existingContract.continuation_row_keys.filter(entry=>typeof entry==="string"):[];const rowKeys=existingRowKeys.length>0?existingRowKeys:diagnosticRowKeys;const continuationRowKeys=[...new Set(diagnosticRowKeys)];return JSON.stringify(rowKeys)===JSON.stringify(existingRowKeys)&&JSON.stringify(continuationRowKeys)===JSON.stringify(existingContinuationRowKeys)?result:{...result,row_contract:{...existingContract,row_keys:rowKeys,continuation_row_keys:continuationRowKeys,jq_selector:typeof existingContract.jq_selector==="string"?existingContract.jq_selector:".checks[].details"}}}function projectReadOutputRows(result,resolved,session,cursor){let projected={...result};if(resolved.include?.source==="canonical"){projected=applyIncludeProjection(resolved.command,projected,resolved.include.value)}if(resolved.command==="assurance"){projected=prioritizeAssuranceAssertions(projected)}projected=applyReadOutputContinuation(projected,resolved.command,cursor);if(resolved.amount?.source==="canonical"){projected=applyAmountBound(projected,resolved.amount.value)}return session===void 0?projected:applyReadOutputSessionReferences(projected,session)}function resolveBindingReadOutputBudget(resolved,session){const budgets=[...resolved.cost!==void 0&&resolved.cost.value!=="unbounded"&&(resolved.cost.source==="canonical"||resolved.cost.source==="default")?[{source:resolved.cost.source,tokens:resolved.cost.value}]:[],...session===void 0?[]:[{source:"session",tokens:readOutputSessionRemainingTokens(session)}]];return budgets.sort((left,right)=>left.tokens-right.tokens)[0]}function canonicalReadOutputReceiptFields(resolved){const canonicalOptions=resolved.canonical_options_used;return canonicalOptions&&canonicalOptions.length>0?{canonical_options_used:canonicalOptions}:{}}function omitReadOutputForBudget(resolved,requested,session,bindingBudget,omittedResultEstimatedTokens,format){const minimalReceipt={contract_version:1,command:resolved.command,requested_dimensions:requested,...bindingBudget.source==="default"?{budget_source:bindingBudget.source,budget_tokens:bindingBudget.tokens}:{},precedence:resolved.precedence,...canonicalReadOutputReceiptFields(resolved),legacy_aliases_used:[],migration_hints:[],estimated_tokens:0,within_budget:false,strings_compacted:false,rows_compacted:false,result_omitted:true,...session===void 0?{omitted_result_estimated_tokens:omittedResultEstimatedTokens}:{}};const omitted={output_budget_exceeded:{omitted_result:true,reason:"requested_budget_infeasible",restore_with:"Unbounded",recovery:{outputBudget:"unbounded"}},read_output:minimalReceipt};const boundedOmission=session===void 0?omitted:attachReadOutputSessionContracts(omitted,session,minimalReceipt,format);if(session===void 0){updateReadOutputReceiptEstimate(boundedOmission,minimalReceipt,format)}if(session!==void 0&&minimalReceipt.estimated_tokens>bindingBudget.tokens){throw new PmCliError("The remaining output-session budget cannot fit its mandatory receipts; start a new session with a larger token_budget.",EXIT_CODE.USAGE)}return boundedOmission}function canReturnReadOutputUnchanged(resolved,session,result,format){if(session!==void 0)return false;const canonicalRequestedCount=resolved.canonical_options_used.length;if(resolved.cost?.value==="unbounded"){return canonicalRequestedCount===(resolved.cost.source==="canonical"?1:0)}if(resolved.cost?.source==="legacy"&&canonicalRequestedCount===0){return true}return canonicalRequestedCount===0&&(resolved.cost===void 0||estimateReadOutputTokens(result,format)<=resolved.cost.value)}function attachReadOutputTruncationDisclosure(projected,resolved,receipt,bindingBudget,continuationCursorRebased,measuredResultTokens,collectionsBeforeBudget){if(!receipt.rows_compacted)return;const overridden=resolved.amount?.value==="unbounded"?["amount"]:[];const afterByPath=new Map(readOutputContinuationRowCollections(projected).map(collection=>[collection.path,Array.isArray(collection.value)?collection.value.length:Object.keys(collection.value).length]));const continuations=[...collectionsBeforeBudget.entries()].flatMap(([path,before])=>{const retainedRows=afterByPath.get(path);if(retainedRows>=before.rows)return[];const offset=before.baseOffset+retainedRows;return[{path,cursor:encodeReadOutputContinuationCursor({command:resolved.command,path,offset,total_rows:before.totalRows,fingerprint:before.fingerprint}),retained_rows:retainedRows,remaining_rows:before.totalRows-offset,total_rows:before.totalRows}]});const primary=continuations[0];const continuationHint=primary?"; page --output-cursor":"";const budgetHint=bindingBudget.source==="session"?`Truncated by the remaining ${bindingBudget.tokens}-token session budget; start a new output session with a larger token_budget${continuationHint}.`:`${bindingBudget.tokens}-token: raise --output-budget${continuationHint}`;receipt.migration_hints=[budgetHint,...resolved.migration_hints];const recoveryBudget=resolveReadOutputRecoveryBudget({effective_budget_tokens:bindingBudget.tokens,measured_result_tokens:measuredResultTokens});if(primary&&typeof projected.next_cursor!=="string"){projected.next_cursor=primary.cursor}projected.continuation_kind=continuationCursorRebased?"producer_cursor":primary?"output_cursor":"none";projected.output_budget_truncation={reason:"output_budget_reached",budget_source:bindingBudget.source,budget_tokens:bindingBudget.tokens,overridden_dimensions:overridden,compacted_row_paths:receipt.compacted_row_paths,continuation_cursor_rebased:continuationCursorRebased,continuation_available:continuations.length>0,recovery_budget_multiplier:primary?1:recoveryBudget.recovery_budget_multiplier,continuations,restore_with:primary?"recovery":`Retry with --output-budget ${recoveryBudget.output_budget} because no declared row collection can be continued.`,recovery:primary?{cursor:primary.cursor,cli:"--output-cursor",sdk:"outputCursor",mcp:"outputCursor"}:{cli:`--output-budget ${recoveryBudget.output_budget}`,sdk:{outputBudget:recoveryBudget.output_budget},mcp:{outputBudget:recoveryBudget.output_budget}}}}function rebaseBudgetCompactedCursor(projected,originalItemCount,cursorSource,cursorContinuesExistingPage){if(typeof cursorSource!=="string"||!Array.isArray(projected.items)){return false}const retainedCount=projected.items.length;if(retainedCount===0||retainedCount>=originalItemCount){return false}let cursor;try{cursor=decodeQueryCursorEnvelope(cursorSource)}catch{return false}const sourceIndex=cursor.after_index;if(sourceIndex===void 0)return false;const last=projected.items.at(-1);if(Object.prototype.toString.call(last)!=="[object Object]"){return false}const lastId=Reflect.get(last,"id");if(typeof lastId!=="string"||lastId.length===0)return false;const afterIndex=cursorContinuesExistingPage?sourceIndex-(originalItemCount-retainedCount):sourceIndex+retainedCount;if(afterIndex<0)return false;projected.next_cursor=encodeQueryCursor(cursor.fingerprint,lastId,afterIndex,cursor.snapshot);if(typeof projected.applied_limit==="number"){projected.applied_limit=retainedCount}return true}function captureReadOutputContinuationState(projected,command,cursor,options){const collectionsBeforeBudget=new Map(readOutputContinuationRowCollections(projected).map(collection=>{const rows=Array.isArray(collection.value)?collection.value.length:Object.keys(collection.value).length;const continued=cursor?.path===collection.path;return[collection.path,{rows,totalRows:continued?cursor.total_rows:rows,baseOffset:continued?cursor.offset:0,fingerprint:continued?cursor.fingerprint:readOutputCollectionFingerprint(collection.path,collection.value,command)}]}));const cursorContinuesExistingPage=typeof projected.next_cursor==="string";return{collectionsBeforeBudget,originalItemCount:Array.isArray(projected.items)?projected.items.length:0,cursorContinuesExistingPage,cursorSource:cursorContinuesExistingPage?projected.next_cursor:options.after}}function compactReadOutputProjection(projected,resolved,receipt,bindingBudget,session,continuationState,measuredResultTokens,format){const assuranceMinimumRows=resolved.command==="assurance"&&Array.isArray(projected.assertions)?projected.assertions.filter(row=>isRecord(row)&&row.verdict!=="pass").length:0;let targetBudget=bindingBudget.tokens;let compacted=projected;for(let iteration=0;iteration<8;iteration+=1){compacted=compactReadOutputToBudget(projected,receipt,targetBudget,assuranceMinimumRows>0?new Map([["assertions",assuranceMinimumRows]]):new Map,format);const continuationCursorRebased=rebaseBudgetCompactedCursor(compacted,continuationState.originalItemCount,continuationState.cursorSource,continuationState.cursorContinuesExistingPage);attachReadOutputTruncationDisclosure(compacted,resolved,receipt,bindingBudget,continuationCursorRebased,measuredResultTokens,continuationState.collectionsBeforeBudget);if(session!==void 0){compacted=attachReadOutputSessionContracts(compacted,session,receipt,format)}updateReadOutputReceiptEstimate(compacted,receipt,format);const overrun=receipt.estimated_tokens-bindingBudget.tokens;if(overrun<=0||targetBudget<=0)return compacted;targetBudget=Math.max(0,targetBudget-overrun)}return compacted}function applyReadOutputDimensions(command,options,result){const resolved=resolveReadOutputDimensions(command,options);if(!resolved)return result;const format=readOutputMeasurementFormat(options);const session=parseReadOutputSession(options.outputSession??options.output_session);const rawCursor=options.outputCursor??options.output_cursor;const cursor=typeof rawCursor==="string"?decodeReadOutputContinuationCursor(rawCursor):void 0;const requested=requestedDimensions(resolved);if(cursor===void 0&&canReturnReadOutputUnchanged(resolved,session,result,format)){return result}const continuationReadyResult=attachValidateDiagnosticRowContract(resolved.command,result);const bindingBudget=resolveBindingReadOutputBudget(resolved,session);let projected=projectReadOutputRows(continuationReadyResult,resolved,session,cursor);const receipt={contract_version:1,command:resolved.command,requested_dimensions:requested,...bindingBudget?.source==="default"?{budget_source:bindingBudget.source,budget_tokens:bindingBudget.tokens}:{},precedence:resolved.precedence,...canonicalReadOutputReceiptFields(resolved),legacy_aliases_used:resolved.legacy_aliases_used,migration_hints:resolved.migration_hints,estimated_tokens:0,within_budget:true,strings_compacted:false,rows_compacted:false,result_omitted:false};projected.read_output=receipt;projected=session===void 0?projected:attachReadOutputSessionContracts(projected,session,receipt,format);updateReadOutputReceiptEstimate(projected,receipt,format);if(bindingBudget!==void 0&&receipt.estimated_tokens>bindingBudget.tokens){const brief=projectReadOutputItemToBrief(resolved.command,options,projected);if(brief!==void 0){receipt.applied_depth="brief";receipt.degradation_reason="output_budget_reached";projected=stabilizeReadOutputReceiptEstimates(brief,options)}if(receipt.estimated_tokens>bindingBudget.tokens){projected=compactReadOutputProjection(projected,resolved,receipt,bindingBudget,session,captureReadOutputContinuationState(projected,resolved.command,cursor,options),receipt.estimated_tokens,format)}}if(bindingBudget!==void 0&&receipt.estimated_tokens>bindingBudget.tokens){return omitReadOutputForBudget(resolved,requested,session,bindingBudget,receipt.estimated_tokens,format)}return projected}function isReadOutputBudgetExceeded(result){return isRecord(result)&&isRecord(result.output_budget_exceeded)&&result.output_budget_exceeded.omitted_result===true&&result.output_budget_exceeded.reason==="requested_budget_infeasible"}function resolveReadOutputEncoding(command,options){const encoding=resolveReadOutputDimensions(command,options)?.encoding;return encoding?.value==="json"||encoding?.value==="toon"?encoding.value:void 0}export{PM_READ_OUTPUT_COMPOSITION_OPTION_FLAGS,PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES,PM_READ_OUTPUT_DIMENSIONS,PM_READ_OUTPUT_OPTION_FLAGS,PM_READ_OUTPUT_SURFACES,PM_READ_OUTPUT_SURFACE_CONTRACTS,applyReadOutputDimensions,applyReadOutputIncludeModes,decodeReadOutputContinuationCursor2 as decodeReadOutputContinuationCursor,encodeReadOutputContinuationCursor2 as encodeReadOutputContinuationCursor,isReadOutputBudgetExceeded,normalizeReadOutputIncludeModeOptions,readOutputCollectionFingerprint2 as readOutputCollectionFingerprint,readOutputIncludeModeOptions,resolveReadOutputDimensions,resolveReadOutputEncoding,resolveReadOutputRecoveryBudget2 as resolveReadOutputRecoveryBudget,resolveReadOutputSurface,stabilizeReadOutputReceiptEstimates,validateReadOutputOptions};
|
|
2
2
|
//# sourceMappingURL=read-output-contracts.js.map
|
package/docs/MERGE_SAFETY.md
CHANGED
|
@@ -38,8 +38,13 @@ git commit -m "chore(pm): install tracker merge drivers"
|
|
|
38
38
|
|
|
39
39
|
`pm merge install` writes an idempotent, fenced `.gitattributes` block and repository-local `git config` entries. The attributes are committed; the driver commands are clone-local, so every collaborator and fresh CI clone that performs merges must run the install command.
|
|
40
40
|
|
|
41
|
-
The clone-local driver values record the absolute
|
|
42
|
-
`dist/cli.js` path resolved by the installing SDK.
|
|
41
|
+
The clone-local driver values record the absolute runtime launcher and bundled
|
|
42
|
+
`dist/cli.js` path resolved by the installing SDK. The installer preserves an
|
|
43
|
+
absolute PATH symlink when it resolves to the executing runtime, so a runtime
|
|
44
|
+
manager can retarget that launcher during upgrades without breaking every clone.
|
|
45
|
+
Relative PATH entries, inaccessible launchers, and different runtimes are ignored;
|
|
46
|
+
without a matching launcher, the installer retains the executing binary path.
|
|
47
|
+
Git therefore does not depend
|
|
43
48
|
on a bare `pm` command or the caller's later `PATH` when it merges tracker data.
|
|
44
49
|
The item-path placeholder is stored as bare `%P`: Git performs the required
|
|
45
50
|
shell quoting when it expands the placeholder. Receipt ingestion also removes
|
|
@@ -53,6 +58,9 @@ also accepted when its Node and `dist/cli.js` paths exist, its manifest owns the
|
|
|
53
58
|
copied worktrees and upgraded global installs healthy without accepting an
|
|
54
59
|
arbitrary executable. A missing, malformed, or semantically stale definition is
|
|
55
60
|
reported even when the committed attribute fence is correct.
|
|
61
|
+
Health and validation name `pm merge install` as the repair command for missing
|
|
62
|
+
or drifted drivers. This upgrade behavior is tracked by
|
|
63
|
+
[pm-rcjyft](../.agents/pm/issues/pm-rcjyft.toon).
|
|
56
64
|
|
|
57
65
|
The installer publishes the shared `.gitattributes` fence only after the clone-local driver commands are configured. If the repository Git config is read-only or another Git process holds its lock, the command returns the stable `merge_git_config_unwritable` error with recovery guidance and leaves an absent fence absent. Use `pm merge install --dry-run --json` to inspect the contract in intentionally read-only workspaces.
|
|
58
66
|
|
|
@@ -476,3 +484,6 @@ Only aged `committed` or `compensated` journals are removed. `applying`, `compen
|
|
|
476
484
|
## Temporary-clone acceptance test
|
|
477
485
|
|
|
478
486
|
Before releasing merge-contract changes, validate the packed package in a temporary Git repository: initialize pm, install the merge contract, create one base item, branch twice, append disjoint metadata/history on both branches, merge, and run the strict validation commands above. Include a same-key conflict case and prove Git leaves it unresolved while the output remains parseable.
|
|
487
|
+
|
|
488
|
+
The [packed first-run matrix](PACKED_FIRST_RUN.md) exercises the installed
|
|
489
|
+
README workflow, a real comment/history merge, and MCP on supported platforms.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Packed First-Run Acceptance
|
|
2
|
+
|
|
3
|
+
Tracked by [pm-ygli86](../.agents/pm/tasks/pm-ygli86.toon) and
|
|
4
|
+
[pm-rcjyft](../.agents/pm/issues/pm-rcjyft.toon).
|
|
5
|
+
|
|
6
|
+
The `Packed first run` CI matrix installs the same tarball globally into an
|
|
7
|
+
isolated npm prefix on Ubuntu, macOS, and Windows, using Node 22.18.0 and Node 24.
|
|
8
|
+
It executes the installed `pm` shim before passing the installed package directory
|
|
9
|
+
to the acceptance harness:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node scripts/release/packed-first-run.mjs /path/to/installed/@unbrained/pm-cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The harness extracts the first three commands from the installed README's
|
|
16
|
+
`60 Second Example` section. It executes `init`, `create`, and `list` in a
|
|
17
|
+
temporary Git workspace, requires nonempty output below 4,096 characters per
|
|
18
|
+
command, and checks that the created item was persisted. Missing sections,
|
|
19
|
+
reordered commands, unsupported shell expressions, and unbalanced quotes fail.
|
|
20
|
+
Arguments are passed directly to the installed CLI without a shell.
|
|
21
|
+
|
|
22
|
+
Two branches then append independent comments through that CLI. A real Git merge
|
|
23
|
+
must preserve both comments and their history. The installed reconciliation and
|
|
24
|
+
strict history verifier must succeed. The installed MCP server must complete an
|
|
25
|
+
initialize round trip and advertise the installed package version. An additional
|
|
26
|
+
mutation enables telemetry only against a loopback HTTP collector. The harness
|
|
27
|
+
waits for the detached worker's request and then verifies the physical queue is
|
|
28
|
+
empty and a successful flush is recorded. It removes inherited inline-flush and
|
|
29
|
+
test-runner overrides so this exercises the real detached process. Other commands
|
|
30
|
+
and MCP keep telemetry disabled; the install and workspace use isolated home
|
|
31
|
+
and global tracker directories.
|
|
32
|
+
|
|
33
|
+
MCP cleanup waits for process closure before removing its workspace. It allows
|
|
34
|
+
five seconds after SIGTERM, then sends SIGKILL and allows five more seconds. If
|
|
35
|
+
the child still does not close, the harness fails with captured diagnostics and
|
|
36
|
+
retains that workspace rather than attempting removal while it is in use.
|
|
37
|
+
|
|
38
|
+
The separate runtime-upgrade regression installs drivers through an absolute
|
|
39
|
+
runtime symlink, removes the original runtime directory, retargets the symlink,
|
|
40
|
+
and performs a real Git merge. It verifies the upgrade failure from GitHub #1248
|
|
41
|
+
without altering any developer runtime or repository.
|
|
42
|
+
|
|
43
|
+
This matrix proves the packed artifact's first-run behavior. Registry propagation,
|
|
44
|
+
npm/Bun installed agent sessions, npx/bunx execution, production telemetry, and
|
|
45
|
+
previous-release compatibility remain separate acceptance claims under the
|
|
46
|
+
[release workflow](RELEASING.md).
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -62,6 +62,22 @@ Use `pm init --type-preset agile|ops|research` when a fresh project should start
|
|
|
62
62
|
|
|
63
63
|
## Create Your First Item
|
|
64
64
|
|
|
65
|
+
For a scratch project, minimal governance is already the initialization default
|
|
66
|
+
([pm-z436](../.agents/pm/stories/pm-z436.toon)). The default init display shows
|
|
67
|
+
the selected tracker, policy, telemetry setting, and three next commands;
|
|
68
|
+
`--verbose` or `--json` restores the complete setup result.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pm init --yes --agent-guidance skip
|
|
72
|
+
pm config set governance-metadata-validation-profile custom
|
|
73
|
+
pm config set metadata-required-fields --criterion author --criterion close_reason
|
|
74
|
+
pm create Task "Understand the problem"
|
|
75
|
+
pm create Task "Implement the change"
|
|
76
|
+
pm create Task "Verify the result"
|
|
77
|
+
pm next
|
|
78
|
+
pm close <item-id> "Verified" --resolution "Implemented" --expected "Works" --actual "Verified"
|
|
79
|
+
```
|
|
80
|
+
|
|
65
81
|
Use strict create mode when all required fields are ready. Use progressive mode for staged triage.
|
|
66
82
|
|
|
67
83
|
```bash
|
|
@@ -71,6 +71,20 @@ example, `list` declares `brief`, `compact`, and `full`; `health` declares
|
|
|
71
71
|
includes `projection_modes` for every canonical read surface, including an
|
|
72
72
|
explicit empty array when a surface has no whole-result modes.
|
|
73
73
|
|
|
74
|
+
## Single-item detail fallback
|
|
75
|
+
|
|
76
|
+
Tracked by [pm-8eclqf](../.agents/pm/issues/pm-8eclqf.toon).
|
|
77
|
+
When a standard `get` exceeds its budget, the SDK first tries the declared
|
|
78
|
+
brief projection. It retains complete item metadata and dependencies while
|
|
79
|
+
omitting body, linked artifacts, claim history, and schedule details. The
|
|
80
|
+
receipt records `applied_depth: brief` and
|
|
81
|
+
`degradation_reason: output_budget_reached`; the omission receipt names the
|
|
82
|
+
removed sections and how to restore them. Explicit field selections, full/deep
|
|
83
|
+
reads, trees, and continuation requests keep their selected semantics.
|
|
84
|
+
If brief still exceeds the ceiling, normal compaction and eventual refusal
|
|
85
|
+
apply. `estimated_tokens` measures the emitted envelope;
|
|
86
|
+
`omitted_result_estimated_tokens` measures the useful result that could not fit.
|
|
87
|
+
|
|
74
88
|
## Cross-Call Context Sessions
|
|
75
89
|
|
|
76
90
|
`--output-session <json>` / `outputSession` composes the four per-call
|
|
@@ -4,12 +4,12 @@ Tracker: `pm-f05lsg`.
|
|
|
4
4
|
|
|
5
5
|
Every catalog code is listed. An `uncovered` row is an explicit closure obligation, never an omission or implied approval.
|
|
6
6
|
|
|
7
|
-
- Catalog error codes:
|
|
7
|
+
- Catalog error codes: 377
|
|
8
8
|
- Executable error codes: 19
|
|
9
9
|
- Executable-code ratchet floor: 18
|
|
10
10
|
- Required executable canonical codes: `bulk_ids_input_empty`, `bulk_ids_input_missing_path`, `bulk_ids_input_unreadable`, `invalid_argument_value`, `manifest_unknown_key`, `missing_lifecycle_target`, `missing_required_argument`, `no_version_bounds_declared`, `projection_options_mutually_exclusive`, `tracker_not_initialized`, `tracker_root_missing`, `tracker_root_not_directory`, `tracker_root_unreadable`, `unknown_context_intent`, `unknown_field_projection`, `unknown_option`, `unknown_subcommand`
|
|
11
|
-
- Uncovered error codes:
|
|
12
|
-
- Coverage fraction: 0.
|
|
11
|
+
- Uncovered error codes: 358
|
|
12
|
+
- Coverage fraction: 0.050398
|
|
13
13
|
- Closed-domain probes: 19
|
|
14
14
|
- Grammar probes: 113
|
|
15
15
|
|
|
@@ -196,6 +196,8 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
|
|
|
196
196
|
| `mcp_task_not_found_or_not_authorized` | `mcp_task_not_found_or_not_authorized` | uncovered | none | 0 |
|
|
197
197
|
| `merge_conflict_markers_detected` | `merge_conflict_markers_detected` | uncovered | none | 0 |
|
|
198
198
|
| `merge_decisions_unreviewed` | `merge_decisions_unreviewed` | uncovered | none | 0 |
|
|
199
|
+
| `merge_driver_configuration_drift` | `merge_driver_configuration_drift` | uncovered | none | 0 |
|
|
200
|
+
| `merge_driver_configuration_missing` | `merge_driver_configuration_missing` | uncovered | none | 0 |
|
|
199
201
|
| `merge_git_config_unwritable` | `merge_git_config_unwritable` | uncovered | none | 0 |
|
|
200
202
|
| `merge_receipt_evidence_invalid` | `merge_receipt_evidence_invalid` | uncovered | none | 0 |
|
|
201
203
|
| `merge_receipt_history_reference_missing` | `merge_receipt_history_reference_missing` | uncovered | none | 0 |
|
|
@@ -345,6 +347,7 @@ Every catalog code is listed. An `uncovered` row is an explicit closure obligati
|
|
|
345
347
|
| `validate_lifecycle_dependency_cycles_error` | `validate_lifecycle_dependency_cycles_error` | uncovered | none | 0 |
|
|
346
348
|
| `validate_lifecycle_stale_blockers` | `validate_lifecycle_stale_blockers` | uncovered | none | 0 |
|
|
347
349
|
| `validate_merge_decisions_unreviewed` | `validate_merge_decisions_unreviewed` | uncovered | none | 0 |
|
|
350
|
+
| `validate_merge_driver_configuration` | `validate_merge_driver_configuration` | uncovered | none | 0 |
|
|
348
351
|
| `validate_merge_fence_drift` | `validate_merge_fence_drift` | uncovered | none | 0 |
|
|
349
352
|
| `validate_metadata_custom_profile_missing_required_fields` | `validate_metadata_custom_profile_missing_required_fields` | uncovered | none | 0 |
|
|
350
353
|
| `validate_metadata_duplicate_issue_codes` | `validate_metadata_duplicate_issue_codes` | uncovered | none | 0 |
|
package/marketplace.json
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
|
|
9
|
-
"version": "2026.9.
|
|
9
|
+
"version": "2026.9.17"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "pm-claude",
|
|
14
14
|
"source": "./plugins/pm-claude",
|
|
15
15
|
"description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.",
|
|
16
|
-
"version": "2026.9.
|
|
16
|
+
"version": "2026.9.17",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "unbrained",
|
|
19
19
|
"url": "https://github.com/unbraind/pm-cli"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unbrained/pm-digital-twin",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.17",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Beyond-PM exemplar: a temporal production-facility digital twin built entirely on public pm SDK and extension primitives.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pm-claude",
|
|
3
3
|
"description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents (coordinator, delivery-chain, triage, verification), hybrid TUI task tracking (pm as persistent store + Claude Code task panel as live view), session context injection, and full git-based project management without leaving Claude Code.",
|
|
4
|
-
"version": "2026.9.
|
|
4
|
+
"version": "2026.9.17",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "unbrained",
|
|
7
7
|
"url": "https://github.com/unbraind/pm-cli"
|