@unbrained/pm-cli 2026.10.4 → 2026.10.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +37 -1
- package/dist/cli/after-command-context-usage.js +1 -1
- package/dist/cli/argv-utils.js +1 -1
- package/dist/cli/bootstrap-args.js +1 -1
- package/dist/cli/bundle-integrity.js +2 -2
- package/dist/cli/command-namespaces.js +1 -1
- package/dist/cli/commander-usage.d.ts +1 -1
- package/dist/cli/commander-usage.js +7 -4
- package/dist/cli/commands/annotations/comments.js +1 -1
- package/dist/cli/commands/annotations/docs.js +1 -1
- package/dist/cli/commands/annotations/files.js +1 -1
- package/dist/cli/commands/annotations/learnings.js +1 -1
- package/dist/cli/commands/annotations/notes.js +1 -1
- package/dist/cli/commands/extension/describe.js +1 -1
- package/dist/cli/commands/extension/extension.js +1 -1
- package/dist/cli/commands/extension/scaffold.js +1 -1
- package/dist/cli/commands/extension/shared.js +1 -1
- package/dist/cli/commands/governance/gc.js +1 -1
- package/dist/cli/commands/governance/health.js +1 -1
- package/dist/cli/commands/governance/telemetry.js +1 -1
- package/dist/cli/commands/governance/validate.js +1 -1
- package/dist/cli/commands/history/activity.js +1 -1
- package/dist/cli/commands/history/history-compact.js +1 -1
- package/dist/cli/commands/history/history-redact.js +1 -1
- package/dist/cli/commands/history/history-repair.js +1 -1
- package/dist/cli/commands/history/history.js +1 -1
- package/dist/cli/commands/history/restore.js +1 -1
- package/dist/cli/commands/lifecycle/append.js +1 -1
- package/dist/cli/commands/lifecycle/claim.js +1 -1
- package/dist/cli/commands/lifecycle/close-many.js +1 -1
- package/dist/cli/commands/lifecycle/close.js +1 -1
- package/dist/cli/commands/lifecycle/copy.js +1 -1
- package/dist/cli/commands/lifecycle/create.js +1 -1
- package/dist/cli/commands/lifecycle/delete.js +1 -1
- package/dist/cli/commands/lifecycle/focus.js +1 -1
- package/dist/cli/commands/lifecycle/plan.js +1 -1
- package/dist/cli/commands/lifecycle/update-many.js +1 -1
- package/dist/cli/commands/lifecycle/update.js +1 -1
- package/dist/cli/commands/query/aggregate.js +1 -1
- package/dist/cli/commands/query/context.js +1 -1
- package/dist/cli/commands/query/deps.js +1 -1
- package/dist/cli/commands/query/duplicates.js +1 -1
- package/dist/cli/commands/query/eval.js +1 -1
- package/dist/cli/commands/query/get.js +1 -1
- package/dist/cli/commands/query/graph.js +1 -1
- package/dist/cli/commands/query/list.js +1 -1
- package/dist/cli/commands/query/next.js +1 -1
- package/dist/cli/commands/query/search.js +1 -1
- package/dist/cli/commands/query/stats.js +1 -1
- package/dist/cli/commands/test/test-all.js +1 -1
- package/dist/cli/commands/test/test-runs.js +1 -1
- package/dist/cli/commands/test/test.js +1 -1
- package/dist/cli/commands/workspace/config.js +1 -1
- package/dist/cli/commands/workspace/contracts.js +1 -1
- package/dist/cli/commands/workspace/init.js +1 -1
- package/dist/cli/commands/workspace/merge.js +1 -1
- package/dist/cli/commands/workspace/profile.js +1 -1
- package/dist/cli/commands/workspace/schema.js +1 -1
- package/dist/cli/commands/workspace/upgrade.js +1 -1
- package/dist/cli/context-intent-invocation.js +1 -1
- package/dist/cli/description-stdin.js +1 -1
- package/dist/cli/error-guidance.js +3 -1
- package/dist/cli/extension-command-help.js +5 -3
- package/dist/cli/extension-command-options.js +1 -1
- package/dist/cli/extension-recovery.js +1 -1
- package/dist/cli/help-content.js +5 -2
- package/dist/cli/help-json-payload.js +6 -3
- package/dist/cli/invocation-profile.js +2 -2
- package/dist/cli/main.js +5 -5
- package/dist/cli/migration-gates.js +1 -1
- package/dist/cli/option-values.js +1 -1
- package/dist/cli/public.js +1 -1
- package/dist/cli/register-annotations.js +1 -1
- package/dist/cli/register-assurance.js +1 -1
- package/dist/cli/register-files-lookup.js +1 -1
- package/dist/cli/register-history-activity.js +1 -1
- package/dist/cli/register-history-author.js +1 -1
- package/dist/cli/register-history-maintenance.js +2 -2
- package/dist/cli/register-list-query.js +10 -10
- package/dist/cli/register-mutation-options.js +1 -1
- package/dist/cli/register-mutation.js +2 -2
- package/dist/cli/register-operations.js +1 -1
- package/dist/cli/register-setup.js +1 -1
- package/dist/cli/register-structured-mutation.js +1 -1
- package/dist/cli/registration-helpers.js +1 -1
- package/dist/cli/runtime/activation.js +1 -1
- package/dist/cli/runtime/invocation-options.js +1 -1
- package/dist/cli/runtime/projection-retry.js +1 -1
- package/dist/cli/runtime/selection.js +1 -1
- package/dist/cli/runtime/telemetry-outcome.js +1 -1
- package/dist/cli/runtime-compatibility-boundary.js +4 -4
- package/dist/cli/schema/registration.js +2 -2
- package/dist/cli/schema-registration-helpers.js +1 -1
- package/dist/cli/search-refresh.js +1 -1
- package/dist/cli/stats-analytics-json.js +1 -1
- package/dist/cli/telemetry-flush.js +1 -1
- package/dist/cli-bundle/bundle-manifest.json +163 -163
- package/dist/cli-bundle/chunks/{chunk-SMKHR6BM.js → chunk-25EW53VO.js} +89 -88
- package/dist/cli-bundle/chunks/chunk-3CCVTV6Q.js +8 -0
- package/dist/cli-bundle/chunks/chunk-3REXBTST.js +3 -0
- package/dist/cli-bundle/chunks/chunk-4WB55TBC.js +80 -0
- package/dist/cli-bundle/chunks/{chunk-7CE2DJMA.js → chunk-6STTPXOC.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-ATB4ZZBQ.js +20 -0
- package/dist/cli-bundle/chunks/chunk-D4G43LBV.js +238 -0
- package/dist/cli-bundle/chunks/chunk-K6D6DMRT.js +31 -0
- package/dist/cli-bundle/chunks/chunk-KIRHWPZB.js +2 -0
- package/dist/cli-bundle/chunks/chunk-O67BH435.js +6 -0
- package/dist/cli-bundle/chunks/chunk-R7CG2DB7.js +2 -0
- package/dist/cli-bundle/chunks/chunk-RJHLD64E.js +3 -0
- package/dist/cli-bundle/chunks/chunk-TUKO5NF7.js +2 -0
- package/dist/cli-bundle/chunks/chunk-UZ7BIUCI.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-GZMWISWW.js → chunk-XJD47LUH.js} +3 -3
- package/dist/cli-bundle/chunks/{register-list-query-QBGXO5JJ.js → register-list-query-53WYLNZT.js} +11 -11
- package/dist/cli-bundle/chunks/register-mutation-34XXUBVI.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-WANO6EIM.js +2 -0
- package/dist/cli-bundle/chunks/register-setup-WT37UPBQ.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-6KFKQD2D.js +165 -0
- package/dist/cli-bundle/focused-chunks/chunk-FOHRPFIT.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-GRQXL5G5.js +8 -0
- package/dist/cli-bundle/focused-chunks/{chunk-467EW5RL.js → chunk-JZ4WGUVH.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-NM3PM6O6.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-OT7HK7SG.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-Q6DJ5DFQ.js → chunk-PCLU34KB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-HFAW3FJQ.js → chunk-PSXFFQFT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-QQIE4L42.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-RPUNVKXK.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-RXSVJPZ7.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-SPN5QTZ3.js +30 -0
- package/dist/cli-bundle/focused-chunks/chunk-SUZJNPGB.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-W4BG5HHS.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-Y5HXFDTZ.js +20 -0
- package/dist/cli-bundle/focused-chunks/chunk-ZK5SOOPC.js +75 -0
- package/dist/cli-bundle/focused-chunks/chunk-ZQK2XUSS.js +12 -0
- package/dist/cli-bundle/main.js +25 -25
- 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 +25 -24
- 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 +55 -55
- 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 +10 -10
- package/dist/cli.js +1 -1
- package/dist/core/checkpoint/checkpoint-gc.js +1 -1
- package/dist/core/checkpoint/mutation-checkpoint.js +2 -2
- package/dist/core/config/nested-settings.js +1 -1
- package/dist/core/config/positional-value.js +1 -1
- package/dist/core/diagnostics/remediation.js +1 -1
- package/dist/core/extensions/activation-summary-markdown.js +2 -1
- package/dist/core/extensions/activation-summary.js +1 -1
- package/dist/core/extensions/activation-transaction.js +1 -1
- package/dist/core/extensions/capability-usage.js +1 -1
- package/dist/core/extensions/command-hook-context.js +1 -1
- package/dist/core/extensions/command-metadata-contract.js +1 -1
- package/dist/core/extensions/command-visibility-tier.js +1 -1
- package/dist/core/extensions/contribution-inventory.js +1 -1
- package/dist/core/extensions/exporter-output-contract.js +1 -1
- package/dist/core/extensions/extension-candidate.js +1 -1
- package/dist/core/extensions/extension-capability-aliases.js +1 -1
- package/dist/core/extensions/extension-hook-runtime.js +1 -1
- package/dist/core/extensions/extension-policy.js +1 -1
- package/dist/core/extensions/extension-registries.js +1 -1
- package/dist/core/extensions/extension-runtime-helpers.js +1 -1
- package/dist/core/extensions/extension-types.d.ts +2 -0
- package/dist/core/extensions/extension-types.js +1 -1
- package/dist/core/extensions/flag-definition-validation.js +1 -1
- package/dist/core/extensions/flag-value-types.js +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/item-field-types.js +1 -1
- package/dist/core/extensions/item-fields.js +1 -1
- package/dist/core/extensions/loader.js +1 -1
- package/dist/core/extensions/manifest-parser.js +1 -1
- package/dist/core/extensions/manifest-schema.js +1 -1
- package/dist/core/extensions/module-graph-snapshot.js +1 -1
- package/dist/core/extensions/preflight-ownership.js +1 -1
- package/dist/core/extensions/registration-contracts.js +1 -1
- package/dist/core/extensions/registration-validation.js +1 -1
- package/dist/core/extensions/registration-values.js +1 -1
- package/dist/core/extensions/reserved-host-flags.js +1 -1
- package/dist/core/extensions/runtime-registrations.js +1 -1
- package/dist/core/extensions/service-ownership.js +1 -1
- package/dist/core/extensions/version-compat.js +1 -1
- package/dist/core/fs/atomic-create.js +1 -1
- package/dist/core/fs/fs-utils.js +2 -2
- package/dist/core/fs/host-environment-errors.js +1 -1
- package/dist/core/fs/index.js +1 -1
- package/dist/core/fs/path-utils.js +1 -1
- package/dist/core/governance/content-fields.js +1 -1
- package/dist/core/governance/issue-codes.js +1 -1
- package/dist/core/governance/metadata-coverage.js +1 -1
- package/dist/core/history/digest.js +1 -1
- package/dist/core/history/drift-cache.js +3 -3
- package/dist/core/history/drift-scan.d.ts +4 -0
- package/dist/core/history/drift-scan.js +1 -1
- package/dist/core/history/event-classification.js +1 -1
- package/dist/core/history/event-index.js +8 -7
- package/dist/core/history/history-compact-bulk.js +1 -1
- package/dist/core/history/history-diff.js +1 -1
- package/dist/core/history/history-rewrite.js +1 -1
- package/dist/core/history/history-storage-stats.js +1 -1
- package/dist/core/history/history-stream-policy.js +1 -1
- package/dist/core/history/history.js +2 -2
- package/dist/core/history/identity.js +1 -1
- package/dist/core/history/index.js +1 -1
- package/dist/core/history/operation-contract.js +1 -1
- package/dist/core/history/projection.js +1 -1
- package/dist/core/history/read.js +1 -1
- package/dist/core/history/replay.js +2 -1
- package/dist/core/history/tombstone.js +1 -1
- package/dist/core/history/version-address.js +1 -1
- package/dist/core/history/workspace-history.js +2 -2
- package/dist/core/io/body-file.js +1 -1
- package/dist/core/io/bulk-ids-input.js +2 -1
- package/dist/core/item/actionability.js +1 -1
- package/dist/core/item/dependency-reference.js +1 -1
- package/dist/core/item/id.js +1 -1
- package/dist/core/item/index.js +1 -1
- package/dist/core/item/item-format-version.js +1 -1
- package/dist/core/item/item-format.js +6 -4
- package/dist/core/item/item-record.js +1 -1
- package/dist/core/item/item-type-definition.js +1 -1
- package/dist/core/item/parent-reference-policy.js +1 -1
- package/dist/core/item/parse.js +8 -2
- package/dist/core/item/plan-lifecycle.js +1 -1
- package/dist/core/item/priority.js +1 -1
- package/dist/core/item/sprint-release-format.js +1 -1
- package/dist/core/item/status-filter.js +1 -1
- package/dist/core/item/status.js +1 -1
- package/dist/core/item/toon-decode.js +1 -1
- package/dist/core/item/type-registry.js +1 -1
- package/dist/core/item/type-synonyms.js +1 -1
- package/dist/core/lock/index.js +1 -1
- package/dist/core/lock/lock-gc.js +1 -1
- package/dist/core/lock/lock.js +3 -3
- package/dist/core/output/mutation-projection.js +1 -1
- package/dist/core/output/output-control.js +1 -1
- package/dist/core/output/output.js +22 -10
- package/dist/core/output/query-summary.js +1 -1
- package/dist/core/output/tabular.js +3 -1
- package/dist/core/packages/manifest.js +1 -1
- package/dist/core/packages/root.js +1 -1
- package/dist/core/policy/workflow-policy-schema.js +1 -1
- package/dist/core/policy/workflow-policy-store.js +1 -1
- package/dist/core/policy/workflow-policy.js +1 -1
- package/dist/core/profile/profile-describe.js +1 -1
- package/dist/core/profile/profile-lint.js +1 -1
- package/dist/core/profile/profile-plan.js +1 -1
- package/dist/core/profile/profile-presets.js +25 -1
- package/dist/core/reproducibility/context.js +1 -1
- package/dist/core/schema/fields-file.js +2 -2
- package/dist/core/schema/item-types-file.js +2 -2
- package/dist/core/schema/runtime-field-filters.js +1 -1
- package/dist/core/schema/runtime-field-values.js +1 -1
- package/dist/core/schema/runtime-schema.js +2 -2
- package/dist/core/schema/status-defs-file.js +2 -2
- package/dist/core/schema/status-token.js +1 -1
- package/dist/core/schema/type-inference.js +1 -1
- package/dist/core/schema/type-presets.js +1 -1
- package/dist/core/schema/type-workflows.js +1 -1
- package/dist/core/search/background-refresh.js +2 -2
- package/dist/core/search/bm25.js +1 -1
- package/dist/core/search/cache.js +2 -2
- package/dist/core/search/corpus.js +1 -1
- package/dist/core/search/embedding-batches.js +1 -1
- package/dist/core/search/eval-thresholds.js +1 -1
- package/dist/core/search/eval.js +1 -1
- package/dist/core/search/http-client.js +1 -1
- package/dist/core/search/providers.js +1 -1
- package/dist/core/search/relevance.js +1 -1
- package/dist/core/search/semantic-defaults.js +1 -1
- package/dist/core/search/staleness.js +1 -1
- package/dist/core/search/vector-stores.js +2 -2
- package/dist/core/search/vectorization-metadata.js +1 -1
- package/dist/core/sentry/helpers.js +1 -1
- package/dist/core/sentry/instrument.js +1 -1
- package/dist/core/session/session-state.js +1 -1
- package/dist/core/shared/agent-session-context.js +1 -1
- package/dist/core/shared/author.js +5 -1
- package/dist/core/shared/command-line.js +1 -1
- package/dist/core/shared/command-types.js +1 -1
- package/dist/core/shared/conflict-markers.js +1 -1
- package/dist/core/shared/constants.js +1 -1
- package/dist/core/shared/errors.js +1 -1
- package/dist/core/shared/html-entity-decode.js +1 -1
- package/dist/core/shared/index.js +1 -1
- package/dist/core/shared/item-metadata-contract.js +1 -1
- package/dist/core/shared/lazy-module.js +1 -1
- package/dist/core/shared/levenshtein.js +1 -1
- package/dist/core/shared/memo.js +1 -1
- package/dist/core/shared/numeric-parsers.js +1 -1
- package/dist/core/shared/option-alias-visibility.js +1 -1
- package/dist/core/shared/primitives.js +1 -1
- package/dist/core/shared/secret-rules.js +1 -1
- package/dist/core/shared/serial-queue.js +1 -1
- package/dist/core/shared/serialization.js +1 -1
- package/dist/core/shared/split-comma-list.js +1 -1
- package/dist/core/shared/text-normalization.js +1 -1
- package/dist/core/shared/time.js +2 -1
- package/dist/core/store/index.js +1 -1
- package/dist/core/store/item-format-migration.js +1 -1
- package/dist/core/store/item-metadata-cache.js +1 -1
- package/dist/core/store/item-metadata-query-index.js +7 -7
- package/dist/core/store/item-metadata-read-work.js +1 -1
- package/dist/core/store/item-store.js +1 -1
- package/dist/core/store/paths.js +1 -1
- package/dist/core/store/settings-concurrency.js +1 -1
- package/dist/core/store/settings-read-cache.js +1 -1
- package/dist/core/store/settings-validator.js +1 -1
- package/dist/core/store/settings.js +3 -3
- package/dist/core/store/tracker-preflight.js +1 -1
- package/dist/core/telemetry/consent.js +2 -2
- package/dist/core/telemetry/observability.js +1 -1
- package/dist/core/telemetry/policy.js +1 -1
- package/dist/core/telemetry/read-sampling.js +2 -2
- package/dist/core/telemetry/runtime.js +9 -5
- package/dist/core/test/background-runs.js +3 -3
- package/dist/core/test/item-test-run-tracking.js +1 -1
- package/dist/core/test/run-selectors.js +1 -1
- package/dist/core/validate/estimate-defaults.js +1 -1
- package/dist/core/validate/fix-planning.js +1 -1
- package/dist/core/validate/linked-artifact-reference.js +1 -1
- package/dist/core/validate/missing-by-type.js +1 -1
- package/dist/core/validate/missing-link-owners.js +1 -1
- package/dist/core/validate/stale-file-classification.js +1 -1
- package/dist/mcp/http-server.js +6 -4
- package/dist/mcp/legacy-adapter.js +1 -1
- package/dist/mcp/runtime-capabilities.js +1 -1
- package/dist/mcp/server.js +4 -4
- package/dist/mcp/tool-definitions.js +1 -1
- package/dist/sdk/actionability.js +1 -1
- package/dist/sdk/agent/closed-domain-contracts.js +1 -1
- package/dist/sdk/agent/command-recovery.js +1 -1
- package/dist/sdk/agent/command-suggestions.js +1 -1
- package/dist/sdk/agent/create-option-policy.js +1 -1
- package/dist/sdk/agent/identity-config.js +1 -1
- package/dist/sdk/agent/item-addressing.js +1 -1
- package/dist/sdk/agent/refusal-closure-census.js +2 -1
- package/dist/sdk/agent/refusal-closure.js +1 -1
- package/dist/sdk/agent/refusal-corpus-contracts.js +1 -1
- package/dist/sdk/agent/refusal-reachability.js +3 -1
- package/dist/sdk/agent/subcommand-recovery.js +1 -1
- package/dist/sdk/agent/task-transcript-contracts.js +1 -1
- package/dist/sdk/agent/tracker-preflight-contracts.js +1 -1
- package/dist/sdk/agent-capability-contracts.js +3 -1
- package/dist/sdk/agent-session-context.js +1 -1
- package/dist/sdk/annotations.js +1 -1
- package/dist/sdk/author-attribution.js +1 -1
- package/dist/sdk/authoring.js +1 -1
- package/dist/sdk/cli-bootstrap.d.ts +5 -1
- package/dist/sdk/cli-bootstrap.js +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +5 -3
- package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -1
- package/dist/sdk/cli-contracts/command-aliases.js +1 -1
- package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -1
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1
- package/dist/sdk/cli-contracts/commander-types.js +1 -1
- package/dist/sdk/cli-contracts/completeness.js +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.js +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +2 -1
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
- package/dist/sdk/cli-contracts/registration-helpers.js +7 -7
- package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -1
- package/dist/sdk/cli-contracts/string-lists.js +1 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -1
- package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1
- package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -1
- package/dist/sdk/cli-contracts.js +1 -1
- package/dist/sdk/cli-program.js +1 -1
- package/dist/sdk/command-line.js +1 -1
- package/dist/sdk/comments.js +1 -1
- package/dist/sdk/compile-cache.js +1 -1
- package/dist/sdk/completion/bash.js +2 -1
- package/dist/sdk/completion/fish.js +13 -7
- package/dist/sdk/completion/shared.js +1 -1
- package/dist/sdk/completion/zsh.js +14 -8
- package/dist/sdk/completion.js +1 -1
- package/dist/sdk/compose.js +1 -1
- package/dist/sdk/config.js +1 -1
- package/dist/sdk/context/recency.js +1 -1
- package/dist/sdk/context/semantic-session-attribution.js +1 -1
- package/dist/sdk/context/usage-egress.js +1 -1
- package/dist/sdk/context/usage-ledger.js +6 -3
- package/dist/sdk/context-intent-contracts.js +1 -1
- package/dist/sdk/context-intent-runtime.js +1 -1
- package/dist/sdk/context-packing.js +1 -1
- package/dist/sdk/context-relevance.js +1 -1
- package/dist/sdk/context-signal-store.js +2 -2
- package/dist/sdk/context-usage.js +1 -1
- package/dist/sdk/contracts.js +1 -1
- package/dist/sdk/core-governance.js +1 -1
- package/dist/sdk/core.js +1 -1
- package/dist/sdk/corpus-shape.js +1 -1
- package/dist/sdk/define.js +1 -1
- package/dist/sdk/dependencies.js +1 -1
- package/dist/sdk/dependency-flag-validation.js +1 -1
- package/dist/sdk/dependency-provenance.js +1 -1
- package/dist/sdk/docs.js +1 -1
- package/dist/sdk/duplicates.js +1 -1
- package/dist/sdk/environment/agent-environment.js +1 -1
- package/dist/sdk/environment/host-environment-errors.js +1 -1
- package/dist/sdk/environment/project-runtime-compatibility.js +2 -1
- package/dist/sdk/environment/source-context.js +1 -1
- package/dist/sdk/environment/tracker-preflight.js +1 -1
- package/dist/sdk/error-code-catalog.js +1 -1
- package/dist/sdk/error-runtime.js +1 -1
- package/dist/sdk/errors.js +1 -1
- package/dist/sdk/eval.js +1 -1
- package/dist/sdk/extension/author-manifest.js +1 -1
- package/dist/sdk/extension/bundled-catalog.js +1 -1
- package/dist/sdk/extension/concurrency.js +1 -1
- package/dist/sdk/extension/copy-scope.js +1 -1
- package/dist/sdk/extension/custom-field-collisions.js +1 -1
- package/dist/sdk/extension/describe.js +4 -2
- package/dist/sdk/extension/doctor.js +1 -1
- package/dist/sdk/extension/install-plan.js +1 -1
- package/dist/sdk/extension/install-receipts.js +1 -1
- package/dist/sdk/extension/install-runtime.js +3 -3
- package/dist/sdk/extension/install-snapshot.js +1 -1
- package/dist/sdk/extension/install-sources.js +5 -5
- package/dist/sdk/extension/managed-state.d.ts +2 -0
- package/dist/sdk/extension/managed-state.js +2 -2
- package/dist/sdk/extension/managed-update-status.d.ts +3 -0
- package/dist/sdk/extension/managed-update-status.js +2 -0
- package/dist/sdk/extension/migrations.js +2 -2
- package/dist/sdk/extension/output-ownership.js +1 -1
- package/dist/sdk/extension/runtime-summary.js +1 -1
- package/dist/sdk/extension/scaffold.js +11 -4
- package/dist/sdk/extension/shared.js +1 -1
- package/dist/sdk/extension/source-resolution.d.ts +2 -6
- package/dist/sdk/extension/source-resolution.js +1 -1
- package/dist/sdk/extension/static-inventory.js +1 -1
- package/dist/sdk/extension/update-check.d.ts +10 -0
- package/dist/sdk/extension/update-check.js +1 -1
- package/dist/sdk/extension-command-context.js +2 -1
- package/dist/sdk/extension-contracts.js +1 -1
- package/dist/sdk/extension.d.ts +4 -0
- package/dist/sdk/extension.js +1 -1
- package/dist/sdk/files.js +1 -1
- package/dist/sdk/flag-invocation-contracts.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
- package/dist/sdk/generated-error-code-catalog.js +1 -1
- package/dist/sdk/governance/assurance-action-contracts.js +1 -1
- package/dist/sdk/governance/assurance-action.js +1 -1
- package/dist/sdk/governance/assurance-limits.js +1 -1
- package/dist/sdk/governance/assurance-mutation-error.js +1 -1
- package/dist/sdk/governance/assurance-presets.js +1 -1
- package/dist/sdk/governance/assurance-runtime.js +1 -1
- package/dist/sdk/governance/assurance.js +4 -4
- package/dist/sdk/governance/boundary-fixtures.js +1 -1
- package/dist/sdk/governance/closure-timestamps.js +1 -1
- package/dist/sdk/governance/coverage-assurance.js +1 -1
- package/dist/sdk/governance/defect-recurrence-coverage.js +1 -1
- package/dist/sdk/governance/defect-recurrence-graph.js +1 -1
- package/dist/sdk/governance/defect-recurrence-signals.js +1 -1
- package/dist/sdk/governance/defect-recurrence.js +1 -1
- package/dist/sdk/governance/extension-host-version.js +1 -1
- package/dist/sdk/governance/gc.js +1 -1
- package/dist/sdk/governance/health-merge-evidence.js +1 -1
- package/dist/sdk/governance/health.js +2 -1
- package/dist/sdk/governance/hierarchy-validation.js +1 -1
- package/dist/sdk/governance/linked-file-report.js +1 -1
- package/dist/sdk/governance/merge-receipt-history.js +1 -1
- package/dist/sdk/governance/provenance-health.js +4 -1
- package/dist/sdk/governance/reindex.js +5 -4
- package/dist/sdk/governance/stale-work.js +1 -1
- package/dist/sdk/governance/status-role-diagnostics.js +1 -1
- package/dist/sdk/governance/storage-integrity.js +1 -1
- package/dist/sdk/governance/tracked-runtime-cache.js +1 -1
- package/dist/sdk/governance/upgrade.js +2 -2
- package/dist/sdk/governance/validate-history-drift.js +1 -1
- package/dist/sdk/governance/validate-item-reader.js +1 -1
- package/dist/sdk/governance/validate-normalization.js +1 -1
- package/dist/sdk/governance/validate.js +1 -1
- package/dist/sdk/governance/workflow-completeness.js +1 -1
- package/dist/sdk/governance/workflow-policy.js +3 -3
- package/dist/sdk/governance/workspace-position.js +2 -1
- package/dist/sdk/governance.js +1 -1
- package/dist/sdk/graph/adapter.js +1 -1
- package/dist/sdk/graph/analytics.js +1 -1
- package/dist/sdk/graph/assembly.js +1 -1
- package/dist/sdk/graph/cache.js +1 -1
- package/dist/sdk/graph/centrality.js +1 -1
- package/dist/sdk/graph/conformance.js +1 -1
- package/dist/sdk/graph/deadline-scheduling.js +1 -1
- package/dist/sdk/graph/durable-cache.js +1 -1
- package/dist/sdk/graph/governance-contracts.js +1 -1
- package/dist/sdk/graph/governance.js +1 -1
- package/dist/sdk/graph/hierarchy-integrity.js +1 -1
- package/dist/sdk/graph/index.js +1 -1
- package/dist/sdk/graph/lifecycle-coverage.js +1 -1
- package/dist/sdk/graph/mutation-advisory.js +1 -1
- package/dist/sdk/graph/query-contracts.js +1 -1
- package/dist/sdk/graph/remediation.js +1 -1
- package/dist/sdk/graph/run.js +1 -1
- package/dist/sdk/graph/scheduling.js +1 -1
- package/dist/sdk/graph/traversal.js +1 -1
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -1
- package/dist/sdk/graph.js +1 -1
- package/dist/sdk/guide-topics.js +1 -1
- package/dist/sdk/guide.js +8 -1
- package/dist/sdk/history/attestation-command.js +1 -1
- package/dist/sdk/history/attestation-contract.js +1 -1
- package/dist/sdk/history/attestation-scan.js +1 -1
- package/dist/sdk/history/attestation.js +1 -1
- package/dist/sdk/history/maintenance.js +1 -1
- package/dist/sdk/history/salvage.js +3 -2
- package/dist/sdk/history/subject.js +1 -1
- package/dist/sdk/history-analytics.js +1 -1
- package/dist/sdk/history-compact.js +1 -1
- package/dist/sdk/history-mcp.js +1 -1
- package/dist/sdk/history-provenance.js +1 -1
- package/dist/sdk/history-read.js +1 -1
- package/dist/sdk/history-redact.js +1 -1
- package/dist/sdk/history-repair.js +1 -1
- package/dist/sdk/improvement-ledger-validation.js +1 -1
- package/dist/sdk/improvement-ledger.js +2 -2
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/init-agent-guidance.js +16 -2
- package/dist/sdk/init.js +16 -2
- package/dist/sdk/invocation-author.js +1 -1
- package/dist/sdk/item-children.js +1 -1
- package/dist/sdk/item-metadata-index.js +1 -1
- package/dist/sdk/item-schedule.js +1 -1
- package/dist/sdk/item-transaction.js +1 -1
- package/dist/sdk/learnings.js +1 -1
- package/dist/sdk/lifecycle/append.js +4 -2
- package/dist/sdk/lifecycle/claim.js +1 -1
- package/dist/sdk/lifecycle/close-many.js +1 -1
- package/dist/sdk/lifecycle/close.js +1 -1
- package/dist/sdk/lifecycle/copy.js +1 -1
- package/dist/sdk/lifecycle/create.js +1 -1
- package/dist/sdk/lifecycle/delete.js +1 -1
- package/dist/sdk/lifecycle/event-validation-messages.js +1 -1
- package/dist/sdk/lifecycle/focus.js +1 -1
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -1
- package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -1
- package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -1
- package/dist/sdk/lifecycle/mcp-actions.js +1 -1
- package/dist/sdk/lifecycle/metadata-normalizers.js +1 -1
- package/dist/sdk/lifecycle/mutation-command-options.js +1 -1
- package/dist/sdk/lifecycle/plan-mutation-receipt.js +1 -1
- package/dist/sdk/lifecycle/plan.js +1 -1
- package/dist/sdk/lifecycle/recurrence-parsers.js +1 -1
- package/dist/sdk/lifecycle/reopen.js +1 -1
- package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +2 -1
- package/dist/sdk/lifecycle/restore.js +1 -1
- package/dist/sdk/lifecycle/shared-unset-fields.js +1 -1
- package/dist/sdk/lifecycle/task-composition.js +1 -1
- package/dist/sdk/lifecycle/update-many.js +1 -1
- package/dist/sdk/lifecycle/update.js +2 -1
- package/dist/sdk/lifecycle-completion.js +1 -1
- package/dist/sdk/lifecycle-policy.js +1 -1
- package/dist/sdk/linked-artifacts.js +2 -1
- package/dist/sdk/mcp/apps.js +1 -1
- package/dist/sdk/mcp/authorization.js +1 -1
- package/dist/sdk/mcp/discovery.js +1 -1
- package/dist/sdk/mcp/interactions.js +1 -1
- package/dist/sdk/mcp/protocol.js +1 -1
- package/dist/sdk/mcp/skills.js +3 -1
- package/dist/sdk/mcp/subscriptions.js +1 -1
- package/dist/sdk/mcp/tasks.js +2 -2
- package/dist/sdk/mcp/transport.js +1 -1
- package/dist/sdk/merge/abandoned-receipts.js +1 -1
- package/dist/sdk/merge/driver.js +1 -1
- package/dist/sdk/merge/index.js +1 -1
- package/dist/sdk/merge/install.js +4 -2
- package/dist/sdk/merge/receipt-file-boundary.js +1 -1
- package/dist/sdk/merge/receipt-operation.js +1 -1
- package/dist/sdk/merge/receipt-schema.js +1 -1
- package/dist/sdk/merge/receipts.js +4 -4
- package/dist/sdk/merge/reconcile.js +1 -1
- package/dist/sdk/merge/three-way.js +3 -2
- package/dist/sdk/merge/worktree-config.js +1 -1
- package/dist/sdk/merge.js +1 -1
- package/dist/sdk/mutation-events.js +1 -1
- package/dist/sdk/mutation-guard.js +1 -1
- package/dist/sdk/notes.js +1 -1
- package/dist/sdk/output-contracts.js +1 -1
- package/dist/sdk/output-projection.js +1 -1
- package/dist/sdk/output-token-accounting.js +1 -1
- package/dist/sdk/output.js +2 -1
- package/dist/sdk/ownership-source.js +1 -1
- package/dist/sdk/package-import-adapters.js +1 -1
- package/dist/sdk/package-migrations.js +1 -1
- package/dist/sdk/package-runtime-options.js +1 -1
- package/dist/sdk/pagination.js +1 -1
- package/dist/sdk/profile.js +5 -1
- package/dist/sdk/provenance.js +1 -1
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/activity.js +1 -1
- package/dist/sdk/query/aggregate.js +1 -1
- package/dist/sdk/query/calendar.js +4 -1
- package/dist/sdk/query/complete-list.js +1 -1
- package/dist/sdk/query/context.js +2 -1
- package/dist/sdk/query/duplicate-candidates.js +1 -1
- package/dist/sdk/query/get.d.ts +14 -2
- package/dist/sdk/query/get.js +1 -1
- package/dist/sdk/query/history.js +1 -1
- package/dist/sdk/query/item-filter-options.js +1 -1
- package/dist/sdk/query/light-metadata.js +1 -1
- package/dist/sdk/query/list-filter-shared.js +1 -1
- package/dist/sdk/query/list.js +1 -1
- package/dist/sdk/query/multi-value-filters.js +1 -1
- package/dist/sdk/query/next-ready-budget.js +1 -1
- package/dist/sdk/query/next.js +2 -1
- package/dist/sdk/query/parsers.js +1 -1
- package/dist/sdk/query/projection-contracts.js +1 -1
- package/dist/sdk/query/search/corpus.js +2 -1
- package/dist/sdk/query/search/filters.js +1 -1
- package/dist/sdk/query/search/input.js +1 -1
- package/dist/sdk/query/search/lexical.js +1 -1
- package/dist/sdk/query/search/response.js +1 -1
- package/dist/sdk/query/search/semantic.js +3 -2
- package/dist/sdk/query/search/types.js +1 -1
- package/dist/sdk/query/search-contracts.js +1 -1
- package/dist/sdk/query/search-pagination.js +1 -1
- package/dist/sdk/query/search-rendering.js +1 -1
- package/dist/sdk/query/search.js +1 -1
- package/dist/sdk/query/workspace-contracts.js +1 -1
- package/dist/sdk/query.js +1 -1
- package/dist/sdk/read-output/continuation.js +1 -1
- package/dist/sdk/read-output/options.js +1 -1
- package/dist/sdk/read-output/provenance.js +1 -1
- package/dist/sdk/read-output-budget.js +1 -1
- package/dist/sdk/read-output-contracts.js +1 -1
- package/dist/sdk/read-output-rows.js +1 -1
- package/dist/sdk/read-output-session.js +1 -1
- package/dist/sdk/relationship-analytics.js +1 -1
- package/dist/sdk/relationship-context.js +1 -1
- package/dist/sdk/relationship-history.js +7 -4
- package/dist/sdk/relationship-kinds/contract.js +1 -1
- package/dist/sdk/relationship-migration.js +1 -1
- package/dist/sdk/relationships.js +1 -1
- package/dist/sdk/reproducibility/process.js +1 -1
- package/dist/sdk/runtime/actions.js +1 -1
- package/dist/sdk/runtime/context.js +1 -1
- package/dist/sdk/runtime/schema-preview.js +1 -1
- package/dist/sdk/runtime/schema.js +1 -1
- package/dist/sdk/runtime-action-aliases.js +1 -1
- package/dist/sdk/runtime-extended-actions.js +1 -1
- package/dist/sdk/runtime-input.js +1 -1
- package/dist/sdk/runtime-primitives.js +1 -1
- package/dist/sdk/runtime-public-contracts.js +1 -1
- package/dist/sdk/runtime-stats-options.js +1 -1
- package/dist/sdk/runtime.js +1 -1
- package/dist/sdk/scheduling-shortcuts.js +1 -1
- package/dist/sdk/schema-migration.js +4 -3
- package/dist/sdk/schema.js +7 -1
- package/dist/sdk/search-refresh-worker.js +1 -1
- package/dist/sdk/similarity-scoring.js +1 -1
- package/dist/sdk/similarity.js +1 -1
- package/dist/sdk/start-task-status.js +1 -1
- package/dist/sdk/stats.js +1 -1
- package/dist/sdk/structured-mutations.js +1 -1
- package/dist/sdk/telemetry-flush.js +1 -1
- package/dist/sdk/telemetry.js +4 -3
- package/dist/sdk/templates.js +26 -2
- package/dist/sdk/test/batch.js +2 -2
- package/dist/sdk/test/entry.js +1 -1
- package/dist/sdk/test/execution.d.ts +2 -1
- package/dist/sdk/test/execution.js +6 -5
- package/dist/sdk/test/json-path.js +1 -1
- package/dist/sdk/test/linked-command-detection.js +1 -1
- package/dist/sdk/test/measurements.js +1 -1
- package/dist/sdk/test/parsers.js +1 -1
- package/dist/sdk/test/runs.js +1 -1
- package/dist/sdk/test/trust.js +2 -2
- package/dist/sdk/test/workspace-snapshot.js +1 -1
- package/dist/sdk/testing.js +7 -4
- package/dist/sdk/traceability/runtime-files-lookup.js +1 -1
- package/dist/sdk/traceability/source-traceability.js +2 -1
- package/dist/sdk/tracker-root-discovery.js +1 -1
- package/dist/sdk/workspace-contracts-cache.js +1 -1
- package/dist/sdk/workspace-contracts.js +1 -1
- package/dist/sdk/workspace-memory.js +2 -2
- package/dist/sdk/workspace-recipe.js +1 -1
- package/dist/sdk/workspace-snapshot.js +5 -4
- package/dist/sdk/workspace-transaction-gc.js +1 -1
- package/dist/sdk/workspace-transaction.js +2 -2
- package/dist/sdk/workspace.js +3 -2
- package/dist/types/index.js +1 -1
- package/dist/types.js +1 -1
- package/docs/AGENT_EVIDENCE_CONSISTENCY.md +88 -0
- package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +36 -0
- package/docs/GET_READ_EVIDENCE.md +84 -0
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +23 -0
- package/docs/PR_REVIEW_LOOP.md +21 -4
- package/docs/README.md +3 -0
- package/docs/RELEASING.md +18 -0
- package/docs/SDK_CONFIGURATION_SAFETY.md +123 -0
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +3 -3
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +4 -3
- package/marketplace.json +2 -2
- package/package.json +3 -3
- 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/extensions/vcs/index.ts +4 -2
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/package.json +2 -2
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/package.json +2 -2
- package/plugins/pm-codex/plugin.json +1 -1
- package/scripts/finalize-build.mjs +3 -2
- package/dist/cli-bundle/chunks/chunk-7UVXKI7K.js +0 -2
- package/dist/cli-bundle/chunks/chunk-D7Z2ZMJL.js +0 -3
- package/dist/cli-bundle/chunks/chunk-DEZPZOQ7.js +0 -2
- package/dist/cli-bundle/chunks/chunk-J52QIRRZ.js +0 -80
- package/dist/cli-bundle/chunks/chunk-JDKD3WGG.js +0 -6
- package/dist/cli-bundle/chunks/chunk-JQ7DW663.js +0 -2
- package/dist/cli-bundle/chunks/chunk-QXIDOOWT.js +0 -20
- package/dist/cli-bundle/chunks/chunk-SGFQQXFD.js +0 -2
- package/dist/cli-bundle/chunks/chunk-V3U77H3V.js +0 -31
- package/dist/cli-bundle/chunks/chunk-XZDWAYJC.js +0 -3
- package/dist/cli-bundle/chunks/chunk-Y6VRBTP3.js +0 -238
- package/dist/cli-bundle/chunks/chunk-YAAFYFS4.js +0 -8
- package/dist/cli-bundle/chunks/register-mutation-53ZLT4RX.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-OBK2FXUU.js +0 -2
- package/dist/cli-bundle/chunks/register-setup-HM3OCBH2.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-2JFYR56O.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-32EVUSS4.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-5GUSO2P4.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-6XBRADQQ.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-7O4NUJVO.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-CURTIIQT.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-IJUWEEEB.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-JCVMOSWQ.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-JMJK2L4Z.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-KG3H4UZZ.js +0 -30
- package/dist/cli-bundle/focused-chunks/chunk-MHQ2XICU.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-RJV6QVJE.js +0 -75
- package/dist/cli-bundle/focused-chunks/chunk-ZE2JZ7R6.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-ZLEN4HZD.js +0 -165
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
`});
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="cca38e64-dd53-5086-8825-dc1c8f1cc587")}catch{}})();import{isUtf8}from"node:buffer";import{resolveHistoryHashAlgorithm}from"../../core/history/digest.js";import{readFile}from"node:fs/promises";import{isFileMissingError,readFileIfExists}from"../../core/fs/fs-utils.js";import{acquireLock}from"../../core/lock/lock.js";import{createHistoryEntry,sealHistoryRecord}from"../../core/history/history.js";import{checkHistoryRewriteOwnership,writeHistoryRawWithRollback}from"../../core/history/history-rewrite.js";import{replayHistoryToTarget}from"../../core/history/projection.js";import{replayToItemDocument,verifyHistoryChainWithVersion}from"../../core/history/replay.js";import{findFirstMergeConflictMarker}from"../../core/shared/conflict-markers.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{sha256Hex}from"../../core/shared/serialization.js";import{nowIso}from"../../core/shared/time.js";import{runActiveOnReadHooks,runActiveOnWriteHooks}from"../../core/extensions/index.js";import{locateItem,readLocatedItemSnapshot}from"../../core/store/item-store.js";function decodeSalvageLine(line){let parsed;try{parsed=JSON.parse(line)}catch{if(line.trimStart().startsWith("{")&&line.includes("}"))throw new PmCliError("History salvage cannot discard a potentially complete record with trailing corruption.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused"});return null}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new PmCliError("History salvage would conceal interior corruption or a malformed record.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused"});const entry=parsed;if(!Array.isArray(entry.patch)||![entry.ts,entry.author,entry.op,entry.before_hash,entry.after_hash].every(field=>typeof field=="string"))throw new PmCliError("History salvage requires complete history records before the invalid tail.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused"});return entry}function inspectHistoryTail(raw){if(findFirstMergeConflictMarker(raw))throw new PmCliError("Resolve history merge conflicts before salvage.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused"});const entries=[];let offset=0,invalidOffset,invalidLine=0;for(const[index,line]of raw.split(`
|
|
2
|
+
`).entries()){if(!line.trim()){offset+=line.length+1;continue}const parsed=decodeSalvageLine(line);if(parsed===null){invalidOffset===void 0&&(invalidOffset=offset,invalidLine=index+1),offset+=line.length+1;continue}if(invalidOffset!==void 0)throw new PmCliError("History salvage would discard a record or conceal interior corruption.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused",required:"Recover the damaged record from version control or a backup; no bytes were changed."});entries.push(parsed),offset+=line.length+1}const verification=verifyHistoryChainWithVersion(entries);if(!verification.ok||verification.item_hash_version===void 0)throw new PmCliError("History salvage requires a nonempty verified prefix.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused",verification_errors:verification.errors,required:"Recover an intact history prefix from version control or a backup."});return{entries,itemHashVersion:verification.item_hash_version,prefix:invalidOffset===void 0?raw:raw.slice(0,invalidOffset),receipt:invalidOffset===void 0?null:{first_invalid_line:invalidLine,discarded_bytes:Buffer.byteLength(raw.slice(invalidOffset)),discarded_sha256:sha256Hex(raw.slice(invalidOffset)),retained_entries:entries.length}}}async function readSalvageOwnership(subject,settings,fallback){if(!subject.located)return{itemRaw:null,document:fallback};const snapshot=await readLocatedItemSnapshot(subject.located,{schema:settings.schema});return{itemRaw:snapshot.raw,document:snapshot.document??fallback}}async function readSalvageStream(historyPath){let bytes;try{bytes=await readFile(historyPath)}catch(error){if(isFileMissingError(error))return null;throw error}if(!isUtf8(bytes))throw new PmCliError("History salvage requires UTF-8 input; recover binary corruption from a byte-preserving backup.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused"});return bytes.toString("utf8")}async function salvageHistoryTail(params){const{subject,settings,options,author}=params;if([options.normalizeProvenance,options.auditOperation,options.auditContext,options.auditContextById,options.forceAuditEntry,options.mergeReceiptProof,options.mergeReceiptProofById].some(Boolean))throw new PmCliError("Tail salvage cannot be combined with other repair modes.",EXIT_CODE.USAGE);const raw=await readSalvageStream(subject.historyPath);if(raw===null)throw new PmCliError(`No history stream exists for ${subject.id}.`,EXIT_CODE.NOT_FOUND);await runActiveOnReadHooks({path:subject.historyPath,scope:"project"});const selected=inspectHistoryTail(raw),replay=replayHistoryToTarget(selected.entries,selected.entries.length-1),document=replayToItemDocument(replay);if(typeof replay.metadata.id=="string"&&replay.metadata.id!==subject.id)throw new PmCliError("History belongs to another item; salvage refused.",EXIT_CODE.CONFLICT,{code:"history_salvage_refused"});const ownership=await readSalvageOwnership(subject,settings,document),warnings=checkHistoryRewriteOwnership({itemDocument:ownership.document,subjectId:subject.id,author,force:options.force,settings}),version=selected.itemHashVersion,dryRun=options.dryRun===!0,changed=selected.receipt!==null;if(changed&&!dryRun){const release=await acquireLock(params.pmRoot,subject.id,settings.locks.ttl_seconds,author,!!options.force,settings.governance.force_required_for_stale_lock,settings.locks.wait_ms);try{const currentRaw=await readSalvageStream(subject.historyPath),located=await locateItem(params.pmRoot,subject.id,settings.id_prefix,settings.item_format,params.typeRegistry.type_to_folder),currentItem=located?await readFileIfExists(located.itemPath):null;if(currentRaw!==raw||currentItem!==ownership.itemRaw)throw new PmCliError("History or item changed while waiting for salvage lock; retry.",EXIT_CODE.CONFLICT);const audit=sealHistoryRecord({...createHistoryEntry({hashAlgorithm:resolveHistoryHashAlgorithm(selected.entries.at(-1).hash_algorithm),nowIso:nowIso(),author,op:"history_salvage",before:document,after:document,message:options.message,context:{history_salvage:selected.receipt}}),before_hash:selected.entries.at(-1).after_hash,after_hash:selected.entries.at(-1).after_hash,item_hash_version:version});await writeHistoryRawWithRollback({historyPath:subject.historyPath,historyRawUnderLock:raw,nextHistoryRaw:`${selected.prefix}${JSON.stringify(audit)}
|
|
3
|
+
`}),warnings.push(...await runActiveOnWriteHooks({path:subject.historyPath,scope:"project",op:"history_salvage:history"}))}finally{await release()}}return{id:subject.id,dry_run:dryRun,changed,history:{path:subject.historyPath,entries_scanned:selected.entries.length,chain_drift_before:!1,entries_rehashed:0,entries_patch_repaired:0,converted_replace_to_add:0,skipped_ops:0,reconciled_with_item:!1,audit_entry_added:changed&&!dryRun,verify_ok:!0,verify_errors:[],item_hash_version_before:version,item_hash_version_after:version,version_disposition:"preserved"},item:{exists:subject.located!==null,path:subject.located?.itemPath??null,matched_chain_before:null},provenance_normalization:{requested:!1,changed:!1,events_changed:0,observations_removed:0,invalid_values:[]},...selected.receipt?{salvage:selected.receipt}:{},warnings,generated_at:nowIso()}}export{inspectHistoryTail,salvageHistoryTail};
|
|
3
4
|
//# sourceMappingURL=salvage.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="59842825-3a81-53f4-845d-db2257ec6286")}catch{}})();import{pathExists}from"../../core/fs/fs-utils.js";import{normalizeItemId,normalizeRawItemId}from"../../core/item/id.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{locateItem}from"../../core/store/item-store.js";import{getHistoryPath}from"../../core/store/paths.js";import{getActiveExtensionRegistrations}from"../../core/extensions/index.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{resolvePmRoot}from"../../core/store/paths.js";import{readSettings}from"../../core/store/settings.js";import{assertInitializedTracker}from"../environment/tracker-preflight.js";async function resolveHistoryWorkspace(pmPath){const pmRoot=resolvePmRoot(process.cwd(),pmPath);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());return{pmRoot,settings,typeRegistry}}async function resolveHistorySubject(pmRoot,id,settings,typeToFolder){getHistoryPath(pmRoot,normalizeRawItemId(id));const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeToFolder);if(located)return{id:located.id,historyPath:getHistoryPath(pmRoot,located.id),located};const normalizedId=normalizeItemId(id,settings.id_prefix),rawNormalizedId=normalizeRawItemId(id),candidateIds=normalizedId===rawNormalizedId?[normalizedId]:[normalizedId,rawNormalizedId];for(const candidateId of candidateIds){const historyPath=getHistoryPath(pmRoot,candidateId);if(await pathExists(historyPath))return{id:candidateId,historyPath,located:null}}throw new PmCliError(`Item ${id} not found`,EXIT_CODE.NOT_FOUND)}export{resolveHistorySubject,resolveHistoryWorkspace};
|
|
2
2
|
//# sourceMappingURL=subject.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6b51fdd9-9923-53c5-a798-41c15fd847a0")}catch{}})();import{AGENT_PROVENANCE_DIMENSIONS,BUILTIN_HARNESS_SIGNAL_DESCRIPTORS}from"../core/shared/author.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{listMutationEvents}from"./mutation-events.js";import{analyzeAgentProvenanceDescriptorCoverage,summarizeAgentProvenance}from"./provenance.js";const DEFAULT_HISTORY_ANALYTICS_LIMIT=1e4,MAX_HISTORY_ANALYTICS_LIMIT=1e5,HISTORY_EVENT_PAGE_LIMIT=1e3,DEFAULT_HISTORY_WINDOW_DAYS=30,ANNOTATION_OPERATION_PREFIXES=["append","comment","docs","file","learning","note","test_run"];function parseHistoryAnalyticsLimit(value){const limit=value??DEFAULT_HISTORY_ANALYTICS_LIMIT;if(!Number.isSafeInteger(limit)||limit<1||limit>MAX_HISTORY_ANALYTICS_LIMIT)throw new PmCliError(`History analytics event limit must be an integer from 1 to ${MAX_HISTORY_ANALYTICS_LIMIT}.`,EXIT_CODE.USAGE,{code:"invalid_history_analytics_limit"});return limit}function parseMinimumSample(value){const minimum=value??5;if(!Number.isSafeInteger(minimum)||minimum<1||minimum>1e4)throw new PmCliError("History analytics minimum sample must be an integer from 1 to 10000.",EXIT_CODE.USAGE,{code:"invalid_history_analytics_minimum_sample"});return minimum}function resolveHistoryAnalyticsSince(value){const raw=value?.trim();if(!raw)return new Date(Date.now()-DEFAULT_HISTORY_WINDOW_DAYS*864e5).toISOString();const relative=/^-(\d+)([dh])$/u.exec(raw);if(relative){const amount=Number(relative[1]),multiplier=relative[2]==="d"?864e5:36e5;if(!Number.isSafeInteger(amount)||amount<1)throw new PmCliError("History analytics --since duration must be positive.",EXIT_CODE.USAGE,{code:"invalid_history_analytics_since"});return new Date(Date.now()-amount*multiplier).toISOString()}const milliseconds=Date.parse(raw);if(!Number.isFinite(milliseconds))throw new PmCliError("History analytics --since must be an ISO timestamp or negative duration such as -30d.",EXIT_CODE.USAGE,{code:"invalid_history_analytics_since"});return new Date(milliseconds).toISOString()}async function readHistoryAnalyticsWindow(pmRoot,options){const eventLimit=parseHistoryAnalyticsLimit(options.eventLimit),since=resolveHistoryAnalyticsSince(options.since),events=[];let cursor=since,hasMore=!1;for(;events.length<eventLimit;){const page=await listMutationEvents({pmRoot,since:cursor,limit:Math.min(HISTORY_EVENT_PAGE_LIMIT,eventLimit-events.length),full:!0}),pageEvents=page.events.map(event=>({item_id:event.item_id,entry:event.entry}));if(events.push(...pageEvents),hasMore=page.has_more,cursor=page.next_cursor,!page.has_more)break}return{events,receipt:{since,events:events.length,truncated:hasMore,...hasMore?{next_cursor:cursor}:{},source:"history_event_index"}}}function provenanceValue(entry,dimension){return dimension==="harness"?entry.agent_harness:dimension==="author_source"?entry.author_source:entry.agent_model??entry.agent_provenance?.model?.value}function statusFromEntry(entry){for(let index=entry.patch.length-1;index>=0;index-=1){const operation=entry.patch[index];if(operation.path==="/metadata/status"&&"value"in operation&&typeof operation.value=="string")return operation.value}}function annotationOperation(op){return ANNOTATION_OPERATION_PREFIXES.some(prefix=>op.startsWith(prefix))}function bucketFor(buckets,value){const existing=buckets.get(value);if(existing)return existing;const created={events:0,stateEvents:0,annotationEvents:0,closes:0,reopens:0,defectEscapes:0};return buckets.set(value,created),created}function accumulateFleetEvents(dimension,events,terminalStatuses){const buckets=new Map,streamTerminal=new Map,lastCloseValue=new Map;for(const event of events){const value=provenanceValue(event.entry,dimension),status=statusFromEntry(event.entry),wasTerminal=streamTerminal.get(event.item_id)===!0,isTerminal=status===void 0?wasTerminal:terminalStatuses.has(status);if(status!==void 0&&streamTerminal.set(event.item_id,isTerminal),!value)continue;const bucket=bucketFor(buckets,value);bucket.events+=1,annotationOperation(event.entry.op)?bucket.annotationEvents+=1:bucket.stateEvents+=1,status!==void 0&&!wasTerminal&&isTerminal?(bucket.closes+=1,lastCloseValue.set(event.item_id,value)):status!==void 0&&wasTerminal&&!isTerminal&&(bucket.reopens+=1)}return{buckets,lastCloseValue}}function attributeDefectEscapes(buckets,lastCloseValue,items){for(const item of items){if(item.type!=="Issue")continue;const sources=new Set((item.dependencies??[]).filter(dependency=>dependency.kind==="discovered_from").map(dependency=>dependency.id));for(const source of sources){const value=lastCloseValue.get(source);value&&(bucketFor(buckets,value).defectEscapes+=1)}}}function fleetRow(value,bucket,minimumSample,windowDays){const sampleStatus=bucket.closes>=minimumSample?"available":"insufficient";return{value,events:bucket.events,state_events:bucket.stateEvents,annotation_events:bucket.annotationEvents,closes:bucket.closes,reopens:bucket.reopens,defect_escapes:bucket.defectEscapes,throughput_per_day:sampleStatus==="available"?bucket.closes/windowDays:null,rework_rate:sampleStatus==="available"?bucket.reopens/bucket.closes:null,defect_escape_rate:sampleStatus==="available"?bucket.defectEscapes/bucket.closes:null,sample_status:sampleStatus}}function buildFleetDimension(dimension,events,items,terminalStatuses,minimumSample,windowDays){const{buckets,lastCloseValue}=accumulateFleetEvents(dimension,events,terminalStatuses);return attributeDefectEscapes(buckets,lastCloseValue,items),{dimension,status:buckets.size===0?"unavailable":"available",rows:[...buckets].map(([value,bucket])=>fleetRow(value,bucket,minimumSample,windowDays)).sort((left,right)=>right.events-left.events||left.value.localeCompare(right.value))}}function resolveHistoryWindowDays(events,since){const firstTimestamp=events[0]?.entry.ts??since,lastTimestamp=events[events.length-1]?.entry.ts??firstTimestamp,firstMilliseconds=Date.parse(firstTimestamp),lastMilliseconds=Date.parse(lastTimestamp);return!Number.isFinite(firstMilliseconds)||!Number.isFinite(lastMilliseconds)?1:Math.max(1,(lastMilliseconds-firstMilliseconds)/864e5)}function evaluateProvenanceCoverage(entries,descriptors,minimumSample){const descriptorCoverage=analyzeAgentProvenanceDescriptorCoverage(descriptors),observations=summarizeAgentProvenance(entries,AGENT_PROVENANCE_DIMENSIONS,minimumSample),inert=observations.filter(row=>row.inert).map(row=>({harness:row.harness,dimension:row.dimension,explicit_samples:row.observed+row.unavailable})),undeclared=descriptorCoverage.filter(row=>!row.covered).map(row=>row.dimension);return{descriptors:descriptorCoverage,observations,inert,undeclared,warnings:[...inert.map(row=>`provenance_dimension_inert:${row.harness}:${row.dimension}:${String(row.explicit_samples)}`),...undeclared.map(dimension=>`provenance_dimension_undeclared:${dimension}`)]}}async function runProvenanceCoverageAnalytics(pmRoot,descriptors=BUILTIN_HARNESS_SIGNAL_DESCRIPTORS,options={}){return projectProvenanceCoverageAnalytics(await readHistoryAnalyticsWindow(pmRoot,options),descriptors,options)}function projectProvenanceCoverageAnalytics(window2,descriptors=BUILTIN_HARNESS_SIGNAL_DESCRIPTORS,options={}){const minimumSample=parseMinimumSample(options.minimumSample);return{...evaluateProvenanceCoverage(window2.events.map(event=>event.entry),descriptors,minimumSample),window:window2.receipt}}async function runFleetAttributionAnalytics(pmRoot,items,terminalStatuses,options={}){return projectFleetAttributionAnalytics(await readHistoryAnalyticsWindow(pmRoot,options),items,terminalStatuses,options)}function projectFleetAttributionAnalytics(window2,items,terminalStatuses,options={}){const minimumSample=parseMinimumSample(options.minimumSample),windowDays=resolveHistoryWindowDays(window2.events,window2.receipt.since);return{dimensions:["harness","model","author_source"].map(dimension=>buildFleetDimension(dimension,window2.events,items,terminalStatuses,minimumSample,windowDays)),minimum_sample:minimumSample,policy:"observational_only_not_for_authorization_or_routing",window:window2.receipt}}const _testOnlyHistoryAnalytics={annotationOperation,buildFleetDimension,parseHistoryAnalyticsLimit,parseMinimumSample,provenanceValue,resolveHistoryAnalyticsSince,resolveHistoryWindowDays,statusFromEntry};export{_testOnlyHistoryAnalytics,evaluateProvenanceCoverage,projectFleetAttributionAnalytics,projectProvenanceCoverageAnalytics,readHistoryAnalyticsWindow,runFleetAttributionAnalytics,runProvenanceCoverageAnalytics};
|
|
2
2
|
//# sourceMappingURL=history-analytics.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1dede7b7-eeea-520d-97ce-a71687d93bc2")}catch(e2){}})();import fs from"node:fs/promises";import{resolveHistoryHashAlgorithm}from"../core/history/digest.js";import path from"node:path";import{createHistoryEntry,hashHistoryStream,sealHistoryRecord,SUPPORTED_HISTORY_ITEM_HASH_VERSIONS}from"../core/history/history.js";import{selectHistoryCompactBulkTargets}from"../core/history/history-compact-bulk.js";import{cloneEmptyReplayDocument,replayHashVerificationCandidates,replayToItemDocument,toReplayDocument}from"../core/history/replay.js";import{applyHistoryPatch}from"../core/history/projection.js";import{historyVersionOffset}from"../core/history/version-address.js";import{lifecycleClassifierFromStatusRegistry}from"../core/governance/metadata-coverage.js";import{resolveRuntimeStatusRegistry}from"../core/schema/runtime-schema.js";import{listAllItemMetadataLight}from"../core/store/item-store.js";import{pathExists}from"../core/fs/fs-utils.js";import{normalizeBulkIdsValue,parseBulkIdsText}from"../core/io/bulk-ids-input.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{nowIso}from"../core/shared/time.js";import{runActiveOnReadHooks}from"../core/extensions/index.js";import{resolveHistoryWorkspace,resolveHistorySubject}from"./history/subject.js";import{runHistoryMaintenance}from"./history/maintenance.js";function parseBeforeBoundary(before,entries){if(before===void 0){return{kind:"default",raw:null,compactCount:entries.length,retainedCount:0}}const raw=before.trim();if(raw.length===0){throw new PmCliError("history-compact --before requires a non-empty value.",EXIT_CODE.USAGE)}if(/^\d+$/.test(raw)){const version=Number.parseInt(raw,10);const offset=historyVersionOffset(entries);if(!Number.isSafeInteger(version)||version<offset+1||version>offset+entries.length+1){throw new PmCliError(`history-compact --before version must be between ${offset+1} and ${offset+entries.length+1}.`,EXIT_CODE.USAGE)}const compactCount2=version-offset-1;return{kind:"version",raw,compactCount:compactCount2,retainedCount:entries.length-compactCount2}}const beforeTs=Date.parse(raw);if(!Number.isFinite(beforeTs)){throw new PmCliError(`Invalid history-compact --before value "${before}". Use a version number or ISO timestamp.`,EXIT_CODE.USAGE)}let compactCount=0;for(const[index,entry]of entries.entries()){const entryTs=Date.parse(entry.ts);if(!Number.isFinite(entryTs)){throw new PmCliError(`History for this item contains invalid timestamp at entry ${index+1}.`,EXIT_CODE.GENERIC_FAILURE)}if(entryTs>=beforeTs){break}compactCount+=1}return{kind:"timestamp",raw,compactCount,retainedCount:entries.length-compactCount}}function replayHistoryAndResolveCheckpoint(entries,compactCount){let replay=cloneEmptyReplayDocument();let checkpoint=cloneEmptyReplayDocument();for(let index=0;index<entries.length;index+=1){const entry=entries[index];replay=applyHistoryPatch(replay,entry.patch,index+1,entry.op);if(index+1===compactCount){checkpoint=structuredClone(replay)}}return{checkpoint,finalReplay:replay}}function describeHistoryCompactCurrentItem(loadedItem,historyEntries){if(!loadedItem){return{loadedItem:null,currentItemRawBeforeLock:null,matchedChainBefore:null}}const lastEntry=historyEntries[historyEntries.length-1];return{loadedItem,currentItemRawBeforeLock:loadedItem.raw,matchedChainBefore:SUPPORTED_HISTORY_ITEM_HASH_VERSIONS.some(version=>(lastEntry.item_hash_version===void 0||lastEntry.item_hash_version===version)&&replayHashVerificationCandidates(toReplayDocument(loadedItem.document),version,resolveHistoryHashAlgorithm(lastEntry.hash_algorithm)).includes(lastEntry.after_hash))}}function buildHistoryCompactMessage(options,boundary){if(typeof options.message==="string"&&options.message.trim().length>0){return options.message}if(boundary.raw===null){return`history-compact compacted full stream (${boundary.compactCount} entr${boundary.compactCount===1?"y":"ies"}).`}return`history-compact compacted ${boundary.compactCount} entr${boundary.compactCount===1?"y":"ies"} before ${boundary.raw}.`}function buildHistoryCompactBaselineMessage(boundary){if(boundary.raw===null){return`history-compact baseline snapshot after compacting ${boundary.compactCount} entr${boundary.compactCount===1?"y":"ies"}.`}return`history-compact baseline snapshot before ${boundary.raw}.`}function buildHistoryCompactEntries(params){if(!params.changed){return{rewrittenEntries:params.historyEntries,baselineEntryAdded:false,auditEntryAdded:false}}const{checkpoint,finalReplay}=replayHistoryAndResolveCheckpoint(params.historyEntries,params.boundary.compactCount);const retained=params.historyEntries.slice(params.boundary.compactCount);const offset=historyVersionOffset(params.historyEntries,true);const checkpointEntry=params.historyEntries[params.boundary.compactCount-1];const baselineEntry=createHistoryEntry({hashAlgorithm:resolveHistoryHashAlgorithm(checkpointEntry.hash_algorithm),nowIso:params.historyEntries[params.boundary.compactCount-1].ts,author:params.author,op:"history_compact_baseline",before:replayToItemDocument(cloneEmptyReplayDocument()),after:replayToItemDocument(checkpoint),message:buildHistoryCompactBaselineMessage(params.boundary),context:{history_compaction:{contract_version:1,version_offset:offset===null?null:offset+params.boundary.compactCount-1,checkpoint_timestamp_semantics:"last_compacted_entry",pruned_entry_count:params.boundary.compactCount,pruned_stream_digest:hashHistoryStream(params.historyEntries.slice(0,params.boundary.compactCount)),retained_proof:"stream_digest_and_checkpoint",limitation:"individual_pruned_entries_require_pre_compaction_stream"}}});const rewrittenEntries=[sealHistoryRecord({...baselineEntry,before_hash:replayHashVerificationCandidates(cloneEmptyReplayDocument(),checkpointEntry.item_hash_version??1,resolveHistoryHashAlgorithm(checkpointEntry.hash_algorithm))[0],after_hash:checkpointEntry.after_hash,item_hash_version:checkpointEntry.item_hash_version}),...retained];if(!params.dryRun){rewrittenEntries.push(createHistoryEntry({nowIso:nowIso(),author:params.author,op:"history_compact",before:replayToItemDocument(finalReplay),after:replayToItemDocument(finalReplay),message:buildHistoryCompactMessage(params.options,params.boundary)}))}return{rewrittenEntries,baselineEntryAdded:true,auditEntryAdded:!params.dryRun}}async function runHistoryCompact(id,options,global2){const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path);const subject=await resolveHistorySubject(pmRoot,id,settings,typeRegistry.type_to_folder);return runHistoryMaintenance({pmRoot,subject,settings,typeRegistry,operation:"history-compact",options,transform:snapshot=>buildHistoryCompactPlan(subject,options,snapshot)})}function buildHistoryCompactPlan(subject,options,snapshot){const historyPath=subject.historyPath;const historyEntries=snapshot.entries;const chainVerification=snapshot.verification;if(!chainVerification.ok){throw new PmCliError(`history-compact requires a valid history chain (${chainVerification.errors.join(", ")}). Run pm history-repair ${subject.id} first.`,EXIT_CODE.CONFLICT)}const boundary=parseBeforeBoundary(options.before,historyEntries);const changed=boundary.compactCount>0;const dryRun=Boolean(options.dryRun);const author=snapshot.author;const warnings=[];if(!changed){warnings.push("history_compact_noop_before_boundary")}const currentItem=describeHistoryCompactCurrentItem(snapshot.loadedItem,historyEntries);if(currentItem.matchedChainBefore===false){warnings.push("history_compact_item_chain_mismatch")}const{rewrittenEntries,baselineEntryAdded,auditEntryAdded}=buildHistoryCompactEntries({historyEntries,boundary,changed,dryRun,author,options});const offset=historyVersionOffset(historyEntries,true);const firstRetainedEntry=boundary.retainedCount>0&&offset!==null?offset+boundary.compactCount+1:null;return{changed,rewrittenEntries,report:({verification:rewrittenVerify,warnings:writeWarnings})=>({id:subject.id,dry_run:dryRun,changed,compact_boundary:{kind:boundary.kind,before:boundary.raw,entries_compacted:boundary.compactCount,entries_retained:boundary.retainedCount,first_retained_entry:firstRetainedEntry},history:{path:historyPath,entries_scanned:historyEntries.length,entries_after:rewrittenEntries.length,baseline_entry_added:baselineEntryAdded,audit_entry_added:auditEntryAdded,verify_ok:rewrittenVerify.ok,verify_errors:rewrittenVerify.errors},item:{exists:subject.located!==null,path:subject.located?.itemPath??null,matched_chain_before:currentItem.matchedChainBefore},warnings:[...new Set([...warnings,...writeWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()})}}const HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES=3;function normalizeHistoryCompactBulkOptions(options){for(const key of["allOver","minEntries"]){const value=options[key];if(value!==void 0&&(!Number.isSafeInteger(value)||value<0)){throw new PmCliError(`history-compact ${key} must be a non-negative safe integer.`,EXIT_CODE.USAGE)}}const normalizedIdsText=normalizeBulkIdsValue(options.ids);if(options.ids!==void 0&&normalizedIdsText===""){throw new PmCliError("history-compact ids requires at least one valid item ID.",EXIT_CODE.USAGE,{code:"bulk_ids_input_empty",required:"Provide one or more string or finite numeric IDs; non-finite and unsupported selector values are rejected."})}return{...options,ids:normalizedIdsText===void 0?void 0:parseBulkIdsText(normalizedIdsText)}}function assertHistoryCompactTarget(id,bulk){const hasIds=bulk.ids!==void 0&&bulk.ids.length>0;const hasScan=bulk.allOver!==void 0||bulk.scope!==void 0;const selectorCount=(id!==void 0?1:0)+(hasIds?1:0)+(hasScan?1:0);if(selectorCount===0){throw new PmCliError("history-compact: provide an item <id>, or a bulk selector (--ids, --all-over <N>, --closed, or --all-streams).",EXIT_CODE.USAGE)}if(id!==void 0&&(hasIds||hasScan)){throw new PmCliError("history-compact: <id> and bulk selectors (--ids/--all-over/--closed/--all-streams) are mutually exclusive; pass one item id, or use bulk mode without a positional id.",EXIT_CODE.USAGE)}if(hasIds&&hasScan){throw new PmCliError("history-compact: --ids is mutually exclusive with --all-over/--closed/--all-streams; pass an explicit id list or a scan selector, not both.",EXIT_CODE.USAGE)}}function countHistoryStreamEntries(raw){let count=0;for(const line of raw.split(/\r?\n/)){if(line.trim().length>0){count+=1}}return count}async function collectHistoryCompactBulkCandidates(params){const statusRegistry=resolveRuntimeStatusRegistry(params.settings.schema);const classifier=lifecycleClassifierFromStatusRegistry(statusRegistry);const items=await listAllItemMetadataLight(params.pmRoot,params.settings.item_format,params.typeToFolder,void 0,params.settings.schema);const bucketById=new Map(items.map(item=>[item.id,classifier.classify(item.status)]));const historyDir=path.join(params.pmRoot,"history");const candidates=[];const preselectionErrors=[];if(!await pathExists(historyDir)){return{candidates,preselectionErrors}}const historyFiles=(await fs.readdir(historyDir)).filter(entry=>entry.endsWith(".jsonl")).sort((left,right)=>left.localeCompare(right));for(const fileName of historyFiles){const historyPath=path.join(historyDir,fileName);const id=fileName.slice(0,-".jsonl".length);try{const raw=await fs.readFile(historyPath,"utf8");await runActiveOnReadHooks({path:historyPath,scope:"project"});candidates.push({id,entries:countHistoryStreamEntries(raw),bucket:bucketById.get(id)??null})}catch(error){preselectionErrors.push({id,outcome:"errored",entries_before:0,entries_after:null,skip_reason:null,changed:false,error:error instanceof Error?error.message:String(error)})}}return{candidates,preselectionErrors}}async function runHistoryCompactBulkRow(params){if(!params.row.selected){return{selected:false,compacted:false,errored:false,result:{id:params.row.id,outcome:"skipped",entries_before:params.row.entries,entries_after:null,skip_reason:params.row.skip_reason,changed:false,error:null}}}try{const result=await runHistoryCompact(params.row.id,{dryRun:params.dryRun,author:params.options.author,message:params.options.message,force:params.options.force},params.global);return{selected:true,compacted:true,errored:false,result:{id:params.row.id,outcome:"compacted",entries_before:params.row.entries,entries_after:result.history.entries_after,skip_reason:null,changed:result.changed,error:null}}}catch(error){return{selected:true,compacted:false,errored:true,result:{id:params.row.id,outcome:"errored",entries_before:params.row.entries,entries_after:null,skip_reason:null,changed:false,error:error instanceof Error?error.message:String(error)}}}}async function runHistoryCompactBulk(options,global2){const normalizedOptions=normalizeHistoryCompactBulkOptions(options);const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path);const{candidates,preselectionErrors}=await collectHistoryCompactBulkCandidates({pmRoot,settings,typeToFolder:typeRegistry.type_to_folder});const mode=normalizedOptions.ids!==void 0&&normalizedOptions.ids.length>0?"ids":"scan";const minEntries=options.minEntries??HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES;const policy=settings.history.compact_policy;const policyThresholdApplied=mode==="scan"&&options.allOver===void 0&&policy.enabled;const allOver=options.allOver??(policyThresholdApplied?policy.max_entries:void 0);const selection=selectHistoryCompactBulkTargets(candidates,{ids:normalizedOptions.ids,scope:options.scope,minEntries,allOver});const dryRun=Boolean(options.dryRun);const results=[...preselectionErrors];const totals={streams_considered:candidates.length+preselectionErrors.length,selected:0,items_compacted:0,items_skipped:0,items_errored:preselectionErrors.length};for(const row of selection){const outcome=await runHistoryCompactBulkRow({row,options:normalizedOptions,dryRun,global:global2});results.push(outcome.result);if(!outcome.selected){totals.items_skipped+=1;continue}totals.selected+=1;if(outcome.compacted){totals.items_compacted+=1}if(outcome.errored){totals.items_errored+=1}}return{bulk:true,dry_run:dryRun,mode,scope:options.scope??null,criteria:{min_entries:minEntries,all_over:allOver??null,policy_threshold_applied:policyThresholdApplied},totals,results,generated_at:nowIso()}}export{HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES,assertHistoryCompactTarget,runHistoryCompact,runHistoryCompactBulk};
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c6009e5f-840e-5e3a-b8b9-6e9d42d63410")}catch{}})();import fs from"node:fs/promises";import{resolveHistoryHashAlgorithm}from"../core/history/digest.js";import path from"node:path";import{createHistoryEntry,hashHistoryStream,sealHistoryRecord,SUPPORTED_HISTORY_ITEM_HASH_VERSIONS}from"../core/history/history.js";import{selectHistoryCompactBulkTargets}from"../core/history/history-compact-bulk.js";import{cloneEmptyReplayDocument,replayHashVerificationCandidates,replayToItemDocument,toReplayDocument}from"../core/history/replay.js";import{applyHistoryPatch}from"../core/history/projection.js";import{historyVersionOffset}from"../core/history/version-address.js";import{lifecycleClassifierFromStatusRegistry}from"../core/governance/metadata-coverage.js";import{resolveRuntimeStatusRegistry}from"../core/schema/runtime-schema.js";import{listAllItemMetadataLight}from"../core/store/item-store.js";import{pathExists}from"../core/fs/fs-utils.js";import{normalizeBulkIdsValue,parseBulkIdsText}from"../core/io/bulk-ids-input.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{nowIso}from"../core/shared/time.js";import{runActiveOnReadHooks}from"../core/extensions/index.js";import{resolveHistoryWorkspace,resolveHistorySubject}from"./history/subject.js";import{runHistoryMaintenance}from"./history/maintenance.js";function parseBeforeBoundary(before,entries){if(before===void 0)return{kind:"default",raw:null,compactCount:entries.length,retainedCount:0};const raw=before.trim();if(raw.length===0)throw new PmCliError("history-compact --before requires a non-empty value.",EXIT_CODE.USAGE);if(/^\d+$/.test(raw)){const version=Number.parseInt(raw,10),offset=historyVersionOffset(entries);if(!Number.isSafeInteger(version)||version<offset+1||version>offset+entries.length+1)throw new PmCliError(`history-compact --before version must be between ${offset+1} and ${offset+entries.length+1}.`,EXIT_CODE.USAGE);const compactCount2=version-offset-1;return{kind:"version",raw,compactCount:compactCount2,retainedCount:entries.length-compactCount2}}const beforeTs=Date.parse(raw);if(!Number.isFinite(beforeTs))throw new PmCliError(`Invalid history-compact --before value "${before}". Use a version number or ISO timestamp.`,EXIT_CODE.USAGE);let compactCount=0;for(const[index,entry]of entries.entries()){const entryTs=Date.parse(entry.ts);if(!Number.isFinite(entryTs))throw new PmCliError(`History for this item contains invalid timestamp at entry ${index+1}.`,EXIT_CODE.GENERIC_FAILURE);if(entryTs>=beforeTs)break;compactCount+=1}return{kind:"timestamp",raw,compactCount,retainedCount:entries.length-compactCount}}function replayHistoryAndResolveCheckpoint(entries,compactCount){let replay=cloneEmptyReplayDocument(),checkpoint=cloneEmptyReplayDocument();for(let index=0;index<entries.length;index+=1){const entry=entries[index];replay=applyHistoryPatch(replay,entry.patch,index+1,entry.op),index+1===compactCount&&(checkpoint=structuredClone(replay))}return{checkpoint,finalReplay:replay}}function describeHistoryCompactCurrentItem(loadedItem,historyEntries){if(!loadedItem)return{loadedItem:null,currentItemRawBeforeLock:null,matchedChainBefore:null};const lastEntry=historyEntries[historyEntries.length-1];return{loadedItem,currentItemRawBeforeLock:loadedItem.raw,matchedChainBefore:SUPPORTED_HISTORY_ITEM_HASH_VERSIONS.some(version=>(lastEntry.item_hash_version===void 0||lastEntry.item_hash_version===version)&&replayHashVerificationCandidates(toReplayDocument(loadedItem.document),version,resolveHistoryHashAlgorithm(lastEntry.hash_algorithm)).includes(lastEntry.after_hash))}}function buildHistoryCompactMessage(options,boundary){return typeof options.message=="string"&&options.message.trim().length>0?options.message:boundary.raw===null?`history-compact compacted full stream (${boundary.compactCount} entr${boundary.compactCount===1?"y":"ies"}).`:`history-compact compacted ${boundary.compactCount} entr${boundary.compactCount===1?"y":"ies"} before ${boundary.raw}.`}function buildHistoryCompactBaselineMessage(boundary){return boundary.raw===null?`history-compact baseline snapshot after compacting ${boundary.compactCount} entr${boundary.compactCount===1?"y":"ies"}.`:`history-compact baseline snapshot before ${boundary.raw}.`}function buildHistoryCompactEntries(params){if(!params.changed)return{rewrittenEntries:params.historyEntries,baselineEntryAdded:!1,auditEntryAdded:!1};const{checkpoint,finalReplay}=replayHistoryAndResolveCheckpoint(params.historyEntries,params.boundary.compactCount),retained=params.historyEntries.slice(params.boundary.compactCount),offset=historyVersionOffset(params.historyEntries,!0),checkpointEntry=params.historyEntries[params.boundary.compactCount-1],baselineEntry=createHistoryEntry({hashAlgorithm:resolveHistoryHashAlgorithm(checkpointEntry.hash_algorithm),nowIso:params.historyEntries[params.boundary.compactCount-1].ts,author:params.author,op:"history_compact_baseline",before:replayToItemDocument(cloneEmptyReplayDocument()),after:replayToItemDocument(checkpoint),message:buildHistoryCompactBaselineMessage(params.boundary),context:{history_compaction:{contract_version:1,version_offset:offset===null?null:offset+params.boundary.compactCount-1,checkpoint_timestamp_semantics:"last_compacted_entry",pruned_entry_count:params.boundary.compactCount,pruned_stream_digest:hashHistoryStream(params.historyEntries.slice(0,params.boundary.compactCount)),retained_proof:"stream_digest_and_checkpoint",limitation:"individual_pruned_entries_require_pre_compaction_stream"}}}),rewrittenEntries=[sealHistoryRecord({...baselineEntry,before_hash:replayHashVerificationCandidates(cloneEmptyReplayDocument(),checkpointEntry.item_hash_version??1,resolveHistoryHashAlgorithm(checkpointEntry.hash_algorithm))[0],after_hash:checkpointEntry.after_hash,item_hash_version:checkpointEntry.item_hash_version}),...retained];return params.dryRun||rewrittenEntries.push(createHistoryEntry({nowIso:nowIso(),author:params.author,op:"history_compact",before:replayToItemDocument(finalReplay),after:replayToItemDocument(finalReplay),message:buildHistoryCompactMessage(params.options,params.boundary)})),{rewrittenEntries,baselineEntryAdded:!0,auditEntryAdded:!params.dryRun}}async function runHistoryCompact(id,options,global2){const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path),subject=await resolveHistorySubject(pmRoot,id,settings,typeRegistry.type_to_folder);return runHistoryMaintenance({pmRoot,subject,settings,typeRegistry,operation:"history-compact",options,transform:snapshot=>buildHistoryCompactPlan(subject,options,snapshot)})}function buildHistoryCompactPlan(subject,options,snapshot){const historyPath=subject.historyPath,historyEntries=snapshot.entries,chainVerification=snapshot.verification;if(!chainVerification.ok)throw new PmCliError(`history-compact requires a valid history chain (${chainVerification.errors.join(", ")}). Run pm history-repair ${subject.id} first.`,EXIT_CODE.CONFLICT);const boundary=parseBeforeBoundary(options.before,historyEntries),changed=boundary.compactCount>0,dryRun=!!options.dryRun,author=snapshot.author,warnings=[];changed||warnings.push("history_compact_noop_before_boundary");const currentItem=describeHistoryCompactCurrentItem(snapshot.loadedItem,historyEntries);currentItem.matchedChainBefore===!1&&warnings.push("history_compact_item_chain_mismatch");const{rewrittenEntries,baselineEntryAdded,auditEntryAdded}=buildHistoryCompactEntries({historyEntries,boundary,changed,dryRun,author,options}),offset=historyVersionOffset(historyEntries,!0),firstRetainedEntry=boundary.retainedCount>0&&offset!==null?offset+boundary.compactCount+1:null;return{changed,rewrittenEntries,report:({verification:rewrittenVerify,warnings:writeWarnings})=>({id:subject.id,dry_run:dryRun,changed,compact_boundary:{kind:boundary.kind,before:boundary.raw,entries_compacted:boundary.compactCount,entries_retained:boundary.retainedCount,first_retained_entry:firstRetainedEntry},history:{path:historyPath,entries_scanned:historyEntries.length,entries_after:rewrittenEntries.length,baseline_entry_added:baselineEntryAdded,audit_entry_added:auditEntryAdded,verify_ok:rewrittenVerify.ok,verify_errors:rewrittenVerify.errors},item:{exists:subject.located!==null,path:subject.located?.itemPath??null,matched_chain_before:currentItem.matchedChainBefore},warnings:[...new Set([...warnings,...writeWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()})}}const HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES=3;function normalizeHistoryCompactBulkOptions(options){for(const key of["allOver","minEntries"]){const value=options[key];if(value!==void 0&&(!Number.isSafeInteger(value)||value<0))throw new PmCliError(`history-compact ${key} must be a non-negative safe integer.`,EXIT_CODE.USAGE)}const normalizedIdsText=normalizeBulkIdsValue(options.ids);if(options.ids!==void 0&&normalizedIdsText==="")throw new PmCliError("history-compact ids requires at least one valid item ID.",EXIT_CODE.USAGE,{code:"bulk_ids_input_empty",required:"Provide one or more string or finite numeric IDs; non-finite and unsupported selector values are rejected."});return{...options,ids:normalizedIdsText===void 0?void 0:parseBulkIdsText(normalizedIdsText)}}function assertHistoryCompactTarget(id,bulk){const hasIds=bulk.ids!==void 0&&bulk.ids.length>0,hasScan=bulk.allOver!==void 0||bulk.scope!==void 0;if((id!==void 0?1:0)+(hasIds?1:0)+(hasScan?1:0)==0)throw new PmCliError("history-compact: provide an item <id>, or a bulk selector (--ids, --all-over <N>, --closed, or --all-streams).",EXIT_CODE.USAGE);if(id!==void 0&&(hasIds||hasScan))throw new PmCliError("history-compact: <id> and bulk selectors (--ids/--all-over/--closed/--all-streams) are mutually exclusive; pass one item id, or use bulk mode without a positional id.",EXIT_CODE.USAGE);if(hasIds&&hasScan)throw new PmCliError("history-compact: --ids is mutually exclusive with --all-over/--closed/--all-streams; pass an explicit id list or a scan selector, not both.",EXIT_CODE.USAGE)}function countHistoryStreamEntries(raw){let count=0;for(const line of raw.split(/\r?\n/))line.trim().length>0&&(count+=1);return count}async function collectHistoryCompactBulkCandidates(params){const statusRegistry=resolveRuntimeStatusRegistry(params.settings.schema),classifier=lifecycleClassifierFromStatusRegistry(statusRegistry),items=await listAllItemMetadataLight(params.pmRoot,params.settings.item_format,params.typeToFolder,void 0,params.settings.schema),bucketById=new Map(items.map(item=>[item.id,classifier.classify(item.status)])),historyDir=path.join(params.pmRoot,"history"),candidates=[],preselectionErrors=[];if(!await pathExists(historyDir))return{candidates,preselectionErrors};const historyFiles=(await fs.readdir(historyDir)).filter(entry=>entry.endsWith(".jsonl")).sort((left,right)=>left.localeCompare(right));for(const fileName of historyFiles){const historyPath=path.join(historyDir,fileName),id=fileName.slice(0,-6);try{const raw=await fs.readFile(historyPath,"utf8");await runActiveOnReadHooks({path:historyPath,scope:"project"}),candidates.push({id,entries:countHistoryStreamEntries(raw),bucket:bucketById.get(id)??null})}catch(error){preselectionErrors.push({id,outcome:"errored",entries_before:0,entries_after:null,skip_reason:null,changed:!1,error:error instanceof Error?error.message:String(error)})}}return{candidates,preselectionErrors}}async function runHistoryCompactBulkRow(params){if(!params.row.selected)return{selected:!1,compacted:!1,errored:!1,result:{id:params.row.id,outcome:"skipped",entries_before:params.row.entries,entries_after:null,skip_reason:params.row.skip_reason,changed:!1,error:null}};try{const result=await runHistoryCompact(params.row.id,{dryRun:params.dryRun,author:params.options.author,message:params.options.message,force:params.options.force},params.global);return{selected:!0,compacted:!0,errored:!1,result:{id:params.row.id,outcome:"compacted",entries_before:params.row.entries,entries_after:result.history.entries_after,skip_reason:null,changed:result.changed,error:null}}}catch(error){return{selected:!0,compacted:!1,errored:!0,result:{id:params.row.id,outcome:"errored",entries_before:params.row.entries,entries_after:null,skip_reason:null,changed:!1,error:error instanceof Error?error.message:String(error)}}}}async function runHistoryCompactBulk(options,global2){const normalizedOptions=normalizeHistoryCompactBulkOptions(options),{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path),{candidates,preselectionErrors}=await collectHistoryCompactBulkCandidates({pmRoot,settings,typeToFolder:typeRegistry.type_to_folder}),mode=normalizedOptions.ids!==void 0&&normalizedOptions.ids.length>0?"ids":"scan",minEntries=options.minEntries??HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES,policy=settings.history.compact_policy,policyThresholdApplied=mode==="scan"&&options.allOver===void 0&&policy.enabled,allOver=options.allOver??(policyThresholdApplied?policy.max_entries:void 0),selection=selectHistoryCompactBulkTargets(candidates,{ids:normalizedOptions.ids,scope:options.scope,minEntries,allOver}),dryRun=!!options.dryRun,results=[...preselectionErrors],totals={streams_considered:candidates.length+preselectionErrors.length,selected:0,items_compacted:0,items_skipped:0,items_errored:preselectionErrors.length};for(const row of selection){const outcome=await runHistoryCompactBulkRow({row,options:normalizedOptions,dryRun,global:global2});if(results.push(outcome.result),!outcome.selected){totals.items_skipped+=1;continue}totals.selected+=1,outcome.compacted&&(totals.items_compacted+=1),outcome.errored&&(totals.items_errored+=1)}return{bulk:!0,dry_run:dryRun,mode,scope:options.scope??null,criteria:{min_entries:minEntries,all_over:allOver??null,policy_threshold_applied:policyThresholdApplied},totals,results,generated_at:nowIso()}}export{HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES,assertHistoryCompactTarget,runHistoryCompact,runHistoryCompactBulk};
|
|
2
2
|
//# sourceMappingURL=history-compact.js.map
|
package/dist/sdk/history-mcp.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="feb8c44f-a6bd-5a7e-9600-eb5c45c0a5b4")}catch{}})();import{normalizeBulkIdsValue,parseBulkIdsText}from"../core/io/bulk-ids-input.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{assertHistoryCompactTarget,runHistoryCompact,runHistoryCompactBulk}from"./history-compact.js";import{assertHistoryRepairTarget,runHistoryRepair,runHistoryRepairAll}from"./history-repair.js";import{parseRuntimeInteger,readRuntimeString}from"./runtime-input.js";function runMcpHistoryRepairAction(context){const repairAll=context.options.all===!0,repairId=context.id??readRuntimeString(context.options,"id");return assertHistoryRepairTarget(repairId,repairAll),repairAll?runHistoryRepairAll(context.options,context.global):runHistoryRepair(repairId,context.options,context.global)}function runMcpHistoryCompactAction(context){const idsSource=context.options.ids,normalizedIds=normalizeBulkIdsValue(idsSource);if(idsSource!==void 0&&normalizedIds==="")throw new PmCliError("history-compact ids requires at least one valid item ID.",EXIT_CODE.USAGE,{code:"bulk_ids_input_empty",required:"Provide one or more string or finite numeric IDs; non-finite and unsupported selector values are rejected."});const ids=normalizedIds===void 0?void 0:parseBulkIdsText(normalizedIds),allOver=parseRuntimeInteger(context.options.allOver??context.options.all_over,"history-compact allOver"),minEntries=parseRuntimeInteger(context.options.minEntries??context.options.min_entries,"history-compact minEntries"),explicitScope=readRuntimeString(context.options,"scope"),requestedScopes=[];context.options.closed===!0&&requestedScopes.push("closed"),(context.options.allStreams===!0||context.options.all_streams===!0)&&requestedScopes.push("all-streams"),(explicitScope==="closed"||explicitScope==="all-streams")&&requestedScopes.push(explicitScope);const distinctScopes=[...new Set(requestedScopes)];if(distinctScopes.length>1)throw new PmCliError("history-compact: closed and all-streams scopes are mutually exclusive.",EXIT_CODE.USAGE);const scope=distinctScopes[0];return assertHistoryCompactTarget(context.id,{ids,allOver,scope}),context.id!==void 0?runHistoryCompact(context.id,{before:readRuntimeString(context.options,"before"),dryRun:context.options.dryRun===!0||context.options.dry_run===!0,author:readRuntimeString(context.options,"author"),message:readRuntimeString(context.options,"message"),force:context.force},context.global):runHistoryCompactBulk({ids,scope,allOver,minEntries,dryRun:context.options.dryRun===!0||context.options.dry_run===!0,author:readRuntimeString(context.options,"author"),message:readRuntimeString(context.options,"message"),force:context.force},context.global)}export{runMcpHistoryCompactAction,runMcpHistoryRepairAction};
|
|
2
2
|
//# sourceMappingURL=history-mcp.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2e0c4f91-ea56-5bec-b071-448eff719fec")}catch{}})();import{AGENT_PROVENANCE_DIMENSIONS}from"../core/shared/author.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";const DEFAULT_AUTHOR_IDENTITY_VOCABULARY={version:1,aliases:{}};function resolveHistoryProvenanceDimensions(descriptors=[]){const dimensions=new Set(AGENT_PROVENANCE_DIMENSIONS),addDimension=dimension=>{/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(dimension)&&dimensions.add(dimension)};for(const descriptor of descriptors){for(const dimension of Object.keys(descriptor.provenance_environment_keys??{}))addDimension(dimension);for(const dimension of Object.keys(descriptor.provenance_resolvers??{}))addDimension(dimension);for(const dimension of descriptor.provenance_unavailable_dimensions??[])addDimension(dimension)}return[...dimensions].sort()}function normalizeSet(value){if(value===void 0)return;const normalized=(typeof value=="string"?[value]:value).flatMap(entry=>entry.split(",")).map(entry=>entry.trim()).filter(entry=>entry.length>0);return normalized.length===0?void 0:new Set(normalized)}function resolveCanonicalHarness(entry,vocabulary){if(entry.agent_harness?.trim())return{agent_harness:entry.agent_harness,harness_source:"recorded"};const interpreted=vocabulary.aliases[entry.author];return interpreted?{agent_harness:interpreted,harness_source:"vocabulary"}:{harness_source:"unresolved"}}function parseHistoryProvenanceFilters(filters,dimensions=AGENT_PROVENANCE_DIMENSIONS){const allowed=new Set(dimensions),predicates=new Map,values=filters.provenance===void 0?[]:typeof filters.provenance=="string"?[filters.provenance]:filters.provenance;for(const raw of values.flatMap(entry=>entry.split(","))){const separator=raw.indexOf("=");if(separator<0)throw new PmCliError(`Provenance predicate must use dimension=value; received "${raw.trim()}".`,EXIT_CODE.USAGE,{code:"invalid_provenance_predicate"});const dimension=raw.slice(0,separator).trim().toLowerCase(),value=raw.slice(separator+1).trim();if(!allowed.has(dimension))throw new PmCliError(`Unknown provenance dimension "${dimension||raw.trim()}". Declared dimensions: ${[...allowed].sort().join(", ")}.`,EXIT_CODE.USAGE,{code:"unknown_provenance_dimension"});if(value.length===0)throw new PmCliError(`Provenance predicate must use dimension=value; received "${raw.trim()}".`,EXIT_CODE.USAGE,{code:"invalid_provenance_predicate"});const accepted=predicates.get(dimension)??new Set;accepted.add(value),predicates.set(dimension,accepted)}return predicates}function projectHistoryProvenance(entry,vocabulary=DEFAULT_AUTHOR_IDENTITY_VOCABULARY,coordinates={}){const harness=resolveCanonicalHarness(entry,vocabulary);return{...coordinates.itemId===void 0?{}:{item_id:coordinates.itemId},...coordinates.version===void 0?{}:{version:coordinates.version},ts:entry.ts,op:entry.op,author:entry.author,...entry.author_source===void 0?{}:{author_source:entry.author_source},...harness,vocabulary_version:vocabulary.version,...entry.agent_instance===void 0?{}:{agent_instance:entry.agent_instance},agent_provenance:entry.agent_provenance??{},...entry.message===void 0?{}:{message:entry.message}}}function historyEntryMatchesProvenance(entry,filters,vocabulary=DEFAULT_AUTHOR_IDENTITY_VOCABULARY,dimensions=AGENT_PROVENANCE_DIMENSIONS){return compileHistoryProvenanceMatcher(filters,vocabulary,dimensions)(entry)}function compileHistoryProvenanceMatcher(filters,vocabulary=DEFAULT_AUTHOR_IDENTITY_VOCABULARY,dimensions=AGENT_PROVENANCE_DIMENSIONS){const harnesses=normalizeSet(filters.harness),instances=normalizeSet(filters.agentInstance),predicates=parseHistoryProvenanceFilters(filters,dimensions);return entry=>{const resolvedHarness=resolveCanonicalHarness(entry,vocabulary).agent_harness;if(harnesses&&(!resolvedHarness||!harnesses.has(resolvedHarness))||instances&&!instances.has(entry.agent_instance??""))return!1;for(const[dimension,accepted]of predicates){const observation=entry.agent_provenance?.[dimension];if(!observation||!accepted.has(observation.value))return!1}return!0}}function summarizeHistoryProvenance(entries,vocabulary=DEFAULT_AUTHOR_IDENTITY_VOCABULARY,dimensions=AGENT_PROVENANCE_DIMENSIONS){const allDimensions=new Set(dimensions),unresolvedAuthors=new Map;let resolvedHarnesses=0;for(const entry of entries){for(const dimension of Object.keys(entry.agent_provenance??{}))allDimensions.add(dimension);resolveCanonicalHarness(entry,vocabulary).agent_harness?resolvedHarnesses+=1:unresolvedAuthors.set(entry.author,(unresolvedAuthors.get(entry.author)??0)+1)}return{entries:entries.length,vocabulary_version:vocabulary.version,harness:{resolved:resolvedHarnesses,unresolved:entries.length-resolvedHarnesses,unresolved_authors:[...unresolvedAuthors].map(([author,count])=>({author,entries:count})).sort((left,right)=>right.entries-left.entries||left.author.localeCompare(right.author)).slice(0,20)},dimensions:[...allDimensions].sort().map(dimension=>{let observed=0,unavailable=0;for(const entry of entries){const observation=entry.agent_provenance?.[dimension];observation===null?unavailable+=1:observation!==void 0&&(observed+=1)}return{dimension,observed,unavailable,legacy_missing:entries.length-observed-unavailable}})}}export{DEFAULT_AUTHOR_IDENTITY_VOCABULARY,compileHistoryProvenanceMatcher,historyEntryMatchesProvenance,parseHistoryProvenanceFilters,projectHistoryProvenance,resolveHistoryProvenanceDimensions,summarizeHistoryProvenance};
|
|
2
2
|
//# sourceMappingURL=history-provenance.js.map
|
package/dist/sdk/history-read.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="eb2e6046-156c-56ee-a03a-ecaa1cccfb45")}catch{}})();import{resolveHistoryHashAlgorithm}from"../core/history/digest.js";import{assertInitializedTracker}from"./environment/tracker-preflight.js";import{getActiveExtensionRegistrations}from"../core/extensions/index.js";import{applyHistoryPatch,ensureMaterializedHistoryTarget,extractPatchFailureContext,replayHistoryToTarget,resolveHistoryTarget}from"../core/history/projection.js";import{readHistoryEntries}from"../core/history/read.js";import{historyVersionOffset}from"../core/history/version-address.js";import{hashDocument,hashDocumentVerificationCandidates,hashEmptyDocument}from"../core/history/history.js";import{replayToCanonicalItemDocument,verifyHistoryChainWithVersion}from"../core/history/replay.js";import{resolveItemTypeRegistry}from"../core/item/type-registry.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{resolvePmRoot}from"../core/store/paths.js";import{readSettings}from"../core/store/settings.js";import{resolveHistorySubject}from"./history/subject.js";import{findHistoryIdentityDiscontinuities}from"../core/history/identity.js";function verifyHistoryEntries(history,currentDocument){const verification=verifyHistoryChainWithVersion(history),latestAfterHash=history.length>0?history[history.length-1].after_hash:hashEmptyDocument(),currentItemHashCandidates=currentDocument===void 0||verification.item_hash_version===void 0?void 0:hashDocumentVerificationCandidates(currentDocument,verification.item_hash_version,resolveHistoryHashAlgorithm(history.at(-1)?.hash_algorithm)),currentItemHash=currentDocument===void 0?void 0:currentItemHashCandidates===void 0?hashDocument(currentDocument):currentItemHashCandidates[Math.max(0,currentItemHashCandidates.indexOf(latestAfterHash))],currentMatchesLatest=currentItemHash===void 0?void 0:currentItemHash===latestAfterHash,errors=[...verification.errors];return currentMatchesLatest===!1&&errors.push("verify_failed:current_item_hash_mismatch"),{ok:errors.length===0,entries:history.length,errors,latest_after_hash:history.length>0?history[history.length-1].after_hash:void 0,current_item_hash:currentItemHash,current_matches_latest:currentMatchesLatest}}async function getItemAt(id,target,options={}){const pmRoot=resolvePmRoot(options.cwd??process.cwd(),options.pmRoot);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()),subject=await resolveHistorySubject(pmRoot,id,settings,typeRegistry.type_to_folder),history=await readHistoryEntries(subject.historyPath,subject.id);if(history.length===0)throw new PmCliError(`No history exists for ${subject.id}; point-in-time reads are unavailable.`,EXIT_CODE.NOT_FOUND);const resolvedTarget=resolveHistoryTarget(target,history),replay=ensureMaterializedHistoryTarget(replayHistoryToTarget(history,resolvedTarget.historyIndex),resolvedTarget),document=replayToCanonicalItemDocument(replay,{schema:settings.schema});if(document.metadata.id!==subject.id)throw new PmCliError(`History target resolved to item ${document.metadata.id}, expected ${subject.id}.`,EXIT_CODE.GENERIC_FAILURE);const targetEntry=history[resolvedTarget.historyIndex],offset=historyVersionOffset(history,!0);return{document,reconstructed:!0,as_of_version:offset===null?null:offset+resolvedTarget.historyIndex+1,as_of_timestamp:targetEntry.ts,target:resolvedTarget,history_length:history.length}}export{applyHistoryPatch,ensureMaterializedHistoryTarget,extractPatchFailureContext,findHistoryIdentityDiscontinuities,getItemAt,readHistoryEntries,replayHistoryToTarget,resolveHistoryTarget,verifyHistoryEntries};
|
|
2
2
|
//# sourceMappingURL=history-read.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9d9d625b-152d-5417-8702-6e0e45839500")}catch(e2){}})();import{resolveHistoryWorkspace,resolveHistorySubject}from"./history/subject.js";import{resolveHistorySubject as resolveHistorySubject2}from"./history/subject.js";import fs from"node:fs/promises";import{resolveHistoryHashAlgorithm}from"../core/history/digest.js";import{writeFileAtomic}from"../core/fs/fs-utils.js";import{createHistoryEntry,resealHistoryRewrite,verifyHistoryRecordHash}from"../core/history/history.js";import{invalidateHistoryDriftCacheForPath}from"../core/history/drift-cache.js";import{runHistoryMaintenance}from"./history/maintenance.js";import{EMPTY_REPLAY_DOCUMENT,historyEntriesToRaw,replayHash,replayToItemDocument}from"../core/history/replay.js";import{applyHistoryPatch}from"../core/history/projection.js";import{canonicalDocument,serializeItemDocument}from"../core/item/item-format.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{nowIso}from"../core/shared/time.js";import{runActiveOnWriteHooks}from"../core/extensions/index.js";import{acquireItemMetadataDerivedIndexLock,refreshItemMetadataDerivedIndex}from"../core/store/item-metadata-cache.js";import{getItemPath}from"../core/store/paths.js";function normalizeStringArrayInput(value){if(Array.isArray(value)){return value}if(typeof value==="string"){return[value]}return[]}function normalizeRegexFlags(flags){const unique=[];for(const token of flags){if(!unique.includes(token)){unique.push(token)}}if(!unique.includes("g")){unique.push("g")}return unique.join("")}function parseRegexRule(spec){const trimmed=spec.trim();if(trimmed.length===0){throw new PmCliError("history-redact --regex requires a non-empty pattern.",EXIT_CODE.USAGE)}let source=trimmed;let flags="g";if(trimmed.startsWith("/")&&trimmed.length>1){const slashIndex=trimmed.lastIndexOf("/");if(slashIndex>0){source=trimmed.slice(1,slashIndex);flags=normalizeRegexFlags(trimmed.slice(slashIndex+1))}}if(source.length===0){throw new PmCliError("history-redact --regex cannot use an empty pattern.",EXIT_CODE.USAGE)}try{new RegExp(source,flags)}catch{throw new PmCliError("Invalid --regex value; provide a valid JavaScript regular expression.",EXIT_CODE.USAGE)}return{kind:"regex",source,flags}}function buildRedactionRules(literalInput,regexInput){const literalRules=[...new Set(normalizeStringArrayInput(literalInput).map(entry=>entry.trim()))].filter(entry=>entry.length>0).map(entry=>({kind:"literal",value:entry}));const regexRules=[...new Set(normalizeStringArrayInput(regexInput).map(entry=>entry.trim()))].filter(entry=>entry.length>0).map(parseRegexRule);const rules=[...literalRules,...regexRules];if(rules.length===0){throw new PmCliError("history-redact requires at least one matcher via --literal or --regex.",EXIT_CODE.USAGE,{code:"missing_required_argument",required:"Provide --literal <value> and/or --regex <pattern>.",examples:['pm history-redact pm-a1b2 --literal "[redacted_path_prefix]/private"','pm history-redact pm-a1b2 --regex "/192\\\\.168\\\\.[0-9.]+/g" --replacement "[scrubbed_ip]"']})}return rules}function applyLiteralRule(value,literal,replacement){if(literal.length===0){return{value,replacements:0}}let cursor=0;let replacements=0;while(cursor<=value.length){const index=value.indexOf(literal,cursor);if(index===-1){break}replacements+=1;cursor=index+Math.max(1,literal.length)}if(replacements===0){return{value,replacements:0}}return{value:value.split(literal).join(replacement),replacements}}function applyRegexRule(value,rule,replacement){const regex=new RegExp(rule.source,rule.flags);const matches=[...value.matchAll(regex)];if(matches.length===0){return{value,replacements:0}}return{value:value.replace(regex,replacement),replacements:matches.length}}function redactStringValue(value,rules,replacement){let next=value;let replacements=0;for(const rule of rules){const result=rule.kind==="literal"?applyLiteralRule(next,rule.value,replacement):applyRegexRule(next,rule,replacement);next=result.value;replacements+=result.replacements}return{value:next,replacements}}function redactUnknownValue(value,rules,replacement){if(typeof value==="string"){return redactStringValue(value,rules,replacement)}if(Array.isArray(value)){let replacements=0;const nextValues=value.map(entry=>{const redacted=redactUnknownValue(entry,rules,replacement);replacements+=redacted.replacements;return redacted.value});return{value:nextValues,replacements}}if(typeof value==="object"&&value!==null){let replacements=0;const nextRecord={};for(const[key,entry]of Object.entries(value)){const redacted=redactUnknownValue(entry,rules,replacement);replacements+=redacted.replacements;nextRecord[key]=redacted.value}return{value:nextRecord,replacements}}return{value,replacements:0}}function redactHistoryPatch(patch,rules,replacement){let replacements=0;const redactedPatch=patch.map(operation=>{if(!Object.prototype.hasOwnProperty.call(operation,"value")){return operation}const redactedValue=redactUnknownValue(operation.value,rules,replacement);replacements+=redactedValue.replacements;return redactedValue.replacements>0?{...operation,value:redactedValue.value}:operation});return{patch:redactedPatch,replacements}}function inspectHistoryIntegrity(entries){let replay=structuredClone(EMPTY_REPLAY_DOCUMENT);let hashMismatchesBefore=0;let hashMismatchesAfter=0;for(let index=0;index<entries.length;index+=1){const entry=entries[index];if(replayHash(replay,void 0,resolveHistoryHashAlgorithm(entry.hash_algorithm))!==entry.before_hash){hashMismatchesBefore+=1}replay=applyHistoryPatch(replay,entry.patch,index+1,entry.op);if(replayHash(replay,void 0,resolveHistoryHashAlgorithm(entry.hash_algorithm))!==entry.after_hash){hashMismatchesAfter+=1}}return{hashMismatchesBefore,hashMismatchesAfter,finalDocument:replay}}function redactHistoryEntry(entry,rules,replacement){let replacements=0;let changed=false;let reanchorEvidenceRedacted=false;let nextMessage=entry.message;if(typeof entry.message==="string"){const redactedMessage=redactStringValue(entry.message,rules,replacement);nextMessage=redactedMessage.value;replacements+=redactedMessage.replacements;if(redactedMessage.replacements>0){changed=true}}const redactedPatch=redactHistoryPatch(entry.patch,rules,replacement);replacements+=redactedPatch.replacements;changed||=redactedPatch.replacements>0;const nextReanchorEvidence=entry.reanchor_evidence?.map(evidence=>{const redactedEvidencePatch=evidence.patch?redactHistoryPatch(evidence.patch,rules,replacement):{patch:void 0,replacements:0};const redactedEvidenceRecord=evidence.record?redactUnknownValue(evidence.record,rules,replacement):{value:void 0,replacements:0};replacements+=redactedEvidencePatch.replacements;replacements+=redactedEvidenceRecord.replacements;const evidenceChanged=redactedEvidencePatch.replacements>0||redactedEvidenceRecord.replacements>0;changed||=evidenceChanged;if(!evidenceChanged)return evidence;reanchorEvidenceRedacted=true;const{patch:_sensitivePatch,record:_sensitiveRecord,record_hash:_priorRecordHash,record_hash_version:_priorRecordHashVersion,...digestOnlyEvidence}=evidence;return redactedEvidencePatch.replacements>0?digestOnlyEvidence:{...digestOnlyEvidence,patch:evidence.patch}});return{entry:{...entry,message:nextMessage,patch:redactedPatch.patch,...nextReanchorEvidence?{reanchor_evidence:nextReanchorEvidence}:{}},replacements,changed,reanchorEvidenceRedacted}}function rewriteHistoryEntries(entries,rules,replacement){let replay=structuredClone(EMPTY_REPLAY_DOCUMENT);let entriesChanged=0;let replacements=0;const rewrittenEntries=[];for(let index=0;index<entries.length;index+=1){const original=entries[index];const recordVerification=verifyHistoryRecordHash(original);if(!recordVerification.ok){throw new PmCliError(`history-redact refuses invalid immutable record ${index+1} (${recordVerification.error}).`,EXIT_CODE.GENERIC_FAILURE)}const redacted=redactHistoryEntry(original,rules,replacement);replacements+=redacted.replacements;if(redacted.changed){entriesChanged+=1}const beforeHash=replayHash(replay,void 0,resolveHistoryHashAlgorithm(original.hash_algorithm));replay=applyHistoryPatch(replay,redacted.entry.patch,index+1,redacted.entry.op);const afterHash=replayHash(replay,void 0,resolveHistoryHashAlgorithm(original.hash_algorithm));rewrittenEntries.push(resealHistoryRewrite(original,{...redacted.entry,before_hash:beforeHash,after_hash:afterHash},{retainPriorRecord:redacted.changed,retainPriorRecordHash:!redacted.changed}))}return{entries:rewrittenEntries,finalDocument:replay,entriesChanged,replacements}}function hasItemMetadata(replay){return Object.keys(replay.metadata).length>0}function resolveHistoryRedactNextItem(params){if(!hasItemMetadata(params.finalDocument)){return{raw:null,path:null,document:null}}const canonical=canonicalDocument(replayToItemDocument(params.finalDocument),{schema:params.settings.schema});if(canonical.metadata.id!==params.subject.id){throw new PmCliError("history-redact would change the item id; narrow your patterns.",EXIT_CODE.USAGE)}return{document:canonical,path:getItemPath(params.pmRoot,canonical.metadata.type,params.subject.id,"toon",params.typeToFolder),raw:serializeItemDocument(canonical,{format:"toon",schema:params.settings.schema})}}function buildHistoryRedactMessage(options,rewritten){if(typeof options.message==="string"&&options.message.trim().length>0){return options.message}return`history-redact replaced ${rewritten.replacements} match(es) across ${rewritten.entriesChanged} entr${rewritten.entriesChanged===1?"y":"ies"}.`}function buildHistoryRedactEntries(params){const rewrittenEntries=[...params.rewritten.entries];if(params.dryRun||!params.changed){return{rewrittenEntries,auditEntryAdded:false}}const finalDocument=params.nextItemDocument??replayToItemDocument(params.rewritten.finalDocument);rewrittenEntries.push(createHistoryEntry({nowIso:nowIso(),author:params.author,op:"history_redact",before:finalDocument,after:finalDocument,message:params.message}));return{rewrittenEntries,auditEntryAdded:true}}function createHistoryRedactTransaction(params){let derivedIndexWarnings=[];return{applyRewrite:async({historyRawUnderLock})=>{const releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(params.pmRoot,params.author);const affectedItemPaths=new Set;if(params.currentItem.path){affectedItemPaths.add(params.currentItem.path)}if(params.nextItem.path){affectedItemPaths.add(params.nextItem.path)}const itemSnapshots=new Map;if(params.currentItem.path&¶ms.currentItem.raw!==null){itemSnapshots.set(params.currentItem.path,params.currentItem.raw)}let rethrowReleaseFailure=()=>{};try{try{if(params.nextItem.path&¶ms.nextItem.raw!==null&¶ms.nextItem.raw!==params.currentItem.raw){await writeFileAtomic(params.nextItem.path,params.nextItem.raw)}if(params.currentItem.path&&(!params.nextItem.path||params.nextItem.path!==params.currentItem.path)){await fs.rm(params.currentItem.path,{force:true})}await writeFileAtomic(params.subject.historyPath,historyEntriesToRaw(params.rewrittenEntries))}catch(error){try{await rollbackHistoryRedactRewrite(params.subject.historyPath,historyRawUnderLock,affectedItemPaths,itemSnapshots)}finally{await invalidateHistoryDriftCacheForPath(params.subject.historyPath)}throw error}await invalidateHistoryDriftCacheForPath(params.subject.historyPath);const itemPath=params.nextItem.path??params.currentItem.path;if(itemPath){derivedIndexWarnings=await refreshItemMetadataDerivedIndex({pmRoot:params.pmRoot,preferredFormat:params.settings.item_format,typeToFolder:params.typeRegistry.type_to_folder,schema:params.settings.schema,itemPath,...params.currentItem.path?{previousItemPath:params.currentItem.path}:{},document:params.nextItem.document})}}finally{await releaseDerivedIndexLock().catch(error=>{rethrowReleaseFailure=()=>{throw error}})}rethrowReleaseFailure()},afterWrite:async()=>[...derivedIndexWarnings,...await runHistoryRedactWriteHooks(params.subject.historyPath,[params.nextItem.path,params.currentItem.path])]}}async function rollbackHistoryRedactRewrite(historyPath,historyRawUnderLock,affectedItemPaths,itemSnapshots){if(historyRawUnderLock===null){await fs.rm(historyPath,{force:true})}else{await writeFileAtomic(historyPath,historyRawUnderLock)}for(const itemPath of affectedItemPaths){const snapshot=itemSnapshots.get(itemPath);if(snapshot===void 0){await fs.rm(itemPath,{force:true})}else{await writeFileAtomic(itemPath,snapshot)}}}async function runHistoryRedactWriteHooks(historyPath,itemHookPaths){const hookWarnings=[];const uniqueItemHookPaths=new Set(itemHookPaths.filter(itemPath=>itemPath!==null));for(const itemHookPath of uniqueItemHookPaths){hookWarnings.push(...await runActiveOnWriteHooks({path:itemHookPath,scope:"project",op:"history_redact"}))}hookWarnings.push(...await runActiveOnWriteHooks({path:historyPath,scope:"project",op:"history_redact:history"}));return hookWarnings}async function runHistoryRedact(id,options,global2){const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path);const replacementInput=options.replacement??"";const replacementIsDefault=replacementInput.length===0;const replacement=replacementIsDefault?"[redacted]":replacementInput;const rules=buildRedactionRules(options.literal,options.regex);const subject=await resolveHistorySubject(pmRoot,id,settings,typeRegistry.type_to_folder);return runHistoryMaintenance({pmRoot,subject,settings,typeRegistry,operation:"history-redact",options,transform:snapshot=>buildHistoryRedactPlan({pmRoot,subject,settings,typeRegistry,options,rules,replacement,replacementIsDefault},snapshot)})}function buildHistoryRedactPlan(params,snapshot){const{pmRoot,subject,settings,typeRegistry,options,rules,replacement,replacementIsDefault}=params;const historyEntries=snapshot.entries;const integritySnapshot=inspectHistoryIntegrity(historyEntries);const rewritten=rewriteHistoryEntries(historyEntries,rules,replacement);const preexistingHashMismatches=integritySnapshot.hashMismatchesBefore+integritySnapshot.hashMismatchesAfter;const dryRun=Boolean(options.dryRun);const changed=rewritten.replacements>0;const warnings=[];if(preexistingHashMismatches>0){warnings.push(`history_redact_preexisting_hash_mismatches:${preexistingHashMismatches}`)}if(!changed){warnings.push("history_redact_no_matches")}const currentItem={raw:snapshot.loadedItem?.raw??null,path:subject.located?.itemPath??null,document:snapshot.loadedItem?.document??null};const nextItem=resolveHistoryRedactNextItem({pmRoot,subject,settings,typeToFolder:typeRegistry.type_to_folder,finalDocument:rewritten.finalDocument});const itemChanged=(currentItem.path??null)!==(nextItem.path??null)||(currentItem.raw??null)!==(nextItem.raw??null);const author=snapshot.author;const redactionMessage=buildHistoryRedactMessage(options,rewritten);const{rewrittenEntries,auditEntryAdded}=buildHistoryRedactEntries({rewritten,dryRun,changed,nextItemDocument:nextItem.document,author,message:redactionMessage});return{changed,rewrittenEntries,...createHistoryRedactTransaction({pmRoot,subject,settings,typeRegistry,currentItem,nextItem,author,rewrittenEntries}),report:({verification:historyVerify,warnings:writeWarnings})=>({id:subject.id,dry_run:dryRun,changed,patterns:{literal_count:rules.filter(rule=>rule.kind==="literal").length,regex_count:rules.filter(rule=>rule.kind==="regex").length,total_count:rules.length,replacement_is_default:replacementIsDefault},history:{path:subject.historyPath,entries_scanned:historyEntries.length,entries_changed:rewritten.entriesChanged,replacements:rewritten.replacements,hash_mismatches_before:integritySnapshot.hashMismatchesBefore,hash_mismatches_after:integritySnapshot.hashMismatchesAfter,preexisting_hash_mismatches:preexistingHashMismatches,audit_entry_added:auditEntryAdded,verify_ok:historyVerify.ok,verify_errors:historyVerify.errors},item:{existed_before:currentItem.path!==null,exists_after:nextItem.path!==null,path_before:currentItem.path,path_after:nextItem.path,changed:itemChanged},warnings:[...new Set([...warnings,...writeWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()})}}const _testOnly={applyLiteralRule,applyRegexRule,buildRedactionRules,hasItemMetadata,normalizeRegexFlags,normalizeStringArrayInput,parseRegexRule,redactStringValue,redactUnknownValue};export{_testOnly,resolveHistorySubject2 as resolveHistorySubject,runHistoryRedact};
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ebf3254f-1fed-5972-b91a-b8ff101675f4")}catch{}})();import{resolveHistoryWorkspace,resolveHistorySubject}from"./history/subject.js";import{resolveHistorySubject as resolveHistorySubject2}from"./history/subject.js";import fs from"node:fs/promises";import{resolveHistoryHashAlgorithm}from"../core/history/digest.js";import{writeFileAtomic}from"../core/fs/fs-utils.js";import{createHistoryEntry,resealHistoryRewrite,verifyHistoryRecordHash}from"../core/history/history.js";import{invalidateHistoryDriftCacheForPath}from"../core/history/drift-cache.js";import{runHistoryMaintenance}from"./history/maintenance.js";import{EMPTY_REPLAY_DOCUMENT,historyEntriesToRaw,replayHash,replayToItemDocument}from"../core/history/replay.js";import{applyHistoryPatch}from"../core/history/projection.js";import{canonicalDocument,serializeItemDocument}from"../core/item/item-format.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{nowIso}from"../core/shared/time.js";import{runActiveOnWriteHooks}from"../core/extensions/index.js";import{acquireItemMetadataDerivedIndexLock,refreshItemMetadataDerivedIndex}from"../core/store/item-metadata-cache.js";import{getItemPath}from"../core/store/paths.js";function normalizeStringArrayInput(value){return Array.isArray(value)?value:typeof value=="string"?[value]:[]}function normalizeRegexFlags(flags){const unique=[];for(const token of flags)unique.includes(token)||unique.push(token);return unique.includes("g")||unique.push("g"),unique.join("")}function parseRegexRule(spec){const trimmed=spec.trim();if(trimmed.length===0)throw new PmCliError("history-redact --regex requires a non-empty pattern.",EXIT_CODE.USAGE);let source=trimmed,flags="g";if(trimmed.startsWith("/")&&trimmed.length>1){const slashIndex=trimmed.lastIndexOf("/");slashIndex>0&&(source=trimmed.slice(1,slashIndex),flags=normalizeRegexFlags(trimmed.slice(slashIndex+1)))}if(source.length===0)throw new PmCliError("history-redact --regex cannot use an empty pattern.",EXIT_CODE.USAGE);try{new RegExp(source,flags)}catch{throw new PmCliError("Invalid --regex value; provide a valid JavaScript regular expression.",EXIT_CODE.USAGE)}return{kind:"regex",source,flags}}function buildRedactionRules(literalInput,regexInput){const literalRules=[...new Set(normalizeStringArrayInput(literalInput).map(entry=>entry.trim()))].filter(entry=>entry.length>0).map(entry=>({kind:"literal",value:entry})),regexRules=[...new Set(normalizeStringArrayInput(regexInput).map(entry=>entry.trim()))].filter(entry=>entry.length>0).map(parseRegexRule),rules=[...literalRules,...regexRules];if(rules.length===0)throw new PmCliError("history-redact requires at least one matcher via --literal or --regex.",EXIT_CODE.USAGE,{code:"missing_required_argument",required:"Provide --literal <value> and/or --regex <pattern>.",examples:['pm history-redact pm-a1b2 --literal "[redacted_path_prefix]/private"','pm history-redact pm-a1b2 --regex "/192\\\\.168\\\\.[0-9.]+/g" --replacement "[scrubbed_ip]"']});return rules}function applyLiteralRule(value,literal,replacement){if(literal.length===0)return{value,replacements:0};let cursor=0,replacements=0;for(;cursor<=value.length;){const index=value.indexOf(literal,cursor);if(index===-1)break;replacements+=1,cursor=index+Math.max(1,literal.length)}return replacements===0?{value,replacements:0}:{value:value.split(literal).join(replacement),replacements}}function applyRegexRule(value,rule,replacement){const regex=new RegExp(rule.source,rule.flags),matches=[...value.matchAll(regex)];return matches.length===0?{value,replacements:0}:{value:value.replace(regex,replacement),replacements:matches.length}}function redactStringValue(value,rules,replacement){let next=value,replacements=0;for(const rule of rules){const result=rule.kind==="literal"?applyLiteralRule(next,rule.value,replacement):applyRegexRule(next,rule,replacement);next=result.value,replacements+=result.replacements}return{value:next,replacements}}function redactUnknownValue(value,rules,replacement){if(typeof value=="string")return redactStringValue(value,rules,replacement);if(Array.isArray(value)){let replacements=0;return{value:value.map(entry=>{const redacted=redactUnknownValue(entry,rules,replacement);return replacements+=redacted.replacements,redacted.value}),replacements}}if(typeof value=="object"&&value!==null){let replacements=0;const nextRecord={};for(const[key,entry]of Object.entries(value)){const redacted=redactUnknownValue(entry,rules,replacement);replacements+=redacted.replacements,nextRecord[key]=redacted.value}return{value:nextRecord,replacements}}return{value,replacements:0}}function redactHistoryPatch(patch,rules,replacement){let replacements=0;return{patch:patch.map(operation=>{if(!Object.prototype.hasOwnProperty.call(operation,"value"))return operation;const redactedValue=redactUnknownValue(operation.value,rules,replacement);return replacements+=redactedValue.replacements,redactedValue.replacements>0?{...operation,value:redactedValue.value}:operation}),replacements}}function inspectHistoryIntegrity(entries){let replay=structuredClone(EMPTY_REPLAY_DOCUMENT),hashMismatchesBefore=0,hashMismatchesAfter=0;for(let index=0;index<entries.length;index+=1){const entry=entries[index];replayHash(replay,void 0,resolveHistoryHashAlgorithm(entry.hash_algorithm))!==entry.before_hash&&(hashMismatchesBefore+=1),replay=applyHistoryPatch(replay,entry.patch,index+1,entry.op),replayHash(replay,void 0,resolveHistoryHashAlgorithm(entry.hash_algorithm))!==entry.after_hash&&(hashMismatchesAfter+=1)}return{hashMismatchesBefore,hashMismatchesAfter,finalDocument:replay}}function redactHistoryEntry(entry,rules,replacement){let replacements=0,changed=!1,reanchorEvidenceRedacted=!1,nextMessage=entry.message;if(typeof entry.message=="string"){const redactedMessage=redactStringValue(entry.message,rules,replacement);nextMessage=redactedMessage.value,replacements+=redactedMessage.replacements,redactedMessage.replacements>0&&(changed=!0)}const redactedPatch=redactHistoryPatch(entry.patch,rules,replacement);replacements+=redactedPatch.replacements,changed||=redactedPatch.replacements>0;const nextReanchorEvidence=entry.reanchor_evidence?.map(evidence=>{const redactedEvidencePatch=evidence.patch?redactHistoryPatch(evidence.patch,rules,replacement):{patch:void 0,replacements:0},redactedEvidenceRecord=evidence.record?redactUnknownValue(evidence.record,rules,replacement):{value:void 0,replacements:0};replacements+=redactedEvidencePatch.replacements,replacements+=redactedEvidenceRecord.replacements;const evidenceChanged=redactedEvidencePatch.replacements>0||redactedEvidenceRecord.replacements>0;if(changed||=evidenceChanged,!evidenceChanged)return evidence;reanchorEvidenceRedacted=!0;const{patch:_sensitivePatch,record:_sensitiveRecord,record_hash:_priorRecordHash,record_hash_version:_priorRecordHashVersion,...digestOnlyEvidence}=evidence;return redactedEvidencePatch.replacements>0?digestOnlyEvidence:{...digestOnlyEvidence,patch:evidence.patch}});return{entry:{...entry,message:nextMessage,patch:redactedPatch.patch,...nextReanchorEvidence?{reanchor_evidence:nextReanchorEvidence}:{}},replacements,changed,reanchorEvidenceRedacted}}function rewriteHistoryEntries(entries,rules,replacement){let replay=structuredClone(EMPTY_REPLAY_DOCUMENT),entriesChanged=0,replacements=0;const rewrittenEntries=[];for(let index=0;index<entries.length;index+=1){const original=entries[index],recordVerification=verifyHistoryRecordHash(original);if(!recordVerification.ok)throw new PmCliError(`history-redact refuses invalid immutable record ${index+1} (${recordVerification.error}).`,EXIT_CODE.GENERIC_FAILURE);const redacted=redactHistoryEntry(original,rules,replacement);replacements+=redacted.replacements,redacted.changed&&(entriesChanged+=1);const beforeHash=replayHash(replay,void 0,resolveHistoryHashAlgorithm(original.hash_algorithm));replay=applyHistoryPatch(replay,redacted.entry.patch,index+1,redacted.entry.op);const afterHash=replayHash(replay,void 0,resolveHistoryHashAlgorithm(original.hash_algorithm));rewrittenEntries.push(resealHistoryRewrite(original,{...redacted.entry,before_hash:beforeHash,after_hash:afterHash},{retainPriorRecord:redacted.changed,retainPriorRecordHash:!redacted.changed}))}return{entries:rewrittenEntries,finalDocument:replay,entriesChanged,replacements}}function hasItemMetadata(replay){return Object.keys(replay.metadata).length>0}function resolveHistoryRedactNextItem(params){if(!hasItemMetadata(params.finalDocument))return{raw:null,path:null,document:null};const canonical=canonicalDocument(replayToItemDocument(params.finalDocument),{schema:params.settings.schema});if(canonical.metadata.id!==params.subject.id)throw new PmCliError("history-redact would change the item id; narrow your patterns.",EXIT_CODE.USAGE);return{document:canonical,path:getItemPath(params.pmRoot,canonical.metadata.type,params.subject.id,"toon",params.typeToFolder),raw:serializeItemDocument(canonical,{format:"toon",schema:params.settings.schema})}}function buildHistoryRedactMessage(options,rewritten){return typeof options.message=="string"&&options.message.trim().length>0?options.message:`history-redact replaced ${rewritten.replacements} match(es) across ${rewritten.entriesChanged} entr${rewritten.entriesChanged===1?"y":"ies"}.`}function buildHistoryRedactEntries(params){const rewrittenEntries=[...params.rewritten.entries];if(params.dryRun||!params.changed)return{rewrittenEntries,auditEntryAdded:!1};const finalDocument=params.nextItemDocument??replayToItemDocument(params.rewritten.finalDocument);return rewrittenEntries.push(createHistoryEntry({nowIso:nowIso(),author:params.author,op:"history_redact",before:finalDocument,after:finalDocument,message:params.message})),{rewrittenEntries,auditEntryAdded:!0}}function createHistoryRedactTransaction(params){let derivedIndexWarnings=[];return{applyRewrite:async({historyRawUnderLock})=>{const releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(params.pmRoot,params.author),affectedItemPaths=new Set;params.currentItem.path&&affectedItemPaths.add(params.currentItem.path),params.nextItem.path&&affectedItemPaths.add(params.nextItem.path);const itemSnapshots=new Map;params.currentItem.path&¶ms.currentItem.raw!==null&&itemSnapshots.set(params.currentItem.path,params.currentItem.raw);let rethrowReleaseFailure=()=>{};try{try{params.nextItem.path&¶ms.nextItem.raw!==null&¶ms.nextItem.raw!==params.currentItem.raw&&await writeFileAtomic(params.nextItem.path,params.nextItem.raw),params.currentItem.path&&(!params.nextItem.path||params.nextItem.path!==params.currentItem.path)&&await fs.rm(params.currentItem.path,{force:!0}),await writeFileAtomic(params.subject.historyPath,historyEntriesToRaw(params.rewrittenEntries))}catch(error){try{await rollbackHistoryRedactRewrite(params.subject.historyPath,historyRawUnderLock,affectedItemPaths,itemSnapshots)}finally{await invalidateHistoryDriftCacheForPath(params.subject.historyPath)}throw error}await invalidateHistoryDriftCacheForPath(params.subject.historyPath);const itemPath=params.nextItem.path??params.currentItem.path;itemPath&&(derivedIndexWarnings=await refreshItemMetadataDerivedIndex({pmRoot:params.pmRoot,preferredFormat:params.settings.item_format,typeToFolder:params.typeRegistry.type_to_folder,schema:params.settings.schema,itemPath,...params.currentItem.path?{previousItemPath:params.currentItem.path}:{},document:params.nextItem.document}))}finally{await releaseDerivedIndexLock().catch(error=>{rethrowReleaseFailure=()=>{throw error}})}rethrowReleaseFailure()},afterWrite:async()=>[...derivedIndexWarnings,...await runHistoryRedactWriteHooks(params.subject.historyPath,[params.nextItem.path,params.currentItem.path])]}}async function rollbackHistoryRedactRewrite(historyPath,historyRawUnderLock,affectedItemPaths,itemSnapshots){historyRawUnderLock===null?await fs.rm(historyPath,{force:!0}):await writeFileAtomic(historyPath,historyRawUnderLock);for(const itemPath of affectedItemPaths){const snapshot=itemSnapshots.get(itemPath);snapshot===void 0?await fs.rm(itemPath,{force:!0}):await writeFileAtomic(itemPath,snapshot)}}async function runHistoryRedactWriteHooks(historyPath,itemHookPaths){const hookWarnings=[],uniqueItemHookPaths=new Set(itemHookPaths.filter(itemPath=>itemPath!==null));for(const itemHookPath of uniqueItemHookPaths)hookWarnings.push(...await runActiveOnWriteHooks({path:itemHookPath,scope:"project",op:"history_redact"}));return hookWarnings.push(...await runActiveOnWriteHooks({path:historyPath,scope:"project",op:"history_redact:history"})),hookWarnings}async function runHistoryRedact(id,options,global2){const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path),replacementInput=options.replacement??"",replacementIsDefault=replacementInput.length===0,replacement=replacementIsDefault?"[redacted]":replacementInput,rules=buildRedactionRules(options.literal,options.regex),subject=await resolveHistorySubject(pmRoot,id,settings,typeRegistry.type_to_folder);return runHistoryMaintenance({pmRoot,subject,settings,typeRegistry,operation:"history-redact",options,transform:snapshot=>buildHistoryRedactPlan({pmRoot,subject,settings,typeRegistry,options,rules,replacement,replacementIsDefault},snapshot)})}function buildHistoryRedactPlan(params,snapshot){const{pmRoot,subject,settings,typeRegistry,options,rules,replacement,replacementIsDefault}=params,historyEntries=snapshot.entries,integritySnapshot=inspectHistoryIntegrity(historyEntries),rewritten=rewriteHistoryEntries(historyEntries,rules,replacement),preexistingHashMismatches=integritySnapshot.hashMismatchesBefore+integritySnapshot.hashMismatchesAfter,dryRun=!!options.dryRun,changed=rewritten.replacements>0,warnings=[];preexistingHashMismatches>0&&warnings.push(`history_redact_preexisting_hash_mismatches:${preexistingHashMismatches}`),changed||warnings.push("history_redact_no_matches");const currentItem={raw:snapshot.loadedItem?.raw??null,path:subject.located?.itemPath??null,document:snapshot.loadedItem?.document??null},nextItem=resolveHistoryRedactNextItem({pmRoot,subject,settings,typeToFolder:typeRegistry.type_to_folder,finalDocument:rewritten.finalDocument}),itemChanged=(currentItem.path??null)!==(nextItem.path??null)||(currentItem.raw??null)!==(nextItem.raw??null),author=snapshot.author,redactionMessage=buildHistoryRedactMessage(options,rewritten),{rewrittenEntries,auditEntryAdded}=buildHistoryRedactEntries({rewritten,dryRun,changed,nextItemDocument:nextItem.document,author,message:redactionMessage});return{changed,rewrittenEntries,...createHistoryRedactTransaction({pmRoot,subject,settings,typeRegistry,currentItem,nextItem,author,rewrittenEntries}),report:({verification:historyVerify,warnings:writeWarnings})=>({id:subject.id,dry_run:dryRun,changed,patterns:{literal_count:rules.filter(rule=>rule.kind==="literal").length,regex_count:rules.filter(rule=>rule.kind==="regex").length,total_count:rules.length,replacement_is_default:replacementIsDefault},history:{path:subject.historyPath,entries_scanned:historyEntries.length,entries_changed:rewritten.entriesChanged,replacements:rewritten.replacements,hash_mismatches_before:integritySnapshot.hashMismatchesBefore,hash_mismatches_after:integritySnapshot.hashMismatchesAfter,preexisting_hash_mismatches:preexistingHashMismatches,audit_entry_added:auditEntryAdded,verify_ok:historyVerify.ok,verify_errors:historyVerify.errors},item:{existed_before:currentItem.path!==null,exists_after:nextItem.path!==null,path_before:currentItem.path,path_after:nextItem.path,changed:itemChanged},warnings:[...new Set([...warnings,...writeWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()})}}const _testOnly={applyLiteralRule,applyRegexRule,buildRedactionRules,hasItemMetadata,normalizeRegexFlags,normalizeStringArrayInput,parseRegexRule,redactStringValue,redactUnknownValue};export{_testOnly,resolveHistorySubject2 as resolveHistorySubject,runHistoryRedact};
|
|
2
2
|
//# sourceMappingURL=history-redact.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="55e22181-7bbf-5fed-965c-219fe465ed72")}catch(e2){}})();import{salvageHistoryTail}from"./history/salvage.js";import{resolveHistoryHashAlgorithm}from"../core/history/digest.js";import{realpath}from"node:fs/promises";import path from"node:path";import jsonPatch from"fast-json-patch";import{patchPathToChangedField}from"../core/history/history-diff.js";import{normalizeReplayPatchOps,reanchorHistoryEntries,replayHashVerificationCandidates,resolveHistoryRepairItemHashVersion,toReplayDocument,verifyHistoryChainWithVersion}from"../core/history/replay.js";import{sealHistoryRecord}from"../core/history/history.js";import{classifyHistoryEvent}from"../core/history/event-classification.js";import{scanHistoryDrift}from"../core/history/drift-scan.js";import{invalidateHistoryDriftCache}from"../core/history/drift-cache.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{sha256Hex,stableStringify}from"../core/shared/serialization.js";import{resolveAuthor}from"../core/shared/author.js";import{nowIso}from"../core/shared/time.js";import{listAllItemMetadataWithBody}from"../core/store/item-store.js";import{resolveHistoryWorkspace,resolveHistorySubject}from"./history/subject.js";import{runHistoryMaintenance}from"./history/maintenance.js";import{isOriginalGitStateRestored}from"./merge/receipt-operation.js";import{inspectMergeReceiptEvidence,summarizeMergeReceipt}from"./merge/receipts.js";import{encodeItemScalarDecisionValue,hashItemScalarDecisionValue}from"./merge/three-way.js";import{listInvalidProvenanceHistoryStreamIds,normalizeInvalidHistoryProvenance}from"./governance/provenance-health.js";function replayFieldValue(document,field){return field==="body"?document.body:document.metadata[field]}function isReplayValuePreserved(replayed,reconciled){if(replayed===void 0||Object.is(replayed,reconciled)){return true}if(Array.isArray(replayed)){if(!Array.isArray(reconciled)){return false}const matched=new Set;return replayed.every(expected=>{const index=reconciled.findIndex((candidate,candidateIndex)=>!matched.has(candidateIndex)&&isReplayValuePreserved(expected,candidate));if(index<0){return false}matched.add(index);return true})}if(replayed===null||reconciled===null||typeof replayed!=="object"||typeof reconciled!=="object"||Array.isArray(reconciled)){return false}const reconciledRecord=reconciled;return Object.entries(replayed).every(([key,value])=>Object.hasOwn(reconciledRecord,key)&&isReplayValuePreserved(value,reconciledRecord[key]))}function collectReconciliationEvents(entries,fields){const remaining=new Set(fields);const events=[];for(let index=entries.length-1;index>=0&&remaining.size>0;index-=1){const entry=entries[index];const entryFields=new Set;for(const op of normalizeReplayPatchOps(entry.patch)){entryFields.add(patchPathToChangedField(op.path));if(op.from){entryFields.add(patchPathToChangedField(op.from))}}const overlap=[...remaining].filter(field=>entryFields.has(field));if(overlap.length===0){continue}for(const field of overlap){remaining.delete(field)}events.push({index:index+1,ts:entry.ts,author:entry.author,op:entry.op,fields:overlap.sort((left,right)=>left.localeCompare(right))})}return events.reverse()}function analyzeReconciliationDiscard(entries,finalReplay,currentItemReplay){const reconcilePatch=jsonPatch.compare(finalReplay,currentItemReplay);if(reconcilePatch.length===0){return void 0}const reconciledFields=new Set;for(const op of reconcilePatch){reconciledFields.add(patchPathToChangedField(op.path))}const preservedFields=new Set([...reconciledFields].filter(field=>isReplayValuePreserved(replayFieldValue(finalReplay,field),replayFieldValue(currentItemReplay,field))));const revertedFields=new Set([...reconciledFields].filter(field=>!preservedFields.has(field)));const discardedEvents=collectReconciliationEvents(entries,revertedFields);const preservedEvents=collectReconciliationEvents(entries,preservedFields);const sortedReconciledFields=[...reconciledFields].sort((left,right)=>left.localeCompare(right));const sortedRevertedFields=[...revertedFields].sort((left,right)=>left.localeCompare(right));const sortedPreservedFields=[...preservedFields].sort((left,right)=>left.localeCompare(right));const discardedAuthors=[...new Set(discardedEvents.map(event=>event.author))].sort((left,right)=>left.localeCompare(right));const preservedAuthors=[...new Set(preservedEvents.map(event=>event.author))].sort((left,right)=>left.localeCompare(right));return{reconciled_field_count:reconciledFields.size,reconciled_fields:sortedReconciledFields,reverted_field_count:revertedFields.size,reverted_fields:sortedRevertedFields,discarded_events:discardedEvents,discarded_authors:discardedAuthors,preserved_field_count:preservedFields.size,preserved_fields:sortedPreservedFields,preserved_events:preservedEvents,preserved_authors:preservedAuthors,recovery_hint:discardedEvents.length>0?"Reconciliation keeps the on-disk item and overwrites these replayed mutations. To recover one, inspect it with pm history <id> --diff --field <field>, then re-apply the lost value with pm update.":null}}async function canonicalRealPath(value){try{return await realpath(value)}catch{return null}}async function verifyReceiptAgainstSnapshot(params){const receiptPath=await canonicalRealPath(path.resolve(params.gitWorkspaceRoot,params.receipt.item_path));if(receiptPath!==params.currentPath)return null;const declaredFields=[...new Set([...params.receipt.fields_from_theirs,...params.receipt.union_fields,...params.receipt.decisions.map(decision=>decision.field)])].sort();const hashes=params.receipt.merged_field_hashes;if(!hashes||declaredFields.length===0)return null;const hashFields=Object.keys(hashes).sort();if(declaredFields.length!==hashFields.length||declaredFields.some((field,index)=>field!==hashFields[index])){return null}const currentMetadata=params.currentItemReplay.metadata;const valuesMatch=declaredFields.every(field=>{const value=field==="body"?params.currentItemReplay.body:currentMetadata[field];return[hashItemScalarDecisionValue(value),sha256Hex(stableStringify(encodeItemScalarDecisionValue(value)))].includes(hashes[field])});return valuesMatch?{receipt:params.receipt,declaredFields}:null}async function verifyMergeReceiptProof(params){if(params.proof.gitWorkspaceRoot===null){return{trusted:false,reason:"git_workspace_unavailable",receipt_ids:[]}}if(params.itemPath===null||params.currentItemReplay===null){return{trusted:false,reason:"item_path_unavailable",receipt_ids:[]}}const itemReceipts=params.proof.receipts.filter(receipt=>receipt.item_id===params.id);if(itemReceipts.length===0){return{trusted:false,reason:"no_item_receipts",receipt_ids:[]}}const currentPath=await realpath(params.itemPath);const trustedReceipts=[];for(const receipt of itemReceipts){const trusted=await verifyReceiptAgainstSnapshot({receipt,gitWorkspaceRoot:params.proof.gitWorkspaceRoot,currentPath,currentItemReplay:params.currentItemReplay});if(trusted)trustedReceipts.push(trusted)}const trustedFields=new Set(trustedReceipts.flatMap(({declaredFields})=>declaredFields));const reconciliationFields=params.reconciliation?.reconciled_fields;if(trustedReceipts.length>0&&(reconciliationFields===void 0||reconciliationFields.length>0&&reconciliationFields.every(field=>trustedFields.has(field)))){return{trusted:true,reason:"trusted_merge_driver_hash_evidence",receipt_ids:trustedReceipts.map(({receipt})=>receipt.id)}}return{trusted:false,reason:"no_receipt_set_proves_snapshot",receipt_ids:[]}}async function assertHistoryRepairAbandonmentProof(proof,context,chainOk,reanchor){if(proof===void 0)return;const{receipt,gitWorkspaceRoot}=proof;const canonicalPath=context.currentItemPath===null?null:path.relative(gitWorkspaceRoot,context.currentItemPath).split(path.sep).join("/");if(!chainOk||reanchor.entriesRehashed!==0||reanchor.entriesPatchRepaired!==0||context.matchedChainBefore!==true||context.currentItemRawBeforeLock===null||canonicalPath!==receipt.item_path||receipt.operation===void 0||!await isOriginalGitStateRestored(gitWorkspaceRoot,receipt.item_path,receipt.operation,context.currentItemRawBeforeLock)){throw new PmCliError("Restored-origin receipt evidence no longer proves the exact clean item snapshot.",EXIT_CODE.CONFLICT,{code:"merge_reconcile_receipt_evidence_untrusted",recovery:{suggested_retry:"pm merge reconcile --dry-run"}})}}async function resolveHistoryRepairMergeEvidence(params){const requestedReceiptIds=new Set(params.options.mergeReceiptProof?.receipts.filter(receipt=>receipt.item_id===params.subjectId).map(receipt=>receipt.id)??[]);const authoritativeReceiptEvidence=params.options.mergeReceiptProof?await inspectMergeReceiptEvidence(params.options.mergeReceiptProof.gitWorkspaceRoot??process.cwd(),{includeReconciled:true,includeLossless:true,pmRoot:params.pmRoot}):void 0;const subjectMergeReceipts=authoritativeReceiptEvidence?.receipts.filter(receipt=>receipt.item_id===params.subjectId&&requestedReceiptIds.has(receipt.id))??[];const mergeReceiptProof=params.options.mergeReceiptProof?await verifyMergeReceiptProof({proof:{...params.options.mergeReceiptProof,receipts:subjectMergeReceipts},id:params.subjectId,itemPath:params.itemReplayContext.currentItemPath,currentItemReplay:params.itemReplayContext.currentItemReplay,reconciliation:params.reconciliation}):void 0;if(mergeReceiptProof&&!mergeReceiptProof.trusted&¶ms.options.force!==true){throw new PmCliError(`Merge receipt evidence for ${params.subjectId} does not prove the exact item snapshot (${mergeReceiptProof.reason}).`,EXIT_CODE.CONFLICT,{code:"merge_reconcile_receipt_evidence_untrusted",required:"Use authoritative clone-local or durable receipt evidence whose canonical path, declared fields, and merged-value hashes match the current item, or review the mismatch and rerun with --force.",recovery:{suggested_retry:"pm merge reconcile --dry-run"}})}const provenMergeReceipts=mergeReceiptProof?.trusted?subjectMergeReceipts.filter(receipt=>mergeReceiptProof.receipt_ids.includes(receipt.id)):[];return{mergeReceiptProof,effectiveAuditContext:provenMergeReceipts.length>0&¶ms.options.force!==true?{...params.options.auditContext,merge:{receipts:provenMergeReceipts.map(summarizeMergeReceipt)}}:params.options.auditContext}}function describeHistoryRepairItemReplay(subject,snapshot,itemHashVersion){const currentItemPath=subject.located?.itemPath??null;const loadedItem=snapshot.loadedItem;const historyEntries=snapshot.entries;if(!loadedItem){return{currentItemReplay:null,currentItemPath,matchedChainBefore:null,currentItemRawBeforeLock:null,loadedItem:null}}const currentItemReplay=toReplayDocument(loadedItem.document);const lastOriginalAfterHash=historyEntries[historyEntries.length-1].after_hash;return{currentItemReplay,currentItemPath,matchedChainBefore:replayHashVerificationCandidates(currentItemReplay,itemHashVersion,resolveHistoryHashAlgorithm(historyEntries.at(-1)?.hash_algorithm)).includes(lastOriginalAfterHash),currentItemRawBeforeLock:loadedItem.raw,loadedItem}}function buildHistoryRepairMessage(params){if(typeof params.message==="string"&¶ms.message.trim().length>0){return params.message}return`history-repair re-anchored ${params.entriesRehashed} entr${params.entriesRehashed===1?"y":"ies"}${params.entriesPatchRepaired>0?`, repaired ${params.entriesPatchRepaired} patch(es)`:""}${params.reconcileNeeded?", reconciled chain with on-disk item":""}.`}function buildHistoryRepairEntries(params){const rewrittenEntries=[...params.reanchorEntries];if(!params.changed){return{rewrittenEntries,auditEntryAdded:false}}const afterReplay=params.reconcileNeeded&¶ms.currentItemReplay?params.currentItemReplay:params.finalReplay;const algorithm=resolveHistoryHashAlgorithm(params.reanchorEntries.at(-1)?.hash_algorithm);const beforeHashes=replayHashVerificationCandidates(params.finalReplay,params.itemHashVersion,algorithm);const previousAfterHash=params.reanchorEntries[params.reanchorEntries.length-1].after_hash;const semanticIndex=beforeHashes.indexOf(previousAfterHash);const afterHashes=replayHashVerificationCandidates(afterReplay,params.itemHashVersion,algorithm);const auditEntry={hash_algorithm:algorithm,ts:nowIso(),author:params.author,op:params.auditOperation,patch:params.reconcileNeeded&¶ms.currentItemReplay?jsonPatch.compare(params.finalReplay,params.currentItemReplay):[],before_hash:beforeHashes[semanticIndex],after_hash:afterHashes[semanticIndex],message:params.message,...params.explicitItemHashVersion?{item_hash_version:params.itemHashVersion}:{},...params.auditContext===void 0?{}:{context:params.auditContext}};rewrittenEntries.push(sealHistoryRecord({...auditEntry,event_class:classifyHistoryEvent(auditEntry)}));return{rewrittenEntries,auditEntryAdded:true}}function collectHistoryRepairWarnings(changed,skippedOps,reconciliation){const warnings=[];if(!changed){warnings.push("history_repair_no_changes")}if(skippedOps>0){warnings.push(`history_repair_skipped_unresolvable_ops:${skippedOps}`)}if(reconciliation&&reconciliation.discarded_events.length>0){warnings.push(`history_repair_reconcile_discards_events:${reconciliation.discarded_events.length}`,`history_repair_discarded_authors:${reconciliation.discarded_authors.join(",")}`)}return warnings}async function runHistoryRepair(id,options,global2){const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path);const subject=await resolveHistorySubject(pmRoot,id,settings,typeRegistry.type_to_folder);if(options.salvageTail===true){return salvageHistoryTail({pmRoot,subject,settings,typeRegistry,options,author:resolveAuthor(options.author,settings.author_default)})}return runHistoryMaintenance({pmRoot,subject,settings,typeRegistry,operation:"history-repair",options,transform:snapshot=>buildHistoryRepairPlan({pmRoot,subject,options},snapshot)})}function shouldAppendForcedHistoryAudit(options,historyEntries){const alreadyRecorded=options.mergeAbandonmentProof!==void 0&&options.auditContext!==void 0&&historyEntries.some(entry=>entry.op==="merge_reconcile"&&stableStringify(entry.context)===stableStringify(options.auditContext));return options.forceAuditEntry===true&&!alreadyRecorded}async function buildHistoryRepairPlan(params,snapshot){const{pmRoot,subject,options}=params;const historyEntries=snapshot.entries;const chainBefore=snapshot.verification;const chainVersionBefore=verifyHistoryChainWithVersion(historyEntries);const provenanceNormalization=options.normalizeProvenance?normalizeInvalidHistoryProvenance(historyEntries):{entries:historyEntries,receipt:{changed:false,events_changed:0,observations_removed:0,invalid_values:[]}};const itemHashVersion=resolveHistoryRepairItemHashVersion(provenanceNormalization.entries);const explicitVersionsBefore=new Set(provenanceNormalization.entries.map(entry=>entry.item_hash_version).filter(version=>version!==void 0));const reanchor=reanchorHistoryEntries(provenanceNormalization.entries,itemHashVersion);const itemReplayContext=describeHistoryRepairItemReplay(subject,snapshot,itemHashVersion);await assertHistoryRepairAbandonmentProof(options.mergeAbandonmentProof,itemReplayContext,chainBefore.ok,reanchor);const finalReplay=reanchor.finalDocument;const finalReplayHashes=replayHashVerificationCandidates(finalReplay,itemHashVersion);let reconcileNeeded=false;if(itemReplayContext.currentItemReplay!==null){const currentItemReplayHashes=replayHashVerificationCandidates(itemReplayContext.currentItemReplay,itemHashVersion);reconcileNeeded=!finalReplayHashes.some((hash,hashIndex)=>hash===currentItemReplayHashes[hashIndex])}const reconciliation=reconcileNeeded&&itemReplayContext.currentItemReplay?analyzeReconciliationDiscard(reanchor.entries,finalReplay,itemReplayContext.currentItemReplay):void 0;const{mergeReceiptProof,effectiveAuditContext}=await resolveHistoryRepairMergeEvidence({options,pmRoot,subjectId:subject.id,itemReplayContext,reconciliation});const changed=[reanchor.entriesRehashed>0,reanchor.entriesPatchRepaired>0,reconcileNeeded,shouldAppendForcedHistoryAudit(options,historyEntries),provenanceNormalization.receipt.changed].some(Boolean);const author=snapshot.author;const dryRun=Boolean(options.dryRun);const repairMessage=buildHistoryRepairMessage({message:options.message,entriesRehashed:reanchor.entriesRehashed,entriesPatchRepaired:reanchor.entriesPatchRepaired,reconcileNeeded});const{rewrittenEntries,auditEntryAdded}=buildHistoryRepairEntries({reanchorEntries:reanchor.entries,changed,reconcileNeeded,currentItemReplay:itemReplayContext.currentItemReplay,finalReplay,author,message:repairMessage,auditOperation:options.auditOperation??"history_repair",auditContext:provenanceNormalization.receipt.changed?{...effectiveAuditContext,provenance_normalization:provenanceNormalization.receipt}:effectiveAuditContext,itemHashVersion,explicitItemHashVersion:reanchor.explicitItemHashVersion});const warnings=collectHistoryRepairWarnings(changed,reanchor.skippedOps,reconciliation);return{changed,rewrittenEntries,beforeWrite:async()=>assertHistoryRepairAbandonmentProof(options.mergeAbandonmentProof,itemReplayContext,chainBefore.ok,reanchor),report:({verification:historyVerify,warnings:writeWarnings})=>({id:subject.id,dry_run:dryRun,changed,history:{path:subject.historyPath,entries_scanned:historyEntries.length,chain_drift_before:!chainBefore.ok,entries_rehashed:reanchor.entriesRehashed,entries_patch_repaired:reanchor.entriesPatchRepaired,converted_replace_to_add:reanchor.convertedReplaceToAdd,skipped_ops:reanchor.skippedOps,reconciled_with_item:reconcileNeeded,audit_entry_added:auditEntryAdded,verify_ok:historyVerify.ok,verify_errors:historyVerify.errors,item_hash_version_before:chainVersionBefore.item_hash_version??null,item_hash_version_after:itemHashVersion,version_disposition:explicitVersionsBefore.size>1?"selected_for_ambiguous_stream":"preserved"},item:{exists:itemReplayContext.currentItemPath!==null,path:itemReplayContext.currentItemPath,matched_chain_before:itemReplayContext.matchedChainBefore},provenance_normalization:{requested:options.normalizeProvenance===true,...provenanceNormalization.receipt},...reconciliation?{reconciliation}:{},...mergeReceiptProof?{merge_receipt_proof:mergeReceiptProof}:{},warnings:[...new Set([...warnings,...writeWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()})}}function assertHistoryRepairTarget(id,all){if(all&&id!==void 0){throw new PmCliError("history-repair: <id> and --all are mutually exclusive; pass an item id to repair one stream or --all to repair every drifted stream.",EXIT_CODE.USAGE)}if(!all&&id===void 0){throw new PmCliError("history-repair: provide an item <id> or pass --all to repair every drifted stream.",EXIT_CODE.USAGE)}}async function runHistoryRepairAll(options,global2){if(options.salvageTail===true){throw new PmCliError("Tail salvage requires one explicit item ID; --all is not supported.",EXIT_CODE.USAGE)}const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path);const itemReadWarnings=[];const items=await listAllItemMetadataWithBody(pmRoot,settings.item_format,typeRegistry.type_to_folder,itemReadWarnings,settings.schema,{forceSourceScan:true});const drift=await scanHistoryDrift(pmRoot,items);const invalidProvenanceIds=options.normalizeProvenance?await listInvalidProvenanceHistoryStreamIds(pmRoot):[];const targetedIds=[...new Set([...drift.driftedItems,...invalidProvenanceIds])].sort((left,right)=>left.localeCompare(right));const streams=[];const repairWarnings=[];const totals={repaired:0,skipped_clean:0,failed:0};for(const driftedId of targetedIds){try{const result=await runHistoryRepair(driftedId,{...options,auditContext:options.auditContextById?.[driftedId],auditContextById:void 0,mergeReceiptProof:options.mergeReceiptProofById?.[driftedId]??options.mergeReceiptProof,mergeReceiptProofById:void 0},global2);const outcome=result.changed?"repaired":"skipped_clean";totals[outcome]+=1;repairWarnings.push(...result.warnings.map(warning=>`${driftedId}:${warning}`));streams.push({id:driftedId,outcome,entries_rehashed:result.history.entries_rehashed,entries_patch_repaired:result.history.entries_patch_repaired,reconciled_with_item:result.history.reconciled_with_item,...result.reconciliation?{reconciliation:result.reconciliation}:{},...result.merge_receipt_proof?{merge_receipt_proof:result.merge_receipt_proof}:{},warnings:result.warnings})}catch(error){totals.failed+=1;streams.push({id:driftedId,outcome:"failed",error:error instanceof Error?error.message:String(error)})}}if(!options.dryRun){await invalidateHistoryDriftCache(pmRoot)}return{all:true,dry_run:Boolean(options.dryRun),scanned_streams:items.length,drifted_streams:drift.driftedItems.length,provenance_invalid_streams:invalidProvenanceIds.length,streams,totals,warnings:[...new Set([...itemReadWarnings,...repairWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()}}export{analyzeReconciliationDiscard,assertHistoryRepairTarget,runHistoryRepair,runHistoryRepairAll};
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5df05541-b114-52bd-9540-d741b2657edf")}catch{}})();import{salvageHistoryTail}from"./history/salvage.js";import{resolveHistoryHashAlgorithm}from"../core/history/digest.js";import{realpath}from"node:fs/promises";import path from"node:path";import jsonPatch from"fast-json-patch";import{patchPathToChangedField}from"../core/history/history-diff.js";import{normalizeReplayPatchOps,reanchorHistoryEntries,replayHashVerificationCandidates,resolveHistoryRepairItemHashVersion,toReplayDocument,verifyHistoryChainWithVersion}from"../core/history/replay.js";import{sealHistoryRecord}from"../core/history/history.js";import{classifyHistoryEvent}from"../core/history/event-classification.js";import{scanHistoryDrift}from"../core/history/drift-scan.js";import{invalidateHistoryDriftCache}from"../core/history/drift-cache.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{sha256Hex,stableStringify}from"../core/shared/serialization.js";import{resolveAuthor}from"../core/shared/author.js";import{nowIso}from"../core/shared/time.js";import{listAllItemMetadataWithBody}from"../core/store/item-store.js";import{resolveHistoryWorkspace,resolveHistorySubject}from"./history/subject.js";import{runHistoryMaintenance}from"./history/maintenance.js";import{isOriginalGitStateRestored}from"./merge/receipt-operation.js";import{inspectMergeReceiptEvidence,summarizeMergeReceipt}from"./merge/receipts.js";import{encodeItemScalarDecisionValue,hashItemScalarDecisionValue}from"./merge/three-way.js";import{listInvalidProvenanceHistoryStreamIds,normalizeInvalidHistoryProvenance}from"./governance/provenance-health.js";function replayFieldValue(document,field){return field==="body"?document.body:document.metadata[field]}function isReplayValuePreserved(replayed,reconciled){if(replayed===void 0||Object.is(replayed,reconciled))return!0;if(Array.isArray(replayed)){if(!Array.isArray(reconciled))return!1;const matched=new Set;return replayed.every(expected=>{const index=reconciled.findIndex((candidate,candidateIndex)=>!matched.has(candidateIndex)&&isReplayValuePreserved(expected,candidate));return index<0?!1:(matched.add(index),!0)})}if(replayed===null||reconciled===null||typeof replayed!="object"||typeof reconciled!="object"||Array.isArray(reconciled))return!1;const reconciledRecord=reconciled;return Object.entries(replayed).every(([key,value])=>Object.hasOwn(reconciledRecord,key)&&isReplayValuePreserved(value,reconciledRecord[key]))}function collectReconciliationEvents(entries,fields){const remaining=new Set(fields),events=[];for(let index=entries.length-1;index>=0&&remaining.size>0;index-=1){const entry=entries[index],entryFields=new Set;for(const op of normalizeReplayPatchOps(entry.patch))entryFields.add(patchPathToChangedField(op.path)),op.from&&entryFields.add(patchPathToChangedField(op.from));const overlap=[...remaining].filter(field=>entryFields.has(field));if(overlap.length!==0){for(const field of overlap)remaining.delete(field);events.push({index:index+1,ts:entry.ts,author:entry.author,op:entry.op,fields:overlap.sort((left,right)=>left.localeCompare(right))})}}return events.reverse()}function analyzeReconciliationDiscard(entries,finalReplay,currentItemReplay){const reconcilePatch=jsonPatch.compare(finalReplay,currentItemReplay);if(reconcilePatch.length===0)return;const reconciledFields=new Set;for(const op of reconcilePatch)reconciledFields.add(patchPathToChangedField(op.path));const preservedFields=new Set([...reconciledFields].filter(field=>isReplayValuePreserved(replayFieldValue(finalReplay,field),replayFieldValue(currentItemReplay,field)))),revertedFields=new Set([...reconciledFields].filter(field=>!preservedFields.has(field))),discardedEvents=collectReconciliationEvents(entries,revertedFields),preservedEvents=collectReconciliationEvents(entries,preservedFields),sortedReconciledFields=[...reconciledFields].sort((left,right)=>left.localeCompare(right)),sortedRevertedFields=[...revertedFields].sort((left,right)=>left.localeCompare(right)),sortedPreservedFields=[...preservedFields].sort((left,right)=>left.localeCompare(right)),discardedAuthors=[...new Set(discardedEvents.map(event=>event.author))].sort((left,right)=>left.localeCompare(right)),preservedAuthors=[...new Set(preservedEvents.map(event=>event.author))].sort((left,right)=>left.localeCompare(right));return{reconciled_field_count:reconciledFields.size,reconciled_fields:sortedReconciledFields,reverted_field_count:revertedFields.size,reverted_fields:sortedRevertedFields,discarded_events:discardedEvents,discarded_authors:discardedAuthors,preserved_field_count:preservedFields.size,preserved_fields:sortedPreservedFields,preserved_events:preservedEvents,preserved_authors:preservedAuthors,recovery_hint:discardedEvents.length>0?"Reconciliation keeps the on-disk item and overwrites these replayed mutations. To recover one, inspect it with pm history <id> --diff --field <field>, then re-apply the lost value with pm update.":null}}async function canonicalRealPath(value){try{return await realpath(value)}catch{return null}}async function verifyReceiptAgainstSnapshot(params){if(await canonicalRealPath(path.resolve(params.gitWorkspaceRoot,params.receipt.item_path))!==params.currentPath)return null;const declaredFields=[...new Set([...params.receipt.fields_from_theirs,...params.receipt.union_fields,...params.receipt.decisions.map(decision=>decision.field)])].sort(),hashes=params.receipt.merged_field_hashes;if(!hashes||declaredFields.length===0)return null;const hashFields=Object.keys(hashes).sort();if(declaredFields.length!==hashFields.length||declaredFields.some((field,index)=>field!==hashFields[index]))return null;const currentMetadata=params.currentItemReplay.metadata;return declaredFields.every(field=>{const value=field==="body"?params.currentItemReplay.body:currentMetadata[field];return[hashItemScalarDecisionValue(value),sha256Hex(stableStringify(encodeItemScalarDecisionValue(value)))].includes(hashes[field])})?{receipt:params.receipt,declaredFields}:null}async function verifyMergeReceiptProof(params){if(params.proof.gitWorkspaceRoot===null)return{trusted:!1,reason:"git_workspace_unavailable",receipt_ids:[]};if(params.itemPath===null||params.currentItemReplay===null)return{trusted:!1,reason:"item_path_unavailable",receipt_ids:[]};const itemReceipts=params.proof.receipts.filter(receipt=>receipt.item_id===params.id);if(itemReceipts.length===0)return{trusted:!1,reason:"no_item_receipts",receipt_ids:[]};const currentPath=await realpath(params.itemPath),trustedReceipts=[];for(const receipt of itemReceipts){const trusted=await verifyReceiptAgainstSnapshot({receipt,gitWorkspaceRoot:params.proof.gitWorkspaceRoot,currentPath,currentItemReplay:params.currentItemReplay});trusted&&trustedReceipts.push(trusted)}const trustedFields=new Set(trustedReceipts.flatMap(({declaredFields})=>declaredFields)),reconciliationFields=params.reconciliation?.reconciled_fields;return trustedReceipts.length>0&&(reconciliationFields===void 0||reconciliationFields.length>0&&reconciliationFields.every(field=>trustedFields.has(field)))?{trusted:!0,reason:"trusted_merge_driver_hash_evidence",receipt_ids:trustedReceipts.map(({receipt})=>receipt.id)}:{trusted:!1,reason:"no_receipt_set_proves_snapshot",receipt_ids:[]}}async function assertHistoryRepairAbandonmentProof(proof,context,chainOk,reanchor){if(proof===void 0)return;const{receipt,gitWorkspaceRoot}=proof,canonicalPath=context.currentItemPath===null?null:path.relative(gitWorkspaceRoot,context.currentItemPath).split(path.sep).join("/");if(!chainOk||reanchor.entriesRehashed!==0||reanchor.entriesPatchRepaired!==0||context.matchedChainBefore!==!0||context.currentItemRawBeforeLock===null||canonicalPath!==receipt.item_path||receipt.operation===void 0||!await isOriginalGitStateRestored(gitWorkspaceRoot,receipt.item_path,receipt.operation,context.currentItemRawBeforeLock))throw new PmCliError("Restored-origin receipt evidence no longer proves the exact clean item snapshot.",EXIT_CODE.CONFLICT,{code:"merge_reconcile_receipt_evidence_untrusted",recovery:{suggested_retry:"pm merge reconcile --dry-run"}})}async function resolveHistoryRepairMergeEvidence(params){const requestedReceiptIds=new Set(params.options.mergeReceiptProof?.receipts.filter(receipt=>receipt.item_id===params.subjectId).map(receipt=>receipt.id)??[]),subjectMergeReceipts=(params.options.mergeReceiptProof?await inspectMergeReceiptEvidence(params.options.mergeReceiptProof.gitWorkspaceRoot??process.cwd(),{includeReconciled:!0,includeLossless:!0,pmRoot:params.pmRoot}):void 0)?.receipts.filter(receipt=>receipt.item_id===params.subjectId&&requestedReceiptIds.has(receipt.id))??[],mergeReceiptProof=params.options.mergeReceiptProof?await verifyMergeReceiptProof({proof:{...params.options.mergeReceiptProof,receipts:subjectMergeReceipts},id:params.subjectId,itemPath:params.itemReplayContext.currentItemPath,currentItemReplay:params.itemReplayContext.currentItemReplay,reconciliation:params.reconciliation}):void 0;if(mergeReceiptProof&&!mergeReceiptProof.trusted&¶ms.options.force!==!0)throw new PmCliError(`Merge receipt evidence for ${params.subjectId} does not prove the exact item snapshot (${mergeReceiptProof.reason}).`,EXIT_CODE.CONFLICT,{code:"merge_reconcile_receipt_evidence_untrusted",required:"Use authoritative clone-local or durable receipt evidence whose canonical path, declared fields, and merged-value hashes match the current item, or review the mismatch and rerun with --force.",recovery:{suggested_retry:"pm merge reconcile --dry-run"}});const provenMergeReceipts=mergeReceiptProof?.trusted?subjectMergeReceipts.filter(receipt=>mergeReceiptProof.receipt_ids.includes(receipt.id)):[];return{mergeReceiptProof,effectiveAuditContext:provenMergeReceipts.length>0&¶ms.options.force!==!0?{...params.options.auditContext,merge:{receipts:provenMergeReceipts.map(summarizeMergeReceipt)}}:params.options.auditContext}}function describeHistoryRepairItemReplay(subject,snapshot,itemHashVersion){const currentItemPath=subject.located?.itemPath??null,loadedItem=snapshot.loadedItem,historyEntries=snapshot.entries;if(!loadedItem)return{currentItemReplay:null,currentItemPath,matchedChainBefore:null,currentItemRawBeforeLock:null,loadedItem:null};const currentItemReplay=toReplayDocument(loadedItem.document),lastOriginalAfterHash=historyEntries[historyEntries.length-1].after_hash;return{currentItemReplay,currentItemPath,matchedChainBefore:replayHashVerificationCandidates(currentItemReplay,itemHashVersion,resolveHistoryHashAlgorithm(historyEntries.at(-1)?.hash_algorithm)).includes(lastOriginalAfterHash),currentItemRawBeforeLock:loadedItem.raw,loadedItem}}function buildHistoryRepairMessage(params){return typeof params.message=="string"&¶ms.message.trim().length>0?params.message:`history-repair re-anchored ${params.entriesRehashed} entr${params.entriesRehashed===1?"y":"ies"}${params.entriesPatchRepaired>0?`, repaired ${params.entriesPatchRepaired} patch(es)`:""}${params.reconcileNeeded?", reconciled chain with on-disk item":""}.`}function buildHistoryRepairEntries(params){const rewrittenEntries=[...params.reanchorEntries];if(!params.changed)return{rewrittenEntries,auditEntryAdded:!1};const afterReplay=params.reconcileNeeded&¶ms.currentItemReplay?params.currentItemReplay:params.finalReplay,algorithm=resolveHistoryHashAlgorithm(params.reanchorEntries.at(-1)?.hash_algorithm),beforeHashes=replayHashVerificationCandidates(params.finalReplay,params.itemHashVersion,algorithm),previousAfterHash=params.reanchorEntries[params.reanchorEntries.length-1].after_hash,semanticIndex=beforeHashes.indexOf(previousAfterHash),afterHashes=replayHashVerificationCandidates(afterReplay,params.itemHashVersion,algorithm),auditEntry={hash_algorithm:algorithm,ts:nowIso(),author:params.author,op:params.auditOperation,patch:params.reconcileNeeded&¶ms.currentItemReplay?jsonPatch.compare(params.finalReplay,params.currentItemReplay):[],before_hash:beforeHashes[semanticIndex],after_hash:afterHashes[semanticIndex],message:params.message,...params.explicitItemHashVersion?{item_hash_version:params.itemHashVersion}:{},...params.auditContext===void 0?{}:{context:params.auditContext}};return rewrittenEntries.push(sealHistoryRecord({...auditEntry,event_class:classifyHistoryEvent(auditEntry)})),{rewrittenEntries,auditEntryAdded:!0}}function collectHistoryRepairWarnings(changed,skippedOps,reconciliation){const warnings=[];return changed||warnings.push("history_repair_no_changes"),skippedOps>0&&warnings.push(`history_repair_skipped_unresolvable_ops:${skippedOps}`),reconciliation&&reconciliation.discarded_events.length>0&&warnings.push(`history_repair_reconcile_discards_events:${reconciliation.discarded_events.length}`,`history_repair_discarded_authors:${reconciliation.discarded_authors.join(",")}`),warnings}async function runHistoryRepair(id,options,global2){const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path),subject=await resolveHistorySubject(pmRoot,id,settings,typeRegistry.type_to_folder);return options.salvageTail===!0?salvageHistoryTail({pmRoot,subject,settings,typeRegistry,options,author:resolveAuthor(options.author,settings.author_default)}):runHistoryMaintenance({pmRoot,subject,settings,typeRegistry,operation:"history-repair",options,transform:snapshot=>buildHistoryRepairPlan({pmRoot,subject,options},snapshot)})}function shouldAppendForcedHistoryAudit(options,historyEntries){const alreadyRecorded=options.mergeAbandonmentProof!==void 0&&options.auditContext!==void 0&&historyEntries.some(entry=>entry.op==="merge_reconcile"&&stableStringify(entry.context)===stableStringify(options.auditContext));return options.forceAuditEntry===!0&&!alreadyRecorded}async function buildHistoryRepairPlan(params,snapshot){const{pmRoot,subject,options}=params,historyEntries=snapshot.entries,chainBefore=snapshot.verification,chainVersionBefore=verifyHistoryChainWithVersion(historyEntries),provenanceNormalization=options.normalizeProvenance?normalizeInvalidHistoryProvenance(historyEntries):{entries:historyEntries,receipt:{changed:!1,events_changed:0,observations_removed:0,invalid_values:[]}},itemHashVersion=resolveHistoryRepairItemHashVersion(provenanceNormalization.entries),explicitVersionsBefore=new Set(provenanceNormalization.entries.map(entry=>entry.item_hash_version).filter(version=>version!==void 0)),reanchor=reanchorHistoryEntries(provenanceNormalization.entries,itemHashVersion),itemReplayContext=describeHistoryRepairItemReplay(subject,snapshot,itemHashVersion);await assertHistoryRepairAbandonmentProof(options.mergeAbandonmentProof,itemReplayContext,chainBefore.ok,reanchor);const finalReplay=reanchor.finalDocument,finalReplayHashes=replayHashVerificationCandidates(finalReplay,itemHashVersion);let reconcileNeeded=!1;if(itemReplayContext.currentItemReplay!==null){const currentItemReplayHashes=replayHashVerificationCandidates(itemReplayContext.currentItemReplay,itemHashVersion);reconcileNeeded=!finalReplayHashes.some((hash,hashIndex)=>hash===currentItemReplayHashes[hashIndex])}const reconciliation=reconcileNeeded&&itemReplayContext.currentItemReplay?analyzeReconciliationDiscard(reanchor.entries,finalReplay,itemReplayContext.currentItemReplay):void 0,{mergeReceiptProof,effectiveAuditContext}=await resolveHistoryRepairMergeEvidence({options,pmRoot,subjectId:subject.id,itemReplayContext,reconciliation}),changed=[reanchor.entriesRehashed>0,reanchor.entriesPatchRepaired>0,reconcileNeeded,shouldAppendForcedHistoryAudit(options,historyEntries),provenanceNormalization.receipt.changed].some(Boolean),author=snapshot.author,dryRun=!!options.dryRun,repairMessage=buildHistoryRepairMessage({message:options.message,entriesRehashed:reanchor.entriesRehashed,entriesPatchRepaired:reanchor.entriesPatchRepaired,reconcileNeeded}),{rewrittenEntries,auditEntryAdded}=buildHistoryRepairEntries({reanchorEntries:reanchor.entries,changed,reconcileNeeded,currentItemReplay:itemReplayContext.currentItemReplay,finalReplay,author,message:repairMessage,auditOperation:options.auditOperation??"history_repair",auditContext:provenanceNormalization.receipt.changed?{...effectiveAuditContext,provenance_normalization:provenanceNormalization.receipt}:effectiveAuditContext,itemHashVersion,explicitItemHashVersion:reanchor.explicitItemHashVersion}),warnings=collectHistoryRepairWarnings(changed,reanchor.skippedOps,reconciliation);return{changed,rewrittenEntries,beforeWrite:async()=>assertHistoryRepairAbandonmentProof(options.mergeAbandonmentProof,itemReplayContext,chainBefore.ok,reanchor),report:({verification:historyVerify,warnings:writeWarnings})=>({id:subject.id,dry_run:dryRun,changed,history:{path:subject.historyPath,entries_scanned:historyEntries.length,chain_drift_before:!chainBefore.ok,entries_rehashed:reanchor.entriesRehashed,entries_patch_repaired:reanchor.entriesPatchRepaired,converted_replace_to_add:reanchor.convertedReplaceToAdd,skipped_ops:reanchor.skippedOps,reconciled_with_item:reconcileNeeded,audit_entry_added:auditEntryAdded,verify_ok:historyVerify.ok,verify_errors:historyVerify.errors,item_hash_version_before:chainVersionBefore.item_hash_version??null,item_hash_version_after:itemHashVersion,version_disposition:explicitVersionsBefore.size>1?"selected_for_ambiguous_stream":"preserved"},item:{exists:itemReplayContext.currentItemPath!==null,path:itemReplayContext.currentItemPath,matched_chain_before:itemReplayContext.matchedChainBefore},provenance_normalization:{requested:options.normalizeProvenance===!0,...provenanceNormalization.receipt},...reconciliation?{reconciliation}:{},...mergeReceiptProof?{merge_receipt_proof:mergeReceiptProof}:{},warnings:[...new Set([...warnings,...writeWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()})}}function assertHistoryRepairTarget(id,all){if(all&&id!==void 0)throw new PmCliError("history-repair: <id> and --all are mutually exclusive; pass an item id to repair one stream or --all to repair every drifted stream.",EXIT_CODE.USAGE);if(!all&&id===void 0)throw new PmCliError("history-repair: provide an item <id> or pass --all to repair every drifted stream.",EXIT_CODE.USAGE)}async function runHistoryRepairAll(options,global2){if(options.salvageTail===!0)throw new PmCliError("Tail salvage requires one explicit item ID; --all is not supported.",EXIT_CODE.USAGE);const{pmRoot,settings,typeRegistry}=await resolveHistoryWorkspace(global2.path),itemReadWarnings=[],items=await listAllItemMetadataWithBody(pmRoot,settings.item_format,typeRegistry.type_to_folder,itemReadWarnings,settings.schema,{forceSourceScan:!0}),drift=await scanHistoryDrift(pmRoot,items),invalidProvenanceIds=options.normalizeProvenance?await listInvalidProvenanceHistoryStreamIds(pmRoot):[],targetedIds=[...new Set([...drift.driftedItems,...invalidProvenanceIds])].sort((left,right)=>left.localeCompare(right)),streams=[],repairWarnings=[],totals={repaired:0,skipped_clean:0,failed:0};for(const driftedId of targetedIds)try{const result=await runHistoryRepair(driftedId,{...options,auditContext:options.auditContextById?.[driftedId],auditContextById:void 0,mergeReceiptProof:options.mergeReceiptProofById?.[driftedId]??options.mergeReceiptProof,mergeReceiptProofById:void 0},global2),outcome=result.changed?"repaired":"skipped_clean";totals[outcome]+=1,repairWarnings.push(...result.warnings.map(warning=>`${driftedId}:${warning}`)),streams.push({id:driftedId,outcome,entries_rehashed:result.history.entries_rehashed,entries_patch_repaired:result.history.entries_patch_repaired,reconciled_with_item:result.history.reconciled_with_item,...result.reconciliation?{reconciliation:result.reconciliation}:{},...result.merge_receipt_proof?{merge_receipt_proof:result.merge_receipt_proof}:{},warnings:result.warnings})}catch(error){totals.failed+=1,streams.push({id:driftedId,outcome:"failed",error:error instanceof Error?error.message:String(error)})}return options.dryRun||await invalidateHistoryDriftCache(pmRoot),{all:!0,dry_run:!!options.dryRun,scanned_streams:items.length,drifted_streams:drift.driftedItems.length,provenance_invalid_streams:invalidProvenanceIds.length,streams,totals,warnings:[...new Set([...itemReadWarnings,...repairWarnings])].sort((left,right)=>left.localeCompare(right)),generated_at:nowIso()}}export{analyzeReconciliationDiscard,assertHistoryRepairTarget,runHistoryRepair,runHistoryRepairAll};
|
|
2
2
|
//# sourceMappingURL=history-repair.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ed03b6c8-6275-55a6-8e5f-4f27a23d6696")}catch{}})();import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";const IMPROVEMENT_LEDGER_FORMAT_VERSION=1;function isValidLedgerObservation(observation){if(typeof observation!="object"||observation===null)return!1;const candidate=observation;return typeof candidate.id=="string"&&typeof candidate.metric=="string"&&typeof candidate.value=="number"&&Number.isFinite(candidate.value)&&["higher","lower","target"].includes(String(candidate.direction))&&typeof candidate.observed_at=="string"&&typeof candidate.revision=="string"&&["caller","git","unversioned"].includes(String(candidate.revision_source))&&typeof candidate.author=="string"?candidate.direction!=="target"||typeof candidate.threshold=="number"&&Number.isFinite(candidate.threshold):!1}function parseImprovementLedgerDocument(raw){if(raw===null)return{format_version:IMPROVEMENT_LEDGER_FORMAT_VERSION,observations:[]};let parsed;try{parsed=JSON.parse(raw)}catch{throw new PmCliError("Improvement ledger contains invalid JSON.",EXIT_CODE.GENERIC_FAILURE,{code:"invalid_improvement_ledger"})}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed)||parsed.format_version!==IMPROVEMENT_LEDGER_FORMAT_VERSION||!Array.isArray(parsed.observations))throw new PmCliError("Improvement ledger has an unsupported shape or format version.",EXIT_CODE.GENERIC_FAILURE,{code:"invalid_improvement_ledger"});const observations=parsed.observations;for(const observation of observations)if(!isValidLedgerObservation(observation))throw new PmCliError("Improvement ledger contains an invalid observation.",EXIT_CODE.GENERIC_FAILURE,{code:"invalid_improvement_ledger"});return parsed}export{parseImprovementLedgerDocument};
|
|
2
2
|
//# sourceMappingURL=improvement-ledger-validation.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
`,result:observation}}});return{changed:mutation.changed,observation:mutation.result,ledger_path:"improvement-ledger.json"}}async function readImprovementLedger(options={}){const pmRoot=resolvePmRoot(options.cwd??process.cwd(),options.pmRoot);await assertInitializedTracker(pmRoot);const metric=options.metric===void 0?void 0:normalizeMetricName(options.metric)
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e7ad59ce-5111-5649-9025-340183539b4a")}catch{}})();import{assertInitializedTracker}from"./environment/tracker-preflight.js";import{createHash}from"node:crypto";import{execFile}from"node:child_process";import path from"node:path";import{promisify}from"node:util";import{readFileIfExists}from"../core/fs/fs-utils.js";import{mutateWorkspaceJsonWithHistory}from"../core/history/workspace-history.js";import{EXIT_CODE}from"../core/shared/constants.js";import{resolveAuthor}from"../core/shared/author.js";import{PmCliError}from"../core/shared/errors.js";import{stableStringify}from"../core/shared/serialization.js";import{nowIso}from"../core/shared/time.js";import{resolvePmRoot,resolveWorkspaceRoot}from"../core/store/paths.js";import{readSettings}from"../core/store/settings.js";import{parseImprovementLedgerDocument as parseLedger}from"./improvement-ledger-validation.js";const execFileAsync=promisify(execFile),DEFAULT_OBSERVATION_LIMIT=50,MAX_OBSERVATION_LIMIT=1e3,METRIC_NAME_PATTERN=/^[a-z0-9](?:[a-z0-9._/-]{0,126}[a-z0-9])?$/u;function normalizeMetricName(value){const metric=value.trim().toLowerCase();if(!METRIC_NAME_PATTERN.test(metric))throw new PmCliError(`Invalid metric name "${value}"; use 1-128 lowercase letters, digits, dots, slashes, underscores, or hyphens.`,EXIT_CODE.USAGE,{code:"invalid_improvement_metric"});return metric}function normalizeDirection(value){const direction=value??"lower";if(!["higher","lower","target"].includes(direction))throw new PmCliError("Improvement direction must be higher, lower, or target.",EXIT_CODE.USAGE,{code:"invalid_improvement_observation"});return direction}function normalizeOptionalText(value,field){const normalized=value?.trim();if(normalized){if(normalized.length>256)throw new PmCliError(`${field} must not exceed 256 characters.`,EXIT_CODE.USAGE,{code:"invalid_improvement_observation"});return normalized}}function parseObservationLimit(value){const limit=value??DEFAULT_OBSERVATION_LIMIT;if(!Number.isSafeInteger(limit)||limit<0||limit>MAX_OBSERVATION_LIMIT)throw new PmCliError(`Improvement observation limit must be an integer from 0 to ${MAX_OBSERVATION_LIMIT}.`,EXIT_CODE.USAGE,{code:"invalid_improvement_observation_limit"});return limit}function parseIsoTimestamp(value,field){const milliseconds=Date.parse(value);if(!Number.isFinite(milliseconds))throw new PmCliError(`${field} must be an ISO timestamp.`,EXIT_CODE.USAGE,{code:"invalid_improvement_observation_timestamp"});return new Date(milliseconds).toISOString()}async function buildImprovementObservation(pmRoot,settings,options){if(!Number.isFinite(options.value))throw new PmCliError("Improvement observation value must be finite.",EXIT_CODE.USAGE,{code:"invalid_improvement_observation"});const metric=normalizeMetricName(options.metric),direction=normalizeDirection(options.direction);if(options.threshold!==void 0&&!Number.isFinite(options.threshold)||direction==="target"&&options.threshold===void 0)throw new PmCliError("Target-directed observations require a finite threshold.",EXIT_CODE.USAGE,{code:"invalid_improvement_observation"});const revision=await resolveObservationRevision(pmRoot,options.revision),source=normalizeOptionalText(options.source,"source"),itemId=normalizeOptionalText(options.itemId,"itemId"),unit=normalizeOptionalText(options.unit,"unit"),idempotencyKey=normalizeOptionalText(options.idempotencyKey,"idempotencyKey")??(revision.revision_source==="unversioned"?void 0:[revision.revision,metric,source??"manual",itemId??"workspace"].join(":")),observationWithoutId={metric,value:options.value,direction,...unit===void 0?{}:{unit},...options.threshold===void 0?{}:{threshold:options.threshold},observed_at:parseIsoTimestamp(options.observedAt??nowIso(),"observedAt"),...revision,author:resolveAuthor(options.author,settings.author_default),...itemId===void 0?{}:{item_id:itemId},...source===void 0?{}:{source},...idempotencyKey===void 0?{}:{idempotency_key:idempotencyKey}};return{id:createHash("sha256").update(stableStringify(observationWithoutId)).digest("hex").slice(0,24),...observationWithoutId}}function ensureObservationCanAppend(ledger,observation){const existing=observation.idempotency_key?ledger.observations.find(row=>row.idempotency_key===observation.idempotency_key):ledger.observations.find(row=>row.id===observation.id);if(existing){if(existing.metric!==observation.metric||existing.value!==observation.value||existing.direction!==observation.direction||existing.threshold!==observation.threshold||existing.unit!==observation.unit)throw new PmCliError(`Improvement observation retry key already records a different value for ${observation.metric}.`,EXIT_CODE.CONFLICT,{code:"improvement_observation_conflict"});return existing}const priorMetric=ledger.observations.find(row=>row.metric===observation.metric);if(priorMetric&&(priorMetric.direction!==observation.direction||priorMetric.unit!==observation.unit||observation.direction==="target"&&priorMetric.threshold!==observation.threshold))throw new PmCliError(`Metric ${observation.metric} is already declared with direction ${priorMetric.direction} and unit ${priorMetric.unit??"<none>"}.`,EXIT_CODE.CONFLICT,{code:"improvement_metric_contract_conflict"})}async function resolveObservationRevision(pmRoot,explicit){const callerRevision=normalizeOptionalText(explicit,"revision");if(callerRevision)return{revision:callerRevision,revision_source:"caller"};try{return{revision:(await execFileAsync("git",["rev-parse","--verify","HEAD^{commit}"],{cwd:resolveWorkspaceRoot(pmRoot),encoding:"utf8",timeout:5e3})).stdout.trim(),revision_source:"git"}}catch{}return{revision:"unversioned",revision_source:"unversioned"}}function trendForMetric(observations){const baseline=observations[0],latest=observations[observations.length-1],delta=latest.value-baseline.value,improved=latest.direction==="higher"?delta>0:latest.direction==="lower"?delta<0:Math.abs(latest.value-latest.threshold)<Math.abs(baseline.value-baseline.threshold);return{metric:latest.metric,direction:latest.direction,baseline,latest,delta,improved,sample_count:observations.length}}async function recordImprovementObservation(options,global2={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),observation=await buildImprovementObservation(pmRoot,settings,options),filePath=path.join(pmRoot,"improvement-ledger.json"),mutation=await mutateWorkspaceJsonWithHistory({pmRoot,filePath,op:"improvement_observe",author:observation.author,lockTtlSeconds:settings.locks.ttl_seconds,lockWaitMs:settings.locks.wait_ms,message:options.message??`Record ${observation.metric}=${String(options.value)} improvement observation`,mutate:beforeRaw=>{const ledger=parseLedger(beforeRaw),existing=ensureObservationCanAppend(ledger,observation);return existing?{raw:beforeRaw,result:existing}:(ledger.observations.push(observation),ledger.observations.sort((left,right)=>left.observed_at.localeCompare(right.observed_at)||left.metric.localeCompare(right.metric)||left.id.localeCompare(right.id)),{raw:`${stableStringify(ledger)}
|
|
2
|
+
`,result:observation})}});return{changed:mutation.changed,observation:mutation.result,ledger_path:"improvement-ledger.json"}}async function readImprovementLedger(options={}){const pmRoot=resolvePmRoot(options.cwd??process.cwd(),options.pmRoot);await assertInitializedTracker(pmRoot);const metric=options.metric===void 0?void 0:normalizeMetricName(options.metric),since=options.since===void 0?void 0:parseIsoTimestamp(options.since,"since"),limit=parseObservationLimit(options.limit),matching=parseLedger(await readFileIfExists(path.join(pmRoot,"improvement-ledger.json"))).observations.filter(row=>(metric===void 0||row.metric===metric)&&(options.itemId===void 0||row.item_id===options.itemId)&&(since===void 0||row.observed_at>=since)),byMetric=new Map;for(const observation of matching){const rows=byMetric.get(observation.metric)??[];rows.push(observation),byMetric.set(observation.metric,rows)}return{observations:[...matching].reverse().slice(0,limit),total:matching.length,truncated:matching.length>limit,trends:[...byMetric].map(([,observations])=>trendForMetric(observations)).sort((left,right)=>left.metric.localeCompare(right.metric)),source:"audited_workspace_singleton"}}const _testOnlyImprovementLedger={normalizeMetricName,normalizeDirection,parseLedger,parseObservationLimit,trendForMetric};export{_testOnlyImprovementLedger,readImprovementLedger,recordImprovementObservation};
|
|
3
3
|
//# sourceMappingURL=improvement-ledger.js.map
|