@unbrained/pm-cli 2026.9.7 → 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 +211 -181
- 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/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,618 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Implements append-only history and replay behavior for History.
|
|
5
|
-
*/
|
|
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]="a5449fec-c5b4-5cf4-9a7f-b7c5dc7161c2")}catch(e){}}();
|
|
8
|
-
import jsonPatch from "fast-json-patch";
|
|
9
|
-
import fs from "node:fs/promises";
|
|
10
|
-
import path from "node:path";
|
|
11
|
-
import { EXIT_CODE, ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
|
|
12
|
-
import { runActiveServiceOverride } from "../extensions/index.js";
|
|
13
|
-
import { appendLineAtomic } from "../fs/fs-utils.js";
|
|
14
|
-
import { canonicalDocument } from "../item/item-format.js";
|
|
15
|
-
import { toItemRecord } from "../item/item-record.js";
|
|
16
|
-
import { orderObject, sha256Hex, stableStringify, } from "../shared/serialization.js";
|
|
17
|
-
import { isMillisecondPrecisionRfc3339DateTime, nowIso, } from "../shared/time.js";
|
|
18
|
-
import { diagnoseAgentIdentity, resolveHistoryAgentIdentity, resolveHistoryAuthorSource, } from "../shared/author.js";
|
|
19
|
-
import { appendHistoryEntryWithEventIndex, removeHistoryEventIndexForHistoryPath, } from "./event-index.js";
|
|
20
|
-
import { classifyHistoryEvent } from "./event-classification.js";
|
|
21
|
-
import { invalidateHistoryDriftCacheForPath } from "./drift-cache.js";
|
|
22
|
-
import { PmCliError } from "../shared/errors.js";
|
|
23
|
-
const EMPTY_LEGACY_HASH_DOCUMENT = {
|
|
24
|
-
front_matter: {},
|
|
25
|
-
body: "",
|
|
26
|
-
};
|
|
27
|
-
/** Hash epoch for the current canonical item surface written into immutable history. */
|
|
28
|
-
export const CURRENT_HISTORY_ITEM_HASH_VERSION = 3;
|
|
29
|
-
/** Hash epochs understood by this runtime. */
|
|
30
|
-
export const SUPPORTED_HISTORY_ITEM_HASH_VERSIONS = [1, 2, 3];
|
|
31
|
-
/** Record-integrity epoch written beside new immutable history events. */
|
|
32
|
-
export const CURRENT_HISTORY_RECORD_HASH_VERSION = 1;
|
|
33
|
-
/** Record-integrity epochs understood by this runtime. */
|
|
34
|
-
export const SUPPORTED_HISTORY_RECORD_HASH_VERSIONS = [1];
|
|
35
|
-
/** Canonicalize and hash every immutable record field except the hash value itself. */
|
|
36
|
-
export function hashHistoryRecord(entry) {
|
|
37
|
-
return sha256Hex(stableStringify(entry));
|
|
38
|
-
}
|
|
39
|
-
/** Hash one patch representation without retaining its potentially sensitive values. */
|
|
40
|
-
export function hashHistoryPatch(patch) {
|
|
41
|
-
return sha256Hex(stableStringify(patch));
|
|
42
|
-
}
|
|
43
|
-
/** Hash an ordered history prefix for compact checkpoint provenance. */
|
|
44
|
-
export function hashHistoryStream(entries) {
|
|
45
|
-
return sha256Hex(stableStringify(entries));
|
|
46
|
-
}
|
|
47
|
-
/** Attach the current immutable-record integrity envelope to one history event. */
|
|
48
|
-
export function sealHistoryRecord(entry) {
|
|
49
|
-
const sealed = {
|
|
50
|
-
...entry,
|
|
51
|
-
record_hash_version: CURRENT_HISTORY_RECORD_HASH_VERSION,
|
|
52
|
-
};
|
|
53
|
-
const { record_hash: _recordHash, ...canonical } = sealed;
|
|
54
|
-
return { ...sealed, record_hash: hashHistoryRecord(canonical) };
|
|
55
|
-
}
|
|
56
|
-
/** Verify record-level attribution coverage while accepting explicit legacy item-state-only entries. */
|
|
57
|
-
export function verifyHistoryRecordHash(entry) {
|
|
58
|
-
if (entry.record_hash_version === undefined &&
|
|
59
|
-
entry.record_hash === undefined) {
|
|
60
|
-
return { ok: true, coverage: "item_state_only" };
|
|
61
|
-
}
|
|
62
|
-
if (entry.record_hash_version === undefined ||
|
|
63
|
-
entry.record_hash === undefined) {
|
|
64
|
-
return { ok: false, error: "incomplete_record_hash_envelope" };
|
|
65
|
-
}
|
|
66
|
-
if (!SUPPORTED_HISTORY_RECORD_HASH_VERSIONS.includes(entry.record_hash_version)) {
|
|
67
|
-
return { ok: false, error: "unsupported_record_hash_version" };
|
|
68
|
-
}
|
|
69
|
-
const { record_hash: _recordHash, ...canonical } = entry;
|
|
70
|
-
return hashHistoryRecord(canonical) === entry.record_hash
|
|
71
|
-
? { ok: true, coverage: "record_and_item_state" }
|
|
72
|
-
: { ok: false, error: "record_hash_mismatch" };
|
|
73
|
-
}
|
|
74
|
-
/** Build the retained coordinate and optional exact-record rewrite evidence. */
|
|
75
|
-
function createHistoryRewriteEvidence(original, options) {
|
|
76
|
-
const evidence = {
|
|
77
|
-
before_hash: original.before_hash,
|
|
78
|
-
after_hash: original.after_hash,
|
|
79
|
-
patch_hash: hashHistoryPatch(original.patch),
|
|
80
|
-
};
|
|
81
|
-
if (original.item_hash_version !== undefined) {
|
|
82
|
-
evidence.item_hash_version = original.item_hash_version;
|
|
83
|
-
}
|
|
84
|
-
if (options.retainOriginalPatch) {
|
|
85
|
-
evidence.patch = structuredClone(original.patch);
|
|
86
|
-
}
|
|
87
|
-
if (options.retainPriorRecordHash !== false &&
|
|
88
|
-
original.record_hash_version !== undefined &&
|
|
89
|
-
original.record_hash !== undefined) {
|
|
90
|
-
evidence.record_hash_version = original.record_hash_version;
|
|
91
|
-
evidence.record_hash = original.record_hash;
|
|
92
|
-
evidence.record = structuredClone(original);
|
|
93
|
-
}
|
|
94
|
-
return evidence;
|
|
95
|
-
}
|
|
96
|
-
/** Reseal a maintenance rewrite and retain the anchors and patch digest it replaced. */
|
|
97
|
-
export function resealHistoryRewrite(original, rewritten, options = {}) {
|
|
98
|
-
const originalRecordVerification = verifyHistoryRecordHash(original);
|
|
99
|
-
if (!originalRecordVerification.ok) {
|
|
100
|
-
throw new TypeError(originalRecordVerification.error);
|
|
101
|
-
}
|
|
102
|
-
const originalPatchHash = hashHistoryPatch(original.patch);
|
|
103
|
-
const retainsRewriteEvidence = options.retainPriorRecord === true ||
|
|
104
|
-
original.before_hash !== rewritten.before_hash ||
|
|
105
|
-
original.after_hash !== rewritten.after_hash ||
|
|
106
|
-
original.item_hash_version !== rewritten.item_hash_version ||
|
|
107
|
-
originalPatchHash !== hashHistoryPatch(rewritten.patch);
|
|
108
|
-
const sealed = sealHistoryRecord({
|
|
109
|
-
...rewritten,
|
|
110
|
-
...(retainsRewriteEvidence
|
|
111
|
-
? {
|
|
112
|
-
reanchor_evidence: [
|
|
113
|
-
...(rewritten.reanchor_evidence ?? []),
|
|
114
|
-
createHistoryRewriteEvidence(original, options),
|
|
115
|
-
],
|
|
116
|
-
}
|
|
117
|
-
: {}),
|
|
118
|
-
});
|
|
119
|
-
const evidenceVerification = verifyHistoryRewriteEvidence(sealed);
|
|
120
|
-
if (!evidenceVerification.ok) {
|
|
121
|
-
throw new TypeError(evidenceVerification.error);
|
|
122
|
-
}
|
|
123
|
-
return sealed;
|
|
124
|
-
}
|
|
125
|
-
/** Return whether runtime data is a dense list of structurally valid patch operations. */
|
|
126
|
-
function isHistoryPatch(value) {
|
|
127
|
-
if (!Array.isArray(value) || Object.keys(value).length !== value.length) {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
return value.every((operation) => {
|
|
131
|
-
if (!isRecord(operation) || typeof operation.path !== "string") {
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
if (operation.op === "move" || operation.op === "copy") {
|
|
135
|
-
return typeof operation.from === "string";
|
|
136
|
-
}
|
|
137
|
-
if (["add", "replace", "test"].includes(operation.op)) {
|
|
138
|
-
return Object.hasOwn(operation, "value");
|
|
139
|
-
}
|
|
140
|
-
return operation.op === "remove";
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
/** Return whether a retained record has the minimum immutable event shape. */
|
|
144
|
-
function isRetainedHistoryRecordShape(value) {
|
|
145
|
-
return (isRecord(value) &&
|
|
146
|
-
typeof value.ts === "string" &&
|
|
147
|
-
typeof value.author === "string" &&
|
|
148
|
-
typeof value.op === "string" &&
|
|
149
|
-
typeof value.before_hash === "string" &&
|
|
150
|
-
typeof value.after_hash === "string" &&
|
|
151
|
-
isHistoryPatch(value.patch));
|
|
152
|
-
}
|
|
153
|
-
/** Return whether optional retained record-hash fields form a complete pair. */
|
|
154
|
-
function hasCompleteRetainedRecordHashEnvelope(evidence) {
|
|
155
|
-
const hasVersion = evidence.record_hash_version !== undefined;
|
|
156
|
-
const hasHash = evidence.record_hash !== undefined;
|
|
157
|
-
return hasVersion === hasHash;
|
|
158
|
-
}
|
|
159
|
-
/** Return whether runtime evidence has the bounded shape needed for verification. */
|
|
160
|
-
function isHistoryReanchorEvidence(evidence) {
|
|
161
|
-
if (!isRecord(evidence) ||
|
|
162
|
-
!hasCompleteRetainedRecordHashEnvelope(evidence) ||
|
|
163
|
-
typeof evidence.before_hash !== "string" ||
|
|
164
|
-
typeof evidence.after_hash !== "string" ||
|
|
165
|
-
typeof evidence.patch_hash !== "string" ||
|
|
166
|
-
!/^[a-f0-9]{64}$/u.test(evidence.patch_hash) ||
|
|
167
|
-
(evidence.patch !== undefined && !isHistoryPatch(evidence.patch)) ||
|
|
168
|
-
(evidence.record_hash_version !== undefined &&
|
|
169
|
-
typeof evidence.record_hash_version !== "number") ||
|
|
170
|
-
(evidence.record_hash !== undefined &&
|
|
171
|
-
(typeof evidence.record_hash !== "string" ||
|
|
172
|
-
!/^[a-f0-9]{64}$/u.test(evidence.record_hash)))) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
return (evidence.record === undefined ||
|
|
176
|
-
isRetainedHistoryRecordShape(evidence.record));
|
|
177
|
-
}
|
|
178
|
-
/** Return whether a retained exact record agrees with its summary coordinates. */
|
|
179
|
-
function matchesRetainedHistoryRecord(evidence) {
|
|
180
|
-
const record = evidence.record;
|
|
181
|
-
return (record !== undefined &&
|
|
182
|
-
record.before_hash === evidence.before_hash &&
|
|
183
|
-
record.after_hash === evidence.after_hash &&
|
|
184
|
-
record.item_hash_version === evidence.item_hash_version &&
|
|
185
|
-
record.record_hash_version === evidence.record_hash_version &&
|
|
186
|
-
record.record_hash === evidence.record_hash &&
|
|
187
|
-
hashHistoryPatch(record.patch) === evidence.patch_hash);
|
|
188
|
-
}
|
|
189
|
-
/** Reconstruct one prior record represented by retained rewrite evidence. */
|
|
190
|
-
function reconstructPriorHistoryRecord(current, evidence, priorEvidence) {
|
|
191
|
-
if (evidence.patch &&
|
|
192
|
-
hashHistoryPatch(evidence.patch) !== evidence.patch_hash) {
|
|
193
|
-
return { kind: "patch_hash_mismatch" };
|
|
194
|
-
}
|
|
195
|
-
if (evidence.record) {
|
|
196
|
-
if (!matchesRetainedHistoryRecord(evidence)) {
|
|
197
|
-
return { kind: "record_hash_mismatch" };
|
|
198
|
-
}
|
|
199
|
-
return { kind: "record", entry: evidence.record };
|
|
200
|
-
}
|
|
201
|
-
const priorPatch = evidence.patch ?? current.patch;
|
|
202
|
-
if (hashHistoryPatch(priorPatch) !== evidence.patch_hash) {
|
|
203
|
-
return { kind: "digest_only" };
|
|
204
|
-
}
|
|
205
|
-
const priorRecord = {
|
|
206
|
-
...current,
|
|
207
|
-
before_hash: evidence.before_hash,
|
|
208
|
-
after_hash: evidence.after_hash,
|
|
209
|
-
patch: priorPatch,
|
|
210
|
-
...(evidence.item_hash_version === undefined
|
|
211
|
-
? {}
|
|
212
|
-
: { item_hash_version: evidence.item_hash_version }),
|
|
213
|
-
...(evidence.record_hash_version === undefined
|
|
214
|
-
? {}
|
|
215
|
-
: { record_hash_version: evidence.record_hash_version }),
|
|
216
|
-
...(evidence.record_hash === undefined
|
|
217
|
-
? {}
|
|
218
|
-
: { record_hash: evidence.record_hash }),
|
|
219
|
-
...(priorEvidence.length === 0 ? {} : { reanchor_evidence: priorEvidence }),
|
|
220
|
-
};
|
|
221
|
-
if (priorEvidence.length === 0)
|
|
222
|
-
delete priorRecord.reanchor_evidence;
|
|
223
|
-
if (evidence.item_hash_version === undefined) {
|
|
224
|
-
delete priorRecord.item_hash_version;
|
|
225
|
-
}
|
|
226
|
-
return evidence.record_hash_version === undefined ||
|
|
227
|
-
evidence.record_hash === undefined
|
|
228
|
-
? { kind: "legacy", entry: priorRecord }
|
|
229
|
-
: { kind: "record", entry: priorRecord };
|
|
230
|
-
}
|
|
231
|
-
/** Verify that retained rewrite evidence reconstructs every available prior record envelope. */
|
|
232
|
-
export function verifyHistoryRewriteEvidence(entry) {
|
|
233
|
-
const evidenceEntries = entry.reanchor_evidence;
|
|
234
|
-
if (evidenceEntries === undefined)
|
|
235
|
-
return { ok: true, coverage: "none" };
|
|
236
|
-
if (!Array.isArray(evidenceEntries)) {
|
|
237
|
-
return { ok: false, error: "rewrite_evidence_invalid" };
|
|
238
|
-
}
|
|
239
|
-
if (evidenceEntries.length === 0)
|
|
240
|
-
return { ok: true, coverage: "none" };
|
|
241
|
-
let reconstructed = entry;
|
|
242
|
-
for (let index = evidenceEntries.length - 1; index >= 0; index -= 1) {
|
|
243
|
-
const evidence = evidenceEntries[index];
|
|
244
|
-
if (!(index in evidenceEntries) || !isHistoryReanchorEvidence(evidence)) {
|
|
245
|
-
return { ok: false, error: "rewrite_evidence_invalid" };
|
|
246
|
-
}
|
|
247
|
-
const prior = reconstructPriorHistoryRecord(reconstructed, evidence, evidenceEntries.slice(0, index));
|
|
248
|
-
if (prior.kind === "patch_hash_mismatch") {
|
|
249
|
-
return { ok: false, error: "rewrite_evidence_patch_hash_mismatch" };
|
|
250
|
-
}
|
|
251
|
-
if (prior.kind === "record_hash_mismatch") {
|
|
252
|
-
return { ok: false, error: "rewrite_evidence_record_hash_mismatch" };
|
|
253
|
-
}
|
|
254
|
-
if (prior.kind === "digest_only") {
|
|
255
|
-
return { ok: true, coverage: "digest_only" };
|
|
256
|
-
}
|
|
257
|
-
if (prior.kind === "legacy") {
|
|
258
|
-
return { ok: true, coverage: "legacy_anchor_only" };
|
|
259
|
-
}
|
|
260
|
-
if (!verifyHistoryRecordHash(prior.entry).ok) {
|
|
261
|
-
return { ok: false, error: "rewrite_evidence_record_hash_mismatch" };
|
|
262
|
-
}
|
|
263
|
-
reconstructed = prior.entry;
|
|
264
|
-
}
|
|
265
|
-
return { ok: true, coverage: "complete" };
|
|
266
|
-
}
|
|
267
|
-
function compareOptionalStrings(left, right) {
|
|
268
|
-
return (left ?? "").localeCompare(right ?? "");
|
|
269
|
-
}
|
|
270
|
-
function compareOptionalNumbers(left, right) {
|
|
271
|
-
return (left ?? 0) - (right ?? 0);
|
|
272
|
-
}
|
|
273
|
-
function compareJsonValues(left, right, fallback) {
|
|
274
|
-
// Preserve the original v1 comparator byte-for-byte: replacing JSON.stringify
|
|
275
|
-
// with stableStringify would invalidate immutable hashes from legacy streams.
|
|
276
|
-
return JSON.stringify(left ?? fallback).localeCompare(JSON.stringify(right ?? fallback));
|
|
277
|
-
}
|
|
278
|
-
function compareLegacyLinkedTests(left, right) {
|
|
279
|
-
const comparisons = [
|
|
280
|
-
left.scope.localeCompare(right.scope),
|
|
281
|
-
compareOptionalStrings(left.path, right.path),
|
|
282
|
-
compareOptionalStrings(left.command, right.command),
|
|
283
|
-
compareOptionalNumbers(left.timeout_seconds, right.timeout_seconds),
|
|
284
|
-
compareOptionalStrings(left.pm_context_mode, right.pm_context_mode),
|
|
285
|
-
Number(Boolean(left.shared_host_safe)) -
|
|
286
|
-
Number(Boolean(right.shared_host_safe)),
|
|
287
|
-
compareJsonValues(left.env_clear, right.env_clear, []),
|
|
288
|
-
compareJsonValues(left.env_set, right.env_set, {}),
|
|
289
|
-
compareJsonValues(left.assert_stdout_contains, right.assert_stdout_contains, []),
|
|
290
|
-
compareJsonValues(left.assert_stdout_regex, right.assert_stdout_regex, []),
|
|
291
|
-
compareJsonValues(left.assert_stderr_contains, right.assert_stderr_contains, []),
|
|
292
|
-
compareJsonValues(left.assert_stderr_regex, right.assert_stderr_regex, []),
|
|
293
|
-
compareOptionalNumbers(left.assert_stdout_min_lines, right.assert_stdout_min_lines),
|
|
294
|
-
compareJsonValues(left.assert_json_field_equals, right.assert_json_field_equals, {}),
|
|
295
|
-
compareJsonValues(left.assert_json_field_gte, right.assert_json_field_gte, {}),
|
|
296
|
-
compareOptionalStrings(left.note, right.note),
|
|
297
|
-
];
|
|
298
|
-
return comparisons.find((comparison) => comparison !== 0) ?? 0;
|
|
299
|
-
}
|
|
300
|
-
function decodeJsonPointer(path) {
|
|
301
|
-
if (!path || path === "/") {
|
|
302
|
-
return [];
|
|
303
|
-
}
|
|
304
|
-
if (!path.startsWith("/")) {
|
|
305
|
-
return [];
|
|
306
|
-
}
|
|
307
|
-
return path
|
|
308
|
-
.slice(1)
|
|
309
|
-
.split("/")
|
|
310
|
-
.map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
311
|
-
}
|
|
312
|
-
function isDefinedPointerPath(document, path) {
|
|
313
|
-
const segments = decodeJsonPointer(path);
|
|
314
|
-
if (segments.length === 0) {
|
|
315
|
-
return true;
|
|
316
|
-
}
|
|
317
|
-
let cursor = document;
|
|
318
|
-
for (const segment of segments) {
|
|
319
|
-
const arrayIndex = /^(0|[1-9]\d*)$/.test(segment) ? Number(segment) : -1;
|
|
320
|
-
const next = Array.isArray(cursor)
|
|
321
|
-
? arrayIndex >= 0 && arrayIndex < cursor.length
|
|
322
|
-
? cursor[arrayIndex]
|
|
323
|
-
: undefined
|
|
324
|
-
: isRecord(cursor) &&
|
|
325
|
-
Object.prototype.hasOwnProperty.call(cursor, segment)
|
|
326
|
-
? cursor[segment]
|
|
327
|
-
: undefined;
|
|
328
|
-
if (next === undefined)
|
|
329
|
-
return false;
|
|
330
|
-
cursor = next;
|
|
331
|
-
}
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
function normalizeHistoryPatchOps(beforeDocument, patch) {
|
|
335
|
-
const normalized = [];
|
|
336
|
-
let replayCursor = structuredClone(beforeDocument);
|
|
337
|
-
for (const operation of patch) {
|
|
338
|
-
const normalizedOperation = operation.op === "replace" &&
|
|
339
|
-
!isDefinedPointerPath(replayCursor, operation.path)
|
|
340
|
-
? { ...operation, op: "add" }
|
|
341
|
-
: operation;
|
|
342
|
-
normalized.push(normalizedOperation);
|
|
343
|
-
replayCursor = jsonPatch.applyPatch(replayCursor, [normalizedOperation], true, true).newDocument;
|
|
344
|
-
}
|
|
345
|
-
return normalized;
|
|
346
|
-
}
|
|
347
|
-
function canonicalHashDocument(document, version, legacyV2Fields = false) {
|
|
348
|
-
const hasMetadata = document.metadata && Object.keys(document.metadata).length > 0;
|
|
349
|
-
if (!hasMetadata) {
|
|
350
|
-
return {
|
|
351
|
-
front_matter: {},
|
|
352
|
-
body: document.body ?? "",
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
const canonical = canonicalDocument(document);
|
|
356
|
-
// Epoch 1 and the earliest epoch-2 writer predate linked-test provenance,
|
|
357
|
-
// workspace isolation, per-execution receipts, and case-preserving
|
|
358
|
-
// dependency ids. Later epoch-2 writers included those fields without
|
|
359
|
-
// advancing the marker, so verification must retain both immutable forms.
|
|
360
|
-
const usesLegacyFields = version === 1 || (version === 2 && legacyV2Fields);
|
|
361
|
-
const epochMetadata = usesLegacyFields
|
|
362
|
-
? {
|
|
363
|
-
...canonical.metadata,
|
|
364
|
-
...(canonical.metadata.dependencies === undefined
|
|
365
|
-
? {}
|
|
366
|
-
: {
|
|
367
|
-
dependencies: canonical.metadata.dependencies.map((dependency) => ({
|
|
368
|
-
...dependency,
|
|
369
|
-
id: dependency.id.toLowerCase(),
|
|
370
|
-
})),
|
|
371
|
-
}),
|
|
372
|
-
...(canonical.metadata.tests === undefined
|
|
373
|
-
? {}
|
|
374
|
-
: {
|
|
375
|
-
tests: canonical.metadata.tests.map(({ workspace_context_mode: _workspaceContextMode, provenance: _provenance, provenance_invalid: _provenanceInvalid, ...test }) => test),
|
|
376
|
-
}),
|
|
377
|
-
...(canonical.metadata.test_runs === undefined
|
|
378
|
-
? {}
|
|
379
|
-
: {
|
|
380
|
-
test_runs: canonical.metadata.test_runs.map(({ executions: _executions, ...testRun }) => testRun),
|
|
381
|
-
}),
|
|
382
|
-
}
|
|
383
|
-
: canonical.metadata;
|
|
384
|
-
const metadata = version === 1 && epochMetadata.tests
|
|
385
|
-
? {
|
|
386
|
-
...epochMetadata,
|
|
387
|
-
tests: [...epochMetadata.tests].sort(compareLegacyLinkedTests),
|
|
388
|
-
}
|
|
389
|
-
: epochMetadata;
|
|
390
|
-
const orderedMetadata = orderObject(toItemRecord(metadata), ITEM_METADATA_KEY_ORDER);
|
|
391
|
-
return {
|
|
392
|
-
front_matter: orderedMetadata,
|
|
393
|
-
body: canonical.body,
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
function canonicalPatchDocument(document) {
|
|
397
|
-
const hasMetadata = document.metadata && Object.keys(document.metadata).length > 0;
|
|
398
|
-
if (!hasMetadata) {
|
|
399
|
-
return {
|
|
400
|
-
metadata: {},
|
|
401
|
-
body: document.body ?? "",
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
const canonical = canonicalDocument(document);
|
|
405
|
-
const orderedMetadata = orderObject(toItemRecord(canonical.metadata), ITEM_METADATA_KEY_ORDER);
|
|
406
|
-
return {
|
|
407
|
-
metadata: orderedMetadata,
|
|
408
|
-
body: canonical.body,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
/** Implements hash document for the public runtime surface of this module. */
|
|
412
|
-
export function hashDocument(document) {
|
|
413
|
-
return hashDocumentForVersion(document, CURRENT_HISTORY_ITEM_HASH_VERSION);
|
|
414
|
-
}
|
|
415
|
-
/** Hash an item with an explicit canonicalization epoch for replay compatibility. */
|
|
416
|
-
export function hashDocumentForVersion(document, version) {
|
|
417
|
-
if (!SUPPORTED_HISTORY_ITEM_HASH_VERSIONS.some((supportedVersion) => supportedVersion === version)) {
|
|
418
|
-
throw new TypeError(`unsupported_item_hash_version:${String(version)}`);
|
|
419
|
-
}
|
|
420
|
-
return sha256Hex(stableStringify(canonicalHashDocument(document, version)));
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Return the ordered hash candidates accepted when verifying one immutable
|
|
424
|
-
* history epoch. Epoch 2 has both its established expanded hash first and the
|
|
425
|
-
* earlier field-frozen writer hash second; the other epochs have one form.
|
|
426
|
-
*/
|
|
427
|
-
export function hashDocumentVerificationCandidates(document, version) {
|
|
428
|
-
const canonicalHash = hashDocumentForVersion(document, version);
|
|
429
|
-
return version === 2
|
|
430
|
-
? [
|
|
431
|
-
canonicalHash,
|
|
432
|
-
sha256Hex(stableStringify(canonicalHashDocument(document, version, true))),
|
|
433
|
-
]
|
|
434
|
-
: [canonicalHash];
|
|
435
|
-
}
|
|
436
|
-
/** Implements hash empty document for the public runtime surface of this module. */
|
|
437
|
-
export function hashEmptyDocument() {
|
|
438
|
-
return sha256Hex(stableStringify(EMPTY_LEGACY_HASH_DOCUMENT));
|
|
439
|
-
}
|
|
440
|
-
/** Implements create history entry for the public runtime surface of this module. */
|
|
441
|
-
export function createHistoryEntry(params) {
|
|
442
|
-
const beforeHashCanonical = canonicalHashDocument(params.before, CURRENT_HISTORY_ITEM_HASH_VERSION);
|
|
443
|
-
const afterHashCanonical = canonicalHashDocument(params.after, CURRENT_HISTORY_ITEM_HASH_VERSION);
|
|
444
|
-
const beforePatchCanonical = canonicalPatchDocument(params.before);
|
|
445
|
-
const afterPatchCanonical = canonicalPatchDocument(params.after);
|
|
446
|
-
const rawPatch = jsonPatch.compare(beforePatchCanonical, afterPatchCanonical);
|
|
447
|
-
const patch = normalizeHistoryPatchOps(beforePatchCanonical, rawPatch);
|
|
448
|
-
const agentIdentity = resolveHistoryAgentIdentity(params.author);
|
|
449
|
-
const provenanceOutcomes = agentIdentity.harness
|
|
450
|
-
? Object.fromEntries(Object.entries(diagnoseAgentIdentity().provenance_outcomes).filter(([, outcome]) => outcome.resolver !== undefined && outcome.status !== "resolved"))
|
|
451
|
-
: undefined;
|
|
452
|
-
const context = provenanceOutcomes === undefined ||
|
|
453
|
-
Object.keys(provenanceOutcomes).length === 0
|
|
454
|
-
? params.context
|
|
455
|
-
: {
|
|
456
|
-
...params.context,
|
|
457
|
-
agent_provenance_outcomes: provenanceOutcomes,
|
|
458
|
-
};
|
|
459
|
-
const entry = {
|
|
460
|
-
ts: params.nowIso,
|
|
461
|
-
author: params.author,
|
|
462
|
-
author_source: params.authorSource ?? resolveHistoryAuthorSource(params.author),
|
|
463
|
-
...(agentIdentity.harness ? { agent_harness: agentIdentity.harness } : {}),
|
|
464
|
-
...(agentIdentity.model ? { agent_model: agentIdentity.model } : {}),
|
|
465
|
-
...(agentIdentity.model_source
|
|
466
|
-
? { agent_model_source: agentIdentity.model_source }
|
|
467
|
-
: {}),
|
|
468
|
-
...(agentIdentity.instance
|
|
469
|
-
? { agent_instance: agentIdentity.instance }
|
|
470
|
-
: {}),
|
|
471
|
-
...(agentIdentity.provenance
|
|
472
|
-
? { agent_provenance: agentIdentity.provenance }
|
|
473
|
-
: {}),
|
|
474
|
-
...(agentIdentity.episode ? { agent_episode: agentIdentity.episode } : {}),
|
|
475
|
-
op: params.op,
|
|
476
|
-
patch,
|
|
477
|
-
before_hash: sha256Hex(stableStringify(beforeHashCanonical)),
|
|
478
|
-
after_hash: sha256Hex(stableStringify(afterHashCanonical)),
|
|
479
|
-
item_hash_version: CURRENT_HISTORY_ITEM_HASH_VERSION,
|
|
480
|
-
message: params.message === undefined ? undefined : params.message,
|
|
481
|
-
...(context === undefined ? {} : { context }),
|
|
482
|
-
};
|
|
483
|
-
return sealHistoryRecord({
|
|
484
|
-
...entry,
|
|
485
|
-
event_class: classifyHistoryEvent(entry),
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
function isRecord(value) {
|
|
489
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
490
|
-
}
|
|
491
|
-
function invalidHistoryTimestamp(message) {
|
|
492
|
-
return new PmCliError(message, EXIT_CODE.GENERIC_FAILURE, {
|
|
493
|
-
code: "history_timestamp_invalid",
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
function fallbackHistoryTimestamp(entry) {
|
|
497
|
-
const ts = entry.ts.trim();
|
|
498
|
-
if (ts.length === 0)
|
|
499
|
-
return nowIso();
|
|
500
|
-
if (!isMillisecondPrecisionRfc3339DateTime(ts)) {
|
|
501
|
-
throw invalidHistoryTimestamp("History timestamp must be a valid RFC 3339 date-time with millisecond precision");
|
|
502
|
-
}
|
|
503
|
-
if (ts !== entry.ts) {
|
|
504
|
-
throw invalidHistoryTimestamp("History timestamp must not contain surrounding whitespace");
|
|
505
|
-
}
|
|
506
|
-
return entry.ts;
|
|
507
|
-
}
|
|
508
|
-
function withHistoryTimestamp(value, fallbackTs) {
|
|
509
|
-
const ts = value.ts;
|
|
510
|
-
if (typeof ts === "string" && ts.trim().length > 0) {
|
|
511
|
-
if (!isMillisecondPrecisionRfc3339DateTime(ts)) {
|
|
512
|
-
throw invalidHistoryTimestamp("History timestamp must be a valid RFC 3339 date-time with millisecond precision");
|
|
513
|
-
}
|
|
514
|
-
return value;
|
|
515
|
-
}
|
|
516
|
-
return { ...value, ts: fallbackTs };
|
|
517
|
-
}
|
|
518
|
-
function serializeHistoryLine(value, fallbackEntry) {
|
|
519
|
-
const fallbackTs = fallbackHistoryTimestamp(fallbackEntry);
|
|
520
|
-
if (typeof value === "string") {
|
|
521
|
-
let parsed;
|
|
522
|
-
try {
|
|
523
|
-
parsed = JSON.parse(value);
|
|
524
|
-
}
|
|
525
|
-
catch {
|
|
526
|
-
// Non-JSON extension lines are preserved for compatibility.
|
|
527
|
-
return value;
|
|
528
|
-
}
|
|
529
|
-
if (isRecord(parsed)) {
|
|
530
|
-
return JSON.stringify(withHistoryTimestamp(parsed, fallbackTs));
|
|
531
|
-
}
|
|
532
|
-
return value;
|
|
533
|
-
}
|
|
534
|
-
if (isRecord(value)) {
|
|
535
|
-
return JSON.stringify(withHistoryTimestamp(value, fallbackTs));
|
|
536
|
-
}
|
|
537
|
-
return JSON.stringify(value);
|
|
538
|
-
}
|
|
539
|
-
/** Apply one extension-provided append decision and report whether it consumed the write. */
|
|
540
|
-
async function applyHistoryAppendOverride(historyPath, entry, result) {
|
|
541
|
-
if (result === false)
|
|
542
|
-
return true;
|
|
543
|
-
if (typeof result === "string") {
|
|
544
|
-
const line = serializeHistoryLine(result, entry);
|
|
545
|
-
await appendHistoryLineWithIdentityReservation(historyPath, line);
|
|
546
|
-
await invalidateHistoryDriftCacheForPath(historyPath);
|
|
547
|
-
await removeHistoryEventIndexForHistoryPath(historyPath);
|
|
548
|
-
return true;
|
|
549
|
-
}
|
|
550
|
-
if (typeof result !== "object" || result === null)
|
|
551
|
-
return false;
|
|
552
|
-
const record = result;
|
|
553
|
-
if (record.skip === true)
|
|
554
|
-
return true;
|
|
555
|
-
const nextHistoryPath = typeof record.history_path === "string" ? record.history_path : historyPath;
|
|
556
|
-
const line = serializeHistoryLine(typeof record.line === "string" ? record.line : (record.entry ?? entry), entry);
|
|
557
|
-
await appendHistoryLineWithIdentityReservation(nextHistoryPath, line);
|
|
558
|
-
await invalidateHistoryDriftCacheForPath(nextHistoryPath);
|
|
559
|
-
await removeHistoryEventIndexForHistoryPath(nextHistoryPath);
|
|
560
|
-
return true;
|
|
561
|
-
}
|
|
562
|
-
/** Exclusively create genesis streams at their effective destination; never remove a failed partial reservation. */
|
|
563
|
-
async function appendHistoryLineWithIdentityReservation(historyPath, line) {
|
|
564
|
-
let record;
|
|
565
|
-
try {
|
|
566
|
-
record = JSON.parse(line);
|
|
567
|
-
}
|
|
568
|
-
catch {
|
|
569
|
-
// Legacy service overrides may provide non-JSON lines; verification diagnoses them.
|
|
570
|
-
record = null;
|
|
571
|
-
}
|
|
572
|
-
if (!isRecord(record) || record.op !== "create") {
|
|
573
|
-
await appendLineAtomic(historyPath, line);
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
await fs.mkdir(path.dirname(historyPath), { recursive: true });
|
|
577
|
-
try {
|
|
578
|
-
await fs.writeFile(historyPath, `${line}\n`, { encoding: "utf8", flag: "wx" });
|
|
579
|
-
}
|
|
580
|
-
catch (error) {
|
|
581
|
-
if (error.code !== "EEXIST")
|
|
582
|
-
throw error;
|
|
583
|
-
throw new PmCliError("This item identity is reserved by an existing history stream.", EXIT_CODE.CONFLICT, {
|
|
584
|
-
code: "item_identity_reserved",
|
|
585
|
-
required: "Choose a new item ID or restore the original item from its history.",
|
|
586
|
-
nextSteps: ["Run pm history <id> --full, then pm restore <id> <version> to recover the original item."],
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
/** Implements append history entry for the public runtime surface of this module. */
|
|
591
|
-
export async function appendHistoryEntry(historyPath, entry) {
|
|
592
|
-
const override = await runActiveServiceOverride("history_append", {
|
|
593
|
-
history_path: historyPath,
|
|
594
|
-
entry,
|
|
595
|
-
});
|
|
596
|
-
if (override.handled &&
|
|
597
|
-
(await applyHistoryAppendOverride(historyPath, entry, override.result))) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
const timestampedEntry = entry.ts.trim().length > 0
|
|
601
|
-
? entry
|
|
602
|
-
: { ...entry, ts: fallbackHistoryTimestamp(entry) };
|
|
603
|
-
const normalizedEntry = sealHistoryRecord({
|
|
604
|
-
...timestampedEntry,
|
|
605
|
-
event_class: classifyHistoryEvent(timestampedEntry),
|
|
606
|
-
});
|
|
607
|
-
await appendHistoryEntryWithEventIndex(historyPath, normalizedEntry, async () => {
|
|
608
|
-
await appendHistoryLineWithIdentityReservation(historyPath, serializeHistoryLine(normalizedEntry, normalizedEntry));
|
|
609
|
-
});
|
|
610
|
-
await invalidateHistoryDriftCacheForPath(historyPath);
|
|
611
|
-
}
|
|
612
|
-
/** Public contract for test only, shared by SDK and presentation-layer consumers. */
|
|
613
|
-
export const _testOnly = {
|
|
614
|
-
decodeJsonPointer,
|
|
615
|
-
isDefinedPointerPath,
|
|
616
|
-
};
|
|
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]="70eda133-68fd-5dd6-afe9-c892f23e50a5")}catch(e2){}})();import jsonPatch from"fast-json-patch";import fs from"node:fs/promises";import path from"node:path";import{EXIT_CODE,ITEM_METADATA_KEY_ORDER}from"../shared/constants.js";import{runActiveServiceOverride}from"../extensions/index.js";import{appendLineAtomic}from"../fs/fs-utils.js";import{canonicalDocument}from"../item/item-format.js";import{toItemRecord}from"../item/item-record.js";import{orderObject,sha256Hex,stableStringify}from"../shared/serialization.js";import{isMillisecondPrecisionRfc3339DateTime,nowIso}from"../shared/time.js";import{diagnoseAgentIdentity,resolveHistoryAgentIdentity,resolveHistoryAuthorSource}from"../shared/author.js";import{appendHistoryEntryWithEventIndex,removeHistoryEventIndexForHistoryPath}from"./event-index.js";import{classifyHistoryEvent}from"./event-classification.js";import{invalidateHistoryDriftCacheForPath}from"./drift-cache.js";import{PmCliError}from"../shared/errors.js";const EMPTY_LEGACY_HASH_DOCUMENT={front_matter:{},body:""};const CURRENT_HISTORY_ITEM_HASH_VERSION=3;const SUPPORTED_HISTORY_ITEM_HASH_VERSIONS=[1,2,3];const CURRENT_HISTORY_RECORD_HASH_VERSION=1;const SUPPORTED_HISTORY_RECORD_HASH_VERSIONS=[1];function hashHistoryRecord(entry){return sha256Hex(stableStringify(entry))}function hashHistoryPatch(patch){return sha256Hex(stableStringify(patch))}function hashHistoryStream(entries){return sha256Hex(stableStringify(entries))}function sealHistoryRecord(entry){const sealed={...entry,record_hash_version:CURRENT_HISTORY_RECORD_HASH_VERSION};const{record_hash:_recordHash,...canonical}=sealed;return{...sealed,record_hash:hashHistoryRecord(canonical)}}function verifyHistoryRecordHash(entry){if(entry.record_hash_version===void 0&&entry.record_hash===void 0){return{ok:true,coverage:"item_state_only"}}if(entry.record_hash_version===void 0||entry.record_hash===void 0){return{ok:false,error:"incomplete_record_hash_envelope"}}if(!SUPPORTED_HISTORY_RECORD_HASH_VERSIONS.includes(entry.record_hash_version)){return{ok:false,error:"unsupported_record_hash_version"}}const{record_hash:_recordHash,...canonical}=entry;return hashHistoryRecord(canonical)===entry.record_hash?{ok:true,coverage:"record_and_item_state"}:{ok:false,error:"record_hash_mismatch"}}function createHistoryRewriteEvidence(original,options){const evidence={before_hash:original.before_hash,after_hash:original.after_hash,patch_hash:hashHistoryPatch(original.patch)};if(original.item_hash_version!==void 0){evidence.item_hash_version=original.item_hash_version}if(options.retainOriginalPatch){evidence.patch=structuredClone(original.patch)}if(options.retainPriorRecordHash!==false&&original.record_hash_version!==void 0&&original.record_hash!==void 0){evidence.record_hash_version=original.record_hash_version;evidence.record_hash=original.record_hash;evidence.record=structuredClone(original)}return evidence}function resealHistoryRewrite(original,rewritten,options={}){const originalRecordVerification=verifyHistoryRecordHash(original);if(!originalRecordVerification.ok){throw new TypeError(originalRecordVerification.error)}const originalPatchHash=hashHistoryPatch(original.patch);const retainsRewriteEvidence=options.retainPriorRecord===true||original.before_hash!==rewritten.before_hash||original.after_hash!==rewritten.after_hash||original.item_hash_version!==rewritten.item_hash_version||originalPatchHash!==hashHistoryPatch(rewritten.patch);const sealed=sealHistoryRecord({...rewritten,...retainsRewriteEvidence?{reanchor_evidence:[...rewritten.reanchor_evidence??[],createHistoryRewriteEvidence(original,options)]}:{}});const evidenceVerification=verifyHistoryRewriteEvidence(sealed);if(!evidenceVerification.ok){throw new TypeError(evidenceVerification.error)}return sealed}function isHistoryPatch(value){if(!Array.isArray(value)||Object.keys(value).length!==value.length){return false}return value.every(operation=>{if(!isRecord(operation)||typeof operation.path!=="string"){return false}if(operation.op==="move"||operation.op==="copy"){return typeof operation.from==="string"}if(["add","replace","test"].includes(operation.op)){return Object.hasOwn(operation,"value")}return operation.op==="remove"})}function isRetainedHistoryRecordShape(value){return isRecord(value)&&typeof value.ts==="string"&&typeof value.author==="string"&&typeof value.op==="string"&&typeof value.before_hash==="string"&&typeof value.after_hash==="string"&&isHistoryPatch(value.patch)}function hasCompleteRetainedRecordHashEnvelope(evidence){const hasVersion=evidence.record_hash_version!==void 0;const hasHash=evidence.record_hash!==void 0;return hasVersion===hasHash}function isHistoryReanchorEvidence(evidence){if(!isRecord(evidence)||!hasCompleteRetainedRecordHashEnvelope(evidence)||typeof evidence.before_hash!=="string"||typeof evidence.after_hash!=="string"||typeof evidence.patch_hash!=="string"||!/^[a-f0-9]{64}$/u.test(evidence.patch_hash)||evidence.patch!==void 0&&!isHistoryPatch(evidence.patch)||evidence.record_hash_version!==void 0&&typeof evidence.record_hash_version!=="number"||evidence.record_hash!==void 0&&(typeof evidence.record_hash!=="string"||!/^[a-f0-9]{64}$/u.test(evidence.record_hash))){return false}return evidence.record===void 0||isRetainedHistoryRecordShape(evidence.record)}function matchesRetainedHistoryRecord(evidence){const record=evidence.record;return record!==void 0&&record.before_hash===evidence.before_hash&&record.after_hash===evidence.after_hash&&record.item_hash_version===evidence.item_hash_version&&record.record_hash_version===evidence.record_hash_version&&record.record_hash===evidence.record_hash&&hashHistoryPatch(record.patch)===evidence.patch_hash}function reconstructPriorHistoryRecord(current,evidence,priorEvidence){if(evidence.patch&&hashHistoryPatch(evidence.patch)!==evidence.patch_hash){return{kind:"patch_hash_mismatch"}}if(evidence.record){if(!matchesRetainedHistoryRecord(evidence)){return{kind:"record_hash_mismatch"}}return{kind:"record",entry:evidence.record}}const priorPatch=evidence.patch??current.patch;if(hashHistoryPatch(priorPatch)!==evidence.patch_hash){return{kind:"digest_only"}}const priorRecord={...current,before_hash:evidence.before_hash,after_hash:evidence.after_hash,patch:priorPatch,...evidence.item_hash_version===void 0?{}:{item_hash_version:evidence.item_hash_version},...evidence.record_hash_version===void 0?{}:{record_hash_version:evidence.record_hash_version},...evidence.record_hash===void 0?{}:{record_hash:evidence.record_hash},...priorEvidence.length===0?{}:{reanchor_evidence:priorEvidence}};if(priorEvidence.length===0)delete priorRecord.reanchor_evidence;if(evidence.item_hash_version===void 0){delete priorRecord.item_hash_version}return evidence.record_hash_version===void 0||evidence.record_hash===void 0?{kind:"legacy",entry:priorRecord}:{kind:"record",entry:priorRecord}}function verifyHistoryRewriteEvidence(entry){const evidenceEntries=entry.reanchor_evidence;if(evidenceEntries===void 0)return{ok:true,coverage:"none"};if(!Array.isArray(evidenceEntries)){return{ok:false,error:"rewrite_evidence_invalid"}}if(evidenceEntries.length===0)return{ok:true,coverage:"none"};let reconstructed=entry;for(let index=evidenceEntries.length-1;index>=0;index-=1){const evidence=evidenceEntries[index];if(!(index in evidenceEntries)||!isHistoryReanchorEvidence(evidence)){return{ok:false,error:"rewrite_evidence_invalid"}}const prior=reconstructPriorHistoryRecord(reconstructed,evidence,evidenceEntries.slice(0,index));if(prior.kind==="patch_hash_mismatch"){return{ok:false,error:"rewrite_evidence_patch_hash_mismatch"}}if(prior.kind==="record_hash_mismatch"){return{ok:false,error:"rewrite_evidence_record_hash_mismatch"}}if(prior.kind==="digest_only"){return{ok:true,coverage:"digest_only"}}if(prior.kind==="legacy"){return{ok:true,coverage:"legacy_anchor_only"}}if(!verifyHistoryRecordHash(prior.entry).ok){return{ok:false,error:"rewrite_evidence_record_hash_mismatch"}}reconstructed=prior.entry}return{ok:true,coverage:"complete"}}function compareOptionalStrings(left,right){return(left??"").localeCompare(right??"")}function compareOptionalNumbers(left,right){return(left??0)-(right??0)}function compareJsonValues(left,right,fallback){return JSON.stringify(left??fallback).localeCompare(JSON.stringify(right??fallback))}function compareLegacyLinkedTests(left,right){const comparisons=[left.scope.localeCompare(right.scope),compareOptionalStrings(left.path,right.path),compareOptionalStrings(left.command,right.command),compareOptionalNumbers(left.timeout_seconds,right.timeout_seconds),compareOptionalStrings(left.pm_context_mode,right.pm_context_mode),Number(Boolean(left.shared_host_safe))-Number(Boolean(right.shared_host_safe)),compareJsonValues(left.env_clear,right.env_clear,[]),compareJsonValues(left.env_set,right.env_set,{}),compareJsonValues(left.assert_stdout_contains,right.assert_stdout_contains,[]),compareJsonValues(left.assert_stdout_regex,right.assert_stdout_regex,[]),compareJsonValues(left.assert_stderr_contains,right.assert_stderr_contains,[]),compareJsonValues(left.assert_stderr_regex,right.assert_stderr_regex,[]),compareOptionalNumbers(left.assert_stdout_min_lines,right.assert_stdout_min_lines),compareJsonValues(left.assert_json_field_equals,right.assert_json_field_equals,{}),compareJsonValues(left.assert_json_field_gte,right.assert_json_field_gte,{}),compareOptionalStrings(left.note,right.note)];return comparisons.find(comparison=>comparison!==0)??0}function decodeJsonPointer(path2){if(!path2||path2==="/"){return[]}if(!path2.startsWith("/")){return[]}return path2.slice(1).split("/").map(segment=>segment.replaceAll("~1","/").replaceAll("~0","~"))}function isDefinedPointerPath(document,path2){const segments=decodeJsonPointer(path2);if(segments.length===0){return true}let cursor=document;for(const segment of segments){const arrayIndex=/^(0|[1-9]\d*)$/.test(segment)?Number(segment):-1;const next=Array.isArray(cursor)?arrayIndex>=0&&arrayIndex<cursor.length?cursor[arrayIndex]:void 0:isRecord(cursor)&&Object.prototype.hasOwnProperty.call(cursor,segment)?cursor[segment]:void 0;if(next===void 0)return false;cursor=next}return true}function normalizeHistoryPatchOps(beforeDocument,patch){const normalized=[];let replayCursor=structuredClone(beforeDocument);for(const operation of patch){const normalizedOperation=operation.op==="replace"&&!isDefinedPointerPath(replayCursor,operation.path)?{...operation,op:"add"}:operation;normalized.push(normalizedOperation);replayCursor=jsonPatch.applyPatch(replayCursor,[normalizedOperation],true,true).newDocument}return normalized}function canonicalHashDocument(document,version,legacyV2Fields=false){const hasMetadata=document.metadata&&Object.keys(document.metadata).length>0;if(!hasMetadata){return{front_matter:{},body:document.body??""}}const canonical=canonicalDocument(document);const usesLegacyFields=version===1||version===2&&legacyV2Fields;const epochMetadata=usesLegacyFields?{...canonical.metadata,...canonical.metadata.dependencies===void 0?{}:{dependencies:canonical.metadata.dependencies.map(dependency=>({...dependency,id:dependency.id.toLowerCase()}))},...canonical.metadata.tests===void 0?{}:{tests:canonical.metadata.tests.map(({workspace_context_mode:_workspaceContextMode,provenance:_provenance,provenance_invalid:_provenanceInvalid,...test})=>test)},...canonical.metadata.test_runs===void 0?{}:{test_runs:canonical.metadata.test_runs.map(({executions:_executions,...testRun})=>testRun)}}:canonical.metadata;const metadata=version===1&&epochMetadata.tests?{...epochMetadata,tests:[...epochMetadata.tests].sort(compareLegacyLinkedTests)}:epochMetadata;const orderedMetadata=orderObject(toItemRecord(metadata),ITEM_METADATA_KEY_ORDER);return{front_matter:orderedMetadata,body:canonical.body}}function canonicalPatchDocument(document){const hasMetadata=document.metadata&&Object.keys(document.metadata).length>0;if(!hasMetadata){return{metadata:{},body:document.body??""}}const canonical=canonicalDocument(document);const orderedMetadata=orderObject(toItemRecord(canonical.metadata),ITEM_METADATA_KEY_ORDER);return{metadata:orderedMetadata,body:canonical.body}}function hashDocument(document){return hashDocumentForVersion(document,CURRENT_HISTORY_ITEM_HASH_VERSION)}function hashDocumentForVersion(document,version){if(!SUPPORTED_HISTORY_ITEM_HASH_VERSIONS.some(supportedVersion=>supportedVersion===version)){throw new TypeError(`unsupported_item_hash_version:${String(version)}`)}return sha256Hex(stableStringify(canonicalHashDocument(document,version)))}function hashDocumentVerificationCandidates(document,version){const canonicalHash=hashDocumentForVersion(document,version);return version===2?[canonicalHash,sha256Hex(stableStringify(canonicalHashDocument(document,version,true)))]:[canonicalHash]}function hashEmptyDocument(){return sha256Hex(stableStringify(EMPTY_LEGACY_HASH_DOCUMENT))}function createHistoryEntry(params){const beforeHashCanonical=canonicalHashDocument(params.before,CURRENT_HISTORY_ITEM_HASH_VERSION);const afterHashCanonical=canonicalHashDocument(params.after,CURRENT_HISTORY_ITEM_HASH_VERSION);const beforePatchCanonical=canonicalPatchDocument(params.before);const afterPatchCanonical=canonicalPatchDocument(params.after);const rawPatch=jsonPatch.compare(beforePatchCanonical,afterPatchCanonical);const patch=normalizeHistoryPatchOps(beforePatchCanonical,rawPatch);const agentIdentity=resolveHistoryAgentIdentity(params.author);const provenanceOutcomes=agentIdentity.harness?Object.fromEntries(Object.entries(diagnoseAgentIdentity().provenance_outcomes).filter(([,outcome])=>outcome.resolver!==void 0&&outcome.status!=="resolved")):void 0;const context=provenanceOutcomes===void 0||Object.keys(provenanceOutcomes).length===0?params.context:{...params.context,agent_provenance_outcomes:provenanceOutcomes};const entry={ts:params.nowIso,author:params.author,author_source:params.authorSource??resolveHistoryAuthorSource(params.author),...agentIdentity.harness?{agent_harness:agentIdentity.harness}:{},...agentIdentity.model?{agent_model:agentIdentity.model}:{},...agentIdentity.model_source?{agent_model_source:agentIdentity.model_source}:{},...agentIdentity.instance?{agent_instance:agentIdentity.instance}:{},...agentIdentity.provenance?{agent_provenance:agentIdentity.provenance}:{},...agentIdentity.episode?{agent_episode:agentIdentity.episode}:{},op:params.op,patch,before_hash:sha256Hex(stableStringify(beforeHashCanonical)),after_hash:sha256Hex(stableStringify(afterHashCanonical)),item_hash_version:CURRENT_HISTORY_ITEM_HASH_VERSION,message:params.message===void 0?void 0:params.message,...context===void 0?{}:{context}};return sealHistoryRecord({...entry,event_class:classifyHistoryEvent(entry)})}function isRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function invalidHistoryTimestamp(message){return new PmCliError(message,EXIT_CODE.GENERIC_FAILURE,{code:"history_timestamp_invalid"})}function fallbackHistoryTimestamp(entry){const ts=entry.ts.trim();if(ts.length===0)return nowIso();if(!isMillisecondPrecisionRfc3339DateTime(ts)){throw invalidHistoryTimestamp("History timestamp must be a valid RFC 3339 date-time with millisecond precision")}if(ts!==entry.ts){throw invalidHistoryTimestamp("History timestamp must not contain surrounding whitespace")}return entry.ts}function withHistoryTimestamp(value,fallbackTs){const ts=value.ts;if(typeof ts==="string"&&ts.trim().length>0){if(!isMillisecondPrecisionRfc3339DateTime(ts)){throw invalidHistoryTimestamp("History timestamp must be a valid RFC 3339 date-time with millisecond precision")}return value}return{...value,ts:fallbackTs}}function serializeHistoryLine(value,fallbackEntry){const fallbackTs=fallbackHistoryTimestamp(fallbackEntry);if(typeof value==="string"){let parsed;try{parsed=JSON.parse(value)}catch{return value}if(isRecord(parsed)){return JSON.stringify(withHistoryTimestamp(parsed,fallbackTs))}return value}if(isRecord(value)){return JSON.stringify(withHistoryTimestamp(value,fallbackTs))}return JSON.stringify(value)}async function applyHistoryAppendOverride(historyPath,entry,result){if(result===false)return true;if(typeof result==="string"){const line2=serializeHistoryLine(result,entry);await appendHistoryLineWithIdentityReservation(historyPath,line2);await invalidateHistoryDriftCacheForPath(historyPath);await removeHistoryEventIndexForHistoryPath(historyPath);return true}if(typeof result!=="object"||result===null)return false;const record=result;if(record.skip===true)return true;const nextHistoryPath=typeof record.history_path==="string"?record.history_path:historyPath;const line=serializeHistoryLine(typeof record.line==="string"?record.line:record.entry??entry,entry);await appendHistoryLineWithIdentityReservation(nextHistoryPath,line);await invalidateHistoryDriftCacheForPath(nextHistoryPath);await removeHistoryEventIndexForHistoryPath(nextHistoryPath);return true}async function appendHistoryLineWithIdentityReservation(historyPath,line){let record;try{record=JSON.parse(line)}catch{record=null}if(!isRecord(record)||record.op!=="create"){await appendLineAtomic(historyPath,line);return}await fs.mkdir(path.dirname(historyPath),{recursive:true});try{await fs.writeFile(historyPath,`${line}
|
|
2
|
+
`,{encoding:"utf8",flag:"wx"})}catch(error){if(error.code!=="EEXIST")throw error;throw new PmCliError("This item identity is reserved by an existing history stream.",EXIT_CODE.CONFLICT,{code:"item_identity_reserved",required:"Choose a new item ID or restore the original item from its history.",nextSteps:["Run pm history <id> --full, then pm restore <id> <version> to recover the original item."]})}}async function appendHistoryEntry(historyPath,entry){const override=await runActiveServiceOverride("history_append",{history_path:historyPath,entry});if(override.handled&&await applyHistoryAppendOverride(historyPath,entry,override.result)){return}const timestampedEntry=entry.ts.trim().length>0?entry:{...entry,ts:fallbackHistoryTimestamp(entry)};const normalizedEntry=sealHistoryRecord({...timestampedEntry,event_class:classifyHistoryEvent(timestampedEntry)});await appendHistoryEntryWithEventIndex(historyPath,normalizedEntry,async()=>{await appendHistoryLineWithIdentityReservation(historyPath,serializeHistoryLine(normalizedEntry,normalizedEntry))});await invalidateHistoryDriftCacheForPath(historyPath)}const _testOnly={decodeJsonPointer,isDefinedPointerPath};export{CURRENT_HISTORY_ITEM_HASH_VERSION,CURRENT_HISTORY_RECORD_HASH_VERSION,SUPPORTED_HISTORY_ITEM_HASH_VERSIONS,SUPPORTED_HISTORY_RECORD_HASH_VERSIONS,_testOnly,appendHistoryEntry,createHistoryEntry,hashDocument,hashDocumentForVersion,hashDocumentVerificationCandidates,hashEmptyDocument,hashHistoryPatch,hashHistoryRecord,hashHistoryStream,resealHistoryRewrite,sealHistoryRecord,verifyHistoryRecordHash,verifyHistoryRewriteEvidence};
|
|
617
3
|
//# sourceMappingURL=history.js.map
|
|
618
|
-
//# debugId=a5449fec-c5b4-5cf4-9a7f-b7c5dc7161c2
|