@unbrained/pm-cli 2026.9.7 → 2026.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/pm-developer/SKILL.md +12 -4
- package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
- package/.agents/skills/pm-extensions/SKILL.md +6 -0
- package/.agents/skills/pm-sdk/SKILL.md +11 -2
- package/.agents/skills/pm-user/SKILL.md +7 -2
- package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +231 -182
- package/dist/cli/after-command-context-usage.js +1 -48
- package/dist/cli/argv-utils.js +1 -40
- package/dist/cli/bootstrap-args.js +1 -9
- package/dist/cli/bundle-integrity.js +2 -110
- package/dist/cli/commander-usage.js +11 -771
- package/dist/cli/commands/activity.js +1 -9
- package/dist/cli/commands/aggregate.js +1 -5
- package/dist/cli/commands/append.js +1 -5
- package/dist/cli/commands/claim.js +1 -5
- package/dist/cli/commands/close-many.js +1 -5
- package/dist/cli/commands/close.js +1 -9
- package/dist/cli/commands/comments.js +1 -5
- package/dist/cli/commands/config.js +1 -9
- package/dist/cli/commands/context.js +1 -9
- package/dist/cli/commands/contracts.js +1 -5
- package/dist/cli/commands/copy.js +1 -9
- package/dist/cli/commands/create.js +1 -9
- package/dist/cli/commands/delete.js +1 -9
- package/dist/cli/commands/deps.js +1 -9
- package/dist/cli/commands/docs.js +1 -9
- package/dist/cli/commands/duplicates.js +1 -9
- package/dist/cli/commands/eval.js +1 -9
- package/dist/cli/commands/extension/describe.js +1 -5
- package/dist/cli/commands/extension/scaffold.js +1 -5
- package/dist/cli/commands/extension/shared.js +1 -5
- package/dist/cli/commands/extension.js +1 -9
- package/dist/cli/commands/files.js +1 -9
- package/dist/cli/commands/focus.js +1 -9
- package/dist/cli/commands/gc.js +1 -9
- package/dist/cli/commands/get.js +1 -9
- package/dist/cli/commands/graph.js +1 -10
- package/dist/cli/commands/health.js +1 -9
- package/dist/cli/commands/history-compact.js +1 -10
- package/dist/cli/commands/history-redact.js +1 -11
- package/dist/cli/commands/history-repair.js +1 -10
- package/dist/cli/commands/history.js +1 -5
- package/dist/cli/commands/index.js +1 -58
- package/dist/cli/commands/init-agent-guidance.js +1 -9
- package/dist/cli/commands/init.js +1 -9
- package/dist/cli/commands/learnings.js +1 -5
- package/dist/cli/commands/lifecycle-transitions.js +1 -5
- package/dist/cli/commands/list.js +1 -9
- package/dist/cli/commands/merge.js +1 -11
- package/dist/cli/commands/next.js +1 -9
- package/dist/cli/commands/notes.js +1 -5
- package/dist/cli/commands/plan.js +1 -9
- package/dist/cli/commands/profile.js +1 -9
- package/dist/cli/commands/restore.js +1 -9
- package/dist/cli/commands/scheduling-shortcuts.js +1 -9
- package/dist/cli/commands/schema.js +1 -10
- package/dist/cli/commands/search.js +1 -9
- package/dist/cli/commands/stats.js +1 -9
- package/dist/cli/commands/telemetry.js +1 -9
- package/dist/cli/commands/test-all.js +1 -9
- package/dist/cli/commands/test-runs.js +1 -9
- package/dist/cli/commands/test.js +1 -9
- package/dist/cli/commands/update-many.js +1 -5
- package/dist/cli/commands/update.js +1 -9
- package/dist/cli/commands/upgrade.js +1 -5
- package/dist/cli/commands/validate.js +1 -15
- package/dist/cli/context-intent-invocation.js +1 -20
- package/dist/cli/description-stdin.js +1 -17
- package/dist/cli/error-guidance.js +1 -1353
- package/dist/cli/extension-command-help.js +5 -636
- package/dist/cli/extension-command-options.js +1 -427
- package/dist/cli/extension-recovery.js +1 -126
- package/dist/cli/help-content.js +2 -1001
- package/dist/cli/help-json-payload.js +4 -570
- package/dist/cli/main.d.ts +4 -0
- package/dist/cli/main.js +5 -2573
- package/dist/cli/migration-gates.js +1 -289
- package/dist/cli/public.js +1 -20
- package/dist/cli/register-annotations.js +1 -270
- package/dist/cli/register-assurance.js +1 -62
- package/dist/cli/register-files-lookup.js +1 -56
- package/dist/cli/register-history-activity.d.ts +8 -0
- package/dist/cli/register-history-activity.js +2 -0
- package/dist/cli/register-history-author.js +1 -38
- package/dist/cli/register-history-maintenance.d.ts +9 -0
- package/dist/cli/register-history-maintenance.js +2 -0
- package/dist/cli/register-list-query.js +10 -943
- package/dist/cli/register-mutation-options.js +1 -9
- package/dist/cli/register-mutation.d.ts +0 -5
- package/dist/cli/register-mutation.js +19 -1893
- package/dist/cli/register-operations.js +1 -920
- package/dist/cli/register-setup.js +1 -716
- package/dist/cli/register-structured-mutation.js +1 -196
- package/dist/cli/registration-helpers.js +1 -5
- package/dist/cli/runtime-compatibility-boundary.js +4 -42
- package/dist/cli/schema-registration-helpers.js +1 -73
- package/dist/cli/search-refresh.js +1 -13
- package/dist/cli/stats-analytics-json.js +1 -68
- package/dist/cli/telemetry-flush.js +1 -10
- package/dist/cli-bundle/bundle-manifest.json +164 -156
- package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-3IPRM75M.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-4VL5P22L.js +2 -0
- package/dist/cli-bundle/chunks/chunk-AAFBV3U3.js +29 -0
- package/dist/cli-bundle/chunks/chunk-D3YVILJJ.js +20 -0
- package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-ECBLPN7B.js +3 -0
- package/dist/cli-bundle/chunks/chunk-J6ERHBV2.js +235 -0
- package/dist/cli-bundle/chunks/chunk-JUNJ5EKI.js +2 -0
- package/dist/cli-bundle/chunks/chunk-L5RCDKQ2.js +2 -0
- package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
- package/dist/cli-bundle/chunks/chunk-OHNLSGGV.js +79 -0
- package/dist/cli-bundle/chunks/chunk-WQKMSFBV.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-BAX2BYUW.js → chunk-XZ6T7YPP.js} +256 -150
- package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-Z3XVXUVF.js} +4 -4
- package/dist/cli-bundle/chunks/register-list-query-UIHRCS6D.js +11 -0
- package/dist/cli-bundle/chunks/register-mutation-WHWMGRVX.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-64YZYTC5.js +2 -0
- package/dist/cli-bundle/chunks/register-setup-PERI45EM.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-2W4XIYOB.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-2WSBXIGF.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-5FHTCOHS.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-7N6DOREF.js +26 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-7PC4R5QB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-BUCJUZVG.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-FE3BABLJ.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-IWITF53W.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-OQUGRHKV.js +10 -0
- package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-PNKIANFZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-QQQ4SAUO.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-TTYXF5YD.js +177 -0
- package/dist/cli-bundle/focused-chunks/chunk-XNR3DM6J.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-XSS3APUF.js +9 -0
- package/dist/cli-bundle/focused-chunks/chunk-YCDQ2N23.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-YJUXGS57.js +20 -0
- package/dist/cli-bundle/focused-chunks/chunk-ZTCE4UO6.js +58 -0
- package/dist/cli-bundle/main.js +20 -20
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +37 -37
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +42 -42
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +11 -11
- package/dist/cli.js +1 -104
- package/dist/core/checkpoint/checkpoint-gc.js +1 -169
- package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
- package/dist/core/config/nested-settings.js +1 -534
- package/dist/core/config/positional-value.js +1 -109
- package/dist/core/diagnostics/remediation.js +1 -506
- package/dist/core/extensions/activation-summary-markdown.js +2 -145
- package/dist/core/extensions/activation-summary.js +1 -92
- package/dist/core/extensions/activation-transaction.js +1 -46
- package/dist/core/extensions/capability-usage.js +1 -173
- package/dist/core/extensions/command-hook-context.js +1 -13
- package/dist/core/extensions/command-metadata-contract.js +1 -22
- package/dist/core/extensions/command-visibility-tier.js +1 -29
- package/dist/core/extensions/contribution-inventory.js +1 -173
- package/dist/core/extensions/exporter-output-contract.js +1 -66
- package/dist/core/extensions/extension-candidate.js +1 -18
- package/dist/core/extensions/extension-capability-aliases.js +1 -158
- package/dist/core/extensions/extension-hook-runtime.js +1 -699
- package/dist/core/extensions/extension-policy.js +1 -599
- package/dist/core/extensions/extension-registries.js +1 -62
- package/dist/core/extensions/extension-runtime-helpers.js +1 -33
- package/dist/core/extensions/extension-types.js +1 -102
- package/dist/core/extensions/flag-definition-validation.js +1 -52
- package/dist/core/extensions/flag-value-types.js +1 -64
- package/dist/core/extensions/index.js +1 -526
- package/dist/core/extensions/item-field-types.js +1 -39
- package/dist/core/extensions/item-fields.js +1 -261
- package/dist/core/extensions/loader.js +1 -2223
- package/dist/core/extensions/manifest-schema.js +1 -69
- package/dist/core/extensions/module-graph-snapshot.js +1 -33
- package/dist/core/extensions/preflight-ownership.js +1 -41
- package/dist/core/extensions/registration-validation.js +1 -82
- package/dist/core/extensions/registration-values.js +1 -209
- package/dist/core/extensions/reserved-host-flags.js +1 -36
- package/dist/core/extensions/runtime-registrations.js +1 -67
- package/dist/core/extensions/service-ownership.js +1 -19
- package/dist/core/extensions/version-compat.js +1 -216
- package/dist/core/fs/fs-utils.js +2 -158
- package/dist/core/fs/host-environment-errors.js +1 -141
- package/dist/core/fs/index.js +1 -9
- package/dist/core/fs/path-utils.js +1 -17
- package/dist/core/governance/content-fields.js +1 -160
- package/dist/core/governance/issue-codes.js +1 -151
- package/dist/core/governance/metadata-coverage.js +1 -358
- package/dist/core/history/drift-cache.js +3 -72
- package/dist/core/history/drift-scan.js +1 -342
- package/dist/core/history/event-classification.js +1 -109
- package/dist/core/history/event-index.js +8 -784
- package/dist/core/history/history-compact-bulk.js +1 -104
- package/dist/core/history/history-diff.js +1 -158
- package/dist/core/history/history-rewrite.d.ts +6 -1
- package/dist/core/history/history-rewrite.js +1 -107
- package/dist/core/history/history-storage-stats.js +1 -102
- package/dist/core/history/history-stream-policy.js +1 -62
- package/dist/core/history/history.js +2 -617
- package/dist/core/history/identity.js +1 -30
- package/dist/core/history/index.js +1 -9
- package/dist/core/history/projection.js +1 -196
- package/dist/core/history/read.d.ts +9 -0
- package/dist/core/history/read.js +1 -57
- package/dist/core/history/replay.js +2 -439
- package/dist/core/history/version-address.js +1 -32
- package/dist/core/history/workspace-history.js +2 -433
- package/dist/core/io/body-file.js +1 -62
- package/dist/core/io/bulk-ids-input.js +1 -112
- package/dist/core/item/actionability.js +1 -327
- package/dist/core/item/dependency-reference.js +1 -20
- package/dist/core/item/id.js +1 -112
- package/dist/core/item/index.js +1 -12
- package/dist/core/item/item-format-version.js +1 -78
- package/dist/core/item/item-format.js +5 -1473
- package/dist/core/item/item-record.js +1 -23
- package/dist/core/item/item-type-definition.js +1 -133
- package/dist/core/item/parent-reference-policy.js +1 -57
- package/dist/core/item/parse.js +2 -603
- package/dist/core/item/plan-lifecycle.js +1 -19
- package/dist/core/item/priority.js +1 -61
- package/dist/core/item/sprint-release-format.js +1 -38
- package/dist/core/item/status-filter.js +1 -115
- package/dist/core/item/status.js +1 -43
- package/dist/core/item/toon-decode.js +1 -29
- package/dist/core/item/type-registry.js +1 -715
- package/dist/core/item/type-synonyms.js +1 -38
- package/dist/core/lock/index.js +1 -9
- package/dist/core/lock/lock-gc.js +1 -240
- package/dist/core/lock/lock.js +3 -590
- package/dist/core/output/mutation-projection.js +1 -217
- package/dist/core/output/output-control.js +1 -25
- package/dist/core/output/output.js +11 -494
- package/dist/core/output/query-summary.js +1 -58
- package/dist/core/output/tabular.js +1 -77
- package/dist/core/packages/manifest.js +1 -244
- package/dist/core/packages/root.js +1 -84
- package/dist/core/policy/workflow-policy-schema.d.ts +312 -0
- package/dist/core/policy/workflow-policy-schema.js +2 -0
- package/dist/core/policy/workflow-policy-store.d.ts +24 -0
- package/dist/core/policy/workflow-policy-store.js +2 -0
- package/dist/core/policy/workflow-policy.d.ts +139 -0
- package/dist/core/policy/workflow-policy.js +2 -0
- package/dist/core/profile/profile-describe.js +1 -83
- package/dist/core/profile/profile-lint.js +1 -415
- package/dist/core/profile/profile-plan.js +0 -0
- package/dist/core/profile/profile-presets.js +1 -370
- package/dist/core/reproducibility/context.js +1 -82
- package/dist/core/schema/fields-file.js +2 -288
- package/dist/core/schema/item-types-file.js +2 -296
- package/dist/core/schema/runtime-field-filters.js +1 -49
- package/dist/core/schema/runtime-field-values.js +1 -313
- package/dist/core/schema/runtime-schema.js +2 -826
- package/dist/core/schema/status-defs-file.js +2 -227
- package/dist/core/schema/status-token.js +1 -31
- package/dist/core/schema/type-inference.js +1 -95
- package/dist/core/schema/type-presets.js +1 -87
- package/dist/core/schema/type-workflows.js +1 -104
- package/dist/core/search/background-refresh.js +2 -286
- package/dist/core/search/bm25.js +1 -146
- package/dist/core/search/cache.js +2 -534
- package/dist/core/search/corpus.js +1 -311
- package/dist/core/search/embedding-batches.js +1 -163
- package/dist/core/search/eval.js +1 -225
- package/dist/core/search/http-client.js +1 -75
- package/dist/core/search/providers.js +1 -242
- package/dist/core/search/relevance.js +1 -244
- package/dist/core/search/semantic-defaults.js +1 -199
- package/dist/core/search/staleness.js +1 -30
- package/dist/core/search/vector-stores.js +2 -664
- package/dist/core/search/vectorization-metadata.js +1 -81
- package/dist/core/sentry/helpers.js +1 -272
- package/dist/core/sentry/instrument.js +1 -387
- package/dist/core/session/session-state.js +1 -260
- package/dist/core/shared/agent-session-context.js +1 -133
- package/dist/core/shared/author.js +1 -1172
- package/dist/core/shared/command-types.js +1 -4
- package/dist/core/shared/conflict-markers.js +1 -31
- package/dist/core/shared/constants.js +1 -405
- package/dist/core/shared/errors.js +1 -20
- package/dist/core/shared/html-entity-decode.js +1 -131
- package/dist/core/shared/index.js +1 -12
- package/dist/core/shared/item-metadata-contract.js +1 -89
- package/dist/core/shared/lazy-module.js +1 -16
- package/dist/core/shared/levenshtein.js +1 -61
- package/dist/core/shared/memo.js +1 -19
- package/dist/core/shared/numeric-parsers.js +1 -20
- package/dist/core/shared/option-alias-visibility.js +1 -67
- package/dist/core/shared/primitives.js +1 -127
- package/dist/core/shared/serial-queue.js +1 -79
- package/dist/core/shared/serialization.js +1 -210
- package/dist/core/shared/split-comma-list.js +1 -30
- package/dist/core/shared/text-normalization.js +1 -38
- package/dist/core/shared/time.js +1 -306
- package/dist/core/store/index.js +1 -12
- package/dist/core/store/item-format-migration.js +1 -125
- package/dist/core/store/item-metadata-cache.js +1 -1116
- package/dist/core/store/item-metadata-query-index.js +9 -394
- package/dist/core/store/item-metadata-read-work.js +1 -43
- package/dist/core/store/item-store.js +1 -693
- package/dist/core/store/paths.d.ts +1 -1
- package/dist/core/store/paths.js +1 -214
- package/dist/core/store/settings-read-cache.js +1 -85
- package/dist/core/store/settings-validator.d.ts +1 -0
- package/dist/core/store/settings-validator.js +1 -421
- package/dist/core/store/settings.js +3 -1309
- package/dist/core/store/tracker-preflight.js +1 -141
- package/dist/core/telemetry/consent.js +5 -108
- package/dist/core/telemetry/observability.js +1 -246
- package/dist/core/telemetry/runtime.js +4 -1988
- package/dist/core/test/background-runs.js +4 -945
- package/dist/core/test/item-test-run-tracking.js +1 -63
- package/dist/core/test/run-selectors.js +1 -120
- package/dist/core/validate/estimate-defaults.js +1 -89
- package/dist/core/validate/fix-planning.js +1 -189
- package/dist/core/validate/linked-artifact-reference.js +1 -36
- package/dist/core/validate/missing-by-type.js +1 -34
- package/dist/core/validate/missing-link-owners.js +1 -95
- package/dist/core/validate/stale-file-classification.js +1 -82
- package/dist/mcp/http-server.js +5 -448
- package/dist/mcp/legacy-adapter.js +1 -77
- package/dist/mcp/runtime-capabilities.js +1 -200
- package/dist/mcp/server.js +4 -1233
- package/dist/mcp/tool-definitions.js +1 -804
- package/dist/sdk/actionability.js +1 -13
- package/dist/sdk/agent/closed-domain-contracts.js +1 -161
- package/dist/sdk/agent/command-recovery.js +1 -59
- package/dist/sdk/agent/command-suggestions.js +1 -66
- package/dist/sdk/agent/create-option-policy.js +1 -31
- package/dist/sdk/agent/identity-config.js +1 -106
- package/dist/sdk/agent/item-addressing.js +1 -207
- package/dist/sdk/agent/refusal-closure-census.js +1 -151
- package/dist/sdk/agent/refusal-closure.js +1 -133
- package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
- package/dist/sdk/agent/refusal-reachability.js +1 -593
- package/dist/sdk/agent/subcommand-recovery.js +1 -83
- package/dist/sdk/agent/task-transcript-contracts.js +1 -197
- package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
- package/dist/sdk/agent-capability-contracts.js +1 -428
- package/dist/sdk/agent-session-context.js +1 -9
- package/dist/sdk/annotations.js +1 -448
- package/dist/sdk/author-attribution.js +1 -468
- package/dist/sdk/authoring.js +1 -20
- package/dist/sdk/cli-bootstrap.js +1 -838
- package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
- package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
- package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
- package/dist/sdk/cli-contracts/command-aliases.js +1 -107
- package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
- package/dist/sdk/cli-contracts/commander-types.js +1 -159
- package/dist/sdk/cli-contracts/completeness.js +1 -393
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
- package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
- package/dist/sdk/cli-contracts/string-lists.js +1 -16
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
- package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
- package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +1 -17
- package/dist/sdk/cli-program.js +1 -49
- package/dist/sdk/command-line.d.ts +2 -5
- package/dist/sdk/command-line.js +1 -78
- package/dist/sdk/comments.js +1 -133
- package/dist/sdk/compile-cache.js +1 -73
- package/dist/sdk/completion.js +174 -839
- package/dist/sdk/compose.js +1 -1090
- package/dist/sdk/config.js +1 -1204
- package/dist/sdk/context/recency.js +1 -33
- package/dist/sdk/context/semantic-session-attribution.js +1 -82
- package/dist/sdk/context/usage-egress.js +1 -29
- package/dist/sdk/context/usage-ledger.js +3 -185
- package/dist/sdk/context-intent-contracts.js +1 -709
- package/dist/sdk/context-intent-runtime.js +1 -115
- package/dist/sdk/context-packing.js +1 -218
- package/dist/sdk/context-relevance.js +1 -503
- package/dist/sdk/context-signal-store.js +2 -426
- package/dist/sdk/context-usage.js +1 -367
- package/dist/sdk/contracts.js +1 -23
- package/dist/sdk/core-governance.js +1 -14
- package/dist/sdk/core.js +1 -14
- package/dist/sdk/corpus-shape.js +1 -401
- package/dist/sdk/define.js +1 -220
- package/dist/sdk/dependencies.js +1 -718
- package/dist/sdk/dependency-flag-validation.js +1 -156
- package/dist/sdk/dependency-provenance.js +1 -135
- package/dist/sdk/docs.js +1 -14
- package/dist/sdk/duplicates.js +1 -40
- package/dist/sdk/environment/agent-environment.js +1 -466
- package/dist/sdk/environment/host-environment-errors.js +1 -8
- package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
- package/dist/sdk/environment/source-context.js +1 -28
- package/dist/sdk/environment/tracker-preflight.js +1 -9
- package/dist/sdk/error-code-catalog.js +1 -153
- package/dist/sdk/error-runtime.js +1 -58
- package/dist/sdk/errors.js +1 -58
- package/dist/sdk/eval.js +1 -190
- package/dist/sdk/extension/author-manifest.js +1 -92
- package/dist/sdk/extension/bundled-catalog.js +1 -332
- package/dist/sdk/extension/concurrency.js +1 -25
- package/dist/sdk/extension/copy-scope.d.ts +2 -0
- package/dist/sdk/extension/copy-scope.js +2 -0
- package/dist/sdk/extension/custom-field-collisions.js +1 -30
- package/dist/sdk/extension/describe.js +3 -189
- package/dist/sdk/extension/doctor.js +1 -606
- package/dist/sdk/extension/install-plan.d.ts +69 -0
- package/dist/sdk/extension/install-plan.js +2 -0
- package/dist/sdk/extension/install-receipts.d.ts +7 -0
- package/dist/sdk/extension/install-receipts.js +2 -0
- package/dist/sdk/extension/install-runtime.js +3 -313
- package/dist/sdk/extension/install-snapshot.js +1 -66
- package/dist/sdk/extension/install-sources.js +5 -1057
- package/dist/sdk/extension/managed-state.js +2 -252
- package/dist/sdk/extension/migrations.js +2 -174
- package/dist/sdk/extension/output-ownership.js +1 -25
- package/dist/sdk/extension/runtime-summary.js +1 -18
- package/dist/sdk/extension/scaffold.js +4 -2308
- package/dist/sdk/extension/shared.js +1 -147
- package/dist/sdk/extension/source-resolution.js +1 -65
- package/dist/sdk/extension/update-check.js +1 -67
- package/dist/sdk/extension-command-context.js +1 -44
- package/dist/sdk/extension-contracts.js +1 -73
- package/dist/sdk/extension.d.ts +7 -2
- package/dist/sdk/extension.js +1 -2196
- package/dist/sdk/files.js +1 -535
- package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
- package/dist/sdk/flag-invocation-contracts.js +1 -344
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
- package/dist/sdk/generated-error-code-catalog.js +1 -16
- package/dist/sdk/governance/assurance-action-contracts.js +1 -4
- package/dist/sdk/governance/assurance-action.js +1 -411
- package/dist/sdk/governance/assurance-limits.js +1 -10
- package/dist/sdk/governance/assurance-mutation-error.js +1 -81
- package/dist/sdk/governance/assurance-presets.js +1 -135
- package/dist/sdk/governance/assurance-runtime.js +1 -238
- package/dist/sdk/governance/assurance.js +4 -1182
- package/dist/sdk/governance/boundary-fixtures.js +1 -200
- package/dist/sdk/governance/coverage-assurance.js +1 -60
- package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
- package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
- package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
- package/dist/sdk/governance/defect-recurrence.js +1 -623
- package/dist/sdk/governance/extension-host-version.js +1 -115
- package/dist/sdk/governance/gc.js +1 -368
- package/dist/sdk/governance/health.js +1 -2367
- package/dist/sdk/governance/hierarchy-validation.js +1 -108
- package/dist/sdk/governance/linked-file-report.js +1 -71
- package/dist/sdk/governance/merge-receipt-history.js +1 -206
- package/dist/sdk/governance/provenance-health.js +1 -282
- package/dist/sdk/governance/reindex.js +4 -761
- package/dist/sdk/governance/stale-work.js +1 -82
- package/dist/sdk/governance/status-role-diagnostics.js +1 -35
- package/dist/sdk/governance/storage-integrity.js +1 -280
- package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
- package/dist/sdk/governance/upgrade.js +2 -327
- package/dist/sdk/governance/validate-history-drift.js +1 -81
- package/dist/sdk/governance/validate-item-reader.js +1 -17
- package/dist/sdk/governance/validate-normalization.js +1 -36
- package/dist/sdk/governance/validate.d.ts +3 -1
- package/dist/sdk/governance/validate.js +1 -2261
- package/dist/sdk/governance/workflow-completeness.d.ts +32 -0
- package/dist/sdk/governance/workflow-completeness.js +2 -0
- package/dist/sdk/governance/workflow-policy.d.ts +47 -0
- package/dist/sdk/governance/workflow-policy.js +4 -0
- package/dist/sdk/governance/workspace-position.js +1 -163
- package/dist/sdk/governance.d.ts +2 -0
- package/dist/sdk/governance.js +1 -31
- package/dist/sdk/graph/adapter.js +1 -181
- package/dist/sdk/graph/analytics.js +1 -474
- package/dist/sdk/graph/assembly.js +1 -377
- package/dist/sdk/graph/cache.js +1 -160
- package/dist/sdk/graph/centrality.js +1 -258
- package/dist/sdk/graph/conformance.js +1 -130
- package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
- package/dist/sdk/graph/deadline-scheduling.js +2 -0
- package/dist/sdk/graph/durable-cache.d.ts +1 -1
- package/dist/sdk/graph/durable-cache.js +1 -361
- package/dist/sdk/graph/governance-contracts.js +1 -34
- package/dist/sdk/graph/governance.d.ts +13 -1
- package/dist/sdk/graph/governance.js +1 -735
- package/dist/sdk/graph/hierarchy-integrity.js +1 -310
- package/dist/sdk/graph/index.d.ts +3 -2
- package/dist/sdk/graph/index.js +1 -26
- package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
- package/dist/sdk/graph/lifecycle-coverage.js +2 -0
- package/dist/sdk/graph/mutation-advisory.js +1 -176
- package/dist/sdk/graph/remediation.js +1 -197
- package/dist/sdk/graph/run.d.ts +15 -1
- package/dist/sdk/graph/run.js +1 -768
- package/dist/sdk/graph/scheduling.js +1 -124
- package/dist/sdk/graph/traversal.js +1 -284
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
- package/dist/sdk/graph.js +1 -15
- package/dist/sdk/guide-topics.js +1 -707
- package/dist/sdk/guide.js +1 -279
- package/dist/sdk/history/maintenance.d.ts +71 -0
- package/dist/sdk/history/maintenance.js +2 -0
- package/dist/sdk/history/salvage.js +2 -247
- package/dist/sdk/history/subject.d.ts +19 -0
- package/dist/sdk/history/subject.js +2 -0
- package/dist/sdk/history-analytics.js +1 -282
- package/dist/sdk/history-compact.js +1 -527
- package/dist/sdk/history-mcp.js +1 -68
- package/dist/sdk/history-provenance.js +1 -182
- package/dist/sdk/history-read.js +1 -96
- package/dist/sdk/history-redact.d.ts +1 -14
- package/dist/sdk/history-redact.js +1 -643
- package/dist/sdk/history-repair.d.ts +5 -0
- package/dist/sdk/history-repair.js +1 -657
- package/dist/sdk/improvement-ledger-validation.js +1 -62
- package/dist/sdk/improvement-ledger.js +2 -257
- package/dist/sdk/index.d.ts +4 -1
- package/dist/sdk/index.js +1 -183
- package/dist/sdk/init-agent-guidance.js +2 -496
- package/dist/sdk/init.js +2 -820
- package/dist/sdk/invocation-author.js +1 -39
- package/dist/sdk/item-children.js +1 -90
- package/dist/sdk/item-metadata-index.js +1 -15
- package/dist/sdk/item-schedule.js +1 -27
- package/dist/sdk/item-transaction.js +1 -396
- package/dist/sdk/learnings.js +1 -29
- package/dist/sdk/lifecycle/append.js +2 -53
- package/dist/sdk/lifecycle/claim.d.ts +2 -0
- package/dist/sdk/lifecycle/claim.js +1 -242
- package/dist/sdk/lifecycle/close-many.js +1 -438
- package/dist/sdk/lifecycle/close.js +1 -468
- package/dist/sdk/lifecycle/copy.js +1 -212
- package/dist/sdk/lifecycle/create.js +1 -1949
- package/dist/sdk/lifecycle/delete.js +1 -45
- package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
- package/dist/sdk/lifecycle/focus.js +1 -91
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
- package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
- package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
- package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
- package/dist/sdk/lifecycle/mcp-actions.js +1 -51
- package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
- package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
- package/dist/sdk/lifecycle/plan.js +1 -1606
- package/dist/sdk/lifecycle/recurrence-parsers.d.ts +1 -1
- package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
- package/dist/sdk/lifecycle/reopen.js +1 -68
- package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
- package/dist/sdk/lifecycle/restore.d.ts +1 -0
- package/dist/sdk/lifecycle/restore.js +1 -330
- package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
- package/dist/sdk/lifecycle/update-many.js +1 -861
- package/dist/sdk/lifecycle/update.js +1 -2136
- package/dist/sdk/lifecycle-completion.js +1 -92
- package/dist/sdk/lifecycle-policy.js +1 -120
- package/dist/sdk/linked-artifacts.js +1 -530
- package/dist/sdk/mcp/apps.js +4 -133
- package/dist/sdk/mcp/authorization.js +1 -404
- package/dist/sdk/mcp/discovery.js +1 -494
- package/dist/sdk/mcp/interactions.js +1 -336
- package/dist/sdk/mcp/protocol.d.ts +7 -0
- package/dist/sdk/mcp/protocol.js +1 -184
- package/dist/sdk/mcp/skills.js +1 -389
- package/dist/sdk/mcp/subscriptions.js +1 -211
- package/dist/sdk/mcp/tasks.js +2 -430
- package/dist/sdk/mcp/transport.js +1 -260
- package/dist/sdk/merge/abandoned-receipts.js +1 -46
- package/dist/sdk/merge/driver.js +1 -212
- package/dist/sdk/merge/index.js +1 -16
- package/dist/sdk/merge/install.js +3 -561
- package/dist/sdk/merge/receipt-file-boundary.js +1 -46
- package/dist/sdk/merge/receipt-operation.js +1 -96
- package/dist/sdk/merge/receipt-schema.js +1 -397
- package/dist/sdk/merge/receipts.js +4 -525
- package/dist/sdk/merge/reconcile.js +1 -352
- package/dist/sdk/merge/three-way.js +3 -775
- package/dist/sdk/merge.js +1 -10
- package/dist/sdk/mutation-events.js +1 -292
- package/dist/sdk/mutation-guard.js +1 -216
- package/dist/sdk/notes.js +1 -139
- package/dist/sdk/output-contracts.js +1 -172
- package/dist/sdk/output-projection.js +1 -430
- package/dist/sdk/output-token-accounting.js +1 -140
- package/dist/sdk/output.js +1 -64
- package/dist/sdk/ownership-source.js +1 -21
- package/dist/sdk/package-import-adapters.js +1 -442
- package/dist/sdk/package-migrations.js +1 -20
- package/dist/sdk/package-runtime-options.js +1 -80
- package/dist/sdk/pagination.js +1 -162
- package/dist/sdk/profile.js +1 -454
- package/dist/sdk/provenance.js +1 -258
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/activity.js +1 -401
- package/dist/sdk/query/aggregate.d.ts +16 -0
- package/dist/sdk/query/aggregate.js +1 -390
- package/dist/sdk/query/calendar.js +1 -964
- package/dist/sdk/query/complete-list.js +1 -215
- package/dist/sdk/query/context.js +1 -1702
- package/dist/sdk/query/duplicate-candidates.js +1 -70
- package/dist/sdk/query/get.js +1 -450
- package/dist/sdk/query/history.js +1 -186
- package/dist/sdk/query/item-filter-options.js +1 -9
- package/dist/sdk/query/light-metadata.js +1 -18
- package/dist/sdk/query/list-filter-shared.js +1 -81
- package/dist/sdk/query/list.js +1 -1304
- package/dist/sdk/query/multi-value-filters.js +1 -78
- package/dist/sdk/query/next.js +1 -513
- package/dist/sdk/query/parsers.js +1 -44
- package/dist/sdk/query/projection-contracts.js +1 -184
- package/dist/sdk/query/search-contracts.d.ts +27 -0
- package/dist/sdk/query/search-contracts.js +1 -230
- package/dist/sdk/query/search-pagination.js +1 -35
- package/dist/sdk/query/search-rendering.js +1 -105
- package/dist/sdk/query/search.d.ts +6 -4
- package/dist/sdk/query/search.js +2 -1987
- package/dist/sdk/query.js +1 -35
- package/dist/sdk/read-output/continuation.js +1 -194
- package/dist/sdk/read-output-budget.js +1 -135
- package/dist/sdk/read-output-contracts.d.ts +1 -1
- package/dist/sdk/read-output-contracts.js +1 -1225
- package/dist/sdk/read-output-rows.js +1 -186
- package/dist/sdk/read-output-session.js +1 -208
- package/dist/sdk/relationship-analytics.js +1 -410
- package/dist/sdk/relationship-context.js +1 -284
- package/dist/sdk/relationship-history.js +4 -519
- package/dist/sdk/relationship-kinds/contract.js +1 -22
- package/dist/sdk/relationship-migration.js +1 -77
- package/dist/sdk/relationships.js +1 -579
- package/dist/sdk/reproducibility/process.js +1 -87
- package/dist/sdk/runtime-action-aliases.js +1 -59
- package/dist/sdk/runtime-extended-actions.js +1 -177
- package/dist/sdk/runtime-input.js +1 -614
- package/dist/sdk/runtime-primitives.js +1 -84
- package/dist/sdk/runtime-public-contracts.d.ts +2 -1
- package/dist/sdk/runtime-public-contracts.js +1 -4
- package/dist/sdk/runtime-stats-options.js +1 -38
- package/dist/sdk/runtime.d.ts +4 -0
- package/dist/sdk/runtime.js +1 -1928
- package/dist/sdk/scheduling-shortcuts.js +1 -63
- package/dist/sdk/schema-migration.js +3 -856
- package/dist/sdk/schema.d.ts +2 -1
- package/dist/sdk/schema.js +1 -1376
- package/dist/sdk/search-refresh-worker.js +1 -18
- package/dist/sdk/similarity-scoring.js +1 -53
- package/dist/sdk/similarity.js +1 -326
- package/dist/sdk/start-task-status.js +1 -14
- package/dist/sdk/stats.js +1 -270
- package/dist/sdk/structured-mutations.js +1 -580
- package/dist/sdk/telemetry-flush.js +1 -13
- package/dist/sdk/telemetry.js +1 -405
- package/dist/sdk/templates.js +2 -292
- package/dist/sdk/test/batch.js +2 -509
- package/dist/sdk/test/entry.js +1 -70
- package/dist/sdk/test/execution.js +6 -2211
- package/dist/sdk/test/linked-command-detection.js +1 -546
- package/dist/sdk/test/measurements.js +1 -91
- package/dist/sdk/test/parsers.js +1 -545
- package/dist/sdk/test/runs.js +1 -193
- package/dist/sdk/test/trust.js +2 -206
- package/dist/sdk/testing.js +4 -1391
- package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
- package/dist/sdk/traceability/source-traceability.js +1 -292
- package/dist/sdk/tracker-root-discovery.js +1 -9
- package/dist/sdk/workspace-contracts-cache.js +1 -28
- package/dist/sdk/workspace-contracts.js +1 -33
- package/dist/sdk/workspace-memory.js +2 -318
- package/dist/sdk/workspace-recipe.js +1 -71
- package/dist/sdk/workspace-snapshot.js +4 -613
- package/dist/sdk/workspace-transaction-gc.js +1 -149
- package/dist/sdk/workspace-transaction.js +2 -363
- package/dist/sdk/workspace.js +3 -127
- package/dist/types/index.js +1 -9
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -245
- package/docs/AGENT_GUIDE.md +1 -1
- package/docs/COMMANDS.md +10 -0
- package/docs/CONFIGURATION.md +12 -1
- package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
- package/docs/EXTENSIONS.md +1 -0
- package/docs/HISTORY_MAINTENANCE.md +125 -0
- package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
- package/docs/PACKAGE_EVIDENCE.md +92 -0
- package/docs/PLANNING_MEASUREMENTS.md +183 -0
- package/docs/README.md +4 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +5 -0
- package/docs/SCRIPTING.md +21 -0
- package/docs/TESTING.md +33 -0
- package/docs/WORKFLOW_POLICIES.md +129 -0
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +7 -7
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -5
- package/marketplace.json +2 -2
- package/package.json +5 -5
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/finalize-build.mjs +45 -3
- package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
- package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
- package/dist/cli-bundle/chunks/chunk-JX4DH4WC.js +0 -3
- package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
- package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
- package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
- package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
- package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
- package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
- package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +0 -2
- package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
- package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
- package/dist/cli-bundle/focused-chunks/chunk-PEFABF7E.js +0 -26
- package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
- package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
|
@@ -1,150 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* @module sdk/workspace-transaction-gc
|
|
3
|
-
*
|
|
4
|
-
* Age-based garbage collector for the durable SDK workspace-transaction
|
|
5
|
-
* journals written by `commitWorkspaceTransaction` under
|
|
6
|
-
* `transactions/sdk/<transactionId>.json`. Only terminal journals (status
|
|
7
|
-
* `committed` or `compensated`) older than the configured retention are
|
|
8
|
-
* pruned; in-flight journals (`applying`/`compensating`) are crash-recovery
|
|
9
|
-
* state and are always retained, as are journals whose status or timestamp
|
|
10
|
-
* cannot be read (safety-first, mirroring the checkpoint and stale-lock
|
|
11
|
-
* sweeps). Transaction steps are contract-idempotent, so pruning a terminal
|
|
12
|
-
* receipt only costs the ability to short-circuit an identical replay — it
|
|
13
|
-
* never breaks correctness.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
!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]="7df80849-51e1-5efa-b40a-b44088f941a9")}catch(e){}}();
|
|
17
|
-
import { isFileMissingError } from "../core/fs/fs-utils.js";
|
|
18
|
-
import fs from "node:fs/promises";
|
|
19
|
-
import path from "node:path";
|
|
20
|
-
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
21
|
-
const TERMINAL_JOURNAL_STATUSES = new Set(["committed", "compensated"]);
|
|
22
|
-
function readJournalStatusAndTimestamp(raw) {
|
|
23
|
-
let parsed;
|
|
24
|
-
try {
|
|
25
|
-
parsed = JSON.parse(raw);
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
return { status: null, updatedAt: null };
|
|
29
|
-
}
|
|
30
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
31
|
-
return { status: null, updatedAt: null };
|
|
32
|
-
}
|
|
33
|
-
const record = parsed;
|
|
34
|
-
return {
|
|
35
|
-
status: typeof record.status === "string" ? record.status : null,
|
|
36
|
-
updatedAt: typeof record.updatedAt === "string" ? record.updatedAt : null,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function classifyWorkspaceTransactionJournal(file, status, updatedAt, nowMs, retentionMs) {
|
|
40
|
-
const updatedAtMs = updatedAt === null ? Number.NaN : Date.parse(updatedAt);
|
|
41
|
-
if (status === null || !Number.isFinite(updatedAtMs)) {
|
|
42
|
-
return {
|
|
43
|
-
entry: {
|
|
44
|
-
file,
|
|
45
|
-
status,
|
|
46
|
-
age_seconds: null,
|
|
47
|
-
stale: false,
|
|
48
|
-
reason: "unparseable",
|
|
49
|
-
},
|
|
50
|
-
remove: false,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const ageMs = nowMs - updatedAtMs;
|
|
54
|
-
if (!TERMINAL_JOURNAL_STATUSES.has(status)) {
|
|
55
|
-
return {
|
|
56
|
-
entry: {
|
|
57
|
-
file,
|
|
58
|
-
status,
|
|
59
|
-
age_seconds: Math.floor(ageMs / 1000),
|
|
60
|
-
stale: false,
|
|
61
|
-
reason: "active",
|
|
62
|
-
},
|
|
63
|
-
remove: false,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
// A non-finite retentionMs makes this comparison false, disabling pruning
|
|
67
|
-
// rather than risking deletion under bad input.
|
|
68
|
-
if (!(ageMs > retentionMs)) {
|
|
69
|
-
return {
|
|
70
|
-
entry: {
|
|
71
|
-
file,
|
|
72
|
-
status,
|
|
73
|
-
age_seconds: Math.floor(ageMs / 1000),
|
|
74
|
-
stale: false,
|
|
75
|
-
reason: "fresh",
|
|
76
|
-
},
|
|
77
|
-
remove: false,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
return {
|
|
81
|
-
entry: {
|
|
82
|
-
file,
|
|
83
|
-
status,
|
|
84
|
-
age_seconds: Math.floor(ageMs / 1000),
|
|
85
|
-
stale: true,
|
|
86
|
-
},
|
|
87
|
-
remove: true,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
async function processWorkspaceTransactionJournal(absolutePath, relativePath, fileName, options) {
|
|
91
|
-
const warnings = options.hooks?.onRead
|
|
92
|
-
? await options.hooks.onRead(absolutePath)
|
|
93
|
-
: [];
|
|
94
|
-
const journal = readJournalStatusAndTimestamp(await fs.readFile(absolutePath, "utf8"));
|
|
95
|
-
const decision = classifyWorkspaceTransactionJournal(relativePath, journal.status, journal.updatedAt, options.nowMs, options.retentionMs);
|
|
96
|
-
if (decision.entry.reason === "unparseable") {
|
|
97
|
-
warnings.push(`transaction_journal_unparseable:${fileName}`);
|
|
98
|
-
}
|
|
99
|
-
if (decision.remove && !options.dryRun) {
|
|
100
|
-
await fs.rm(absolutePath, { force: true });
|
|
101
|
-
if (options.hooks?.onWrite) {
|
|
102
|
-
warnings.push(...(await options.hooks.onWrite(absolutePath)));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return { decision, warnings };
|
|
106
|
-
}
|
|
107
|
-
/** Sweep `transactions/sdk/` and prune terminal workspace-transaction journals older than the retention window. One decision row is reported per journal so `pm gc` output stays auditable. */
|
|
108
|
-
export async function runWorkspaceTransactionGc(pmRoot, options) {
|
|
109
|
-
const { dryRun, hooks } = options;
|
|
110
|
-
const nowMs = options.now ?? Date.now();
|
|
111
|
-
const retentionMs = Math.max(0, options.retentionDays) * MILLISECONDS_PER_DAY;
|
|
112
|
-
const journalsDir = path.join(pmRoot, "transactions", "sdk");
|
|
113
|
-
const result = {
|
|
114
|
-
scanned: 0,
|
|
115
|
-
removed: [],
|
|
116
|
-
retained: [],
|
|
117
|
-
warnings: [],
|
|
118
|
-
entries: [],
|
|
119
|
-
};
|
|
120
|
-
let files;
|
|
121
|
-
try {
|
|
122
|
-
files = (await fs.readdir(journalsDir))
|
|
123
|
-
.filter((file) => file.endsWith(".json"))
|
|
124
|
-
.sort((left, right) => left.localeCompare(right));
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
if (isFileMissingError(error)) {
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
throw error;
|
|
131
|
-
}
|
|
132
|
-
for (const file of files) {
|
|
133
|
-
const absPath = path.join(journalsDir, file);
|
|
134
|
-
const relPath = `transactions/sdk/${file}`;
|
|
135
|
-
const fileResult = await processWorkspaceTransactionJournal(absPath, relPath, file, { dryRun, hooks, nowMs, retentionMs });
|
|
136
|
-
result.warnings.push(...fileResult.warnings);
|
|
137
|
-
result.scanned += 1;
|
|
138
|
-
const { decision } = fileResult;
|
|
139
|
-
if (!decision.remove) {
|
|
140
|
-
result.retained.push(relPath);
|
|
141
|
-
result.entries.push(decision.entry);
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
result.removed.push(relPath);
|
|
145
|
-
result.entries.push(decision.entry);
|
|
146
|
-
}
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
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]="9189cea6-950f-5594-9321-b7590171297c")}catch(e2){}})();import{isFileMissingError}from"../core/fs/fs-utils.js";import fs from"node:fs/promises";import path from"node:path";const MILLISECONDS_PER_DAY=24*60*60*1e3;const TERMINAL_JOURNAL_STATUSES=new Set(["committed","compensated"]);function readJournalStatusAndTimestamp(raw){let parsed;try{parsed=JSON.parse(raw)}catch{return{status:null,updatedAt:null}}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){return{status:null,updatedAt:null}}const record=parsed;return{status:typeof record.status==="string"?record.status:null,updatedAt:typeof record.updatedAt==="string"?record.updatedAt:null}}function classifyWorkspaceTransactionJournal(file,status,updatedAt,nowMs,retentionMs){const updatedAtMs=updatedAt===null?Number.NaN:Date.parse(updatedAt);if(status===null||!Number.isFinite(updatedAtMs)){return{entry:{file,status,age_seconds:null,stale:false,reason:"unparseable"},remove:false}}const ageMs=nowMs-updatedAtMs;if(!TERMINAL_JOURNAL_STATUSES.has(status)){return{entry:{file,status,age_seconds:Math.floor(ageMs/1e3),stale:false,reason:"active"},remove:false}}if(!(ageMs>retentionMs)){return{entry:{file,status,age_seconds:Math.floor(ageMs/1e3),stale:false,reason:"fresh"},remove:false}}return{entry:{file,status,age_seconds:Math.floor(ageMs/1e3),stale:true},remove:true}}async function processWorkspaceTransactionJournal(absolutePath,relativePath,fileName,options){const warnings=options.hooks?.onRead?await options.hooks.onRead(absolutePath):[];const journal=readJournalStatusAndTimestamp(await fs.readFile(absolutePath,"utf8"));const decision=classifyWorkspaceTransactionJournal(relativePath,journal.status,journal.updatedAt,options.nowMs,options.retentionMs);if(decision.entry.reason==="unparseable"){warnings.push(`transaction_journal_unparseable:${fileName}`)}if(decision.remove&&!options.dryRun){await fs.rm(absolutePath,{force:true});if(options.hooks?.onWrite){warnings.push(...await options.hooks.onWrite(absolutePath))}}return{decision,warnings}}async function runWorkspaceTransactionGc(pmRoot,options){const{dryRun,hooks}=options;const nowMs=options.now??Date.now();const retentionMs=Math.max(0,options.retentionDays)*MILLISECONDS_PER_DAY;const journalsDir=path.join(pmRoot,"transactions","sdk");const result={scanned:0,removed:[],retained:[],warnings:[],entries:[]};let files;try{files=(await fs.readdir(journalsDir)).filter(file=>file.endsWith(".json")).sort((left,right)=>left.localeCompare(right))}catch(error){if(isFileMissingError(error)){return result}throw error}for(const file of files){const absPath=path.join(journalsDir,file);const relPath=`transactions/sdk/${file}`;const fileResult=await processWorkspaceTransactionJournal(absPath,relPath,file,{dryRun,hooks,nowMs,retentionMs});result.warnings.push(...fileResult.warnings);result.scanned+=1;const{decision}=fileResult;if(!decision.remove){result.retained.push(relPath);result.entries.push(decision.entry);continue}result.removed.push(relPath);result.entries.push(decision.entry)}return result}export{runWorkspaceTransactionGc};
|
|
149
2
|
//# sourceMappingURL=workspace-transaction-gc.js.map
|
|
150
|
-
//# debugId=7df80849-51e1-5efa-b40a-b44088f941a9
|
|
@@ -1,364 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Coordinates crash-recoverable, compensating transactions across public SDK
|
|
5
|
-
* mutation primitives without rewriting immutable item or relationship history.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6ed4a26f-2ae2-556a-87db-56844108757f")}catch(e){}}();
|
|
9
|
-
import { mkdir, readFile } from "node:fs/promises";
|
|
10
|
-
import path from "node:path";
|
|
11
|
-
import { acquireLock } from "../core/lock/lock.js";
|
|
12
|
-
import { isFileMissingError, writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
13
|
-
import { nowIso } from "../core/shared/time.js";
|
|
14
|
-
/**
|
|
15
|
-
* Deliberate process-boundary interruption used by deterministic crash tests.
|
|
16
|
-
* Throwing this from `onTransition` leaves the journal resumable and skips the
|
|
17
|
-
* normal in-process compensation path.
|
|
18
|
-
*/
|
|
19
|
-
export class WorkspaceTransactionInterruptedError extends Error {
|
|
20
|
-
/** Create one explicit crash-boundary interruption. */
|
|
21
|
-
constructor(message = "Workspace transaction interrupted") {
|
|
22
|
-
super(message);
|
|
23
|
-
this.name = "WorkspaceTransactionInterruptedError";
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const WORKSPACE_TRANSACTION_LOCK_ID = "sdk-workspace-transaction";
|
|
27
|
-
const TRANSACTION_ID_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
28
|
-
const DEFAULT_LOCK_TTL_SECONDS = 30;
|
|
29
|
-
const DEFAULT_LOCK_WAIT_MS = 3_000;
|
|
30
|
-
function requiredIdentifier(value, label) {
|
|
31
|
-
if (typeof value !== "string")
|
|
32
|
-
throw new TypeError(`${label} must be a string`);
|
|
33
|
-
const normalized = value.trim();
|
|
34
|
-
if (!normalized || !TRANSACTION_ID_PATTERN.test(normalized))
|
|
35
|
-
throw new TypeError(`${label} must match [a-zA-Z0-9._-]+`);
|
|
36
|
-
return normalized;
|
|
37
|
-
}
|
|
38
|
-
function requiredText(value, label) {
|
|
39
|
-
if (typeof value !== "string")
|
|
40
|
-
throw new TypeError(`${label} must be a string`);
|
|
41
|
-
const normalized = value.trim();
|
|
42
|
-
if (!normalized)
|
|
43
|
-
throw new TypeError(`${label} must be non-empty`);
|
|
44
|
-
return normalized;
|
|
45
|
-
}
|
|
46
|
-
function positiveInteger(value, fallback, label) {
|
|
47
|
-
const resolved = value ?? fallback;
|
|
48
|
-
if (!Number.isInteger(resolved) || resolved <= 0)
|
|
49
|
-
throw new TypeError(`${label} must be a positive integer`);
|
|
50
|
-
return resolved;
|
|
51
|
-
}
|
|
52
|
-
function journalPath(pmRoot, transactionId) {
|
|
53
|
-
return path.join(pmRoot, "transactions", "sdk", `${transactionId}.json`);
|
|
54
|
-
}
|
|
55
|
-
async function writeJournal(pmRoot, journal) {
|
|
56
|
-
journal.updatedAt = nowIso();
|
|
57
|
-
const target = journalPath(pmRoot, journal.transactionId);
|
|
58
|
-
await mkdir(path.dirname(target), { recursive: true });
|
|
59
|
-
await writeFileAtomic(target, `${JSON.stringify(journal, null, 2)}\n`);
|
|
60
|
-
}
|
|
61
|
-
function hasValidJournalMetadata(journal) {
|
|
62
|
-
return (Number.isInteger(journal.attempt) &&
|
|
63
|
-
typeof journal.author === "string" &&
|
|
64
|
-
typeof journal.createdAt === "string" &&
|
|
65
|
-
typeof journal.updatedAt === "string");
|
|
66
|
-
}
|
|
67
|
-
function createResultMap(source) {
|
|
68
|
-
return Object.assign(Object.create(null), source);
|
|
69
|
-
}
|
|
70
|
-
function cloneJournalValue(value, label) {
|
|
71
|
-
try {
|
|
72
|
-
const serialized = JSON.stringify(value, (_key, nestedValue) => {
|
|
73
|
-
if (typeof nestedValue === "number" && !Number.isFinite(nestedValue))
|
|
74
|
-
throw new TypeError(`${label} contains a non-finite number`);
|
|
75
|
-
if (nestedValue === undefined ||
|
|
76
|
-
typeof nestedValue === "function" ||
|
|
77
|
-
typeof nestedValue === "symbol")
|
|
78
|
-
throw new TypeError(`${label} contains a non-JSON value`);
|
|
79
|
-
return nestedValue;
|
|
80
|
-
});
|
|
81
|
-
return JSON.parse(serialized);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
throw new TypeError(`${label} must be JSON serializable`, { cause: error });
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
function cloneOptionalJournalValue(value, label) {
|
|
88
|
-
return value === undefined ? undefined : cloneJournalValue(value, label);
|
|
89
|
-
}
|
|
90
|
-
function setJournalEntry(target, stepId, value, label) {
|
|
91
|
-
const cloned = cloneOptionalJournalValue(value, label);
|
|
92
|
-
if (cloned === undefined)
|
|
93
|
-
delete target[stepId];
|
|
94
|
-
else
|
|
95
|
-
target[stepId] = cloned;
|
|
96
|
-
}
|
|
97
|
-
function isJournalMap(value) {
|
|
98
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
99
|
-
}
|
|
100
|
-
function hasUniqueKnownStepIds(value, stepIds) {
|
|
101
|
-
return (Array.isArray(value) &&
|
|
102
|
-
new Set(value).size === value.length &&
|
|
103
|
-
value.every((stepId) => typeof stepId === "string" && stepIds.includes(stepId)));
|
|
104
|
-
}
|
|
105
|
-
function hasValidJournalLifecycle(journal, stepIds) {
|
|
106
|
-
if (!hasUniqueKnownStepIds(journal.startedStepIds, stepIds) ||
|
|
107
|
-
!hasUniqueKnownStepIds(journal.completedStepIds, stepIds) ||
|
|
108
|
-
!isJournalMap(journal.results) ||
|
|
109
|
-
!isJournalMap(journal.compensationData))
|
|
110
|
-
return false;
|
|
111
|
-
const startedStepIds = journal.startedStepIds;
|
|
112
|
-
const started = new Set(startedStepIds);
|
|
113
|
-
const completedStepIds = journal.completedStepIds;
|
|
114
|
-
const completed = new Set(completedStepIds);
|
|
115
|
-
if (Object.keys(journal.compensationData).some((stepId) => !started.has(stepId)) ||
|
|
116
|
-
Object.keys(journal.results).some((stepId) => !completed.has(stepId)))
|
|
117
|
-
return false;
|
|
118
|
-
if (journal.status === "committed")
|
|
119
|
-
return stepIds.every((stepId) => completed.has(stepId));
|
|
120
|
-
return (journal.status !== "compensated" ||
|
|
121
|
-
(completed.size === 0 && started.size === 0));
|
|
122
|
-
}
|
|
123
|
-
function parseJournal(raw, transactionId, stepIds) {
|
|
124
|
-
let parsed;
|
|
125
|
-
try {
|
|
126
|
-
parsed = JSON.parse(raw);
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
throw new TypeError(`Workspace transaction ${transactionId} journal is invalid JSON`);
|
|
130
|
-
}
|
|
131
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
132
|
-
throw new TypeError(`Workspace transaction ${transactionId} journal is invalid`);
|
|
133
|
-
const journal = parsed;
|
|
134
|
-
const identityMatches = journal.schemaVersion === 1 && journal.transactionId === transactionId;
|
|
135
|
-
const stepsMatch = Array.isArray(journal.stepIds) &&
|
|
136
|
-
journal.stepIds.length === stepIds.length &&
|
|
137
|
-
journal.stepIds.every((stepId, index) => stepId === stepIds[index]);
|
|
138
|
-
const lifecycleMatches = hasValidJournalLifecycle(journal, stepIds);
|
|
139
|
-
const metadataMatches = hasValidJournalMetadata(journal);
|
|
140
|
-
const statusMatches = [
|
|
141
|
-
"applying",
|
|
142
|
-
"compensating",
|
|
143
|
-
"compensated",
|
|
144
|
-
"committed",
|
|
145
|
-
].includes(String(journal.status));
|
|
146
|
-
if (!identityMatches ||
|
|
147
|
-
!stepsMatch ||
|
|
148
|
-
!lifecycleMatches ||
|
|
149
|
-
!metadataMatches ||
|
|
150
|
-
!statusMatches)
|
|
151
|
-
throw new TypeError(`Workspace transaction ${transactionId} journal does not match the supplied plan`);
|
|
152
|
-
return {
|
|
153
|
-
...journal,
|
|
154
|
-
results: createResultMap(journal.results),
|
|
155
|
-
compensationData: createResultMap(journal.compensationData),
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
async function prepareJournalForApply(options, transactionId, author, stepIds, existing) {
|
|
159
|
-
let journal = existing;
|
|
160
|
-
const recovered = journal !== undefined;
|
|
161
|
-
if (journal?.status === "compensating")
|
|
162
|
-
await compensateAppliedSteps(options, journal);
|
|
163
|
-
if (journal === undefined || journal.status === "compensated") {
|
|
164
|
-
const timestamp = nowIso();
|
|
165
|
-
journal = {
|
|
166
|
-
schemaVersion: 1,
|
|
167
|
-
transactionId,
|
|
168
|
-
author,
|
|
169
|
-
status: "applying",
|
|
170
|
-
attempt: (journal?.attempt ?? 0) + 1,
|
|
171
|
-
createdAt: journal?.createdAt ?? timestamp,
|
|
172
|
-
updatedAt: timestamp,
|
|
173
|
-
stepIds,
|
|
174
|
-
startedStepIds: [],
|
|
175
|
-
completedStepIds: [],
|
|
176
|
-
results: createResultMap(),
|
|
177
|
-
compensationData: createResultMap(),
|
|
178
|
-
};
|
|
179
|
-
await writeJournal(options.pmRoot, journal);
|
|
180
|
-
await emitTransition(options, journal, "prepared");
|
|
181
|
-
}
|
|
182
|
-
return { journal, recovered };
|
|
183
|
-
}
|
|
184
|
-
async function applyPreparedTransaction(options, journal, recovered) {
|
|
185
|
-
try {
|
|
186
|
-
await discoverAppliedSteps(journal, options.steps);
|
|
187
|
-
await writeJournal(options.pmRoot, journal);
|
|
188
|
-
const completed = new Set(journal.completedStepIds);
|
|
189
|
-
const started = new Set(journal.startedStepIds);
|
|
190
|
-
for (const step of options.steps) {
|
|
191
|
-
if (completed.has(step.id))
|
|
192
|
-
continue;
|
|
193
|
-
const inspection = await step.inspect();
|
|
194
|
-
let result = cloneOptionalJournalValue(inspection.result, `Step ${step.id} result`);
|
|
195
|
-
if (inspection.state !== "applied") {
|
|
196
|
-
const compensationData = await step.prepareCompensation?.();
|
|
197
|
-
setJournalEntry(journal.compensationData, step.id, compensationData, `Step ${step.id} compensation data`);
|
|
198
|
-
started.add(step.id);
|
|
199
|
-
journal.startedStepIds = options.steps
|
|
200
|
-
.map((candidate) => candidate.id)
|
|
201
|
-
.filter((stepId) => started.has(stepId));
|
|
202
|
-
await writeJournal(options.pmRoot, journal);
|
|
203
|
-
const appliedResult = await step.apply();
|
|
204
|
-
result = cloneOptionalJournalValue(appliedResult, `Step ${step.id} result`);
|
|
205
|
-
}
|
|
206
|
-
await emitTransition(options, journal, "step_applied", step.id);
|
|
207
|
-
completed.add(step.id);
|
|
208
|
-
journal.completedStepIds = options.steps
|
|
209
|
-
.map((candidate) => candidate.id)
|
|
210
|
-
.filter((stepId) => completed.has(stepId));
|
|
211
|
-
setJournalEntry(journal.results, step.id, result, `Step ${step.id} result`);
|
|
212
|
-
await writeJournal(options.pmRoot, journal);
|
|
213
|
-
await emitTransition(options, journal, "step_recorded", step.id);
|
|
214
|
-
}
|
|
215
|
-
await emitTransition(options, journal, "committing");
|
|
216
|
-
journal.status = "committed";
|
|
217
|
-
await writeJournal(options.pmRoot, journal);
|
|
218
|
-
await emitTransition(options, journal, "committed");
|
|
219
|
-
return {
|
|
220
|
-
transactionId: journal.transactionId,
|
|
221
|
-
status: "committed",
|
|
222
|
-
recovered,
|
|
223
|
-
results: createResultMap(journal.results),
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
catch (error) {
|
|
227
|
-
if (error instanceof WorkspaceTransactionInterruptedError ||
|
|
228
|
-
journal.status === "committed")
|
|
229
|
-
throw error;
|
|
230
|
-
try {
|
|
231
|
-
await compensateAppliedSteps(options, journal);
|
|
232
|
-
}
|
|
233
|
-
catch (compensationError) {
|
|
234
|
-
throw new AggregateError([error, compensationError], `Workspace transaction failed and compensation failed: ${String(compensationError)}`, { cause: compensationError });
|
|
235
|
-
}
|
|
236
|
-
throw error;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
async function loadJournal(pmRoot, transactionId, stepIds) {
|
|
240
|
-
try {
|
|
241
|
-
return parseJournal(await readFile(journalPath(pmRoot, transactionId), "utf8"), transactionId, stepIds);
|
|
242
|
-
}
|
|
243
|
-
catch (error) {
|
|
244
|
-
if (error !== null &&
|
|
245
|
-
typeof error === "object" &&
|
|
246
|
-
"code" in error &&
|
|
247
|
-
isFileMissingError(error))
|
|
248
|
-
return undefined;
|
|
249
|
-
throw error;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
async function emitTransition(options, journal, transition, stepId) {
|
|
253
|
-
await options.onTransition?.({
|
|
254
|
-
transactionId: journal.transactionId,
|
|
255
|
-
attempt: journal.attempt,
|
|
256
|
-
transition,
|
|
257
|
-
...(stepId === undefined ? {} : { stepId }),
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
async function discoverAppliedSteps(journal, steps) {
|
|
261
|
-
const completed = new Set();
|
|
262
|
-
const results = createResultMap();
|
|
263
|
-
for (const step of steps) {
|
|
264
|
-
const inspection = await step.inspect();
|
|
265
|
-
if (inspection.state === "applied") {
|
|
266
|
-
completed.add(step.id);
|
|
267
|
-
setJournalEntry(results, step.id, inspection.result, `Step ${step.id} result`);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
journal.results = results;
|
|
271
|
-
journal.completedStepIds = steps
|
|
272
|
-
.map((step) => step.id)
|
|
273
|
-
.filter((stepId) => completed.has(stepId));
|
|
274
|
-
}
|
|
275
|
-
async function compensateAppliedSteps(options, journal) {
|
|
276
|
-
journal.status = "compensating";
|
|
277
|
-
await writeJournal(options.pmRoot, journal);
|
|
278
|
-
await emitTransition(options, journal, "compensating");
|
|
279
|
-
const completed = new Set(journal.completedStepIds);
|
|
280
|
-
const started = new Set(journal.startedStepIds);
|
|
281
|
-
for (const step of [...options.steps].reverse()) {
|
|
282
|
-
if (!started.has(step.id) && !completed.has(step.id))
|
|
283
|
-
continue;
|
|
284
|
-
let shouldCompensate;
|
|
285
|
-
try {
|
|
286
|
-
shouldCompensate =
|
|
287
|
-
started.has(step.id) && (await step.inspect()).state === "applied";
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
shouldCompensate = started.has(step.id);
|
|
291
|
-
}
|
|
292
|
-
if (shouldCompensate) {
|
|
293
|
-
await emitTransition(options, journal, "step_compensating", step.id);
|
|
294
|
-
await step.compensate(journal.compensationData[step.id]);
|
|
295
|
-
}
|
|
296
|
-
completed.delete(step.id);
|
|
297
|
-
started.delete(step.id);
|
|
298
|
-
journal.completedStepIds = options.steps
|
|
299
|
-
.map((candidate) => candidate.id)
|
|
300
|
-
.filter((stepId) => completed.has(stepId));
|
|
301
|
-
journal.startedStepIds = options.steps
|
|
302
|
-
.map((candidate) => candidate.id)
|
|
303
|
-
.filter((stepId) => started.has(stepId));
|
|
304
|
-
delete journal.results[step.id];
|
|
305
|
-
delete journal.compensationData[step.id];
|
|
306
|
-
await writeJournal(options.pmRoot, journal);
|
|
307
|
-
await emitTransition(options, journal, "step_compensated", step.id);
|
|
308
|
-
}
|
|
309
|
-
journal.status = "compensated";
|
|
310
|
-
await writeJournal(options.pmRoot, journal);
|
|
311
|
-
await emitTransition(options, journal, "compensated");
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Commit an ordered set of idempotent SDK mutations under one workspace writer
|
|
315
|
-
* lock. The durable journal resumes interrupted forward work, while ordinary
|
|
316
|
-
* failures append reverse-order compensations. This provides atomic logical
|
|
317
|
-
* replay without deleting or rewriting immutable domain histories.
|
|
318
|
-
*/
|
|
319
|
-
export async function commitWorkspaceTransaction(options) {
|
|
320
|
-
const pmRoot = requiredText(options.pmRoot, "Transaction pmRoot");
|
|
321
|
-
const transactionId = requiredIdentifier(options.transactionId, "Transaction id");
|
|
322
|
-
const author = requiredText(options.author, "Transaction author");
|
|
323
|
-
const lockTtlSeconds = positiveInteger(options.lockTtlSeconds, DEFAULT_LOCK_TTL_SECONDS, "Transaction lock TTL");
|
|
324
|
-
const lockWaitMs = positiveInteger(options.lockWaitMs, DEFAULT_LOCK_WAIT_MS, "Transaction lock wait");
|
|
325
|
-
const steps = [...options.steps];
|
|
326
|
-
if (steps.length === 0)
|
|
327
|
-
throw new TypeError("Workspace transaction requires at least one step");
|
|
328
|
-
const stepIds = steps.map((step) => {
|
|
329
|
-
const stepId = requiredIdentifier(step.id, "Transaction step id");
|
|
330
|
-
if (stepId !== step.id)
|
|
331
|
-
throw new TypeError("Transaction step id must not contain surrounding whitespace");
|
|
332
|
-
return stepId;
|
|
333
|
-
});
|
|
334
|
-
if (new Set(stepIds).size !== stepIds.length)
|
|
335
|
-
throw new TypeError("Workspace transaction step ids must be unique");
|
|
336
|
-
const stableOptions = {
|
|
337
|
-
...options,
|
|
338
|
-
pmRoot,
|
|
339
|
-
transactionId,
|
|
340
|
-
author,
|
|
341
|
-
steps,
|
|
342
|
-
lockTtlSeconds,
|
|
343
|
-
lockWaitMs,
|
|
344
|
-
};
|
|
345
|
-
const release = await acquireLock(pmRoot, WORKSPACE_TRANSACTION_LOCK_ID, lockTtlSeconds, author, false, false, lockWaitMs);
|
|
346
|
-
try {
|
|
347
|
-
const existing = await loadJournal(pmRoot, transactionId, stepIds);
|
|
348
|
-
const recovered = existing !== undefined;
|
|
349
|
-
if (existing?.status === "committed")
|
|
350
|
-
return {
|
|
351
|
-
transactionId,
|
|
352
|
-
status: "committed",
|
|
353
|
-
recovered: true,
|
|
354
|
-
results: createResultMap(existing.results),
|
|
355
|
-
};
|
|
356
|
-
const prepared = await prepareJournalForApply(stableOptions, transactionId, author, stepIds, existing);
|
|
357
|
-
return await applyPreparedTransaction(stableOptions, prepared.journal, recovered || prepared.recovered);
|
|
358
|
-
}
|
|
359
|
-
finally {
|
|
360
|
-
await release();
|
|
361
|
-
}
|
|
362
|
-
}
|
|
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]="4d7f490a-03a3-512c-ba3c-b19fcc9a1270")}catch(e2){}})();import{mkdir,readFile}from"node:fs/promises";import path from"node:path";import{acquireLock}from"../core/lock/lock.js";import{isFileMissingError,writeFileAtomic}from"../core/fs/fs-utils.js";import{nowIso}from"../core/shared/time.js";class WorkspaceTransactionInterruptedError extends Error{constructor(message="Workspace transaction interrupted"){super(message);this.name="WorkspaceTransactionInterruptedError"}}const WORKSPACE_TRANSACTION_LOCK_ID="sdk-workspace-transaction";const TRANSACTION_ID_PATTERN=/^[a-zA-Z0-9._-]+$/;const DEFAULT_LOCK_TTL_SECONDS=30;const DEFAULT_LOCK_WAIT_MS=3e3;function requiredIdentifier(value,label){if(typeof value!=="string")throw new TypeError(`${label} must be a string`);const normalized=value.trim();if(!normalized||!TRANSACTION_ID_PATTERN.test(normalized))throw new TypeError(`${label} must match [a-zA-Z0-9._-]+`);return normalized}function requiredText(value,label){if(typeof value!=="string")throw new TypeError(`${label} must be a string`);const normalized=value.trim();if(!normalized)throw new TypeError(`${label} must be non-empty`);return normalized}function positiveInteger(value,fallback,label){const resolved=value??fallback;if(!Number.isInteger(resolved)||resolved<=0)throw new TypeError(`${label} must be a positive integer`);return resolved}function journalPath(pmRoot,transactionId){return path.join(pmRoot,"transactions","sdk",`${transactionId}.json`)}async function writeJournal(pmRoot,journal){journal.updatedAt=nowIso();const target=journalPath(pmRoot,journal.transactionId);await mkdir(path.dirname(target),{recursive:true});await writeFileAtomic(target,`${JSON.stringify(journal,null,2)}
|
|
2
|
+
`)}function hasValidJournalMetadata(journal){return Number.isInteger(journal.attempt)&&typeof journal.author==="string"&&typeof journal.createdAt==="string"&&typeof journal.updatedAt==="string"}function createResultMap(source){return Object.assign(Object.create(null),source)}function cloneJournalValue(value,label){try{const serialized=JSON.stringify(value,(_key,nestedValue)=>{if(typeof nestedValue==="number"&&!Number.isFinite(nestedValue))throw new TypeError(`${label} contains a non-finite number`);if(nestedValue===void 0||typeof nestedValue==="function"||typeof nestedValue==="symbol")throw new TypeError(`${label} contains a non-JSON value`);return nestedValue});return JSON.parse(serialized)}catch(error){throw new TypeError(`${label} must be JSON serializable`,{cause:error})}}function cloneOptionalJournalValue(value,label){return value===void 0?void 0:cloneJournalValue(value,label)}function setJournalEntry(target,stepId,value,label){const cloned=cloneOptionalJournalValue(value,label);if(cloned===void 0)delete target[stepId];else target[stepId]=cloned}function isJournalMap(value){return value!==null&&typeof value==="object"&&!Array.isArray(value)}function hasUniqueKnownStepIds(value,stepIds){return Array.isArray(value)&&new Set(value).size===value.length&&value.every(stepId=>typeof stepId==="string"&&stepIds.includes(stepId))}function hasValidJournalLifecycle(journal,stepIds){if(!hasUniqueKnownStepIds(journal.startedStepIds,stepIds)||!hasUniqueKnownStepIds(journal.completedStepIds,stepIds)||!isJournalMap(journal.results)||!isJournalMap(journal.compensationData))return false;const startedStepIds=journal.startedStepIds;const started=new Set(startedStepIds);const completedStepIds=journal.completedStepIds;const completed=new Set(completedStepIds);if(Object.keys(journal.compensationData).some(stepId=>!started.has(stepId))||Object.keys(journal.results).some(stepId=>!completed.has(stepId)))return false;if(journal.status==="committed")return stepIds.every(stepId=>completed.has(stepId));return journal.status!=="compensated"||completed.size===0&&started.size===0}function parseJournal(raw,transactionId,stepIds){let parsed;try{parsed=JSON.parse(raw)}catch{throw new TypeError(`Workspace transaction ${transactionId} journal is invalid JSON`)}if(!parsed||typeof parsed!=="object"||Array.isArray(parsed))throw new TypeError(`Workspace transaction ${transactionId} journal is invalid`);const journal=parsed;const identityMatches=journal.schemaVersion===1&&journal.transactionId===transactionId;const stepsMatch=Array.isArray(journal.stepIds)&&journal.stepIds.length===stepIds.length&&journal.stepIds.every((stepId,index)=>stepId===stepIds[index]);const lifecycleMatches=hasValidJournalLifecycle(journal,stepIds);const metadataMatches=hasValidJournalMetadata(journal);const statusMatches=["applying","compensating","compensated","committed"].includes(String(journal.status));if(!identityMatches||!stepsMatch||!lifecycleMatches||!metadataMatches||!statusMatches)throw new TypeError(`Workspace transaction ${transactionId} journal does not match the supplied plan`);return{...journal,results:createResultMap(journal.results),compensationData:createResultMap(journal.compensationData)}}async function prepareJournalForApply(options,transactionId,author,stepIds,existing){let journal=existing;const recovered=journal!==void 0;if(journal?.status==="compensating")await compensateAppliedSteps(options,journal);if(journal===void 0||journal.status==="compensated"){const timestamp=nowIso();journal={schemaVersion:1,transactionId,author,status:"applying",attempt:(journal?.attempt??0)+1,createdAt:journal?.createdAt??timestamp,updatedAt:timestamp,stepIds,startedStepIds:[],completedStepIds:[],results:createResultMap(),compensationData:createResultMap()};await writeJournal(options.pmRoot,journal);await emitTransition(options,journal,"prepared")}return{journal,recovered}}async function applyPreparedTransaction(options,journal,recovered){try{await discoverAppliedSteps(journal,options.steps);await writeJournal(options.pmRoot,journal);const completed=new Set(journal.completedStepIds);const started=new Set(journal.startedStepIds);for(const step of options.steps){if(completed.has(step.id))continue;const inspection=await step.inspect();let result=cloneOptionalJournalValue(inspection.result,`Step ${step.id} result`);if(inspection.state!=="applied"){const compensationData=await step.prepareCompensation?.();setJournalEntry(journal.compensationData,step.id,compensationData,`Step ${step.id} compensation data`);started.add(step.id);journal.startedStepIds=options.steps.map(candidate=>candidate.id).filter(stepId=>started.has(stepId));await writeJournal(options.pmRoot,journal);const appliedResult=await step.apply();result=cloneOptionalJournalValue(appliedResult,`Step ${step.id} result`)}await emitTransition(options,journal,"step_applied",step.id);completed.add(step.id);journal.completedStepIds=options.steps.map(candidate=>candidate.id).filter(stepId=>completed.has(stepId));setJournalEntry(journal.results,step.id,result,`Step ${step.id} result`);await writeJournal(options.pmRoot,journal);await emitTransition(options,journal,"step_recorded",step.id)}await emitTransition(options,journal,"committing");journal.status="committed";await writeJournal(options.pmRoot,journal);await emitTransition(options,journal,"committed");return{transactionId:journal.transactionId,status:"committed",recovered,results:createResultMap(journal.results)}}catch(error){if(error instanceof WorkspaceTransactionInterruptedError||journal.status==="committed")throw error;try{await compensateAppliedSteps(options,journal)}catch(compensationError){throw new AggregateError([error,compensationError],`Workspace transaction failed and compensation failed: ${String(compensationError)}`,{cause:compensationError})}throw error}}async function loadJournal(pmRoot,transactionId,stepIds){try{return parseJournal(await readFile(journalPath(pmRoot,transactionId),"utf8"),transactionId,stepIds)}catch(error){if(error!==null&&typeof error==="object"&&"code"in error&&isFileMissingError(error))return void 0;throw error}}async function emitTransition(options,journal,transition,stepId){await options.onTransition?.({transactionId:journal.transactionId,attempt:journal.attempt,transition,...stepId===void 0?{}:{stepId}})}async function discoverAppliedSteps(journal,steps){const completed=new Set;const results=createResultMap();for(const step of steps){const inspection=await step.inspect();if(inspection.state==="applied"){completed.add(step.id);setJournalEntry(results,step.id,inspection.result,`Step ${step.id} result`)}}journal.results=results;journal.completedStepIds=steps.map(step=>step.id).filter(stepId=>completed.has(stepId))}async function compensateAppliedSteps(options,journal){journal.status="compensating";await writeJournal(options.pmRoot,journal);await emitTransition(options,journal,"compensating");const completed=new Set(journal.completedStepIds);const started=new Set(journal.startedStepIds);for(const step of[...options.steps].reverse()){if(!started.has(step.id)&&!completed.has(step.id))continue;let shouldCompensate;try{shouldCompensate=started.has(step.id)&&(await step.inspect()).state==="applied"}catch{shouldCompensate=started.has(step.id)}if(shouldCompensate){await emitTransition(options,journal,"step_compensating",step.id);await step.compensate(journal.compensationData[step.id])}completed.delete(step.id);started.delete(step.id);journal.completedStepIds=options.steps.map(candidate=>candidate.id).filter(stepId=>completed.has(stepId));journal.startedStepIds=options.steps.map(candidate=>candidate.id).filter(stepId=>started.has(stepId));delete journal.results[step.id];delete journal.compensationData[step.id];await writeJournal(options.pmRoot,journal);await emitTransition(options,journal,"step_compensated",step.id)}journal.status="compensated";await writeJournal(options.pmRoot,journal);await emitTransition(options,journal,"compensated")}async function commitWorkspaceTransaction(options){const pmRoot=requiredText(options.pmRoot,"Transaction pmRoot");const transactionId=requiredIdentifier(options.transactionId,"Transaction id");const author=requiredText(options.author,"Transaction author");const lockTtlSeconds=positiveInteger(options.lockTtlSeconds,DEFAULT_LOCK_TTL_SECONDS,"Transaction lock TTL");const lockWaitMs=positiveInteger(options.lockWaitMs,DEFAULT_LOCK_WAIT_MS,"Transaction lock wait");const steps=[...options.steps];if(steps.length===0)throw new TypeError("Workspace transaction requires at least one step");const stepIds=steps.map(step=>{const stepId=requiredIdentifier(step.id,"Transaction step id");if(stepId!==step.id)throw new TypeError("Transaction step id must not contain surrounding whitespace");return stepId});if(new Set(stepIds).size!==stepIds.length)throw new TypeError("Workspace transaction step ids must be unique");const stableOptions={...options,pmRoot,transactionId,author,steps,lockTtlSeconds,lockWaitMs};const release=await acquireLock(pmRoot,WORKSPACE_TRANSACTION_LOCK_ID,lockTtlSeconds,author,false,false,lockWaitMs);try{const existing=await loadJournal(pmRoot,transactionId,stepIds);const recovered=existing!==void 0;if(existing?.status==="committed")return{transactionId,status:"committed",recovered:true,results:createResultMap(existing.results)};const prepared=await prepareJournalForApply(stableOptions,transactionId,author,stepIds,existing);return await applyPreparedTransaction(stableOptions,prepared.journal,recovered||prepared.recovered)}finally{await release()}}export{WorkspaceTransactionInterruptedError,commitWorkspaceTransaction};
|
|
363
3
|
//# sourceMappingURL=workspace-transaction.js.map
|
|
364
|
-
//# debugId=6ed4a26f-2ae2-556a-87db-56844108757f
|