@unbrained/pm-cli 2026.8.23 → 2026.8.25
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 +27 -1
- package/dist/cli/description-stdin.js +5 -4
- package/dist/cli/extension-command-help.d.ts +5 -0
- package/dist/cli/extension-command-help.js +6 -2
- package/dist/cli/help-content.d.ts +5 -0
- package/dist/cli/help-content.js +56 -3
- package/dist/cli/help-json-payload.d.ts +5 -2
- package/dist/cli/help-json-payload.js +57 -17
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.js +28 -3
- package/dist/cli/register-annotations.js +5 -5
- package/dist/cli/register-mutation.js +73 -27
- package/dist/cli-bundle/bundle-manifest.json +152 -152
- package/dist/cli-bundle/chunks/{chunk-HWZ6CELB.js → chunk-244MI4GS.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-QDVHNHAQ.js → chunk-2F3LUFMW.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-EG6CLDZT.js → chunk-5I5RWIJC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-KPH73XXJ.js → chunk-65MHLHAA.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-6C7GIMIL.js +13 -0
- package/dist/cli-bundle/chunks/chunk-OWHNAR2B.js +2 -0
- package/dist/cli-bundle/chunks/chunk-QKGMHGEI.js +202 -0
- package/dist/cli-bundle/chunks/chunk-QLUORNIB.js +2092 -0
- package/dist/cli-bundle/chunks/{chunk-JB4KZWBF.js → chunk-T2ENPRXF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-F3AI2JFL.js → chunk-TPQIBSL2.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-YQMYF3YD.js +35 -0
- package/dist/cli-bundle/chunks/{register-list-query-UJB5FMV2.js → register-list-query-XVN2ZLI7.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-QCKAEGIJ.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-RXIJIYXC.js → register-operations-SDEAXE7E.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-GFUZEKRE.js → register-setup-LXVBRCJ3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-QGFNI65N.js → chunk-2UIWOP3O.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-42S3GGZ7.js +50 -0
- package/dist/cli-bundle/focused-chunks/{chunk-OGLQBL46.js → chunk-7I23XGWO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-7YCDTCBC.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-OFVUGTLJ.js → chunk-A644DUFQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-AUFH5H35.js → chunk-GQR3WH3F.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-3UPTYG44.js → chunk-H5JZEIQV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-IBZZZGK3.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +5 -0
- package/dist/cli-bundle/focused-chunks/{chunk-LYVSW5VM.js → chunk-N7W67YIG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-37Z4OEAP.js → chunk-NOOZGIXP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-FZS4H32O.js → chunk-OHIHZ7HS.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-ONYQCALA.js +19 -0
- package/dist/cli-bundle/focused-chunks/chunk-OVJL6NZE.js +4 -0
- package/dist/cli-bundle/focused-chunks/chunk-RAFKLNZX.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-IFLWKY2R.js → chunk-VXWATRFL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-R27IDGHD.js → chunk-XUQPEKRN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-JOWDB2MH.js → chunk-YO3ZF3FI.js} +2 -2
- package/dist/cli-bundle/main.js +18 -17
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +32 -32
- 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 +32 -33
- 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 +6 -5
- package/dist/core/diagnostics/remediation.js +17 -2
- package/dist/core/extensions/command-metadata-contract.d.ts +10 -0
- package/dist/core/extensions/command-metadata-contract.js +23 -0
- package/dist/core/extensions/command-visibility-tier.js +12 -2
- package/dist/core/extensions/extension-types.d.ts +6 -0
- package/dist/core/extensions/extension-types.js +2 -2
- package/dist/core/extensions/loader.js +4 -3
- package/dist/core/io/body-file.js +7 -2
- package/dist/core/io/bulk-ids-input.d.ts +24 -0
- package/dist/core/io/bulk-ids-input.js +113 -0
- package/dist/core/item/parse.d.ts +22 -2
- package/dist/core/item/parse.js +97 -4
- package/dist/mcp/server.d.ts +3 -2
- package/dist/mcp/server.js +16 -9
- package/dist/sdk/agent/refusal-closure-census.d.ts +66 -0
- package/dist/sdk/agent/refusal-closure-census.js +144 -0
- package/dist/sdk/agent-capability-contracts.d.ts +34 -1
- package/dist/sdk/agent-capability-contracts.js +104 -6
- package/dist/sdk/annotations.d.ts +2 -0
- package/dist/sdk/annotations.js +25 -7
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +10 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +20 -3
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +38 -2
- package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +4 -1
- package/dist/sdk/cli-contracts/typed-action-inputs.js +2 -2
- package/dist/sdk/comments.js +15 -7
- package/dist/sdk/flag-invocation-contracts.d.ts +2 -0
- package/dist/sdk/flag-invocation-contracts.js +28 -3
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +109 -52
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +62 -2
- package/dist/sdk/governance/health.js +98 -11
- package/dist/sdk/governance/validate.js +15 -9
- package/dist/sdk/guide-topics.d.ts +0 -5
- package/dist/sdk/guide-topics.js +28 -2
- package/dist/sdk/history-compact.d.ts +2 -1
- package/dist/sdk/history-compact.js +24 -5
- package/dist/sdk/history-mcp.js +11 -10
- package/dist/sdk/history-repair.d.ts +24 -0
- package/dist/sdk/history-repair.js +145 -4
- package/dist/sdk/index.d.ts +1 -0
- package/dist/sdk/index.js +3 -2
- package/dist/sdk/item-transaction.js +19 -12
- package/dist/sdk/lifecycle/append.js +4 -4
- package/dist/sdk/lifecycle/close-many.js +16 -7
- package/dist/sdk/lifecycle/create.js +29 -21
- package/dist/sdk/lifecycle/plan.js +24 -6
- package/dist/sdk/lifecycle/update-many.js +15 -8
- package/dist/sdk/lifecycle/update.d.ts +2 -0
- package/dist/sdk/lifecycle/update.js +34 -24
- package/dist/sdk/merge/driver.js +25 -4
- package/dist/sdk/merge/receipt-file-boundary.d.ts +21 -0
- package/dist/sdk/merge/receipt-file-boundary.js +47 -0
- package/dist/sdk/merge/receipts.d.ts +24 -1
- package/dist/sdk/merge/receipts.js +342 -36
- package/dist/sdk/merge/reconcile.js +117 -47
- package/dist/sdk/read-output/continuation.d.ts +15 -2
- package/dist/sdk/read-output/continuation.js +86 -6
- package/dist/sdk/read-output-contracts.d.ts +4 -1
- package/dist/sdk/read-output-contracts.js +9 -6
- package/dist/sdk/runtime-extended-actions.js +5 -3
- package/dist/sdk/runtime-input.d.ts +4 -0
- package/dist/sdk/runtime-input.js +98 -23
- package/dist/sdk/runtime-primitives.d.ts +2 -1
- package/dist/sdk/runtime-primitives.js +4 -3
- package/dist/sdk/runtime.js +7 -20
- package/dist/sdk/scheduling-shortcuts.js +5 -3
- package/dist/sdk/structured-mutations.js +10 -3
- package/dist/sdk/workspace-contracts.d.ts +3 -0
- package/dist/sdk/workspace-contracts.js +3 -2
- package/docs/MERGE_SAFETY.md +34 -5
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +13 -1
- package/docs/README.md +2 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +25 -2
- package/docs/RELEASING.md +40 -21
- package/docs/SCRIPTING.md +62 -3
- package/docs/SDK.md +8 -0
- package/docs/generated/AGENT_CAPABILITY_ROUTING.md +17 -0
- package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +359 -0
- 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/README.md +9 -11
- package/packages/pm-command-kit/extensions/command-kit/index.ts +3 -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/extensions/guide-shell/index.ts +10 -0
- 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
- package/scripts/generate-agent-capability-surfaces.mjs +27 -1
- package/sdk/public-surface.json +351 -26
- package/dist/cli-bundle/chunks/chunk-3ENVHX6C.js +0 -36
- package/dist/cli-bundle/chunks/chunk-DW2CGEMU.js +0 -2
- package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +0 -201
- package/dist/cli-bundle/chunks/chunk-KXPMB2YL.js +0 -2092
- package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +0 -13
- package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-5S7E72FY.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-FQCSTBWE.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-OY7QAV4Y.js +0 -51
- package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +0 -5
- package/dist/cli-bundle/focused-chunks/chunk-ZHVA42R5.js +0 -18
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
* Implements the pm update many command surface and its agent-facing runtime behavior.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="fada7a33-ad1d-54f1-ae03-c5f8e4568d75")}catch(e){}}();
|
|
8
8
|
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
9
|
-
import { createCheckpointId, loadMutationCheckpoint, restoreCheckpointItems, writeMutationCheckpoint, toItemRecord, applyAcceptanceCriteriaMutations, applyTagRemovals, mergeAdditiveTags, parseOptionalNonNegativeInteger, parseTags, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, resolveItemTypeRegistry, resolveTypeName, collectRuntimeUpdateFieldValues, buildInvalidTypeError, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, toErrorMessage, stableValueEquals, nowIso, resolveIsoOrRelative, getActiveExtensionRegistrations, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
|
|
9
|
+
import { createCheckpointId, loadMutationCheckpoint, restoreCheckpointItems, writeMutationCheckpoint, toItemRecord, applyAcceptanceCriteriaMutations, applyTagRemovals, mergeAdditiveTags, parseOptionalNonNegativeInteger, parseTags, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, resolveItemTypeRegistry, resolveTypeName, collectRuntimeUpdateFieldValues, buildInvalidTypeError, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, toErrorMessage, stableValueEquals, nowIso, preserveMutationStdinTokenLiterals, resolveIsoOrRelative, getActiveExtensionRegistrations, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
|
|
10
10
|
import { assertDependencyTargetsResolvable } from "../dependency-flag-validation.js";
|
|
11
11
|
import { parseStatusFilterCsv } from "../../core/item/status-filter.js";
|
|
12
12
|
import { hasListFilters } from "../query/list-filter-shared.js";
|
|
13
13
|
import { runList, } from "../query/list.js";
|
|
14
14
|
import { runRestore } from "./restore.js";
|
|
15
|
-
import { assertUpdateMutationOptionCombinations, parseDependencyAdditions, runUpdate, } from "./update.js";
|
|
15
|
+
import { assertUpdateMutationOptionCombinations, parseDependencyAdditions, resolveUpdateTransportOptions, runUpdate, } from "./update.js";
|
|
16
16
|
import { derivePmBulkMutationEffect, } from "../cli-contracts/command-exit-contracts.js";
|
|
17
17
|
const UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION = 1;
|
|
18
18
|
const UPDATE_MANY_CHECKPOINT_SUBDIR = "update-many";
|
|
@@ -703,11 +703,12 @@ const applyUpdateManyRows = async (params) => {
|
|
|
703
703
|
continue;
|
|
704
704
|
}
|
|
705
705
|
try {
|
|
706
|
-
const
|
|
706
|
+
const rowUpdateOptions = preserveMutationStdinTokenLiterals({
|
|
707
707
|
...params.options.update,
|
|
708
708
|
message: updateMessage,
|
|
709
709
|
runtimeFieldCommands: ["update_many"],
|
|
710
|
-
}
|
|
710
|
+
});
|
|
711
|
+
const result = await runUpdate(item.id, rowUpdateOptions, params.global);
|
|
711
712
|
rows.push({
|
|
712
713
|
id: item.id,
|
|
713
714
|
status: "updated",
|
|
@@ -786,6 +787,12 @@ const applyUpdateManyPlan = async (params) => {
|
|
|
786
787
|
export const runUpdateMany = async (options, global) => {
|
|
787
788
|
const runtime = await loadUpdateManyRuntimeContext(global);
|
|
788
789
|
const rollbackId = typeof options.rollback === "string" ? options.rollback : undefined;
|
|
790
|
+
if (rollbackId === undefined) {
|
|
791
|
+
options = {
|
|
792
|
+
...options,
|
|
793
|
+
update: preserveMutationStdinTokenLiterals(await resolveUpdateTransportOptions(options.update)),
|
|
794
|
+
};
|
|
795
|
+
}
|
|
789
796
|
const updateSummary = sanitizeUpdateOptionsForSummary(options.update);
|
|
790
797
|
rejectBlankIdsFilter(options.list);
|
|
791
798
|
if (rollbackId !== undefined) {
|
|
@@ -797,8 +804,8 @@ export const runUpdateMany = async (options, global) => {
|
|
|
797
804
|
updateSummary,
|
|
798
805
|
});
|
|
799
806
|
}
|
|
800
|
-
if (!hasAnyUpdateMutationInput(options.update)) {
|
|
801
|
-
throw new PmCliError(`No update-many mutation flags provided. Add at least one mutation flag (for example: ${UPDATE_MANY_MUTATION_FLAG_GUIDANCE}).`, EXIT_CODE.USAGE);
|
|
807
|
+
if (!hasAnyUpdateMutationInput(options.update) && options.dryRun !== true) {
|
|
808
|
+
throw new PmCliError(`No update-many mutation flags provided. Add at least one mutation flag (for example: ${UPDATE_MANY_MUTATION_FLAG_GUIDANCE}), or pass --dry-run for a filter-only preview.`, EXIT_CODE.USAGE);
|
|
802
809
|
}
|
|
803
810
|
assertPlannedUpdateValuesValid(options.update, runtime.settings, runtime.statusRegistry, runtime.pmRoot);
|
|
804
811
|
assertUpdateMutationOptionCombinations(options.update);
|
|
@@ -852,4 +859,4 @@ export const _testOnlyUpdateManyCommand = {
|
|
|
852
859
|
toComparablePreviewValue,
|
|
853
860
|
};
|
|
854
861
|
//# sourceMappingURL=update-many.js.map
|
|
855
|
-
//# debugId=
|
|
862
|
+
//# debugId=fada7a33-ad1d-54f1-ae03-c5f8e4568d75
|
|
@@ -159,6 +159,8 @@ interface UpdateMutationContext {
|
|
|
159
159
|
author: string;
|
|
160
160
|
pmRoot: string;
|
|
161
161
|
}
|
|
162
|
+
/** Resolve update stdin tokens once while preserving transport-marked literals. */
|
|
163
|
+
export declare function resolveUpdateTransportOptions(options: UpdateCommandOptions): Promise<UpdateCommandOptions>;
|
|
162
164
|
/** Validate mutually exclusive and required update mutation option combinations. */
|
|
163
165
|
export declare function assertUpdateMutationOptionCombinations(options: UpdateCommandOptions): void;
|
|
164
166
|
type UpdateStatusMutationContext = Pick<UpdateMutationContext, "options" | "statusRegistry" | "clearItemMetadataKeys" | "nowIso">;
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Implements the pm update command surface and its agent-facing runtime behavior.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="6865ca88-7ca1-52fd-86fb-2a3439abeafa")}catch(e){}}();
|
|
8
8
|
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveMutationStdinTokenFields } from "../../core/item/parse.js";
|
|
10
|
+
import { COMMON_MUTATION_COMMAND_OPTION_KEYS, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, normalizeItemId, toItemRecord, buildInvalidTypeError, assertParentReferenceIsNotSelf, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, applyAcceptanceCriteriaMutations, applyTagRemovals, assertNoUnknownCsvKeys, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, shouldResolveMutationStdinTokens, transferMutationStdinTokenPolicy, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, isTerminalStatus, collectRuntimeUpdateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, describeAllowedTransitions, evaluateTransition, resolveTypeWorkflows, EXIT_CODE, PmCliError, stableValueEquals, resolveIsoOrRelative, getActiveExtensionRegistrations, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, buildItemNotFoundError, listAllItemMetadataLight, locateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
|
|
10
11
|
import { mutateItemWithHistoryContextResolver } from "../../core/store/item-store.js";
|
|
11
12
|
import { runClose } from "./close.js";
|
|
12
13
|
import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
|
|
@@ -108,7 +109,7 @@ function normalizeLegacyNoneUpdateOptions(options) {
|
|
|
108
109
|
normalized[optionKey] = undefined;
|
|
109
110
|
/* c8 ignore stop */
|
|
110
111
|
}
|
|
111
|
-
return applyLegacyNoneCollectionNormalizers(normalized, UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS);
|
|
112
|
+
return transferMutationStdinTokenPolicy(options, applyLegacyNoneCollectionNormalizers(normalized, UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS));
|
|
112
113
|
}
|
|
113
114
|
function parseUpdateUnsetTargets(raw, runtimeFieldRegistry, extensionFieldNames = []) {
|
|
114
115
|
return parseCommandUnsetTargets({
|
|
@@ -858,23 +859,31 @@ function applyUpdateScalarMutations(definitions, options, context) {
|
|
|
858
859
|
}
|
|
859
860
|
}
|
|
860
861
|
async function resolveStdinUpdateOptions(options) {
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
862
|
+
const scalarFields = [
|
|
863
|
+
["body", "--body"],
|
|
864
|
+
["description", "--description"],
|
|
865
|
+
];
|
|
866
|
+
const listFields = [
|
|
867
|
+
["dep", "--dep"],
|
|
868
|
+
["depRemove", "--dep-remove"],
|
|
869
|
+
["comment", "--comment"],
|
|
870
|
+
["note", "--note"],
|
|
871
|
+
["learning", "--learning"],
|
|
872
|
+
["file", "--file"],
|
|
873
|
+
["test", "--test"],
|
|
874
|
+
["doc", "--doc"],
|
|
875
|
+
["reminder", "--reminder"],
|
|
876
|
+
["event", "--event"],
|
|
877
|
+
["typeOption", "--type-option"],
|
|
878
|
+
["field", "--field"],
|
|
879
|
+
];
|
|
880
|
+
return normalizeLegacyNoneUpdateOptions(await resolveMutationStdinTokenFields(options, scalarFields, listFields));
|
|
881
|
+
}
|
|
882
|
+
/** Resolve update stdin tokens once while preserving transport-marked literals. */
|
|
883
|
+
export async function resolveUpdateTransportOptions(options) {
|
|
884
|
+
return shouldResolveMutationStdinTokens(options)
|
|
885
|
+
? await resolveStdinUpdateOptions(options)
|
|
886
|
+
: normalizeLegacyNoneUpdateOptions(options);
|
|
878
887
|
}
|
|
879
888
|
function buildClearCollectionDefinitions(options) {
|
|
880
889
|
return [
|
|
@@ -1220,12 +1229,13 @@ async function routeCloseStatusUpdate(context) {
|
|
|
1220
1229
|
const routeWarnings = [];
|
|
1221
1230
|
let preChangedFields = [];
|
|
1222
1231
|
if (otherFieldKeys.length > 0) {
|
|
1223
|
-
const
|
|
1232
|
+
const preUpdateOptions = transferMutationStdinTokenPolicy(context.options, {
|
|
1224
1233
|
...context.options,
|
|
1225
1234
|
status: undefined,
|
|
1226
1235
|
closeReason: undefined,
|
|
1227
1236
|
message: undefined,
|
|
1228
|
-
}
|
|
1237
|
+
});
|
|
1238
|
+
const preUpdate = await runUpdate(context.id, preUpdateOptions, context.global);
|
|
1229
1239
|
preChangedFields = preUpdate.changed_fields;
|
|
1230
1240
|
routeWarnings.push(...preUpdate.warnings);
|
|
1231
1241
|
}
|
|
@@ -1804,7 +1814,7 @@ function mutateUpdateDocument(document, context) {
|
|
|
1804
1814
|
}
|
|
1805
1815
|
/** Implements run update for the public runtime surface of this module. */
|
|
1806
1816
|
async function runUpdateWithContext(id, options, global, execution = {}) {
|
|
1807
|
-
options = await
|
|
1817
|
+
options = await resolveUpdateTransportOptions(options);
|
|
1808
1818
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
1809
1819
|
await assertUpdateTrackerInitialized(pmRoot);
|
|
1810
1820
|
const settings = await readSettings(pmRoot);
|
|
@@ -2111,4 +2121,4 @@ export const _testOnlyUpdateCommand = {
|
|
|
2111
2121
|
resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
|
|
2112
2122
|
};
|
|
2113
2123
|
//# sourceMappingURL=update.js.map
|
|
2114
|
-
//# debugId=
|
|
2124
|
+
//# debugId=6865ca88-7ca1-52fd-86fb-2a3439abeafa
|
package/dist/sdk/merge/driver.js
CHANGED
|
@@ -9,14 +9,16 @@
|
|
|
9
9
|
* merge never corrupts tracker storage the way raw conflict markers do.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
!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]="
|
|
12
|
+
!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]="2c8046a5-06aa-58f8-b347-e757086082d1")}catch(e){}}();
|
|
13
13
|
import { readFile, writeFile } from "node:fs/promises";
|
|
14
14
|
import path from "node:path";
|
|
15
15
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
16
16
|
import { collectRegisteredItemFieldNames } from "../../core/extensions/item-fields.js";
|
|
17
17
|
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
18
|
+
import { parseItemDocument } from "../../core/item/item-format.js";
|
|
18
19
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
19
20
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
21
|
+
import { sha256Hex, stableStringify } from "../../core/shared/serialization.js";
|
|
20
22
|
import { nowIso } from "../../core/shared/time.js";
|
|
21
23
|
import { getSettingsPath, resolvePmRoot } from "../../core/store/paths.js";
|
|
22
24
|
import { readSettings } from "../../core/store/settings.js";
|
|
@@ -122,10 +124,12 @@ export async function runMergeDriver(options, global) {
|
|
|
122
124
|
}
|
|
123
125
|
else if (artifact === "item") {
|
|
124
126
|
const settings = await loadOptionalSettings(global);
|
|
127
|
+
const itemFormat = itemFormatForPath(options.itemPath ?? outputPath, settings);
|
|
128
|
+
const extensionFieldNames = collectRegisteredItemFieldNames(getActiveExtensionRegistrations());
|
|
125
129
|
const itemMerge = mergeItemDocuments(baseRaw, oursRaw, theirsRaw, {
|
|
126
|
-
format:
|
|
130
|
+
format: itemFormat,
|
|
127
131
|
schema: settings?.schema,
|
|
128
|
-
extensionFieldNames
|
|
132
|
+
extensionFieldNames,
|
|
129
133
|
preferred,
|
|
130
134
|
conflictResolution: "stable_value_order",
|
|
131
135
|
});
|
|
@@ -137,6 +141,19 @@ export async function runMergeDriver(options, global) {
|
|
|
137
141
|
conflict_resolution: "stable_value_order",
|
|
138
142
|
};
|
|
139
143
|
if (options.itemPath !== undefined) {
|
|
144
|
+
const mergedDocument = parseItemDocument(merged, {
|
|
145
|
+
format: itemFormat,
|
|
146
|
+
schema: settings?.schema,
|
|
147
|
+
extensionFieldNames,
|
|
148
|
+
});
|
|
149
|
+
const mergedMetadata = mergedDocument.metadata;
|
|
150
|
+
const receiptFields = [
|
|
151
|
+
...new Set([
|
|
152
|
+
...itemMerge.fields_from_theirs,
|
|
153
|
+
...itemMerge.union_fields,
|
|
154
|
+
...itemMerge.conflict_decisions.map((decision) => decision.field),
|
|
155
|
+
]),
|
|
156
|
+
];
|
|
140
157
|
receiptInput = {
|
|
141
158
|
cwd: process.cwd(),
|
|
142
159
|
itemPath: options.itemPath,
|
|
@@ -144,6 +161,10 @@ export async function runMergeDriver(options, global) {
|
|
|
144
161
|
conflictResolution: "stable_value_order",
|
|
145
162
|
fieldsFromTheirs: itemMerge.fields_from_theirs,
|
|
146
163
|
unionFields: itemMerge.union_fields,
|
|
164
|
+
mergedFieldHashes: Object.fromEntries(receiptFields.map((field) => [
|
|
165
|
+
field,
|
|
166
|
+
sha256Hex(stableStringify(field === "body" ? mergedDocument.body : mergedMetadata[field])),
|
|
167
|
+
])),
|
|
147
168
|
decisions: itemMerge.conflict_decisions,
|
|
148
169
|
};
|
|
149
170
|
}
|
|
@@ -187,4 +208,4 @@ export async function runMergeDriver(options, global) {
|
|
|
187
208
|
};
|
|
188
209
|
}
|
|
189
210
|
//# sourceMappingURL=driver.js.map
|
|
190
|
-
//# debugId=
|
|
211
|
+
//# debugId=2c8046a5-06aa-58f8-b347-e757086082d1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/merge/receipt-file-boundary
|
|
3
|
+
*
|
|
4
|
+
* Reads untrusted receipt candidates through a bounded, no-follow file
|
|
5
|
+
* boundary whose race and short-read behavior can be exercised directly.
|
|
6
|
+
*/
|
|
7
|
+
import { type Stats } from "node:fs";
|
|
8
|
+
import { type FileHandle } from "node:fs/promises";
|
|
9
|
+
/** Minimal filesystem operations required by the receipt reader. */
|
|
10
|
+
export interface ReceiptFileBoundary {
|
|
11
|
+
/** Inspect the path without following its final symbolic link. */
|
|
12
|
+
lstat(receiptPath: string): Promise<Stats>;
|
|
13
|
+
/** Open the candidate and return the handle used for verified reads. */
|
|
14
|
+
open(receiptPath: string, flags: number): Promise<FileHandle>;
|
|
15
|
+
}
|
|
16
|
+
/** Resolve the platform no-follow flag, falling back only where Node omits it. */
|
|
17
|
+
export declare function resolveReceiptNoFollowFlag(constants: {
|
|
18
|
+
O_NOFOLLOW?: number;
|
|
19
|
+
}): number;
|
|
20
|
+
/** Read one regular file only when its opened identity remains bounded and stable. */
|
|
21
|
+
export declare function readBoundedRegularFile(receiptPath: string, maximumBytes: number, boundary?: ReceiptFileBoundary): Promise<string | null>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/merge/receipt-file-boundary
|
|
3
|
+
*
|
|
4
|
+
* Reads untrusted receipt candidates through a bounded, no-follow file
|
|
5
|
+
* boundary whose race and short-read behavior can be exercised directly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
!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]="6ece0e15-aff5-5e2d-b18a-16ffaa0fe2ea")}catch(e){}}();
|
|
9
|
+
import { constants as fsConstants } from "node:fs";
|
|
10
|
+
import { lstat, open } from "node:fs/promises";
|
|
11
|
+
const NODE_RECEIPT_FILE_BOUNDARY = { lstat, open };
|
|
12
|
+
/** Resolve the platform no-follow flag, falling back only where Node omits it. */
|
|
13
|
+
export function resolveReceiptNoFollowFlag(constants) {
|
|
14
|
+
return constants.O_NOFOLLOW ?? 0;
|
|
15
|
+
}
|
|
16
|
+
/** Read one regular file only when its opened identity remains bounded and stable. */
|
|
17
|
+
export async function readBoundedRegularFile(receiptPath, maximumBytes, boundary = NODE_RECEIPT_FILE_BOUNDARY) {
|
|
18
|
+
const pathStats = await boundary.lstat(receiptPath);
|
|
19
|
+
if (pathStats.isSymbolicLink() ||
|
|
20
|
+
!pathStats.isFile() ||
|
|
21
|
+
pathStats.size > maximumBytes) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const handle = await boundary.open(receiptPath, fsConstants.O_RDONLY | resolveReceiptNoFollowFlag(fsConstants));
|
|
25
|
+
try {
|
|
26
|
+
const openedStats = await handle.stat();
|
|
27
|
+
if (!openedStats.isFile() || openedStats.size > maximumBytes)
|
|
28
|
+
return null;
|
|
29
|
+
const buffer = Buffer.alloc(openedStats.size);
|
|
30
|
+
let offset = 0;
|
|
31
|
+
while (offset < buffer.length) {
|
|
32
|
+
const { bytesRead } = await handle.read(buffer, offset, buffer.length - offset, offset);
|
|
33
|
+
if (bytesRead === 0)
|
|
34
|
+
break;
|
|
35
|
+
offset += bytesRead;
|
|
36
|
+
}
|
|
37
|
+
const finalStats = await handle.stat();
|
|
38
|
+
return finalStats.size === openedStats.size && offset === openedStats.size
|
|
39
|
+
? buffer.toString("utf8", 0, offset)
|
|
40
|
+
: null;
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
await handle.close();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=receipt-file-boundary.js.map
|
|
47
|
+
//# debugId=6ece0e15-aff5-5e2d-b18a-16ffaa0fe2ea
|
|
@@ -19,6 +19,8 @@ export interface MergeDecisionReceipt {
|
|
|
19
19
|
fields_from_theirs: string[];
|
|
20
20
|
/** Collections combined from both branches. */
|
|
21
21
|
union_fields: string[];
|
|
22
|
+
/** SHA-256 hashes of the merged values for every field represented by this receipt. Absent on legacy receipts, which cannot prove drift attribution. */
|
|
23
|
+
merged_field_hashes?: Record<string, string>;
|
|
22
24
|
/** Full recoverable scalar decisions, retained only in the clone. */
|
|
23
25
|
decisions: ItemMergeConflictDecision[];
|
|
24
26
|
/** Whether a merge reconciliation history event consumed this receipt. */
|
|
@@ -29,6 +31,8 @@ export interface MergeDecisionReceipt {
|
|
|
29
31
|
reconciled_at?: string;
|
|
30
32
|
/** Whether decision values are recoverable locally or represented by hashes only. */
|
|
31
33
|
value_availability?: "clone_local" | "hash_only";
|
|
34
|
+
/** Runtime-only provenance assigned by the reader; serialized values are ignored. */
|
|
35
|
+
evidence_source?: "clone_local" | "durable";
|
|
32
36
|
}
|
|
33
37
|
/** Privacy-safe receipt summary suitable for committed history context. */
|
|
34
38
|
export interface MergeDecisionReceiptSummary {
|
|
@@ -66,6 +70,13 @@ export interface MergeReceiptReport {
|
|
|
66
70
|
/** ISO timestamp for the report. */
|
|
67
71
|
generated_at: string;
|
|
68
72
|
}
|
|
73
|
+
/** Internal integrity scan result used by health without exposing malformed receipt contents. */
|
|
74
|
+
export interface MergeReceiptEvidenceScan {
|
|
75
|
+
/** Valid receipts that passed bounded-file, schema, and identity validation. */
|
|
76
|
+
receipts: MergeDecisionReceipt[];
|
|
77
|
+
/** Number of JSON receipt candidates that could not be validated safely. */
|
|
78
|
+
invalid_evidence_count: number;
|
|
79
|
+
}
|
|
69
80
|
/** Convert a raw receipt into privacy-safe history context. */
|
|
70
81
|
export declare function summarizeMergeReceipt(receipt: MergeDecisionReceipt): MergeDecisionReceiptSummary;
|
|
71
82
|
/** Persist one item-driver outcome in the clone-local Git directory. */
|
|
@@ -76,8 +87,18 @@ export declare function writeMergeReceipt(params: {
|
|
|
76
87
|
conflictResolution?: "preferred_side" | "stable_value_order";
|
|
77
88
|
fieldsFromTheirs: string[];
|
|
78
89
|
unionFields: string[];
|
|
90
|
+
mergedFieldHashes?: Record<string, string>;
|
|
79
91
|
decisions: ItemMergeConflictDecision[];
|
|
80
92
|
}): Promise<MergeDecisionReceipt | null>;
|
|
93
|
+
/** Inspect valid receipts and count invalid evidence without returning untrusted file contents. */
|
|
94
|
+
export declare function inspectMergeReceiptEvidence(cwd: string, options?: {
|
|
95
|
+
/** Include receipts whose reconciliation state is already settled. */
|
|
96
|
+
includeReconciled?: boolean;
|
|
97
|
+
/** Include receipts that contain no discarded scalar values. */
|
|
98
|
+
includeLossless?: boolean;
|
|
99
|
+
/** Explicit tracker root used to locate durable receipt evidence. */
|
|
100
|
+
pmRoot?: string;
|
|
101
|
+
}): Promise<MergeReceiptEvidenceScan>;
|
|
81
102
|
/** Read clone-local receipts with explicit reconciled/lossless classification controls. */
|
|
82
103
|
export declare function listMergeReceipts(cwd: string, options?: {
|
|
83
104
|
includeReconciled?: boolean;
|
|
@@ -92,7 +113,9 @@ export declare function partitionMergeReceipts(receipts: MergeDecisionReceipt[])
|
|
|
92
113
|
lossless: MergeDecisionReceipt[];
|
|
93
114
|
};
|
|
94
115
|
/** Mark a receipt as represented by a committed merge history event. */
|
|
95
|
-
export declare function markMergeReceiptReconciled(cwd: string, receipt: MergeDecisionReceipt
|
|
116
|
+
export declare function markMergeReceiptReconciled(cwd: string, receipt: MergeDecisionReceipt, options?: {
|
|
117
|
+
requireExisting?: boolean;
|
|
118
|
+
}): Promise<void>;
|
|
96
119
|
/** Report pending or historical clone-local merge decisions. */
|
|
97
120
|
export declare function runMergeReceiptReport(options: {
|
|
98
121
|
/** Include receipts already represented by merge history events. */
|