@unbrained/pm-cli 2026.8.8 → 2026.8.9
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 +19 -0
- package/dist/cli-bundle/bundle-manifest.json +154 -154
- package/dist/cli-bundle/chunks/chunk-2DTCZXSD.js +13 -0
- package/dist/cli-bundle/chunks/{chunk-ALDHXLPS.js → chunk-5JO6R4BS.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-5KN4DZYV.js +194 -0
- package/dist/cli-bundle/chunks/chunk-EF43KODO.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-NUXRRNAB.js → chunk-GMX5YOI3.js} +25 -25
- package/dist/cli-bundle/chunks/chunk-HUV2Z7IS.js +28 -0
- package/dist/cli-bundle/chunks/{chunk-SQ7QZFQ6.js → chunk-MHBVCUF2.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-PYO5GZU6.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-CBLA33YK.js → chunk-RJC7TPF4.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-2ZMXX3Q6.js → chunk-YC3UF2IO.js} +64 -64
- package/dist/cli-bundle/chunks/{register-list-query-WFZAMJHZ.js → register-list-query-BUE7PTCU.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-SOKKOTHQ.js → register-mutation-FC3XLVIK.js} +2 -2
- package/dist/cli-bundle/chunks/{register-operations-5XQETS6E.js → register-operations-YH2WAOXU.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-2HL5ZHMK.js → register-setup-UQDTNTLJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-2VVP5RAA.js +153 -0
- package/dist/cli-bundle/focused-chunks/{chunk-IAS7PMLG.js → chunk-3GSFUDAI.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-3WVHTUAW.js +5 -0
- package/dist/cli-bundle/focused-chunks/chunk-4H6MVCK3.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ZOLDTUU7.js → chunk-54TZJ4BM.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-YKPE4PPY.js → chunk-5NK5TJ5D.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ANTMGYLI.js → chunk-6DO4YQWZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-73FIJONU.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-PL2EYDJK.js → chunk-C3GCHDSQ.js} +29 -27
- package/dist/cli-bundle/focused-chunks/{chunk-U646T7Z6.js → chunk-JGRSQZJT.js} +3 -3
- package/dist/cli-bundle/focused-chunks/{chunk-YSAHYUXX.js → chunk-KNEHLPBF.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-MRWVJ3ZG.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-NL57J7BZ.js +4 -0
- package/dist/cli-bundle/focused-chunks/{chunk-DMKOMTTY.js → chunk-P6BBIQRG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GWI6YIKJ.js → chunk-PZAGVQNN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-QDAO3XEK.js +14 -0
- package/dist/cli-bundle/focused-chunks/{chunk-SM2PJGP3.js → chunk-T4IGQCSY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-U46GQJNY.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-TCSAPH33.js → chunk-VRXJSGIT.js} +6 -6
- package/dist/cli-bundle/focused-chunks/{chunk-FI6DWU2M.js → chunk-XC2ZW3CJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-ZG54B4XG.js +2 -0
- package/dist/cli-bundle/main.js +2 -2
- 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 +29 -29
- 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 +1 -1
- 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 +12 -2
- package/dist/core/history/history.js +13 -4
- package/dist/core/item/actionability.d.ts +7 -1
- package/dist/core/item/actionability.js +71 -15
- package/dist/core/shared/author.d.ts +25 -0
- package/dist/core/shared/author.js +114 -9
- package/dist/sdk/actionability.d.ts +1 -1
- package/dist/sdk/actionability.js +3 -3
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +8 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +17 -2
- package/dist/sdk/core-governance.d.ts +1 -1
- package/dist/sdk/core-governance.js +3 -3
- package/dist/sdk/dependencies.d.ts +2 -0
- package/dist/sdk/dependencies.js +7 -6
- package/dist/sdk/extension/bundled-catalog.js +19 -6
- package/dist/sdk/generated-error-code-catalog.js +38 -2
- package/dist/sdk/governance/health.js +29 -10
- package/dist/sdk/governance/provenance-health.d.ts +26 -0
- package/dist/sdk/governance/provenance-health.js +139 -0
- package/dist/sdk/governance/validate.js +13 -8
- package/dist/sdk/governance.d.ts +1 -0
- package/dist/sdk/governance.js +3 -2
- package/dist/sdk/graph/assembly.d.ts +4 -0
- package/dist/sdk/graph/assembly.js +22 -2
- package/dist/sdk/graph/run.d.ts +2 -0
- package/dist/sdk/graph/run.js +3 -2
- package/dist/sdk/lifecycle/close.js +13 -8
- package/dist/sdk/lifecycle/create.js +6 -12
- package/dist/sdk/lifecycle/plan.js +6 -3
- package/dist/sdk/lifecycle/update.js +6 -20
- package/dist/sdk/merge/driver.d.ts +2 -1
- package/dist/sdk/merge/driver.js +7 -4
- package/dist/sdk/merge/install.js +3 -3
- package/dist/sdk/merge/receipts.d.ts +14 -1
- package/dist/sdk/merge/receipts.js +36 -8
- package/dist/sdk/merge/reconcile.js +21 -4
- package/dist/sdk/merge/three-way.d.ts +6 -2
- package/dist/sdk/merge/three-way.js +24 -10
- package/dist/sdk/query/get.d.ts +11 -0
- package/dist/sdk/query/get.js +37 -3
- package/dist/sdk/read-output-contracts.d.ts +1 -1
- package/dist/sdk/read-output-contracts.js +23 -4
- package/dist/sdk/relationship-kinds/contract.d.ts +48 -0
- package/dist/sdk/relationship-kinds/contract.js +22 -0
- package/dist/sdk/relationships.d.ts +6 -41
- package/dist/sdk/relationships.js +12 -126
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/similarity.d.ts +5 -0
- package/dist/sdk/similarity.js +40 -10
- package/dist/sdk/structured-mutations.js +5 -2
- package/dist/sdk/test/linked-command-detection.d.ts +2 -7
- package/dist/sdk/test/linked-command-detection.js +22 -9
- package/docs/AGENT_GUIDE.md +2 -1
- package/docs/COMMANDS.md +19 -1
- package/docs/DEPENDENCY_KIND_CONTRACT.md +29 -0
- package/docs/ITEM_READ_PROJECTIONS.md +26 -0
- package/docs/MERGE_SAFETY.md +10 -3
- package/docs/RELATIONSHIP_GRAPH.md +1 -1
- package/docs/SDK_AGENT_SESSION_CONTEXT.md +35 -2
- package/docs/SDK_CONTEXT_INTEGRITY.md +16 -1
- package/docs/SENTRY_CONTRACT_EPOCHS.md +20 -0
- package/docs/agent-task-token-baseline.json +2 -2
- 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
- package/sdk/public-surface.json +231 -27
- package/dist/cli-bundle/chunks/chunk-GKA54IJM.js +0 -5
- package/dist/cli-bundle/chunks/chunk-KRY7SRUO.js +0 -2
- package/dist/cli-bundle/chunks/chunk-MNJ4NNSY.js +0 -26
- package/dist/cli-bundle/chunks/chunk-OJPCFDDY.js +0 -13
- package/dist/cli-bundle/chunks/chunk-PFSD3DAN.js +0 -194
- package/dist/cli-bundle/focused-chunks/chunk-54EU2UVO.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-5FLBTZJQ.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-5GJ57YKN.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-CMDS3KYT.js +0 -14
- package/dist/cli-bundle/focused-chunks/chunk-F5B3HBEZ.js +0 -5
- package/dist/cli-bundle/focused-chunks/chunk-FNOKJG6N.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-FPDYXZBK.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-HCUC62AB.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-HGNKPSCB.js +0 -153
package/dist/sdk/graph/run.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* queries in long-lived hosts are answered from the memoized snapshot.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
!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]="
|
|
14
|
+
!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]="ba8e7432-539e-55d3-b105-689db55d26b2")}catch(e){}}();
|
|
15
15
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
16
16
|
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
17
17
|
import { isTerminalStatus } from "../../core/item/status.js";
|
|
@@ -291,6 +291,7 @@ function runGraphAudit(invocation, isTerminal) {
|
|
|
291
291
|
affected_subjects_by_severity: affectedBySeverity,
|
|
292
292
|
affected_subjects_by_code: affectedByCode,
|
|
293
293
|
profile: report.profile,
|
|
294
|
+
legacy_alias_counts: invocation.assembly.legacyAliasCounts,
|
|
294
295
|
...(invocation.summary ? {} : { findings: report.findings }),
|
|
295
296
|
};
|
|
296
297
|
}
|
|
@@ -713,4 +714,4 @@ export async function runGraph(subcommandRaw, id, target, options, global) {
|
|
|
713
714
|
return attachGraphProjection(value, invocation.summary, "result_rows");
|
|
714
715
|
}
|
|
715
716
|
//# sourceMappingURL=run.js.map
|
|
716
|
-
//# debugId=
|
|
717
|
+
//# debugId=ba8e7432-539e-55d3-b105-689db55d26b2
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Implements the pm close 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]="6e39a90e-8a26-5789-9de6-288900b6b418")}catch(e){}}();
|
|
8
8
|
import { pathExists, toItemRecord, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, buildItemNotFoundError, listAllItemMetadataLight, locateItem, mutateItem, readLocatedItem, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, resolveIsoOrRelative, shouldCompletePlanOnClose, getActiveExtensionRegistrations, } from "../runtime-primitives.js";
|
|
9
|
-
import { collectBlockedByIds } from "../actionability.js";
|
|
9
|
+
import { collectBlockedByIds, indexBlockedByIds, } from "../actionability.js";
|
|
10
10
|
import { applyTerminalOrderingPolicy, requireTerminalReason, } from "../lifecycle-policy.js";
|
|
11
11
|
import { renderPmCommand } from "../command-line.js";
|
|
12
12
|
const CLOSE_VALIDATION_FIELDS = [
|
|
@@ -137,14 +137,19 @@ function findActiveChildIds(items, parentId, statusRegistry) {
|
|
|
137
137
|
.sort((left, right) => left.localeCompare(right));
|
|
138
138
|
}
|
|
139
139
|
function findAutoUnblockCandidates(items, closedId, statusRegistry) {
|
|
140
|
-
const itemsById = new Map(items.map((item) => [item.id, item]));
|
|
140
|
+
const itemsById = new Map(items.map((item) => [item.id.trim().toLowerCase(), item]));
|
|
141
|
+
const blockerIdsByItem = indexBlockedByIds(items);
|
|
142
|
+
const normalizedClosedId = closedId.trim().toLowerCase();
|
|
141
143
|
const blockedStatuses = statusRegistry.blocked_statuses;
|
|
142
144
|
return items
|
|
143
145
|
.filter((item) => blockedStatuses.has(item.status))
|
|
144
|
-
.map((item) => ({
|
|
145
|
-
|
|
146
|
+
.map((item) => ({
|
|
147
|
+
item,
|
|
148
|
+
blockerIds: blockerIdsByItem.get(item.id.trim().toLowerCase()),
|
|
149
|
+
}))
|
|
150
|
+
.filter(({ blockerIds }) => blockerIds.includes(normalizedClosedId))
|
|
146
151
|
.filter(({ blockerIds }) => blockerIds.every((blockerId) => {
|
|
147
|
-
if (blockerId ===
|
|
152
|
+
if (blockerId === normalizedClosedId) {
|
|
148
153
|
return true;
|
|
149
154
|
}
|
|
150
155
|
const blocker = itemsById.get(blockerId);
|
|
@@ -171,7 +176,7 @@ async function autoUnblockResolvedDependents(pmRoot, settings, items, closedId,
|
|
|
171
176
|
const dependencies = document.metadata.dependencies ?? [];
|
|
172
177
|
/* c8 ignore stop */
|
|
173
178
|
const remainingDependencies = dependencies.filter((dependency) => {
|
|
174
|
-
const dependencyId = dependency.id.trim();
|
|
179
|
+
const dependencyId = dependency.id.trim().toLowerCase();
|
|
175
180
|
return (dependency.kind !== "blocked_by" ||
|
|
176
181
|
!candidate.blocker_ids.includes(dependencyId));
|
|
177
182
|
});
|
|
@@ -450,4 +455,4 @@ export function runClose(id, closeReasonText, options, global) {
|
|
|
450
455
|
return closeItem(id, closeReasonText, options, global);
|
|
451
456
|
}
|
|
452
457
|
//# sourceMappingURL=close.js.map
|
|
453
|
-
//# debugId=
|
|
458
|
+
//# debugId=6e39a90e-8a26-5789-9de6-288900b6b418
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements the pm create 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]="af455a7c-354f-54be-99e0-833c9f2710c5")}catch(e){}}();
|
|
8
8
|
import { pathExists, removeFileIfExists, writeFileAtomic, appendHistoryEntry, createHistoryEntry, generateItemId, normalizeItemId, canonicalDocument, normalizeItemMetadata, serializeItemDocument, assertParentReferenceIsNotSelf, isPlaceholderReferenceToken, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, assertNoUnknownCsvKeys, createStdinTokenResolver, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, resolvePriority, getFocusedItem, normalizeStatusInput, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, acquireLock, printError, buildInvalidTypeError, resolveTypeSynonym, collectRuntimeCreateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, ITEM_METADATA_KEY_ORDER, PmCliError, nowIso, resolveIsoOrRelative, getActiveExtensionRegistrations, projectAfterCommandItemSnapshot, recordAfterCommandAffectedItem, runActiveCommandHandler, runActiveBeforeMutationHooks, runActiveOnWriteHooks, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, listAllItemMetadataLight, locateItem, createMutationGuardSdk, getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
|
|
9
9
|
import { requireTerminalReasonWithRecovery } from "../lifecycle-policy.js";
|
|
10
10
|
import { evaluateSimilarityGovernance, similarityAdvisoryWarnings, } from "../similarity.js";
|
|
@@ -19,6 +19,7 @@ import { COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR, COMMON_UNSET_FIELD_DEFINIT
|
|
|
19
19
|
import { ensureEnumValue } from "./recurrence-parsers.js";
|
|
20
20
|
import { assertDependencyEdgesAllowed, assertValidBareDependencyFlagValue, } from "../dependency-flag-validation.js";
|
|
21
21
|
import { normalizeDependencySeedId, normalizeDependencySourceKind, } from "../dependency-provenance.js";
|
|
22
|
+
import { resolveCanonicalRelationshipKind } from "../relationships.js";
|
|
22
23
|
import { parseEventEntries, parseReminderEntries, parseTypeOptionEntries, } from "./repeatable-metadata-parsers.js";
|
|
23
24
|
import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES, SCOPE_VALUES, } from "../../types/index.js";
|
|
24
25
|
const CREATE_MODE_VALUES = ["strict", "progressive"];
|
|
@@ -188,17 +189,10 @@ function parseDependencies(raw, nowValue, prefix, fallbackAuthor) {
|
|
|
188
189
|
});
|
|
189
190
|
return { values, explicitEmpty: false };
|
|
190
191
|
}
|
|
191
|
-
const DEPENDENCY_KIND_INPUT_ALIASES = {
|
|
192
|
-
"blocked-by": "blocked_by",
|
|
193
|
-
depends_on: "blocked_by",
|
|
194
|
-
"depends-on": "blocked_by",
|
|
195
|
-
};
|
|
196
192
|
function normalizeDependencyKindInput(raw) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const alias = DEPENDENCY_KIND_INPUT_ALIASES[raw.toLowerCase()];
|
|
201
|
-
return alias ?? raw;
|
|
193
|
+
return typeof raw === "string"
|
|
194
|
+
? (resolveCanonicalRelationshipKind(raw) ?? raw.trim())
|
|
195
|
+
: raw;
|
|
202
196
|
}
|
|
203
197
|
function looksLikeStructuredEntry(raw, keys) {
|
|
204
198
|
if (raw.startsWith("```") || raw.includes("\n")) {
|
|
@@ -1841,4 +1835,4 @@ export const _testOnlyCreateCommand = {
|
|
|
1841
1835
|
typeOptionExampleValue,
|
|
1842
1836
|
};
|
|
1843
1837
|
//# sourceMappingURL=create.js.map
|
|
1844
|
-
//# debugId=
|
|
1838
|
+
//# debugId=af455a7c-354f-54be-99e0-833c9f2710c5
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements the pm plan 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]="dc87393e-61e3-5d43-a756-d5f156faf29e")}catch(e){}}();
|
|
8
8
|
import { pathExists, getActiveExtensionRegistrations, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, resolveTypeName, EXIT_CODE, PmCliError, splitCommaList, nowIso, locateItem, mutateItem, readLocatedItem, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, isTerminalPlanMode, } from "../runtime-primitives.js";
|
|
9
9
|
import { PLAN_HARNESS_VALUES, PLAN_MODE_VALUES, PLAN_STEP_LINK_KIND_VALUES, PLAN_STEP_STATUS_VALUES, } from "../../types/index.js";
|
|
10
10
|
import { runCreate, } from "./create.js";
|
|
@@ -522,7 +522,10 @@ function nextActionsFor(planId, plan) {
|
|
|
522
522
|
tips.push(`pm plan approve ${planId} --message "ready to execute"`);
|
|
523
523
|
}
|
|
524
524
|
if (plan.steps_summary.completed === plan.steps_summary.total &&
|
|
525
|
-
plan.steps_summary.total > 0
|
|
525
|
+
plan.steps_summary.total > 0 &&
|
|
526
|
+
!isTerminalPlanMode(plan.mode) &&
|
|
527
|
+
plan.status !== "closed" &&
|
|
528
|
+
plan.status !== "canceled") {
|
|
526
529
|
tips.push(`pm close ${planId} "plan complete"`);
|
|
527
530
|
}
|
|
528
531
|
return tips;
|
|
@@ -1579,4 +1582,4 @@ export const _testOnlyPlanCommand = {
|
|
|
1579
1582
|
changedPlanMetadataFields,
|
|
1580
1583
|
};
|
|
1581
1584
|
//# sourceMappingURL=plan.js.map
|
|
1582
|
-
//# debugId=
|
|
1585
|
+
//# debugId=dc87393e-61e3-5d43-a756-d5f156faf29e
|
|
@@ -4,7 +4,7 @@
|
|
|
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]="233df258-47b7-571a-b445-9eab0c811702")}catch(e){}}();
|
|
8
8
|
import { pathExists, COMMON_MUTATION_COMMAND_OPTION_KEYS, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, normalizeItemId, toItemRecord, buildInvalidTypeError, assertParentReferenceIsNotSelf, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, applyAcceptanceCriteriaMutations, applyTagRemovals, assertNoUnknownCsvKeys, createStdinTokenResolver, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, isTerminalStatus, collectRuntimeUpdateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, describeAllowedTransitions, evaluateTransition, resolveTypeWorkflows, EXIT_CODE, PmCliError, stableValueEquals, resolveIsoOrRelative, getActiveExtensionRegistrations, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, buildItemNotFoundError, listAllItemMetadataLight, locateItem, mutateItem, readLocatedItem, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
|
|
9
9
|
import { runClose } from "./close.js";
|
|
10
10
|
import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
|
|
@@ -13,6 +13,7 @@ import { ensureEnumValue as ensureEnum } from "./recurrence-parsers.js";
|
|
|
13
13
|
import { parseEventEntries, parseReminderEntries, parseTypeOptionEntries, } from "./repeatable-metadata-parsers.js";
|
|
14
14
|
import { assertDependencyEdgesAllowed, assertValidBareDependencyFlagValue, } from "../dependency-flag-validation.js";
|
|
15
15
|
import { normalizeDependencySeedId, normalizeDependencySourceKind, } from "../dependency-provenance.js";
|
|
16
|
+
import { resolveCanonicalRelationshipKind } from "../relationships.js";
|
|
16
17
|
import { collectNewOrderingCycleWarnings } from "../graph/mutation-advisory.js";
|
|
17
18
|
import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES, } from "../../types/index.js";
|
|
18
19
|
import { parseDocs, parseFiles, parseLogSeed, parseTests, requireStringOption, } from "./create.js";
|
|
@@ -386,25 +387,10 @@ function looksLikeStructuredDependencyEntry(raw) {
|
|
|
386
387
|
// key is rejected rather than swallowed as a bare item id (GH-258).
|
|
387
388
|
return looksLikeGenericKeyValueEntry(raw);
|
|
388
389
|
}
|
|
389
|
-
// pm-fl0c #4 (2026-05-28): `pm plan` accepts `depends_on` as a link kind
|
|
390
|
-
// (`PLAN_STEP_LINK_KIND_VALUES`) but `pm update --dep kind=depends_on` rejected
|
|
391
|
-
// it because `DEPENDENCY_KIND_VALUES` only lists `blocked_by`. The two terms
|
|
392
|
-
// are semantically identical from this side ("X depends on Y" === "X blocked
|
|
393
|
-
// by Y"), so we normalize input here rather than expanding the persisted enum
|
|
394
|
-
// — the stored kind stays canonical (`blocked_by`) and downstream consumers
|
|
395
|
-
// (closing logic, dependency graphs, blockers views) keep working unchanged.
|
|
396
|
-
const DEPENDENCY_KIND_INPUT_ALIASES = {
|
|
397
|
-
"blocked-by": "blocked_by",
|
|
398
|
-
depends_on: "blocked_by",
|
|
399
|
-
"depends-on": "blocked_by",
|
|
400
|
-
};
|
|
401
390
|
function normalizeDependencyKindInput(raw) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const trimmed = raw.trim();
|
|
406
|
-
const alias = DEPENDENCY_KIND_INPUT_ALIASES[trimmed.toLowerCase()];
|
|
407
|
-
return alias ?? trimmed;
|
|
391
|
+
return typeof raw === "string"
|
|
392
|
+
? (resolveCanonicalRelationshipKind(raw) ?? raw.trim())
|
|
393
|
+
: raw;
|
|
408
394
|
}
|
|
409
395
|
function parseDependencyAdditions(raw, prefix, nowIso, fallbackAuthor) {
|
|
410
396
|
if (!raw) {
|
|
@@ -1874,4 +1860,4 @@ export const _testOnlyUpdateCommand = {
|
|
|
1874
1860
|
resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
|
|
1875
1861
|
};
|
|
1876
1862
|
//# sourceMappingURL=update.js.map
|
|
1877
|
-
//# debugId=
|
|
1863
|
+
//# debugId=233df258-47b7-571a-b445-9eab0c811702
|
|
@@ -30,7 +30,7 @@ export interface MergeDriverResult {
|
|
|
30
30
|
artifact: MergeDriverArtifact;
|
|
31
31
|
/** Path the merged content was written to. */
|
|
32
32
|
output_path: string;
|
|
33
|
-
/**
|
|
33
|
+
/** Invocation-side preference retained for non-item artifact compatibility. */
|
|
34
34
|
preferred: MergePreferredSide;
|
|
35
35
|
/** Unresolvable conflict labels: metadata field names (item), dotted key paths (json). Empty for history merges. */
|
|
36
36
|
conflicts: string[];
|
|
@@ -56,6 +56,7 @@ export interface MergeDriverResult {
|
|
|
56
56
|
item?: {
|
|
57
57
|
fields_from_theirs: string[];
|
|
58
58
|
union_fields: string[];
|
|
59
|
+
conflict_resolution: "stable_value_order";
|
|
59
60
|
};
|
|
60
61
|
/** JSON-merge key accounting; present only for the json artifact. */
|
|
61
62
|
json?: {
|
package/dist/sdk/merge/driver.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
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]="e739a603-35c5-5df9-8d4b-3bbc0fe3e4fd")}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";
|
|
@@ -127,18 +127,21 @@ export async function runMergeDriver(options, global) {
|
|
|
127
127
|
schema: settings?.schema,
|
|
128
128
|
extensionFieldNames: collectRegisteredItemFieldNames(getActiveExtensionRegistrations()),
|
|
129
129
|
preferred,
|
|
130
|
+
conflictResolution: "stable_value_order",
|
|
130
131
|
});
|
|
131
132
|
merged = itemMerge.merged;
|
|
132
133
|
conflicts.push(...itemMerge.conflict_fields);
|
|
133
134
|
result.item = {
|
|
134
135
|
fields_from_theirs: itemMerge.fields_from_theirs,
|
|
135
136
|
union_fields: itemMerge.union_fields,
|
|
137
|
+
conflict_resolution: "stable_value_order",
|
|
136
138
|
};
|
|
137
139
|
if (options.itemPath !== undefined) {
|
|
138
140
|
receiptInput = {
|
|
139
141
|
cwd: process.cwd(),
|
|
140
142
|
itemPath: options.itemPath,
|
|
141
143
|
preferred,
|
|
144
|
+
conflictResolution: "stable_value_order",
|
|
142
145
|
fieldsFromTheirs: itemMerge.fields_from_theirs,
|
|
143
146
|
unionFields: itemMerge.union_fields,
|
|
144
147
|
decisions: itemMerge.conflict_decisions,
|
|
@@ -167,10 +170,10 @@ export async function runMergeDriver(options, global) {
|
|
|
167
170
|
const receiptGuidance = result.receipt === undefined
|
|
168
171
|
? 'Run "pm merge report" to inspect clone-local merge evidence.'
|
|
169
172
|
: `Run "pm merge report" and correlate receipt ${result.receipt.receipt_id} with item ${result.receipt.item_id}; clone-local discarded values are never copied into this result.`;
|
|
170
|
-
guidance.push(`Both branches changed ${conflicts.join(", ")}; the
|
|
173
|
+
guidance.push(`Both branches changed ${conflicts.join(", ")}; the item driver kept the direction-independent stable value. ${receiptGuidance} Review the merged file, re-apply the discarded change if needed, then "git add" it.`);
|
|
171
174
|
}
|
|
172
175
|
if (artifact === "history" && result.history?.reanchored) {
|
|
173
|
-
guidance.push('The merged history chain was re-anchored. Run "pm
|
|
176
|
+
guidance.push('The merged history chain was re-anchored. Run "pm merge reconcile --dry-run" to inspect the complete post-merge repair, then "pm merge reconcile" to apply it; use --force only after explicitly accepting reported discards.');
|
|
174
177
|
}
|
|
175
178
|
return {
|
|
176
179
|
ok: conflicts.length === 0,
|
|
@@ -184,4 +187,4 @@ export async function runMergeDriver(options, global) {
|
|
|
184
187
|
};
|
|
185
188
|
}
|
|
186
189
|
//# sourceMappingURL=driver.js.map
|
|
187
|
-
//# debugId=
|
|
190
|
+
//# debugId=e739a603-35c5-5df9-8d4b-3bbc0fe3e4fd
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* mutations refresh the fenced block automatically once it is installed.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
!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]="
|
|
11
|
+
!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]="cb6dc38e-b317-5739-83ff-cf459b8bb31e")}catch(e){}}();
|
|
12
12
|
import { readFile, realpath, writeFile } from "node:fs/promises";
|
|
13
13
|
import { execFile } from "node:child_process";
|
|
14
14
|
import path from "node:path";
|
|
@@ -541,11 +541,11 @@ export async function installMergeFence(options) {
|
|
|
541
541
|
guidance: [
|
|
542
542
|
"Commit .gitattributes so every branch and collaborator shares the merge mapping.",
|
|
543
543
|
'git config is per-clone: each collaborator (and each fresh worktree/clone) runs "pm merge install" once.',
|
|
544
|
-
'After merging branches, run "pm
|
|
544
|
+
'After merging branches, run "pm merge reconcile --dry-run" to inspect the complete receipt and history repair, then apply "pm merge reconcile"; use --force only after explicitly accepting any discarded values.',
|
|
545
545
|
"Custom item types registered later refresh this fence automatically (pm schema add-type/remove-type); rerun pm merge install only after out-of-band type-folder edits.",
|
|
546
546
|
],
|
|
547
547
|
generated_at: nowIso(),
|
|
548
548
|
};
|
|
549
549
|
}
|
|
550
550
|
//# sourceMappingURL=install.js.map
|
|
551
|
-
//# debugId=
|
|
551
|
+
//# debugId=cb6dc38e-b317-5739-83ff-cf459b8bb31e
|
|
@@ -11,6 +11,8 @@ export interface MergeDecisionReceipt {
|
|
|
11
11
|
item_id: string;
|
|
12
12
|
/** Preferred side used for scalar conflicts. */
|
|
13
13
|
preferred: MergePreferredSide;
|
|
14
|
+
/** Scalar-conflict selection contract used by the item driver. */
|
|
15
|
+
conflict_resolution: "preferred_side" | "stable_value_order";
|
|
14
16
|
/** Fields selected cleanly from the other branch. */
|
|
15
17
|
fields_from_theirs: string[];
|
|
16
18
|
/** Collections combined from both branches. */
|
|
@@ -40,6 +42,8 @@ export interface MergeDecisionReceiptSummary {
|
|
|
40
42
|
union_fields: string[];
|
|
41
43
|
/** Preferred side used for scalar conflicts. */
|
|
42
44
|
preferred: MergePreferredSide;
|
|
45
|
+
/** Scalar-conflict selection contract used by the item driver. */
|
|
46
|
+
conflict_resolution: "preferred_side" | "stable_value_order";
|
|
43
47
|
/** Hashes proving the retained and discarded values without publishing them. */
|
|
44
48
|
decisions: Array<{
|
|
45
49
|
field: string;
|
|
@@ -65,14 +69,23 @@ export declare function writeMergeReceipt(params: {
|
|
|
65
69
|
cwd: string;
|
|
66
70
|
itemPath: string;
|
|
67
71
|
preferred: MergePreferredSide;
|
|
72
|
+
conflictResolution?: "preferred_side" | "stable_value_order";
|
|
68
73
|
fieldsFromTheirs: string[];
|
|
69
74
|
unionFields: string[];
|
|
70
75
|
decisions: ItemMergeConflictDecision[];
|
|
71
76
|
}): Promise<MergeDecisionReceipt | null>;
|
|
72
|
-
/** Read
|
|
77
|
+
/** Read clone-local receipts with explicit reconciled/lossless classification controls. */
|
|
73
78
|
export declare function listMergeReceipts(cwd: string, options?: {
|
|
74
79
|
includeReconciled?: boolean;
|
|
80
|
+
includeLossless?: boolean;
|
|
75
81
|
}): Promise<MergeDecisionReceipt[]>;
|
|
82
|
+
/** Split merge provenance into receipts with discarded values and receipts whose composition was lossless. */
|
|
83
|
+
export declare function partitionMergeReceipts(receipts: MergeDecisionReceipt[]): {
|
|
84
|
+
/** Receipts that require an explicit decision because at least one competing scalar value was discarded. */
|
|
85
|
+
pendingDecisions: MergeDecisionReceipt[];
|
|
86
|
+
/** Receipts that record provenance without a discarded competing scalar value. */
|
|
87
|
+
lossless: MergeDecisionReceipt[];
|
|
88
|
+
};
|
|
76
89
|
/** Mark a receipt as represented by a committed merge history event. */
|
|
77
90
|
export declare function markMergeReceiptReconciled(cwd: string, receipt: MergeDecisionReceipt): Promise<void>;
|
|
78
91
|
/** Report pending or historical clone-local merge decisions. */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* value for the coordinator that performed the merge.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!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]="
|
|
10
|
+
!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]="3ccde5c2-f743-52ac-a3fd-9590f720e1b3")}catch(e){}}();
|
|
11
11
|
import { execFile } from "node:child_process";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
13
|
import { readdir, readFile } from "node:fs/promises";
|
|
@@ -19,7 +19,12 @@ import { nowIso } from "../../core/shared/time.js";
|
|
|
19
19
|
const execFileAsync = promisify(execFile);
|
|
20
20
|
async function resolveReceiptDirectory(cwd) {
|
|
21
21
|
try {
|
|
22
|
-
const { stdout } = await execFileAsync("git", [
|
|
22
|
+
const { stdout } = await execFileAsync("git", [
|
|
23
|
+
"rev-parse",
|
|
24
|
+
"--path-format=absolute",
|
|
25
|
+
"--git-path",
|
|
26
|
+
"pm-merge-receipts",
|
|
27
|
+
], { cwd, encoding: "utf8", windowsHide: true, timeout: 10_000 });
|
|
23
28
|
return stdout.trim();
|
|
24
29
|
}
|
|
25
30
|
catch {
|
|
@@ -39,6 +44,7 @@ export function summarizeMergeReceipt(receipt) {
|
|
|
39
44
|
fields_from_theirs: receipt.fields_from_theirs,
|
|
40
45
|
union_fields: receipt.union_fields,
|
|
41
46
|
preferred: receipt.preferred,
|
|
47
|
+
conflict_resolution: receipt.conflict_resolution,
|
|
42
48
|
decisions: receipt.decisions.map((decision) => ({
|
|
43
49
|
field: decision.field,
|
|
44
50
|
retained_hash: sha256Hex(stableStringify(decision.retained)),
|
|
@@ -65,6 +71,7 @@ export async function writeMergeReceipt(params) {
|
|
|
65
71
|
item_path: itemPath.replaceAll("\\", "/"),
|
|
66
72
|
item_id: itemId,
|
|
67
73
|
preferred: params.preferred,
|
|
74
|
+
conflict_resolution: params.conflictResolution ?? "preferred_side",
|
|
68
75
|
fields_from_theirs: [...params.fieldsFromTheirs],
|
|
69
76
|
union_fields: [...params.unionFields],
|
|
70
77
|
decisions: structuredClone(params.decisions),
|
|
@@ -75,7 +82,7 @@ export async function writeMergeReceipt(params) {
|
|
|
75
82
|
await writeFileAtomic(path.join(directory, receiptFileName(receipt.id)), `${JSON.stringify(receipt, null, 2)}\n`);
|
|
76
83
|
return receipt;
|
|
77
84
|
}
|
|
78
|
-
/** Read
|
|
85
|
+
/** Read clone-local receipts with explicit reconciled/lossless classification controls. */
|
|
79
86
|
export async function listMergeReceipts(cwd, options = {}) {
|
|
80
87
|
const directory = await resolveReceiptDirectory(cwd);
|
|
81
88
|
if (directory === null || !(await pathExists(directory))) {
|
|
@@ -95,9 +102,16 @@ export async function listMergeReceipts(cwd, options = {}) {
|
|
|
95
102
|
}
|
|
96
103
|
try {
|
|
97
104
|
const parsed = JSON.parse(await readFile(path.join(directory, name), "utf8"));
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
const normalizedReceipt = {
|
|
106
|
+
...parsed,
|
|
107
|
+
conflict_resolution: parsed.conflict_resolution ?? "preferred_side",
|
|
108
|
+
};
|
|
109
|
+
if (normalizedReceipt.version === 1 &&
|
|
110
|
+
(options.includeReconciled || normalizedReceipt.state === "pending") &&
|
|
111
|
+
(options.includeLossless !== false ||
|
|
112
|
+
(Array.isArray(normalizedReceipt.decisions) &&
|
|
113
|
+
normalizedReceipt.decisions.length > 0))) {
|
|
114
|
+
receipts.push(normalizedReceipt);
|
|
101
115
|
}
|
|
102
116
|
}
|
|
103
117
|
catch {
|
|
@@ -107,6 +121,17 @@ export async function listMergeReceipts(cwd, options = {}) {
|
|
|
107
121
|
}
|
|
108
122
|
return receipts.sort((left, right) => left.created_at.localeCompare(right.created_at));
|
|
109
123
|
}
|
|
124
|
+
/** Split merge provenance into receipts with discarded values and receipts whose composition was lossless. */
|
|
125
|
+
export function partitionMergeReceipts(receipts) {
|
|
126
|
+
const pendingDecisions = [];
|
|
127
|
+
const lossless = [];
|
|
128
|
+
for (const receipt of receipts) {
|
|
129
|
+
(Array.isArray(receipt.decisions) && receipt.decisions.length > 0
|
|
130
|
+
? pendingDecisions
|
|
131
|
+
: lossless).push(receipt);
|
|
132
|
+
}
|
|
133
|
+
return { pendingDecisions, lossless };
|
|
134
|
+
}
|
|
110
135
|
/** Mark a receipt as represented by a committed merge history event. */
|
|
111
136
|
export async function markMergeReceiptReconciled(cwd, receipt) {
|
|
112
137
|
const directory = await resolveReceiptDirectory(cwd);
|
|
@@ -117,7 +142,10 @@ export async function markMergeReceiptReconciled(cwd, receipt) {
|
|
|
117
142
|
}
|
|
118
143
|
/** Report pending or historical clone-local merge decisions. */
|
|
119
144
|
export async function runMergeReceiptReport(options) {
|
|
120
|
-
const receipts = await listMergeReceipts(options.cwd ?? process.cwd(),
|
|
145
|
+
const receipts = await listMergeReceipts(options.cwd ?? process.cwd(), {
|
|
146
|
+
...options,
|
|
147
|
+
includeLossless: true,
|
|
148
|
+
});
|
|
121
149
|
return {
|
|
122
150
|
ok: true,
|
|
123
151
|
count: receipts.length,
|
|
@@ -126,4 +154,4 @@ export async function runMergeReceiptReport(options) {
|
|
|
126
154
|
};
|
|
127
155
|
}
|
|
128
156
|
//# sourceMappingURL=receipts.js.map
|
|
129
|
-
//# debugId=
|
|
157
|
+
//# debugId=3ccde5c2-f743-52ac-a3fd-9590f720e1b3
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
!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]="
|
|
2
|
+
!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]="c5620467-6c8c-5702-b742-57fba9e302c5")}catch(e){}}();
|
|
3
|
+
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
4
|
+
import { PmCliError } from "../../core/shared/errors.js";
|
|
3
5
|
import { runHistoryRepair, runHistoryRepairAll, } from "../history-repair.js";
|
|
4
6
|
import { runValidate } from "../governance/validate.js";
|
|
5
|
-
import { listMergeReceipts, markMergeReceiptReconciled, summarizeMergeReceipt, } from "./receipts.js";
|
|
7
|
+
import { listMergeReceipts, markMergeReceiptReconciled, partitionMergeReceipts, summarizeMergeReceipt, } from "./receipts.js";
|
|
6
8
|
/**
|
|
7
9
|
* Preview or apply post-merge history reconciliation and immediately validate
|
|
8
10
|
* the two merge-critical invariants. The default remains explicit and safe:
|
|
@@ -11,7 +13,22 @@ import { listMergeReceipts, markMergeReceiptReconciled, summarizeMergeReceipt, }
|
|
|
11
13
|
*/
|
|
12
14
|
export async function runMergeReconcile(options, global) {
|
|
13
15
|
const dryRun = options.dryRun === true;
|
|
14
|
-
const pendingReceipts = await listMergeReceipts(process.cwd()
|
|
16
|
+
const pendingReceipts = await listMergeReceipts(process.cwd(), {
|
|
17
|
+
includeLossless: true,
|
|
18
|
+
});
|
|
19
|
+
const { pendingDecisions: discardedReceipts } = partitionMergeReceipts(pendingReceipts);
|
|
20
|
+
if (!dryRun && options.force !== true && discardedReceipts.length > 0) {
|
|
21
|
+
throw new PmCliError(`Merge reconciliation would accept ${discardedReceipts.length} receipt(s) containing discarded scalar values. Review pm merge report and rerun with --force only after deciding which values to retain or re-apply.`, EXIT_CODE.CONFLICT, {
|
|
22
|
+
code: "merge_reconcile_discards_require_acceptance",
|
|
23
|
+
required: "Explicitly review every discarded field before accepting reconciliation.",
|
|
24
|
+
nextSteps: discardedReceipts.map((receipt) => `Review receipt ${receipt.id} for ${receipt.item_id}: ${receipt.decisions
|
|
25
|
+
.map((decision) => decision.field)
|
|
26
|
+
.join(", ")}.`),
|
|
27
|
+
recovery: {
|
|
28
|
+
suggested_retry: "pm merge reconcile --dry-run",
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
15
32
|
const receiptsByItem = pendingReceipts.reduce((groups, receipt) => {
|
|
16
33
|
(groups[receipt.item_id] ??= []).push(receipt);
|
|
17
34
|
return groups;
|
|
@@ -106,4 +123,4 @@ export async function runMergeReconcile(options, global) {
|
|
|
106
123
|
};
|
|
107
124
|
}
|
|
108
125
|
//# sourceMappingURL=reconcile.js.map
|
|
109
|
-
//# debugId=
|
|
126
|
+
//# debugId=c5620467-6c8c-5702-b742-57fba9e302c5
|
|
@@ -100,6 +100,8 @@ export interface ItemDocumentMergeResult {
|
|
|
100
100
|
conflict_decisions: ItemMergeConflictDecision[];
|
|
101
101
|
/** Which side unresolvable conflicts were resolved toward. */
|
|
102
102
|
preferred: MergePreferredSide;
|
|
103
|
+
/** Scalar-conflict selection contract used for this merge. */
|
|
104
|
+
conflict_resolution: "preferred_side" | "stable_value_order";
|
|
103
105
|
}
|
|
104
106
|
/**
|
|
105
107
|
* Field-aware three-way merge of one tracker item document. Commutative
|
|
@@ -107,8 +109,8 @@ export interface ItemDocumentMergeResult {
|
|
|
107
109
|
* concurrent appends never conflict; `updated_at` resolves to the latest
|
|
108
110
|
* timestamp so disjoint-field edits never collide on the shared freshness
|
|
109
111
|
* scalar; every other metadata field and the body use classic three-way
|
|
110
|
-
* resolution. Unresolvable both-sides-changed conflicts
|
|
111
|
-
*
|
|
112
|
+
* resolution. Unresolvable both-sides-changed conflicts use the configured
|
|
113
|
+
* scalar policy but remain reported in `conflict_fields`, and the merged output
|
|
112
114
|
* is always canonically serialized — count-prefixed TOON array headers are
|
|
113
115
|
* recomputed, so the hand-resolution corruption class (stale `notes[N]`
|
|
114
116
|
* headers) cannot be produced by this merge.
|
|
@@ -116,6 +118,8 @@ export interface ItemDocumentMergeResult {
|
|
|
116
118
|
export declare function mergeItemDocuments(baseRaw: string, oursRaw: string, theirsRaw: string, options?: ItemDocumentFormatOptions & {
|
|
117
119
|
/** Side that wins unresolvable conflicts (default "ours"). */
|
|
118
120
|
preferred?: MergePreferredSide;
|
|
121
|
+
/** Direction-independent scalar selection used by the Git driver. */
|
|
122
|
+
conflictResolution?: "preferred_side" | "stable_value_order";
|
|
119
123
|
}): ItemDocumentMergeResult;
|
|
120
124
|
/** Documents the JSON document merge result payload exchanged by command, SDK, and package integrations. */
|
|
121
125
|
export interface JsonDocumentMergeResult {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* definition for multi-branch agent workflows.
|
|
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]="f6f04eec-0698-5e5b-a40e-de3a4be89f95")}catch(e){}}();
|
|
13
13
|
import { historyEntriesToRaw, reanchorHistoryEntries, } from "../../core/history/replay.js";
|
|
14
14
|
import { canonicalDocument, parseItemDocument, serializeItemDocument, } from "../../core/item/item-format.js";
|
|
15
15
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
@@ -339,6 +339,18 @@ function mergeScalarThreeWay(base, ours, theirs, preferred) {
|
|
|
339
339
|
conflict: true,
|
|
340
340
|
};
|
|
341
341
|
}
|
|
342
|
+
function mergeItemScalarThreeWay(base, ours, theirs, preferred, conflictResolution) {
|
|
343
|
+
const outcome = mergeScalarThreeWay(base, ours, theirs, preferred);
|
|
344
|
+
if (!outcome.conflict || conflictResolution === "preferred_side") {
|
|
345
|
+
return outcome;
|
|
346
|
+
}
|
|
347
|
+
const retainTheirs = stableStringify(theirs).localeCompare(stableStringify(ours)) < 0;
|
|
348
|
+
return {
|
|
349
|
+
value: retainTheirs ? theirs : ours,
|
|
350
|
+
from_theirs: retainTheirs,
|
|
351
|
+
conflict: true,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
342
354
|
function toMetadataRecord(document) {
|
|
343
355
|
return { ...document.metadata };
|
|
344
356
|
}
|
|
@@ -350,7 +362,7 @@ function parseItemMergeSide(raw, label, options) {
|
|
|
350
362
|
throw new PmCliError(`Item merge input (${label}) is not a readable item document: ${String(error)}`, EXIT_CODE.GENERIC_FAILURE);
|
|
351
363
|
}
|
|
352
364
|
}
|
|
353
|
-
function mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferred) {
|
|
365
|
+
function mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferred, conflictResolution) {
|
|
354
366
|
const unionFieldSet = new Set(ITEM_UNION_COLLECTION_FIELDS);
|
|
355
367
|
const latestFieldSet = new Set(ITEM_LATEST_TIMESTAMP_FIELDS);
|
|
356
368
|
const fieldNames = [
|
|
@@ -382,7 +394,7 @@ function mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferre
|
|
|
382
394
|
accumulator.merged[field] = latestTimestamp(oursValue, theirsValue);
|
|
383
395
|
continue;
|
|
384
396
|
}
|
|
385
|
-
const outcome =
|
|
397
|
+
const outcome = mergeItemScalarThreeWay(baseValue, oursValue, theirsValue, preferred, conflictResolution);
|
|
386
398
|
if (outcome.value !== undefined) {
|
|
387
399
|
accumulator.merged[field] = outcome.value;
|
|
388
400
|
}
|
|
@@ -394,7 +406,7 @@ function mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferre
|
|
|
394
406
|
ours: oursValue,
|
|
395
407
|
theirs: theirsValue,
|
|
396
408
|
retained: outcome.value,
|
|
397
|
-
discarded:
|
|
409
|
+
discarded: outcome.from_theirs ? oursValue : theirsValue,
|
|
398
410
|
});
|
|
399
411
|
}
|
|
400
412
|
else if (outcome.from_theirs) {
|
|
@@ -409,14 +421,15 @@ function mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferre
|
|
|
409
421
|
* concurrent appends never conflict; `updated_at` resolves to the latest
|
|
410
422
|
* timestamp so disjoint-field edits never collide on the shared freshness
|
|
411
423
|
* scalar; every other metadata field and the body use classic three-way
|
|
412
|
-
* resolution. Unresolvable both-sides-changed conflicts
|
|
413
|
-
*
|
|
424
|
+
* resolution. Unresolvable both-sides-changed conflicts use the configured
|
|
425
|
+
* scalar policy but remain reported in `conflict_fields`, and the merged output
|
|
414
426
|
* is always canonically serialized — count-prefixed TOON array headers are
|
|
415
427
|
* recomputed, so the hand-resolution corruption class (stale `notes[N]`
|
|
416
428
|
* headers) cannot be produced by this merge.
|
|
417
429
|
*/
|
|
418
430
|
export function mergeItemDocuments(baseRaw, oursRaw, theirsRaw, options = {}) {
|
|
419
431
|
const preferred = options.preferred ?? "ours";
|
|
432
|
+
const conflictResolution = options.conflictResolution ?? "preferred_side";
|
|
420
433
|
// An empty base means both branches created the file independently
|
|
421
434
|
// (add/add); three-way falls back to treating every differing field as an
|
|
422
435
|
// ours/theirs decision, which the scalar resolver already models.
|
|
@@ -429,8 +442,8 @@ export function mergeItemDocuments(baseRaw, oursRaw, theirsRaw, options = {}) {
|
|
|
429
442
|
: {};
|
|
430
443
|
const oursRecord = toMetadataRecord(ours);
|
|
431
444
|
const theirsRecord = toMetadataRecord(theirs);
|
|
432
|
-
const { merged, conflictFields, fieldsFromTheirs, unionFields, conflictDecisions, } = mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferred);
|
|
433
|
-
const bodyOutcome =
|
|
445
|
+
const { merged, conflictFields, fieldsFromTheirs, unionFields, conflictDecisions, } = mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferred, conflictResolution);
|
|
446
|
+
const bodyOutcome = mergeItemScalarThreeWay(hasBase ? base.body : "", ours.body, theirs.body, preferred, conflictResolution);
|
|
434
447
|
if (bodyOutcome.conflict) {
|
|
435
448
|
conflictFields.push("body");
|
|
436
449
|
conflictDecisions.push({
|
|
@@ -439,7 +452,7 @@ export function mergeItemDocuments(baseRaw, oursRaw, theirsRaw, options = {}) {
|
|
|
439
452
|
ours: ours.body,
|
|
440
453
|
theirs: theirs.body,
|
|
441
454
|
retained: bodyOutcome.value,
|
|
442
|
-
discarded:
|
|
455
|
+
discarded: bodyOutcome.from_theirs ? ours.body : theirs.body,
|
|
443
456
|
});
|
|
444
457
|
}
|
|
445
458
|
else if (bodyOutcome.from_theirs) {
|
|
@@ -456,6 +469,7 @@ export function mergeItemDocuments(baseRaw, oursRaw, theirsRaw, options = {}) {
|
|
|
456
469
|
union_fields: unionFields,
|
|
457
470
|
conflict_decisions: conflictDecisions,
|
|
458
471
|
preferred,
|
|
472
|
+
conflict_resolution: conflictResolution,
|
|
459
473
|
};
|
|
460
474
|
}
|
|
461
475
|
function isPlainObject(value) {
|
|
@@ -611,4 +625,4 @@ export function mergeJsonDocuments(baseRaw, oursRaw, theirsRaw, options = {}) {
|
|
|
611
625
|
};
|
|
612
626
|
}
|
|
613
627
|
//# sourceMappingURL=three-way.js.map
|
|
614
|
-
//# debugId=
|
|
628
|
+
//# debugId=f6f04eec-0698-5e5b-a40e-de3a4be89f95
|