@unbrained/pm-cli 2026.9.6 → 2026.9.8
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/.agents/skills/pm-developer/SKILL.md +12 -4
- package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
- package/.agents/skills/pm-extensions/SKILL.md +6 -0
- package/.agents/skills/pm-sdk/SKILL.md +11 -2
- package/.agents/skills/pm-user/SKILL.md +5 -0
- package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +218 -182
- package/dist/cli/after-command-context-usage.js +1 -48
- package/dist/cli/argv-utils.js +1 -40
- package/dist/cli/bootstrap-args.js +1 -9
- package/dist/cli/bundle-integrity.js +2 -110
- package/dist/cli/commander-usage.js +11 -771
- package/dist/cli/commands/activity.js +1 -9
- package/dist/cli/commands/aggregate.js +1 -5
- package/dist/cli/commands/append.js +1 -5
- package/dist/cli/commands/claim.js +1 -5
- package/dist/cli/commands/close-many.js +1 -5
- package/dist/cli/commands/close.js +1 -9
- package/dist/cli/commands/comments.js +1 -5
- package/dist/cli/commands/config.js +1 -9
- package/dist/cli/commands/context.js +1 -9
- package/dist/cli/commands/contracts.js +1 -5
- package/dist/cli/commands/copy.js +1 -9
- package/dist/cli/commands/create.js +1 -9
- package/dist/cli/commands/delete.js +1 -9
- package/dist/cli/commands/deps.js +1 -9
- package/dist/cli/commands/docs.js +1 -9
- package/dist/cli/commands/duplicates.js +1 -9
- package/dist/cli/commands/eval.js +1 -9
- package/dist/cli/commands/extension/describe.js +1 -5
- package/dist/cli/commands/extension/scaffold.js +1 -5
- package/dist/cli/commands/extension/shared.js +1 -5
- package/dist/cli/commands/extension.js +1 -9
- package/dist/cli/commands/files.js +1 -9
- package/dist/cli/commands/focus.js +1 -9
- package/dist/cli/commands/gc.js +1 -9
- package/dist/cli/commands/get.js +1 -9
- package/dist/cli/commands/graph.js +1 -10
- package/dist/cli/commands/health.js +1 -9
- package/dist/cli/commands/history-compact.js +1 -10
- package/dist/cli/commands/history-redact.js +1 -11
- package/dist/cli/commands/history-repair.js +1 -10
- package/dist/cli/commands/history.js +1 -5
- package/dist/cli/commands/index.js +1 -58
- package/dist/cli/commands/init-agent-guidance.js +1 -9
- package/dist/cli/commands/init.js +1 -9
- package/dist/cli/commands/learnings.js +1 -5
- package/dist/cli/commands/lifecycle-transitions.js +1 -5
- package/dist/cli/commands/list.js +1 -9
- package/dist/cli/commands/merge.js +1 -11
- package/dist/cli/commands/next.js +1 -9
- package/dist/cli/commands/notes.js +1 -5
- package/dist/cli/commands/plan.js +1 -9
- package/dist/cli/commands/profile.js +1 -9
- package/dist/cli/commands/restore.js +1 -9
- package/dist/cli/commands/scheduling-shortcuts.js +1 -9
- package/dist/cli/commands/schema.js +1 -10
- package/dist/cli/commands/search.js +1 -9
- package/dist/cli/commands/stats.js +1 -9
- package/dist/cli/commands/telemetry.js +1 -9
- package/dist/cli/commands/test-all.js +1 -9
- package/dist/cli/commands/test-runs.js +1 -9
- package/dist/cli/commands/test.js +1 -9
- package/dist/cli/commands/update-many.js +1 -5
- package/dist/cli/commands/update.js +1 -9
- package/dist/cli/commands/upgrade.js +1 -5
- package/dist/cli/commands/validate.js +1 -15
- package/dist/cli/context-intent-invocation.js +1 -20
- package/dist/cli/description-stdin.js +1 -17
- package/dist/cli/error-guidance.js +1 -1353
- package/dist/cli/extension-command-help.js +5 -636
- package/dist/cli/extension-command-options.js +1 -427
- package/dist/cli/extension-recovery.js +1 -126
- package/dist/cli/help-content.js +2 -1001
- package/dist/cli/help-json-payload.js +4 -570
- package/dist/cli/main.d.ts +4 -0
- package/dist/cli/main.js +5 -2573
- package/dist/cli/migration-gates.js +1 -289
- package/dist/cli/public.js +1 -20
- package/dist/cli/register-annotations.js +1 -270
- package/dist/cli/register-assurance.js +1 -62
- package/dist/cli/register-files-lookup.js +1 -56
- package/dist/cli/register-history-activity.d.ts +8 -0
- package/dist/cli/register-history-activity.js +2 -0
- package/dist/cli/register-history-author.js +1 -38
- package/dist/cli/register-history-maintenance.d.ts +9 -0
- package/dist/cli/register-history-maintenance.js +2 -0
- package/dist/cli/register-list-query.js +10 -943
- package/dist/cli/register-mutation-options.js +1 -9
- package/dist/cli/register-mutation.js +19 -1893
- package/dist/cli/register-operations.js +1 -920
- package/dist/cli/register-setup.js +1 -716
- package/dist/cli/register-structured-mutation.js +1 -196
- package/dist/cli/registration-helpers.js +1 -5
- package/dist/cli/runtime-compatibility-boundary.js +4 -42
- package/dist/cli/schema-registration-helpers.js +1 -73
- package/dist/cli/search-refresh.js +1 -13
- package/dist/cli/stats-analytics-json.js +1 -68
- package/dist/cli/telemetry-flush.js +1 -10
- package/dist/cli-bundle/bundle-manifest.json +164 -156
- package/dist/cli-bundle/chunks/chunk-3BZZA6A3.js +5 -0
- package/dist/cli-bundle/chunks/chunk-AMRDVX36.js +235 -0
- package/dist/cli-bundle/chunks/chunk-DAM4CBBR.js +2202 -0
- package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-FLDWYEND.js +77 -0
- package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-G5ADGQ2D.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-JAAEYHUA.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-JX4DH4WC.js → chunk-KR3RP4FH.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-LEZOUXG6.js +2 -0
- package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
- package/dist/cli-bundle/chunks/chunk-QOEKOECV.js +29 -0
- package/dist/cli-bundle/chunks/chunk-RHSFOMHU.js +2 -0
- package/dist/cli-bundle/chunks/chunk-XOD2PCB6.js +20 -0
- package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-YVEQ2AMO.js} +4 -4
- package/dist/cli-bundle/chunks/register-list-query-KSK3R63M.js +11 -0
- package/dist/cli-bundle/chunks/register-mutation-IQ5C7U6O.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-I5W3KMGB.js → register-operations-DWVHR2NC.js} +2 -2
- package/dist/cli-bundle/chunks/register-setup-BQ5SVD4B.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-3WRPWLA7.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-7MBUII7U.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-COPBO5HW.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-DUN4IXYN.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-EE5QSM4Z.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-HJVARYM3.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-IAUOUGVR.js +177 -0
- package/dist/cli-bundle/focused-chunks/chunk-KOOMJ54F.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-MZDXX7JY.js +56 -0
- package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-OPFHFGDD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-QHNETP77.js +9 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-RMWES4M6.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-RXT4P5QH.js +10 -0
- package/dist/cli-bundle/focused-chunks/chunk-SDOL6FM2.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-SQV4AAUC.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-PEFABF7E.js → chunk-WE3IUNIW.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-YALOUBWJ.js +2 -0
- package/dist/cli-bundle/main.js +20 -20
- 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 +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 +42 -42
- 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 +11 -11
- package/dist/cli.js +1 -104
- package/dist/core/checkpoint/checkpoint-gc.js +1 -169
- package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
- package/dist/core/config/nested-settings.js +1 -534
- package/dist/core/config/positional-value.js +1 -109
- package/dist/core/diagnostics/remediation.js +1 -506
- package/dist/core/extensions/activation-summary-markdown.js +2 -145
- package/dist/core/extensions/activation-summary.js +1 -92
- package/dist/core/extensions/activation-transaction.js +1 -46
- package/dist/core/extensions/capability-usage.js +1 -173
- package/dist/core/extensions/command-hook-context.js +1 -13
- package/dist/core/extensions/command-metadata-contract.js +1 -22
- package/dist/core/extensions/command-visibility-tier.js +1 -29
- package/dist/core/extensions/contribution-inventory.js +1 -173
- package/dist/core/extensions/exporter-output-contract.js +1 -66
- package/dist/core/extensions/extension-candidate.js +1 -18
- package/dist/core/extensions/extension-capability-aliases.js +1 -158
- package/dist/core/extensions/extension-hook-runtime.js +1 -699
- package/dist/core/extensions/extension-policy.js +1 -599
- package/dist/core/extensions/extension-registries.js +1 -62
- package/dist/core/extensions/extension-runtime-helpers.js +1 -33
- package/dist/core/extensions/extension-types.js +1 -102
- package/dist/core/extensions/flag-definition-validation.js +1 -52
- package/dist/core/extensions/flag-value-types.js +1 -64
- package/dist/core/extensions/index.js +1 -526
- package/dist/core/extensions/item-field-types.js +1 -39
- package/dist/core/extensions/item-fields.js +1 -261
- package/dist/core/extensions/loader.js +1 -2223
- package/dist/core/extensions/manifest-schema.js +1 -69
- package/dist/core/extensions/module-graph-snapshot.js +1 -33
- package/dist/core/extensions/preflight-ownership.js +1 -41
- package/dist/core/extensions/registration-validation.js +1 -82
- package/dist/core/extensions/registration-values.js +1 -209
- package/dist/core/extensions/reserved-host-flags.js +1 -36
- package/dist/core/extensions/runtime-registrations.js +1 -67
- package/dist/core/extensions/service-ownership.js +1 -19
- package/dist/core/extensions/version-compat.js +1 -216
- package/dist/core/fs/fs-utils.js +2 -158
- package/dist/core/fs/host-environment-errors.js +1 -141
- package/dist/core/fs/index.js +1 -9
- package/dist/core/fs/path-utils.js +1 -17
- package/dist/core/governance/content-fields.js +1 -160
- package/dist/core/governance/issue-codes.js +1 -151
- package/dist/core/governance/metadata-coverage.js +1 -358
- package/dist/core/history/drift-cache.js +3 -72
- package/dist/core/history/drift-scan.js +1 -342
- package/dist/core/history/event-classification.js +1 -109
- package/dist/core/history/event-index.js +8 -784
- package/dist/core/history/history-compact-bulk.js +1 -104
- package/dist/core/history/history-diff.js +1 -158
- package/dist/core/history/history-rewrite.d.ts +6 -1
- package/dist/core/history/history-rewrite.js +1 -107
- package/dist/core/history/history-storage-stats.js +1 -102
- package/dist/core/history/history-stream-policy.js +1 -62
- package/dist/core/history/history.js +2 -617
- package/dist/core/history/identity.js +1 -30
- package/dist/core/history/index.js +1 -9
- package/dist/core/history/projection.js +1 -196
- package/dist/core/history/read.d.ts +9 -0
- package/dist/core/history/read.js +1 -57
- package/dist/core/history/replay.js +2 -439
- package/dist/core/history/version-address.js +1 -32
- package/dist/core/history/workspace-history.js +2 -433
- package/dist/core/io/body-file.js +1 -62
- package/dist/core/io/bulk-ids-input.js +1 -112
- package/dist/core/item/actionability.js +1 -327
- package/dist/core/item/dependency-reference.js +1 -20
- package/dist/core/item/id.js +1 -112
- package/dist/core/item/index.js +1 -12
- package/dist/core/item/item-format-version.js +1 -78
- package/dist/core/item/item-format.js +5 -1473
- package/dist/core/item/item-record.js +1 -23
- package/dist/core/item/item-type-definition.js +1 -133
- package/dist/core/item/parent-reference-policy.js +1 -57
- package/dist/core/item/parse.js +2 -603
- package/dist/core/item/plan-lifecycle.js +1 -19
- package/dist/core/item/priority.js +1 -61
- package/dist/core/item/sprint-release-format.js +1 -38
- package/dist/core/item/status-filter.js +1 -115
- package/dist/core/item/status.js +1 -43
- package/dist/core/item/toon-decode.js +1 -29
- package/dist/core/item/type-registry.js +1 -715
- package/dist/core/item/type-synonyms.js +1 -38
- package/dist/core/lock/index.js +1 -9
- package/dist/core/lock/lock-gc.js +1 -240
- package/dist/core/lock/lock.js +3 -590
- package/dist/core/output/mutation-projection.js +1 -217
- package/dist/core/output/output-control.js +1 -25
- package/dist/core/output/output.js +11 -494
- package/dist/core/output/query-summary.js +1 -58
- package/dist/core/output/tabular.js +1 -77
- package/dist/core/packages/manifest.js +1 -244
- package/dist/core/packages/root.js +1 -84
- package/dist/core/profile/profile-describe.js +1 -83
- package/dist/core/profile/profile-lint.js +1 -415
- package/dist/core/profile/profile-plan.js +0 -0
- package/dist/core/profile/profile-presets.js +1 -370
- package/dist/core/reproducibility/context.js +1 -82
- package/dist/core/schema/fields-file.js +2 -288
- package/dist/core/schema/item-types-file.js +2 -296
- package/dist/core/schema/runtime-field-filters.js +1 -49
- package/dist/core/schema/runtime-field-values.js +1 -313
- package/dist/core/schema/runtime-schema.js +2 -826
- package/dist/core/schema/status-defs-file.js +2 -227
- package/dist/core/schema/status-token.js +1 -31
- package/dist/core/schema/type-inference.js +1 -95
- package/dist/core/schema/type-presets.js +1 -87
- package/dist/core/schema/type-workflows.js +1 -104
- package/dist/core/search/background-refresh.js +2 -286
- package/dist/core/search/bm25.js +1 -146
- package/dist/core/search/cache.js +2 -534
- package/dist/core/search/corpus.js +1 -311
- package/dist/core/search/embedding-batches.js +1 -163
- package/dist/core/search/eval.js +1 -225
- package/dist/core/search/http-client.js +1 -75
- package/dist/core/search/providers.js +1 -242
- package/dist/core/search/relevance.js +1 -244
- package/dist/core/search/semantic-defaults.js +1 -199
- package/dist/core/search/staleness.js +1 -30
- package/dist/core/search/vector-stores.js +2 -664
- package/dist/core/search/vectorization-metadata.js +1 -81
- package/dist/core/sentry/helpers.js +1 -272
- package/dist/core/sentry/instrument.js +1 -387
- package/dist/core/session/session-state.js +1 -260
- package/dist/core/shared/agent-session-context.js +1 -133
- package/dist/core/shared/author.js +1 -1172
- package/dist/core/shared/command-types.js +1 -4
- package/dist/core/shared/conflict-markers.js +1 -31
- package/dist/core/shared/constants.js +1 -405
- package/dist/core/shared/errors.js +1 -20
- package/dist/core/shared/html-entity-decode.js +1 -131
- package/dist/core/shared/index.js +1 -12
- package/dist/core/shared/item-metadata-contract.js +1 -89
- package/dist/core/shared/lazy-module.js +1 -16
- package/dist/core/shared/levenshtein.js +1 -61
- package/dist/core/shared/memo.js +1 -19
- package/dist/core/shared/numeric-parsers.js +1 -20
- package/dist/core/shared/option-alias-visibility.js +1 -67
- package/dist/core/shared/primitives.js +1 -127
- package/dist/core/shared/serial-queue.js +1 -79
- package/dist/core/shared/serialization.js +1 -210
- package/dist/core/shared/split-comma-list.js +1 -30
- package/dist/core/shared/text-normalization.js +1 -38
- package/dist/core/shared/time.js +1 -306
- package/dist/core/store/index.js +1 -12
- package/dist/core/store/item-format-migration.js +1 -125
- package/dist/core/store/item-metadata-cache.js +1 -1116
- package/dist/core/store/item-metadata-query-index.js +9 -394
- package/dist/core/store/item-metadata-read-work.js +1 -43
- package/dist/core/store/item-store.js +1 -693
- package/dist/core/store/paths.d.ts +1 -1
- package/dist/core/store/paths.js +1 -214
- package/dist/core/store/settings-read-cache.js +1 -85
- package/dist/core/store/settings-validator.js +1 -421
- package/dist/core/store/settings.js +3 -1309
- package/dist/core/store/tracker-preflight.js +1 -141
- package/dist/core/telemetry/consent.js +5 -108
- package/dist/core/telemetry/observability.js +1 -246
- package/dist/core/telemetry/runtime.js +4 -1988
- package/dist/core/test/background-runs.js +4 -945
- package/dist/core/test/item-test-run-tracking.js +1 -63
- package/dist/core/test/run-selectors.js +1 -120
- package/dist/core/validate/estimate-defaults.js +1 -89
- package/dist/core/validate/fix-planning.js +1 -189
- package/dist/core/validate/linked-artifact-reference.js +1 -36
- package/dist/core/validate/missing-by-type.js +1 -34
- package/dist/core/validate/missing-link-owners.js +1 -95
- package/dist/core/validate/stale-file-classification.js +1 -82
- package/dist/mcp/http-server.js +5 -448
- package/dist/mcp/legacy-adapter.js +1 -77
- package/dist/mcp/runtime-capabilities.js +1 -200
- package/dist/mcp/server.js +4 -1233
- package/dist/mcp/tool-definitions.js +1 -804
- package/dist/sdk/actionability.js +1 -13
- package/dist/sdk/agent/closed-domain-contracts.js +1 -161
- package/dist/sdk/agent/command-recovery.js +1 -59
- package/dist/sdk/agent/command-suggestions.js +1 -66
- package/dist/sdk/agent/create-option-policy.js +1 -31
- package/dist/sdk/agent/identity-config.js +1 -106
- package/dist/sdk/agent/item-addressing.js +1 -207
- package/dist/sdk/agent/refusal-closure-census.js +1 -151
- package/dist/sdk/agent/refusal-closure.js +1 -133
- package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
- package/dist/sdk/agent/refusal-reachability.js +1 -593
- package/dist/sdk/agent/subcommand-recovery.js +1 -83
- package/dist/sdk/agent/task-transcript-contracts.js +1 -197
- package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
- package/dist/sdk/agent-capability-contracts.js +1 -428
- package/dist/sdk/agent-session-context.js +1 -9
- package/dist/sdk/annotations.js +1 -448
- package/dist/sdk/author-attribution.js +1 -468
- package/dist/sdk/authoring.js +1 -20
- package/dist/sdk/cli-bootstrap.js +1 -838
- package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
- package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
- package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
- package/dist/sdk/cli-contracts/command-aliases.js +1 -107
- package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
- package/dist/sdk/cli-contracts/commander-types.js +1 -159
- package/dist/sdk/cli-contracts/completeness.js +1 -393
- package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
- package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
- package/dist/sdk/cli-contracts/string-lists.js +1 -16
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
- package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
- package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +1 -17
- package/dist/sdk/cli-program.js +1 -49
- package/dist/sdk/command-line.d.ts +2 -5
- package/dist/sdk/command-line.js +1 -78
- package/dist/sdk/comments.js +1 -133
- package/dist/sdk/compile-cache.js +1 -73
- package/dist/sdk/completion.js +157 -837
- package/dist/sdk/compose.js +1 -1090
- package/dist/sdk/config.js +1 -1204
- package/dist/sdk/context/recency.js +1 -33
- package/dist/sdk/context/semantic-session-attribution.js +1 -82
- package/dist/sdk/context/usage-egress.js +1 -29
- package/dist/sdk/context/usage-ledger.js +3 -185
- package/dist/sdk/context-intent-contracts.js +1 -709
- package/dist/sdk/context-intent-runtime.js +1 -115
- package/dist/sdk/context-packing.js +1 -218
- package/dist/sdk/context-relevance.js +1 -503
- package/dist/sdk/context-signal-store.js +2 -426
- package/dist/sdk/context-usage.js +1 -367
- package/dist/sdk/contracts.js +1 -23
- package/dist/sdk/core-governance.js +1 -14
- package/dist/sdk/core.js +1 -14
- package/dist/sdk/corpus-shape.js +1 -401
- package/dist/sdk/define.js +1 -220
- package/dist/sdk/dependencies.js +1 -718
- package/dist/sdk/dependency-flag-validation.js +1 -156
- package/dist/sdk/dependency-provenance.js +1 -135
- package/dist/sdk/docs.js +1 -14
- package/dist/sdk/duplicates.js +1 -40
- package/dist/sdk/environment/agent-environment.js +1 -466
- package/dist/sdk/environment/host-environment-errors.js +1 -8
- package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
- package/dist/sdk/environment/source-context.js +1 -28
- package/dist/sdk/environment/tracker-preflight.js +1 -9
- package/dist/sdk/error-code-catalog.js +1 -153
- package/dist/sdk/error-runtime.js +1 -58
- package/dist/sdk/errors.js +1 -58
- package/dist/sdk/eval.js +1 -190
- package/dist/sdk/extension/author-manifest.js +1 -92
- package/dist/sdk/extension/bundled-catalog.js +1 -332
- package/dist/sdk/extension/concurrency.js +1 -25
- package/dist/sdk/extension/copy-scope.d.ts +2 -0
- package/dist/sdk/extension/copy-scope.js +2 -0
- package/dist/sdk/extension/custom-field-collisions.js +1 -30
- package/dist/sdk/extension/describe.js +3 -189
- package/dist/sdk/extension/doctor.js +1 -606
- package/dist/sdk/extension/install-plan.d.ts +69 -0
- package/dist/sdk/extension/install-plan.js +2 -0
- package/dist/sdk/extension/install-receipts.d.ts +7 -0
- package/dist/sdk/extension/install-receipts.js +2 -0
- package/dist/sdk/extension/install-runtime.js +3 -313
- package/dist/sdk/extension/install-snapshot.js +1 -66
- package/dist/sdk/extension/install-sources.js +5 -1057
- package/dist/sdk/extension/managed-state.js +2 -252
- package/dist/sdk/extension/migrations.js +2 -174
- package/dist/sdk/extension/output-ownership.js +1 -25
- package/dist/sdk/extension/runtime-summary.js +1 -18
- package/dist/sdk/extension/scaffold.js +4 -2308
- package/dist/sdk/extension/shared.js +1 -147
- package/dist/sdk/extension/source-resolution.js +1 -65
- package/dist/sdk/extension/update-check.js +1 -67
- package/dist/sdk/extension-command-context.js +1 -44
- package/dist/sdk/extension-contracts.js +1 -73
- package/dist/sdk/extension.d.ts +7 -2
- package/dist/sdk/extension.js +1 -2196
- package/dist/sdk/files.js +1 -535
- package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
- package/dist/sdk/flag-invocation-contracts.js +1 -344
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
- package/dist/sdk/generated-error-code-catalog.js +1 -16
- package/dist/sdk/governance/assurance-action-contracts.js +1 -4
- package/dist/sdk/governance/assurance-action.js +1 -411
- package/dist/sdk/governance/assurance-limits.js +1 -10
- package/dist/sdk/governance/assurance-mutation-error.js +1 -81
- package/dist/sdk/governance/assurance-presets.js +1 -135
- package/dist/sdk/governance/assurance-runtime.js +1 -238
- package/dist/sdk/governance/assurance.js +4 -1182
- package/dist/sdk/governance/boundary-fixtures.js +1 -200
- package/dist/sdk/governance/coverage-assurance.js +1 -60
- package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
- package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
- package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
- package/dist/sdk/governance/defect-recurrence.js +1 -623
- package/dist/sdk/governance/extension-host-version.js +1 -115
- package/dist/sdk/governance/gc.js +1 -368
- package/dist/sdk/governance/health.js +1 -2367
- package/dist/sdk/governance/hierarchy-validation.js +1 -108
- package/dist/sdk/governance/linked-file-report.js +1 -71
- package/dist/sdk/governance/merge-receipt-history.js +1 -206
- package/dist/sdk/governance/provenance-health.js +1 -282
- package/dist/sdk/governance/reindex.js +4 -761
- package/dist/sdk/governance/stale-work.js +1 -82
- package/dist/sdk/governance/status-role-diagnostics.js +1 -35
- package/dist/sdk/governance/storage-integrity.js +1 -280
- package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
- package/dist/sdk/governance/upgrade.js +2 -327
- package/dist/sdk/governance/validate-history-drift.js +1 -81
- package/dist/sdk/governance/validate-item-reader.js +1 -17
- package/dist/sdk/governance/validate-normalization.js +1 -36
- package/dist/sdk/governance/validate.js +1 -2261
- package/dist/sdk/governance/workspace-position.js +1 -163
- package/dist/sdk/governance.d.ts +1 -0
- package/dist/sdk/governance.js +1 -31
- package/dist/sdk/graph/adapter.js +1 -181
- package/dist/sdk/graph/analytics.js +1 -474
- package/dist/sdk/graph/assembly.js +1 -377
- package/dist/sdk/graph/cache.js +1 -160
- package/dist/sdk/graph/centrality.js +1 -258
- package/dist/sdk/graph/conformance.js +1 -130
- package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
- package/dist/sdk/graph/deadline-scheduling.js +2 -0
- package/dist/sdk/graph/durable-cache.d.ts +1 -1
- package/dist/sdk/graph/durable-cache.js +1 -361
- package/dist/sdk/graph/governance-contracts.js +1 -34
- package/dist/sdk/graph/governance.d.ts +13 -1
- package/dist/sdk/graph/governance.js +1 -735
- package/dist/sdk/graph/hierarchy-integrity.js +1 -310
- package/dist/sdk/graph/index.d.ts +3 -2
- package/dist/sdk/graph/index.js +1 -26
- package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
- package/dist/sdk/graph/lifecycle-coverage.js +2 -0
- package/dist/sdk/graph/mutation-advisory.js +1 -176
- package/dist/sdk/graph/remediation.js +1 -197
- package/dist/sdk/graph/run.d.ts +15 -1
- package/dist/sdk/graph/run.js +1 -768
- package/dist/sdk/graph/scheduling.js +1 -124
- package/dist/sdk/graph/traversal.js +1 -284
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
- package/dist/sdk/graph.js +1 -15
- package/dist/sdk/guide-topics.js +1 -707
- package/dist/sdk/guide.js +1 -279
- package/dist/sdk/history/maintenance.d.ts +71 -0
- package/dist/sdk/history/maintenance.js +2 -0
- package/dist/sdk/history/salvage.js +2 -247
- package/dist/sdk/history/subject.d.ts +19 -0
- package/dist/sdk/history/subject.js +2 -0
- package/dist/sdk/history-analytics.js +1 -282
- package/dist/sdk/history-compact.js +1 -527
- package/dist/sdk/history-mcp.js +1 -68
- package/dist/sdk/history-provenance.js +1 -182
- package/dist/sdk/history-read.js +1 -96
- package/dist/sdk/history-redact.d.ts +1 -14
- package/dist/sdk/history-redact.js +1 -643
- package/dist/sdk/history-repair.d.ts +5 -0
- package/dist/sdk/history-repair.js +1 -657
- package/dist/sdk/improvement-ledger-validation.js +1 -62
- package/dist/sdk/improvement-ledger.js +2 -257
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +1 -183
- package/dist/sdk/init-agent-guidance.js +2 -496
- package/dist/sdk/init.js +2 -820
- package/dist/sdk/invocation-author.js +1 -39
- package/dist/sdk/item-children.js +1 -90
- package/dist/sdk/item-metadata-index.js +1 -15
- package/dist/sdk/item-schedule.js +1 -27
- package/dist/sdk/item-transaction.js +1 -396
- package/dist/sdk/learnings.js +1 -29
- package/dist/sdk/lifecycle/append.js +2 -53
- package/dist/sdk/lifecycle/claim.d.ts +2 -0
- package/dist/sdk/lifecycle/claim.js +1 -242
- package/dist/sdk/lifecycle/close-many.js +1 -438
- package/dist/sdk/lifecycle/close.js +1 -468
- package/dist/sdk/lifecycle/copy.js +1 -212
- package/dist/sdk/lifecycle/create.js +1 -1949
- package/dist/sdk/lifecycle/delete.js +1 -45
- package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
- package/dist/sdk/lifecycle/focus.js +1 -91
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
- package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
- package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
- package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
- package/dist/sdk/lifecycle/mcp-actions.js +1 -51
- package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
- package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
- package/dist/sdk/lifecycle/plan.js +1 -1606
- package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
- package/dist/sdk/lifecycle/reopen.js +1 -68
- package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
- package/dist/sdk/lifecycle/restore.d.ts +1 -0
- package/dist/sdk/lifecycle/restore.js +1 -330
- package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
- package/dist/sdk/lifecycle/update-many.js +1 -861
- package/dist/sdk/lifecycle/update.js +1 -2136
- package/dist/sdk/lifecycle-completion.js +1 -92
- package/dist/sdk/lifecycle-policy.js +1 -120
- package/dist/sdk/linked-artifacts.js +1 -530
- package/dist/sdk/mcp/apps.js +4 -133
- package/dist/sdk/mcp/authorization.js +1 -404
- package/dist/sdk/mcp/discovery.js +1 -494
- package/dist/sdk/mcp/interactions.js +1 -336
- package/dist/sdk/mcp/protocol.d.ts +7 -0
- package/dist/sdk/mcp/protocol.js +1 -184
- package/dist/sdk/mcp/skills.js +1 -389
- package/dist/sdk/mcp/subscriptions.js +1 -211
- package/dist/sdk/mcp/tasks.js +2 -430
- package/dist/sdk/mcp/transport.js +1 -260
- package/dist/sdk/merge/abandoned-receipts.js +1 -46
- package/dist/sdk/merge/driver.js +1 -212
- package/dist/sdk/merge/index.js +1 -16
- package/dist/sdk/merge/install.js +3 -561
- package/dist/sdk/merge/receipt-file-boundary.js +1 -46
- package/dist/sdk/merge/receipt-operation.js +1 -96
- package/dist/sdk/merge/receipt-schema.js +1 -397
- package/dist/sdk/merge/receipts.js +4 -525
- package/dist/sdk/merge/reconcile.js +1 -352
- package/dist/sdk/merge/three-way.js +3 -775
- package/dist/sdk/merge.js +1 -10
- package/dist/sdk/mutation-events.js +1 -292
- package/dist/sdk/mutation-guard.js +1 -216
- package/dist/sdk/notes.js +1 -139
- package/dist/sdk/output-contracts.js +1 -172
- package/dist/sdk/output-projection.js +1 -430
- package/dist/sdk/output-token-accounting.js +1 -140
- package/dist/sdk/output.js +1 -64
- package/dist/sdk/ownership-source.js +1 -21
- package/dist/sdk/package-import-adapters.js +1 -442
- package/dist/sdk/package-migrations.js +1 -20
- package/dist/sdk/package-runtime-options.js +1 -80
- package/dist/sdk/pagination.js +1 -162
- package/dist/sdk/profile.js +1 -454
- package/dist/sdk/provenance.js +1 -258
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/activity.js +1 -401
- package/dist/sdk/query/aggregate.d.ts +16 -0
- package/dist/sdk/query/aggregate.js +1 -390
- package/dist/sdk/query/calendar.js +1 -964
- package/dist/sdk/query/complete-list.js +1 -215
- package/dist/sdk/query/context.js +1 -1702
- package/dist/sdk/query/duplicate-candidates.js +1 -70
- package/dist/sdk/query/get.js +1 -450
- package/dist/sdk/query/history.js +1 -186
- package/dist/sdk/query/item-filter-options.js +1 -9
- package/dist/sdk/query/light-metadata.js +1 -18
- package/dist/sdk/query/list-filter-shared.js +1 -81
- package/dist/sdk/query/list.js +1 -1304
- package/dist/sdk/query/multi-value-filters.js +1 -78
- package/dist/sdk/query/next.js +1 -513
- package/dist/sdk/query/parsers.js +1 -44
- package/dist/sdk/query/projection-contracts.js +1 -184
- package/dist/sdk/query/search-contracts.js +1 -230
- package/dist/sdk/query/search-pagination.js +1 -35
- package/dist/sdk/query/search-rendering.js +1 -105
- package/dist/sdk/query/search.js +2 -1987
- package/dist/sdk/query.js +1 -35
- package/dist/sdk/read-output/continuation.js +1 -194
- package/dist/sdk/read-output-budget.js +1 -135
- package/dist/sdk/read-output-contracts.js +1 -1225
- package/dist/sdk/read-output-rows.js +1 -186
- package/dist/sdk/read-output-session.js +1 -208
- package/dist/sdk/relationship-analytics.js +1 -410
- package/dist/sdk/relationship-context.js +1 -284
- package/dist/sdk/relationship-history.js +4 -519
- package/dist/sdk/relationship-kinds/contract.js +1 -22
- package/dist/sdk/relationship-migration.js +1 -77
- package/dist/sdk/relationships.js +1 -579
- package/dist/sdk/reproducibility/process.js +1 -87
- package/dist/sdk/runtime-action-aliases.js +1 -59
- package/dist/sdk/runtime-extended-actions.js +1 -177
- package/dist/sdk/runtime-input.js +1 -614
- package/dist/sdk/runtime-primitives.js +1 -84
- package/dist/sdk/runtime-public-contracts.js +1 -4
- package/dist/sdk/runtime-stats-options.js +1 -38
- package/dist/sdk/runtime.js +1 -1928
- package/dist/sdk/scheduling-shortcuts.js +1 -63
- package/dist/sdk/schema-migration.js +3 -856
- package/dist/sdk/schema.js +1 -1376
- package/dist/sdk/search-refresh-worker.js +1 -18
- package/dist/sdk/similarity-scoring.js +1 -53
- package/dist/sdk/similarity.js +1 -326
- package/dist/sdk/start-task-status.js +1 -14
- package/dist/sdk/stats.js +1 -270
- package/dist/sdk/structured-mutations.js +1 -580
- package/dist/sdk/telemetry-flush.js +1 -13
- package/dist/sdk/telemetry.js +1 -405
- package/dist/sdk/templates.js +2 -292
- package/dist/sdk/test/batch.js +2 -509
- package/dist/sdk/test/entry.js +1 -70
- package/dist/sdk/test/execution.js +6 -2211
- package/dist/sdk/test/linked-command-detection.js +1 -546
- package/dist/sdk/test/measurements.js +1 -91
- package/dist/sdk/test/parsers.js +1 -545
- package/dist/sdk/test/runs.js +1 -193
- package/dist/sdk/test/trust.js +2 -206
- package/dist/sdk/testing.js +4 -1391
- package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
- package/dist/sdk/traceability/source-traceability.js +1 -292
- package/dist/sdk/tracker-root-discovery.js +1 -9
- package/dist/sdk/workspace-contracts-cache.js +1 -28
- package/dist/sdk/workspace-contracts.js +1 -33
- package/dist/sdk/workspace-memory.js +2 -318
- package/dist/sdk/workspace-recipe.js +1 -71
- package/dist/sdk/workspace-snapshot.js +4 -613
- package/dist/sdk/workspace-transaction-gc.js +1 -149
- package/dist/sdk/workspace-transaction.js +2 -363
- package/dist/sdk/workspace.js +3 -127
- package/dist/types/index.js +1 -9
- package/dist/types.js +1 -245
- package/docs/AGENT_GUIDE.md +1 -1
- package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
- package/docs/EXTENSIONS.md +1 -0
- package/docs/HISTORY_MAINTENANCE.md +125 -0
- package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
- package/docs/PACKAGE_EVIDENCE.md +92 -0
- package/docs/PLANNING_MEASUREMENTS.md +183 -0
- package/docs/README.md +3 -0
- package/docs/RELEASING.md +1 -0
- package/docs/SCRIPTING.md +21 -0
- package/docs/TESTING.md +23 -0
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +5 -5
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +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/scripts/finalize-build.mjs +45 -3
- package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
- package/dist/cli-bundle/chunks/chunk-BAX2BYUW.js +0 -2111
- package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
- package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
- package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
- package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
- package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
- package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
- package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
- package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
- package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
- package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
- package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
- package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
|
@@ -1,526 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
* Raw losing values deliberately never enter the public tracker history; the
|
|
6
|
-
* history entry records hashes and provenance while this receipt preserves the
|
|
7
|
-
* value for the coordinator that performed the merge.
|
|
8
|
-
*/
|
|
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]="e7fe0fee-9519-593d-ac72-b3c7fb63563e")}catch(e){}}();
|
|
11
|
-
import { execFile } from "node:child_process";
|
|
12
|
-
import { randomUUID } from "node:crypto";
|
|
13
|
-
import { readdir, stat } from "node:fs/promises";
|
|
14
|
-
import path from "node:path";
|
|
15
|
-
import { promisify } from "node:util";
|
|
16
|
-
import { ensureDir, isFileAbsentError, isFileMissingError, pathExists, writeFileAtomic, } from "../../core/fs/fs-utils.js";
|
|
17
|
-
import { sha256Hex, stableStringify } from "../../core/shared/serialization.js";
|
|
18
|
-
import { nowIso } from "../../core/shared/time.js";
|
|
19
|
-
import { encodeItemScalarDecisionValue, hashItemScalarDecisionValue, isItemScalarMissingValue, } from "./three-way.js";
|
|
20
|
-
import { readBoundedRegularFile } from "./receipt-file-boundary.js";
|
|
21
|
-
import { DURABLE_VALUE_POLICY, durableValueEvidence, isSafeReceiptId, isMergeDecisionReceipt, isPrehashedValue, normalizeLegacyReceipt, receiptCollectionValidationPath, receiptValidationError } from "./receipt-schema.js";
|
|
22
|
-
export { isSafeReceiptId } from "./receipt-schema.js";
|
|
23
|
-
const execFileAsync = promisify(execFile);
|
|
24
|
-
const RECEIPT_FILE_MAX_BYTES = 16 * 1024 * 1024;
|
|
25
|
-
const RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT = 100;
|
|
26
|
-
/** Resolve the clone-local receipt store without crossing a Git worktree boundary. */
|
|
27
|
-
async function resolveReceiptDirectory(cwd) {
|
|
28
|
-
try {
|
|
29
|
-
const { stdout } = await execFileAsync("git", [
|
|
30
|
-
"rev-parse",
|
|
31
|
-
"--path-format=absolute",
|
|
32
|
-
"--git-path",
|
|
33
|
-
"pm-merge-receipts",
|
|
34
|
-
], { cwd, encoding: "utf8", windowsHide: true, timeout: 10_000 });
|
|
35
|
-
return stdout.trim();
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/** Derive the tracker root only when the merged item belongs to this workspace. */
|
|
42
|
-
async function resolveTrackerRootFromItemPath(cwd, itemPath) {
|
|
43
|
-
let directory = path.dirname(path.resolve(cwd, itemPath));
|
|
44
|
-
for (let depth = 0; depth < 12; depth += 1) {
|
|
45
|
-
if (await pathExists(path.join(directory, "settings.json")))
|
|
46
|
-
return directory;
|
|
47
|
-
const parent = path.dirname(directory);
|
|
48
|
-
if (parent === directory)
|
|
49
|
-
break;
|
|
50
|
-
directory = parent;
|
|
51
|
-
}
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
/** Locate the tracked durable receipt sidecar directory. */
|
|
55
|
-
function durableReceiptDirectory(pmRoot) {
|
|
56
|
-
return path.join(pmRoot, "merge-receipts");
|
|
57
|
-
}
|
|
58
|
-
/** Map a validated opaque receipt identifier to its canonical filename. */
|
|
59
|
-
function receiptFileName(id) {
|
|
60
|
-
return `${id}.json`;
|
|
61
|
-
}
|
|
62
|
-
/** Revalidate one receipt and stage its atomic reconciled-state replacement. */
|
|
63
|
-
async function prepareReceiptSettlement(params) {
|
|
64
|
-
let raw;
|
|
65
|
-
try {
|
|
66
|
-
raw = params.readReceipt
|
|
67
|
-
? await params.readReceipt(params.receiptPath)
|
|
68
|
-
: await readBoundedRegularFile(params.receiptPath, RECEIPT_FILE_MAX_BYTES);
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
if (isFileAbsentError(error))
|
|
72
|
-
return null;
|
|
73
|
-
throw error;
|
|
74
|
-
}
|
|
75
|
-
if (raw === null) {
|
|
76
|
-
throw new Error(`Receipt ${params.receiptId} settlement source is not a bounded regular file.`);
|
|
77
|
-
}
|
|
78
|
-
let parsed;
|
|
79
|
-
try {
|
|
80
|
-
parsed = normalizeLegacyReceipt(JSON.parse(raw));
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
throw new Error(`Receipt ${params.receiptId} settlement source is not valid JSON.`);
|
|
84
|
-
}
|
|
85
|
-
if (!isMergeDecisionReceipt(parsed, params.evidenceSource) ||
|
|
86
|
-
parsed.id !== params.receiptId ||
|
|
87
|
-
(params.settlement !== undefined && parsed.operation === undefined) ||
|
|
88
|
-
path.basename(params.receiptPath) !== receiptFileName(parsed.id)) {
|
|
89
|
-
throw new Error(`Receipt ${params.receiptId} settlement source failed schema or identity validation.`);
|
|
90
|
-
}
|
|
91
|
-
const { evidence_source: _evidenceSource, ...persistedReceipt } = parsed;
|
|
92
|
-
return {
|
|
93
|
-
path: params.receiptPath,
|
|
94
|
-
fingerprints: receiptProvenanceFingerprints(parsed),
|
|
95
|
-
modern: parsed.value_policy !== undefined,
|
|
96
|
-
content: `${JSON.stringify({
|
|
97
|
-
...persistedReceipt,
|
|
98
|
-
state: "reconciled",
|
|
99
|
-
reconciled_at: params.reconciledAt,
|
|
100
|
-
...(params.settlement ? { settlement: params.settlement } : {}),
|
|
101
|
-
}, null, 2)}\n`,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
/** Fingerprint immutable receipt provenance while excluding lifecycle state. */
|
|
105
|
-
function receiptProvenanceFingerprint(receipt, legacy = false) {
|
|
106
|
-
return sha256Hex(stableStringify({
|
|
107
|
-
id: receipt.id,
|
|
108
|
-
item_id: receipt.item_id,
|
|
109
|
-
item_path: receipt.item_path,
|
|
110
|
-
created_at: receipt.created_at,
|
|
111
|
-
requested_preference: receipt.requested_preference ?? receipt.preferred ?? "ours",
|
|
112
|
-
conflict_resolution: receipt.conflict_resolution ?? "preferred_side",
|
|
113
|
-
fields_from_theirs: receipt.fields_from_theirs,
|
|
114
|
-
union_fields: receipt.union_fields,
|
|
115
|
-
merged_field_hashes: receipt.merged_field_hashes ?? null,
|
|
116
|
-
operation: receipt.operation ?? null,
|
|
117
|
-
decisions: legacy
|
|
118
|
-
? receipt.decisions.map((decision) => ({
|
|
119
|
-
field: decision.field,
|
|
120
|
-
retained_hash: sha256Hex(stableStringify(encodeItemScalarDecisionValue(decision.retained))),
|
|
121
|
-
discarded_hash: sha256Hex(stableStringify(encodeItemScalarDecisionValue(decision.discarded))),
|
|
122
|
-
}))
|
|
123
|
-
: summarizeMergeReceipt(receipt).decisions,
|
|
124
|
-
}));
|
|
125
|
-
}
|
|
126
|
-
/** Compare historical plain-scalar and current presence-domain hashes without changing stored evidence. */
|
|
127
|
-
function receiptProvenanceFingerprints(receipt) {
|
|
128
|
-
const fingerprints = [receiptProvenanceFingerprint(receipt)];
|
|
129
|
-
if (receipt.value_policy === undefined &&
|
|
130
|
-
(receipt.value_availability === undefined || receipt.value_availability === "clone_local")) {
|
|
131
|
-
fingerprints.push(receiptProvenanceFingerprint(receipt, true));
|
|
132
|
-
}
|
|
133
|
-
return fingerprints;
|
|
134
|
-
}
|
|
135
|
-
/** Merge clone-local and durable lifecycle state without losing pending work. */
|
|
136
|
-
function mergeReceiptCopyLifecycle(local, durable) {
|
|
137
|
-
if (local.state === "reconciled" && durable.state === "reconciled" && local.settlement === durable.settlement) {
|
|
138
|
-
return local;
|
|
139
|
-
}
|
|
140
|
-
const { reconciled_at: _reconciledAt, settlement: _settlement, ...pendingLocal } = local;
|
|
141
|
-
return { ...pendingLocal, state: "pending" };
|
|
142
|
-
}
|
|
143
|
-
/** Convert a raw receipt into privacy-safe history context. */
|
|
144
|
-
export function summarizeMergeReceipt(receipt) {
|
|
145
|
-
return {
|
|
146
|
-
receipt_id: receipt.id,
|
|
147
|
-
item_id: receipt.item_id,
|
|
148
|
-
item_path: receipt.item_path,
|
|
149
|
-
conflict_fields: receipt.decisions.map((decision) => decision.field),
|
|
150
|
-
fields_from_theirs: receipt.fields_from_theirs,
|
|
151
|
-
union_fields: receipt.union_fields,
|
|
152
|
-
requested_preference: receipt.requested_preference ?? receipt.preferred ?? "ours",
|
|
153
|
-
requested_preference_applied: receipt.requested_preference_applied ??
|
|
154
|
-
(receipt.conflict_resolution ?? "preferred_side") === "preferred_side",
|
|
155
|
-
conflict_resolution: receipt.conflict_resolution,
|
|
156
|
-
decisions: receipt.decisions.map((decision) => ({
|
|
157
|
-
field: decision.field,
|
|
158
|
-
retained_hash: isPrehashedValue(decision.retained) ??
|
|
159
|
-
hashItemScalarDecisionValue(isItemScalarMissingValue(decision.retained)
|
|
160
|
-
? undefined
|
|
161
|
-
: decision.retained),
|
|
162
|
-
discarded_hash: isPrehashedValue(decision.discarded) ??
|
|
163
|
-
hashItemScalarDecisionValue(isItemScalarMissingValue(decision.discarded)
|
|
164
|
-
? undefined
|
|
165
|
-
: decision.discarded),
|
|
166
|
-
})),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
/** Persist one item-driver outcome in the clone-local Git directory. */
|
|
170
|
-
export async function writeMergeReceipt(params) {
|
|
171
|
-
const directory = await resolveReceiptDirectory(params.cwd);
|
|
172
|
-
if (directory === null) {
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
const trimmedItemPath = params.itemPath.trim();
|
|
176
|
-
const itemPath = /^(['"])(.*)\1$/su.exec(trimmedItemPath)?.[2] ?? trimmedItemPath;
|
|
177
|
-
const itemId = path.basename(itemPath, path.extname(itemPath));
|
|
178
|
-
const receipt = {
|
|
179
|
-
version: 1,
|
|
180
|
-
id: randomUUID(),
|
|
181
|
-
item_path: itemPath.replaceAll("\\", "/"),
|
|
182
|
-
item_id: itemId,
|
|
183
|
-
requested_preference: params.preferred,
|
|
184
|
-
requested_preference_applied: (params.conflictResolution ?? "preferred_side") === "preferred_side",
|
|
185
|
-
conflict_resolution: params.conflictResolution ?? "preferred_side",
|
|
186
|
-
fields_from_theirs: [...params.fieldsFromTheirs],
|
|
187
|
-
union_fields: [...params.unionFields],
|
|
188
|
-
...(params.mergedFieldHashes
|
|
189
|
-
? { merged_field_hashes: { ...params.mergedFieldHashes } }
|
|
190
|
-
: {}),
|
|
191
|
-
decisions: structuredClone(params.decisions).map((decision) => ({
|
|
192
|
-
...decision,
|
|
193
|
-
base: encodeItemScalarDecisionValue(decision.base),
|
|
194
|
-
ours: encodeItemScalarDecisionValue(decision.ours),
|
|
195
|
-
theirs: encodeItemScalarDecisionValue(decision.theirs),
|
|
196
|
-
retained: encodeItemScalarDecisionValue(decision.retained),
|
|
197
|
-
discarded: encodeItemScalarDecisionValue(decision.discarded),
|
|
198
|
-
})),
|
|
199
|
-
...(params.operation ? { operation: params.operation } : {}),
|
|
200
|
-
state: "pending",
|
|
201
|
-
created_at: nowIso(),
|
|
202
|
-
value_availability: "clone_local",
|
|
203
|
-
};
|
|
204
|
-
await ensureDir(directory);
|
|
205
|
-
await writeFileAtomic(path.join(directory, receiptFileName(receipt.id)), `${JSON.stringify(receipt, null, 2)}\n`);
|
|
206
|
-
const trackerRoot = await resolveTrackerRootFromItemPath(params.cwd, receipt.item_path);
|
|
207
|
-
if (trackerRoot !== null) {
|
|
208
|
-
const durableDirectory = durableReceiptDirectory(trackerRoot);
|
|
209
|
-
const durableDecisions = receipt.decisions.map((decision) => ({
|
|
210
|
-
field: decision.field,
|
|
211
|
-
base: null,
|
|
212
|
-
ours: null,
|
|
213
|
-
theirs: null,
|
|
214
|
-
retained: durableValueEvidence(decision.field, decision.retained),
|
|
215
|
-
discarded: durableValueEvidence(decision.field, decision.discarded),
|
|
216
|
-
retained_side: decision.retained_side,
|
|
217
|
-
resolution_basis: decision.resolution_basis,
|
|
218
|
-
}));
|
|
219
|
-
const inlineValueCount = durableDecisions.reduce((count, decision) => count +
|
|
220
|
-
(Object.hasOwn(decision.retained, "pm_value") ? 1 : 0) +
|
|
221
|
-
(Object.hasOwn(decision.discarded, "pm_value") ? 1 : 0), 0);
|
|
222
|
-
const durableReceipt = {
|
|
223
|
-
...receipt,
|
|
224
|
-
decisions: durableDecisions,
|
|
225
|
-
value_availability: inlineValueCount === 0
|
|
226
|
-
? "hash_only"
|
|
227
|
-
: inlineValueCount === durableDecisions.length * 2
|
|
228
|
-
? "bounded_inline"
|
|
229
|
-
: "mixed",
|
|
230
|
-
value_policy: DURABLE_VALUE_POLICY,
|
|
231
|
-
};
|
|
232
|
-
await ensureDir(durableDirectory);
|
|
233
|
-
await writeFileAtomic(path.join(durableDirectory, receiptFileName(receipt.id)), `${JSON.stringify(durableReceipt, null, 2)}\n`);
|
|
234
|
-
}
|
|
235
|
-
return receipt;
|
|
236
|
-
}
|
|
237
|
-
/** Scan one receipt directory with bounded per-candidate failure evidence. */
|
|
238
|
-
async function readReceiptsFromDirectory(directory, evidenceSource) {
|
|
239
|
-
let names;
|
|
240
|
-
try {
|
|
241
|
-
names = await readdir(directory);
|
|
242
|
-
}
|
|
243
|
-
catch (error) {
|
|
244
|
-
const absent = await receiptDirectoryFailureMeansAbsent(directory, error);
|
|
245
|
-
return {
|
|
246
|
-
receipts: [],
|
|
247
|
-
invalid_evidence_count: absent ? 0 : 1,
|
|
248
|
-
invalid_evidence: absent
|
|
249
|
-
? []
|
|
250
|
-
: [{ evidence_source: evidenceSource, reason: "directory_unreadable" }],
|
|
251
|
-
invalid_evidence_truncated: false,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
const receipts = [];
|
|
255
|
-
let invalidEvidenceCount = 0;
|
|
256
|
-
const invalidEvidence = [];
|
|
257
|
-
const recordInvalidEvidence = (name, candidate) => {
|
|
258
|
-
invalidEvidenceCount += 1;
|
|
259
|
-
if (invalidEvidence.length >= RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT)
|
|
260
|
-
return;
|
|
261
|
-
const receiptId = name.slice(0, -".json".length);
|
|
262
|
-
invalidEvidence.push({
|
|
263
|
-
evidence_source: evidenceSource,
|
|
264
|
-
reason: candidate.reason,
|
|
265
|
-
...(candidate.validation_path ? { validation_path: candidate.validation_path } : {}),
|
|
266
|
-
...(candidate.validation_error === undefined
|
|
267
|
-
? {}
|
|
268
|
-
: { validation_error: candidate.validation_error }),
|
|
269
|
-
...(isSafeReceiptId(receiptId)
|
|
270
|
-
? { receipt_id: receiptId }
|
|
271
|
-
: { candidate_name_hash: sha256Hex(name) }),
|
|
272
|
-
});
|
|
273
|
-
};
|
|
274
|
-
for (const name of names.sort((left, right) => left.localeCompare(right))) {
|
|
275
|
-
if (!name.endsWith(".json"))
|
|
276
|
-
continue;
|
|
277
|
-
const candidate = await inspectReceiptCandidate(directory, name, evidenceSource);
|
|
278
|
-
if (candidate.receipt !== undefined) {
|
|
279
|
-
receipts.push(candidate.receipt);
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
recordInvalidEvidence(name, candidate);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return {
|
|
286
|
-
receipts,
|
|
287
|
-
invalid_evidence_count: invalidEvidenceCount,
|
|
288
|
-
invalid_evidence: invalidEvidence,
|
|
289
|
-
invalid_evidence_truncated: invalidEvidenceCount > invalidEvidence.length,
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
/** Distinguish a missing optional receipt store from an unreadable one. */
|
|
293
|
-
async function receiptDirectoryFailureMeansAbsent(directory, error, inspectAncestor = stat) {
|
|
294
|
-
if (!isFileMissingError(error))
|
|
295
|
-
return false;
|
|
296
|
-
let ancestor = directory;
|
|
297
|
-
while (true) {
|
|
298
|
-
try {
|
|
299
|
-
return (await inspectAncestor(ancestor)).isDirectory();
|
|
300
|
-
}
|
|
301
|
-
catch (ancestorError) {
|
|
302
|
-
if (!isFileMissingError(ancestorError))
|
|
303
|
-
return false;
|
|
304
|
-
const parent = path.dirname(ancestor);
|
|
305
|
-
if (parent === ancestor)
|
|
306
|
-
return true;
|
|
307
|
-
ancestor = parent;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
/** Inspect one candidate without exposing rejected file contents. */
|
|
312
|
-
async function inspectReceiptCandidate(directory, name, evidenceSource) {
|
|
313
|
-
let raw;
|
|
314
|
-
try {
|
|
315
|
-
raw = await readBoundedRegularFile(path.join(directory, name), RECEIPT_FILE_MAX_BYTES);
|
|
316
|
-
}
|
|
317
|
-
catch {
|
|
318
|
-
return { reason: "candidate_unreadable" };
|
|
319
|
-
}
|
|
320
|
-
if (raw === null)
|
|
321
|
-
return { reason: "candidate_not_bounded_regular_file" };
|
|
322
|
-
let parsed;
|
|
323
|
-
try {
|
|
324
|
-
parsed = normalizeLegacyReceipt(JSON.parse(raw));
|
|
325
|
-
}
|
|
326
|
-
catch {
|
|
327
|
-
return { reason: "candidate_invalid_json" };
|
|
328
|
-
}
|
|
329
|
-
const validationError = receiptValidationError(parsed, evidenceSource);
|
|
330
|
-
if (validationError !== null) {
|
|
331
|
-
const identityErrors = new Set(["receipt_id", "item_id", "item_path"]);
|
|
332
|
-
return {
|
|
333
|
-
reason: identityErrors.has(validationError)
|
|
334
|
-
? "identity_invalid"
|
|
335
|
-
: "schema_invalid",
|
|
336
|
-
validation_error: validationError,
|
|
337
|
-
...(validationError === "collections" ? { validation_path: receiptCollectionValidationPath(parsed) } : {}),
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
const receipt = parsed;
|
|
341
|
-
if (name !== receiptFileName(receipt.id)) {
|
|
342
|
-
return { reason: "identity_invalid", validation_error: "filename" };
|
|
343
|
-
}
|
|
344
|
-
const { preferred: legacyPreference, evidence_source: _serializedEvidenceSource, ...receiptWithoutRuntimeKeys } = receipt;
|
|
345
|
-
return {
|
|
346
|
-
receipt: {
|
|
347
|
-
...receiptWithoutRuntimeKeys,
|
|
348
|
-
requested_preference: receipt.requested_preference ?? legacyPreference ?? "ours",
|
|
349
|
-
requested_preference_applied: receipt.requested_preference_applied ??
|
|
350
|
-
(receipt.conflict_resolution ?? "preferred_side") === "preferred_side",
|
|
351
|
-
conflict_resolution: receipt.conflict_resolution ?? "preferred_side",
|
|
352
|
-
evidence_source: evidenceSource,
|
|
353
|
-
},
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
/** Inspect valid receipts and count invalid evidence without returning untrusted file contents. */
|
|
357
|
-
export async function inspectMergeReceiptEvidence(cwd, options = {}) {
|
|
358
|
-
const directory = await resolveReceiptDirectory(cwd);
|
|
359
|
-
const local = directory === null
|
|
360
|
-
? {
|
|
361
|
-
receipts: [],
|
|
362
|
-
invalid_evidence_count: 0,
|
|
363
|
-
invalid_evidence: [],
|
|
364
|
-
invalid_evidence_truncated: false,
|
|
365
|
-
}
|
|
366
|
-
: await readReceiptsFromDirectory(directory, "clone_local");
|
|
367
|
-
const trackerRoot = options.pmRoot ?? path.join(cwd, ".agents", "pm");
|
|
368
|
-
const durable = await readReceiptsFromDirectory(durableReceiptDirectory(trackerRoot), "durable");
|
|
369
|
-
const receipts = new Map(durable.receipts.map((receipt) => [receipt.id, receipt]));
|
|
370
|
-
let divergentCopyCount = 0;
|
|
371
|
-
const divergentCopyEvidence = [];
|
|
372
|
-
for (const receipt of local.receipts) {
|
|
373
|
-
const durableCopy = receipts.get(receipt.id);
|
|
374
|
-
if (durableCopy !== undefined &&
|
|
375
|
-
!(durableCopy.value_policy === undefined ? receiptProvenanceFingerprints(receipt)
|
|
376
|
-
: [receiptProvenanceFingerprint(receipt)]).includes(receiptProvenanceFingerprint(durableCopy))) {
|
|
377
|
-
receipts.delete(receipt.id);
|
|
378
|
-
divergentCopyCount += 1;
|
|
379
|
-
if (local.invalid_evidence.length +
|
|
380
|
-
durable.invalid_evidence.length +
|
|
381
|
-
divergentCopyEvidence.length <
|
|
382
|
-
RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT) {
|
|
383
|
-
divergentCopyEvidence.push({
|
|
384
|
-
evidence_source: "clone_local_and_durable",
|
|
385
|
-
reason: "copy_provenance_mismatch",
|
|
386
|
-
receipt_id: receipt.id,
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
continue;
|
|
390
|
-
}
|
|
391
|
-
receipts.set(receipt.id, durableCopy === undefined
|
|
392
|
-
? receipt
|
|
393
|
-
: mergeReceiptCopyLifecycle(receipt, durableCopy));
|
|
394
|
-
}
|
|
395
|
-
return {
|
|
396
|
-
receipts: [...receipts.values()]
|
|
397
|
-
.filter((receipt) => (options.includeReconciled || receipt.state === "pending") &&
|
|
398
|
-
(options.includeLossless !== false || receipt.decisions.length > 0))
|
|
399
|
-
.sort((left, right) => left.created_at.localeCompare(right.created_at)),
|
|
400
|
-
invalid_evidence_count: local.invalid_evidence_count +
|
|
401
|
-
durable.invalid_evidence_count +
|
|
402
|
-
divergentCopyCount,
|
|
403
|
-
invalid_evidence: [
|
|
404
|
-
...local.invalid_evidence,
|
|
405
|
-
...durable.invalid_evidence,
|
|
406
|
-
...divergentCopyEvidence,
|
|
407
|
-
].slice(0, RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT),
|
|
408
|
-
invalid_evidence_truncated: local.invalid_evidence_truncated ||
|
|
409
|
-
durable.invalid_evidence_truncated ||
|
|
410
|
-
local.invalid_evidence_count +
|
|
411
|
-
durable.invalid_evidence_count +
|
|
412
|
-
divergentCopyCount >
|
|
413
|
-
RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT,
|
|
414
|
-
clone_local_evidence_resolved: directory !== null,
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
/** Read clone-local receipts with explicit reconciled/lossless classification controls. */
|
|
418
|
-
export async function listMergeReceipts(cwd, options = {}) {
|
|
419
|
-
return (await inspectMergeReceiptEvidence(cwd, options)).receipts;
|
|
420
|
-
}
|
|
421
|
-
/** Split merge provenance into receipts with discarded values and receipts whose composition was lossless. */
|
|
422
|
-
export function partitionMergeReceipts(receipts) {
|
|
423
|
-
const pendingDecisions = [];
|
|
424
|
-
const lossless = [];
|
|
425
|
-
for (const receipt of receipts) {
|
|
426
|
-
(Array.isArray(receipt.decisions) && receipt.decisions.length > 0
|
|
427
|
-
? pendingDecisions
|
|
428
|
-
: lossless).push(receipt);
|
|
429
|
-
}
|
|
430
|
-
return { pendingDecisions, lossless };
|
|
431
|
-
}
|
|
432
|
-
/** Mark a receipt as represented by a committed merge history event. */
|
|
433
|
-
export async function markMergeReceiptReconciled(cwd, receipt, options = {}) {
|
|
434
|
-
const directory = await resolveReceiptDirectory(cwd);
|
|
435
|
-
if (directory === null) {
|
|
436
|
-
if (options.requireExisting === true) {
|
|
437
|
-
throw new Error(`Receipt ${receipt.id} disappeared before settlement.`);
|
|
438
|
-
}
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
const receiptEvidenceSource = receipt.evidence_source ?? "clone_local";
|
|
442
|
-
if (!isMergeDecisionReceipt(receipt, receiptEvidenceSource)) {
|
|
443
|
-
throw new Error("Merge receipt trusted settlement input failed schema validation.");
|
|
444
|
-
}
|
|
445
|
-
const reconciledAt = nowIso();
|
|
446
|
-
const localPath = path.join(directory, receiptFileName(receipt.id));
|
|
447
|
-
const trackerRoot = await resolveTrackerRootFromItemPath(cwd, receipt.item_path);
|
|
448
|
-
const durablePath = trackerRoot === null
|
|
449
|
-
? null
|
|
450
|
-
: path.join(durableReceiptDirectory(trackerRoot), receiptFileName(receipt.id));
|
|
451
|
-
const prepared = await Promise.all([
|
|
452
|
-
prepareReceiptSettlement({
|
|
453
|
-
receiptPath: localPath,
|
|
454
|
-
receiptId: receipt.id,
|
|
455
|
-
evidenceSource: "clone_local",
|
|
456
|
-
reconciledAt,
|
|
457
|
-
settlement: options.settlement,
|
|
458
|
-
}),
|
|
459
|
-
...(durablePath === null
|
|
460
|
-
? []
|
|
461
|
-
: [
|
|
462
|
-
prepareReceiptSettlement({
|
|
463
|
-
receiptPath: durablePath,
|
|
464
|
-
receiptId: receipt.id,
|
|
465
|
-
evidenceSource: "durable",
|
|
466
|
-
reconciledAt,
|
|
467
|
-
settlement: options.settlement,
|
|
468
|
-
}),
|
|
469
|
-
]),
|
|
470
|
-
]);
|
|
471
|
-
const writes = prepared.filter((entry) => entry !== null);
|
|
472
|
-
if (writes.length === 0) {
|
|
473
|
-
if (options.requireExisting === true) {
|
|
474
|
-
throw new Error(`Receipt ${receipt.id} disappeared before settlement.`);
|
|
475
|
-
}
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
const expectedFingerprints = writes.some((write) => write.modern)
|
|
479
|
-
? [receiptProvenanceFingerprint(receipt)] : receiptProvenanceFingerprints(receipt);
|
|
480
|
-
if (!expectedFingerprints.some((fingerprint) => writes.every((write) => write.fingerprints.includes(fingerprint)))) {
|
|
481
|
-
throw new Error(`Receipt ${receipt.id} settlement copies disagree on immutable merge provenance.`);
|
|
482
|
-
}
|
|
483
|
-
for (const write of writes) {
|
|
484
|
-
await writeFileAtomic(write.path, write.content);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
/** Report pending or historical clone-local merge decisions. */
|
|
488
|
-
export async function runMergeReceiptReport(options) {
|
|
489
|
-
const receipts = await listMergeReceipts(options.cwd ?? process.cwd(), {
|
|
490
|
-
...options,
|
|
491
|
-
includeLossless: true,
|
|
492
|
-
});
|
|
493
|
-
return {
|
|
494
|
-
ok: true,
|
|
495
|
-
count: receipts.length,
|
|
496
|
-
receipts,
|
|
497
|
-
generated_at: nowIso(),
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
/** Inspect every receipt candidate and retain completeness diagnostics without exposing rejected file contents. */
|
|
501
|
-
export async function runMergeReceiptEvidenceReport(options) {
|
|
502
|
-
const evidence = await inspectMergeReceiptEvidence(options.cwd ?? process.cwd(), {
|
|
503
|
-
...options,
|
|
504
|
-
includeLossless: true,
|
|
505
|
-
});
|
|
506
|
-
const complete = evidence.clone_local_evidence_resolved === true &&
|
|
507
|
-
evidence.invalid_evidence_count === 0;
|
|
508
|
-
return {
|
|
509
|
-
ok: complete,
|
|
510
|
-
complete,
|
|
511
|
-
count: evidence.receipts.length,
|
|
512
|
-
invalid_evidence_count: evidence.invalid_evidence_count,
|
|
513
|
-
invalid_evidence: evidence.invalid_evidence,
|
|
514
|
-
invalid_evidence_truncated: evidence.invalid_evidence_truncated,
|
|
515
|
-
clone_local_evidence_resolved: evidence.clone_local_evidence_resolved,
|
|
516
|
-
receipts: evidence.receipts,
|
|
517
|
-
generated_at: nowIso(),
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
/** Test-only seams for deterministic receipt-boundary fault coverage. */
|
|
521
|
-
export const _testOnlyMergeReceipts = {
|
|
522
|
-
prepareReceiptSettlement,
|
|
523
|
-
receiptDirectoryFailureMeansAbsent,
|
|
524
|
-
};
|
|
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]="7793ca52-14e7-544f-a5cf-ebea38bb1401")}catch(e2){}})();import{execFile}from"node:child_process";import{randomUUID}from"node:crypto";import{readdir,stat}from"node:fs/promises";import path from"node:path";import{promisify}from"node:util";import{ensureDir,isFileAbsentError,isFileMissingError,pathExists,writeFileAtomic}from"../../core/fs/fs-utils.js";import{sha256Hex,stableStringify}from"../../core/shared/serialization.js";import{nowIso}from"../../core/shared/time.js";import{encodeItemScalarDecisionValue,hashItemScalarDecisionValue,isItemScalarMissingValue}from"./three-way.js";import{readBoundedRegularFile}from"./receipt-file-boundary.js";import{DURABLE_VALUE_POLICY,durableValueEvidence,isSafeReceiptId,isMergeDecisionReceipt,isPrehashedValue,normalizeLegacyReceipt,receiptCollectionValidationPath,receiptValidationError}from"./receipt-schema.js";import{isSafeReceiptId as isSafeReceiptId2}from"./receipt-schema.js";const execFileAsync=promisify(execFile);const RECEIPT_FILE_MAX_BYTES=16*1024*1024;const RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT=100;async function resolveReceiptDirectory(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--path-format=absolute","--git-path","pm-merge-receipts"],{cwd,encoding:"utf8",windowsHide:true,timeout:1e4});return stdout.trim()}catch{return null}}async function resolveTrackerRootFromItemPath(cwd,itemPath){let directory=path.dirname(path.resolve(cwd,itemPath));for(let depth=0;depth<12;depth+=1){if(await pathExists(path.join(directory,"settings.json")))return directory;const parent=path.dirname(directory);if(parent===directory)break;directory=parent}return null}function durableReceiptDirectory(pmRoot){return path.join(pmRoot,"merge-receipts")}function receiptFileName(id){return`${id}.json`}async function prepareReceiptSettlement(params){let raw;try{raw=params.readReceipt?await params.readReceipt(params.receiptPath):await readBoundedRegularFile(params.receiptPath,RECEIPT_FILE_MAX_BYTES)}catch(error){if(isFileAbsentError(error))return null;throw error}if(raw===null){throw new Error(`Receipt ${params.receiptId} settlement source is not a bounded regular file.`)}let parsed;try{parsed=normalizeLegacyReceipt(JSON.parse(raw))}catch{throw new Error(`Receipt ${params.receiptId} settlement source is not valid JSON.`)}if(!isMergeDecisionReceipt(parsed,params.evidenceSource)||parsed.id!==params.receiptId||params.settlement!==void 0&&parsed.operation===void 0||path.basename(params.receiptPath)!==receiptFileName(parsed.id)){throw new Error(`Receipt ${params.receiptId} settlement source failed schema or identity validation.`)}const{evidence_source:_evidenceSource,...persistedReceipt}=parsed;return{path:params.receiptPath,fingerprints:receiptProvenanceFingerprints(parsed),modern:parsed.value_policy!==void 0,content:`${JSON.stringify({...persistedReceipt,state:"reconciled",reconciled_at:params.reconciledAt,...params.settlement?{settlement:params.settlement}:{}},null,2)}
|
|
2
|
+
`}}function receiptProvenanceFingerprint(receipt,legacy=false){return sha256Hex(stableStringify({id:receipt.id,item_id:receipt.item_id,item_path:receipt.item_path,created_at:receipt.created_at,requested_preference:receipt.requested_preference??receipt.preferred??"ours",conflict_resolution:receipt.conflict_resolution??"preferred_side",fields_from_theirs:receipt.fields_from_theirs,union_fields:receipt.union_fields,merged_field_hashes:receipt.merged_field_hashes??null,operation:receipt.operation??null,decisions:legacy?receipt.decisions.map(decision=>({field:decision.field,retained_hash:sha256Hex(stableStringify(encodeItemScalarDecisionValue(decision.retained))),discarded_hash:sha256Hex(stableStringify(encodeItemScalarDecisionValue(decision.discarded)))})):summarizeMergeReceipt(receipt).decisions}))}function receiptProvenanceFingerprints(receipt){const fingerprints=[receiptProvenanceFingerprint(receipt)];if(receipt.value_policy===void 0&&(receipt.value_availability===void 0||receipt.value_availability==="clone_local")){fingerprints.push(receiptProvenanceFingerprint(receipt,true))}return fingerprints}function mergeReceiptCopyLifecycle(local,durable){if(local.state==="reconciled"&&durable.state==="reconciled"&&local.settlement===durable.settlement){return local}const{reconciled_at:_reconciledAt,settlement:_settlement,...pendingLocal}=local;return{...pendingLocal,state:"pending"}}function summarizeMergeReceipt(receipt){return{receipt_id:receipt.id,item_id:receipt.item_id,item_path:receipt.item_path,conflict_fields:receipt.decisions.map(decision=>decision.field),fields_from_theirs:receipt.fields_from_theirs,union_fields:receipt.union_fields,requested_preference:receipt.requested_preference??receipt.preferred??"ours",requested_preference_applied:receipt.requested_preference_applied??(receipt.conflict_resolution??"preferred_side")==="preferred_side",conflict_resolution:receipt.conflict_resolution,decisions:receipt.decisions.map(decision=>({field:decision.field,retained_hash:isPrehashedValue(decision.retained)??hashItemScalarDecisionValue(isItemScalarMissingValue(decision.retained)?void 0:decision.retained),discarded_hash:isPrehashedValue(decision.discarded)??hashItemScalarDecisionValue(isItemScalarMissingValue(decision.discarded)?void 0:decision.discarded)}))}}async function writeMergeReceipt(params){const directory=await resolveReceiptDirectory(params.cwd);if(directory===null){return null}const trimmedItemPath=params.itemPath.trim();const itemPath=/^(['"])(.*)\1$/su.exec(trimmedItemPath)?.[2]??trimmedItemPath;const itemId=path.basename(itemPath,path.extname(itemPath));const receipt={version:1,id:randomUUID(),item_path:itemPath.replaceAll("\\","/"),item_id:itemId,requested_preference:params.preferred,requested_preference_applied:(params.conflictResolution??"preferred_side")==="preferred_side",conflict_resolution:params.conflictResolution??"preferred_side",fields_from_theirs:[...params.fieldsFromTheirs],union_fields:[...params.unionFields],...params.mergedFieldHashes?{merged_field_hashes:{...params.mergedFieldHashes}}:{},decisions:structuredClone(params.decisions).map(decision=>({...decision,base:encodeItemScalarDecisionValue(decision.base),ours:encodeItemScalarDecisionValue(decision.ours),theirs:encodeItemScalarDecisionValue(decision.theirs),retained:encodeItemScalarDecisionValue(decision.retained),discarded:encodeItemScalarDecisionValue(decision.discarded)})),...params.operation?{operation:params.operation}:{},state:"pending",created_at:nowIso(),value_availability:"clone_local"};await ensureDir(directory);await writeFileAtomic(path.join(directory,receiptFileName(receipt.id)),`${JSON.stringify(receipt,null,2)}
|
|
3
|
+
`);const trackerRoot=await resolveTrackerRootFromItemPath(params.cwd,receipt.item_path);if(trackerRoot!==null){const durableDirectory=durableReceiptDirectory(trackerRoot);const durableDecisions=receipt.decisions.map(decision=>({field:decision.field,base:null,ours:null,theirs:null,retained:durableValueEvidence(decision.field,decision.retained),discarded:durableValueEvidence(decision.field,decision.discarded),retained_side:decision.retained_side,resolution_basis:decision.resolution_basis}));const inlineValueCount=durableDecisions.reduce((count,decision)=>count+(Object.hasOwn(decision.retained,"pm_value")?1:0)+(Object.hasOwn(decision.discarded,"pm_value")?1:0),0);const durableReceipt={...receipt,decisions:durableDecisions,value_availability:inlineValueCount===0?"hash_only":inlineValueCount===durableDecisions.length*2?"bounded_inline":"mixed",value_policy:DURABLE_VALUE_POLICY};await ensureDir(durableDirectory);await writeFileAtomic(path.join(durableDirectory,receiptFileName(receipt.id)),`${JSON.stringify(durableReceipt,null,2)}
|
|
4
|
+
`)}return receipt}async function readReceiptsFromDirectory(directory,evidenceSource){let names;try{names=await readdir(directory)}catch(error){const absent=await receiptDirectoryFailureMeansAbsent(directory,error);return{receipts:[],invalid_evidence_count:absent?0:1,invalid_evidence:absent?[]:[{evidence_source:evidenceSource,reason:"directory_unreadable"}],invalid_evidence_truncated:false}}const receipts=[];let invalidEvidenceCount=0;const invalidEvidence=[];const recordInvalidEvidence=(name,candidate)=>{invalidEvidenceCount+=1;if(invalidEvidence.length>=RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT)return;const receiptId=name.slice(0,-".json".length);invalidEvidence.push({evidence_source:evidenceSource,reason:candidate.reason,...candidate.validation_path?{validation_path:candidate.validation_path}:{},...candidate.validation_error===void 0?{}:{validation_error:candidate.validation_error},...isSafeReceiptId(receiptId)?{receipt_id:receiptId}:{candidate_name_hash:sha256Hex(name)}})};for(const name of names.sort((left,right)=>left.localeCompare(right))){if(!name.endsWith(".json"))continue;const candidate=await inspectReceiptCandidate(directory,name,evidenceSource);if(candidate.receipt!==void 0){receipts.push(candidate.receipt)}else{recordInvalidEvidence(name,candidate)}}return{receipts,invalid_evidence_count:invalidEvidenceCount,invalid_evidence:invalidEvidence,invalid_evidence_truncated:invalidEvidenceCount>invalidEvidence.length}}async function receiptDirectoryFailureMeansAbsent(directory,error,inspectAncestor=stat){if(!isFileMissingError(error))return false;let ancestor=directory;while(true){try{return(await inspectAncestor(ancestor)).isDirectory()}catch(ancestorError){if(!isFileMissingError(ancestorError))return false;const parent=path.dirname(ancestor);if(parent===ancestor)return true;ancestor=parent}}}async function inspectReceiptCandidate(directory,name,evidenceSource){let raw;try{raw=await readBoundedRegularFile(path.join(directory,name),RECEIPT_FILE_MAX_BYTES)}catch{return{reason:"candidate_unreadable"}}if(raw===null)return{reason:"candidate_not_bounded_regular_file"};let parsed;try{parsed=normalizeLegacyReceipt(JSON.parse(raw))}catch{return{reason:"candidate_invalid_json"}}const validationError=receiptValidationError(parsed,evidenceSource);if(validationError!==null){const identityErrors=new Set(["receipt_id","item_id","item_path"]);return{reason:identityErrors.has(validationError)?"identity_invalid":"schema_invalid",validation_error:validationError,...validationError==="collections"?{validation_path:receiptCollectionValidationPath(parsed)}:{}}}const receipt=parsed;if(name!==receiptFileName(receipt.id)){return{reason:"identity_invalid",validation_error:"filename"}}const{preferred:legacyPreference,evidence_source:_serializedEvidenceSource,...receiptWithoutRuntimeKeys}=receipt;return{receipt:{...receiptWithoutRuntimeKeys,requested_preference:receipt.requested_preference??legacyPreference??"ours",requested_preference_applied:receipt.requested_preference_applied??(receipt.conflict_resolution??"preferred_side")==="preferred_side",conflict_resolution:receipt.conflict_resolution??"preferred_side",evidence_source:evidenceSource}}}async function inspectMergeReceiptEvidence(cwd,options={}){const directory=await resolveReceiptDirectory(cwd);const local=directory===null?{receipts:[],invalid_evidence_count:0,invalid_evidence:[],invalid_evidence_truncated:false}:await readReceiptsFromDirectory(directory,"clone_local");const trackerRoot=options.pmRoot??path.join(cwd,".agents","pm");const durable=await readReceiptsFromDirectory(durableReceiptDirectory(trackerRoot),"durable");const receipts=new Map(durable.receipts.map(receipt=>[receipt.id,receipt]));let divergentCopyCount=0;const divergentCopyEvidence=[];for(const receipt of local.receipts){const durableCopy=receipts.get(receipt.id);if(durableCopy!==void 0&&!(durableCopy.value_policy===void 0?receiptProvenanceFingerprints(receipt):[receiptProvenanceFingerprint(receipt)]).includes(receiptProvenanceFingerprint(durableCopy))){receipts.delete(receipt.id);divergentCopyCount+=1;if(local.invalid_evidence.length+durable.invalid_evidence.length+divergentCopyEvidence.length<RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT){divergentCopyEvidence.push({evidence_source:"clone_local_and_durable",reason:"copy_provenance_mismatch",receipt_id:receipt.id})}continue}receipts.set(receipt.id,durableCopy===void 0?receipt:mergeReceiptCopyLifecycle(receipt,durableCopy))}return{receipts:[...receipts.values()].filter(receipt=>(options.includeReconciled||receipt.state==="pending")&&(options.includeLossless!==false||receipt.decisions.length>0)).sort((left,right)=>left.created_at.localeCompare(right.created_at)),invalid_evidence_count:local.invalid_evidence_count+durable.invalid_evidence_count+divergentCopyCount,invalid_evidence:[...local.invalid_evidence,...durable.invalid_evidence,...divergentCopyEvidence].slice(0,RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT),invalid_evidence_truncated:local.invalid_evidence_truncated||durable.invalid_evidence_truncated||local.invalid_evidence_count+durable.invalid_evidence_count+divergentCopyCount>RECEIPT_INVALID_EVIDENCE_DETAIL_LIMIT,clone_local_evidence_resolved:directory!==null}}async function listMergeReceipts(cwd,options={}){return(await inspectMergeReceiptEvidence(cwd,options)).receipts}function partitionMergeReceipts(receipts){const pendingDecisions=[];const lossless=[];for(const receipt of receipts){(Array.isArray(receipt.decisions)&&receipt.decisions.length>0?pendingDecisions:lossless).push(receipt)}return{pendingDecisions,lossless}}async function markMergeReceiptReconciled(cwd,receipt,options={}){const directory=await resolveReceiptDirectory(cwd);if(directory===null){if(options.requireExisting===true){throw new Error(`Receipt ${receipt.id} disappeared before settlement.`)}return}const receiptEvidenceSource=receipt.evidence_source??"clone_local";if(!isMergeDecisionReceipt(receipt,receiptEvidenceSource)){throw new Error("Merge receipt trusted settlement input failed schema validation.")}const reconciledAt=nowIso();const localPath=path.join(directory,receiptFileName(receipt.id));const trackerRoot=await resolveTrackerRootFromItemPath(cwd,receipt.item_path);const durablePath=trackerRoot===null?null:path.join(durableReceiptDirectory(trackerRoot),receiptFileName(receipt.id));const prepared=await Promise.all([prepareReceiptSettlement({receiptPath:localPath,receiptId:receipt.id,evidenceSource:"clone_local",reconciledAt,settlement:options.settlement}),...durablePath===null?[]:[prepareReceiptSettlement({receiptPath:durablePath,receiptId:receipt.id,evidenceSource:"durable",reconciledAt,settlement:options.settlement})]]);const writes=prepared.filter(entry=>entry!==null);if(writes.length===0){if(options.requireExisting===true){throw new Error(`Receipt ${receipt.id} disappeared before settlement.`)}return}const expectedFingerprints=writes.some(write=>write.modern)?[receiptProvenanceFingerprint(receipt)]:receiptProvenanceFingerprints(receipt);if(!expectedFingerprints.some(fingerprint=>writes.every(write=>write.fingerprints.includes(fingerprint)))){throw new Error(`Receipt ${receipt.id} settlement copies disagree on immutable merge provenance.`)}for(const write of writes){await writeFileAtomic(write.path,write.content)}}async function runMergeReceiptReport(options){const receipts=await listMergeReceipts(options.cwd??process.cwd(),{...options,includeLossless:true});return{ok:true,count:receipts.length,receipts,generated_at:nowIso()}}async function runMergeReceiptEvidenceReport(options){const evidence=await inspectMergeReceiptEvidence(options.cwd??process.cwd(),{...options,includeLossless:true});const complete=evidence.clone_local_evidence_resolved===true&&evidence.invalid_evidence_count===0;return{ok:complete,complete,count:evidence.receipts.length,invalid_evidence_count:evidence.invalid_evidence_count,invalid_evidence:evidence.invalid_evidence,invalid_evidence_truncated:evidence.invalid_evidence_truncated,clone_local_evidence_resolved:evidence.clone_local_evidence_resolved,receipts:evidence.receipts,generated_at:nowIso()}}const _testOnlyMergeReceipts={prepareReceiptSettlement,receiptDirectoryFailureMeansAbsent};export{_testOnlyMergeReceipts,inspectMergeReceiptEvidence,isSafeReceiptId2 as isSafeReceiptId,listMergeReceipts,markMergeReceiptReconciled,partitionMergeReceipts,runMergeReceiptEvidenceReport,runMergeReceiptReport,summarizeMergeReceipt,writeMergeReceipt};
|
|
525
5
|
//# sourceMappingURL=receipts.js.map
|
|
526
|
-
//# debugId=e7fe0fee-9519-593d-ac72-b3c7fb63563e
|