@unbrained/pm-cli 2026.9.6 → 2026.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/pm-developer/SKILL.md +12 -4
- package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
- package/.agents/skills/pm-extensions/SKILL.md +6 -0
- package/.agents/skills/pm-sdk/SKILL.md +11 -2
- package/.agents/skills/pm-user/SKILL.md +5 -0
- package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +218 -182
- package/dist/cli/after-command-context-usage.js +1 -48
- package/dist/cli/argv-utils.js +1 -40
- package/dist/cli/bootstrap-args.js +1 -9
- package/dist/cli/bundle-integrity.js +2 -110
- package/dist/cli/commander-usage.js +11 -771
- package/dist/cli/commands/activity.js +1 -9
- package/dist/cli/commands/aggregate.js +1 -5
- package/dist/cli/commands/append.js +1 -5
- package/dist/cli/commands/claim.js +1 -5
- package/dist/cli/commands/close-many.js +1 -5
- package/dist/cli/commands/close.js +1 -9
- package/dist/cli/commands/comments.js +1 -5
- package/dist/cli/commands/config.js +1 -9
- package/dist/cli/commands/context.js +1 -9
- package/dist/cli/commands/contracts.js +1 -5
- package/dist/cli/commands/copy.js +1 -9
- package/dist/cli/commands/create.js +1 -9
- package/dist/cli/commands/delete.js +1 -9
- package/dist/cli/commands/deps.js +1 -9
- package/dist/cli/commands/docs.js +1 -9
- package/dist/cli/commands/duplicates.js +1 -9
- package/dist/cli/commands/eval.js +1 -9
- package/dist/cli/commands/extension/describe.js +1 -5
- package/dist/cli/commands/extension/scaffold.js +1 -5
- package/dist/cli/commands/extension/shared.js +1 -5
- package/dist/cli/commands/extension.js +1 -9
- package/dist/cli/commands/files.js +1 -9
- package/dist/cli/commands/focus.js +1 -9
- package/dist/cli/commands/gc.js +1 -9
- package/dist/cli/commands/get.js +1 -9
- package/dist/cli/commands/graph.js +1 -10
- package/dist/cli/commands/health.js +1 -9
- package/dist/cli/commands/history-compact.js +1 -10
- package/dist/cli/commands/history-redact.js +1 -11
- package/dist/cli/commands/history-repair.js +1 -10
- package/dist/cli/commands/history.js +1 -5
- package/dist/cli/commands/index.js +1 -58
- package/dist/cli/commands/init-agent-guidance.js +1 -9
- package/dist/cli/commands/init.js +1 -9
- package/dist/cli/commands/learnings.js +1 -5
- package/dist/cli/commands/lifecycle-transitions.js +1 -5
- package/dist/cli/commands/list.js +1 -9
- package/dist/cli/commands/merge.js +1 -11
- package/dist/cli/commands/next.js +1 -9
- package/dist/cli/commands/notes.js +1 -5
- package/dist/cli/commands/plan.js +1 -9
- package/dist/cli/commands/profile.js +1 -9
- package/dist/cli/commands/restore.js +1 -9
- package/dist/cli/commands/scheduling-shortcuts.js +1 -9
- package/dist/cli/commands/schema.js +1 -10
- package/dist/cli/commands/search.js +1 -9
- package/dist/cli/commands/stats.js +1 -9
- package/dist/cli/commands/telemetry.js +1 -9
- package/dist/cli/commands/test-all.js +1 -9
- package/dist/cli/commands/test-runs.js +1 -9
- package/dist/cli/commands/test.js +1 -9
- package/dist/cli/commands/update-many.js +1 -5
- package/dist/cli/commands/update.js +1 -9
- package/dist/cli/commands/upgrade.js +1 -5
- package/dist/cli/commands/validate.js +1 -15
- package/dist/cli/context-intent-invocation.js +1 -20
- package/dist/cli/description-stdin.js +1 -17
- package/dist/cli/error-guidance.js +1 -1353
- package/dist/cli/extension-command-help.js +5 -636
- package/dist/cli/extension-command-options.js +1 -427
- package/dist/cli/extension-recovery.js +1 -126
- package/dist/cli/help-content.js +2 -1001
- package/dist/cli/help-json-payload.js +4 -570
- package/dist/cli/main.d.ts +4 -0
- package/dist/cli/main.js +5 -2573
- package/dist/cli/migration-gates.js +1 -289
- package/dist/cli/public.js +1 -20
- package/dist/cli/register-annotations.js +1 -270
- package/dist/cli/register-assurance.js +1 -62
- package/dist/cli/register-files-lookup.js +1 -56
- package/dist/cli/register-history-activity.d.ts +8 -0
- package/dist/cli/register-history-activity.js +2 -0
- package/dist/cli/register-history-author.js +1 -38
- package/dist/cli/register-history-maintenance.d.ts +9 -0
- package/dist/cli/register-history-maintenance.js +2 -0
- package/dist/cli/register-list-query.js +10 -943
- package/dist/cli/register-mutation-options.js +1 -9
- package/dist/cli/register-mutation.js +19 -1893
- package/dist/cli/register-operations.js +1 -920
- package/dist/cli/register-setup.js +1 -716
- package/dist/cli/register-structured-mutation.js +1 -196
- package/dist/cli/registration-helpers.js +1 -5
- package/dist/cli/runtime-compatibility-boundary.js +4 -42
- package/dist/cli/schema-registration-helpers.js +1 -73
- package/dist/cli/search-refresh.js +1 -13
- package/dist/cli/stats-analytics-json.js +1 -68
- package/dist/cli/telemetry-flush.js +1 -10
- package/dist/cli-bundle/bundle-manifest.json +164 -156
- package/dist/cli-bundle/chunks/chunk-3BZZA6A3.js +5 -0
- package/dist/cli-bundle/chunks/chunk-AMRDVX36.js +235 -0
- package/dist/cli-bundle/chunks/chunk-DAM4CBBR.js +2202 -0
- package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-FLDWYEND.js +77 -0
- package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-G5ADGQ2D.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-JAAEYHUA.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-JX4DH4WC.js → chunk-KR3RP4FH.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-LEZOUXG6.js +2 -0
- package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
- package/dist/cli-bundle/chunks/chunk-QOEKOECV.js +29 -0
- package/dist/cli-bundle/chunks/chunk-RHSFOMHU.js +2 -0
- package/dist/cli-bundle/chunks/chunk-XOD2PCB6.js +20 -0
- package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-YVEQ2AMO.js} +4 -4
- package/dist/cli-bundle/chunks/register-list-query-KSK3R63M.js +11 -0
- package/dist/cli-bundle/chunks/register-mutation-IQ5C7U6O.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-I5W3KMGB.js → register-operations-DWVHR2NC.js} +2 -2
- package/dist/cli-bundle/chunks/register-setup-BQ5SVD4B.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-3WRPWLA7.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-7MBUII7U.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-COPBO5HW.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-DUN4IXYN.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-EE5QSM4Z.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-HJVARYM3.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-IAUOUGVR.js +177 -0
- package/dist/cli-bundle/focused-chunks/chunk-KOOMJ54F.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-MZDXX7JY.js +56 -0
- package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-OPFHFGDD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-QHNETP77.js +9 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-RMWES4M6.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-RXT4P5QH.js +10 -0
- package/dist/cli-bundle/focused-chunks/chunk-SDOL6FM2.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-SQV4AAUC.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-PEFABF7E.js → chunk-WE3IUNIW.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-YALOUBWJ.js +2 -0
- package/dist/cli-bundle/main.js +20 -20
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +29 -29
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +42 -42
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +11 -11
- package/dist/cli.js +1 -104
- package/dist/core/checkpoint/checkpoint-gc.js +1 -169
- package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
- package/dist/core/config/nested-settings.js +1 -534
- package/dist/core/config/positional-value.js +1 -109
- package/dist/core/diagnostics/remediation.js +1 -506
- package/dist/core/extensions/activation-summary-markdown.js +2 -145
- package/dist/core/extensions/activation-summary.js +1 -92
- package/dist/core/extensions/activation-transaction.js +1 -46
- package/dist/core/extensions/capability-usage.js +1 -173
- package/dist/core/extensions/command-hook-context.js +1 -13
- package/dist/core/extensions/command-metadata-contract.js +1 -22
- package/dist/core/extensions/command-visibility-tier.js +1 -29
- package/dist/core/extensions/contribution-inventory.js +1 -173
- package/dist/core/extensions/exporter-output-contract.js +1 -66
- package/dist/core/extensions/extension-candidate.js +1 -18
- package/dist/core/extensions/extension-capability-aliases.js +1 -158
- package/dist/core/extensions/extension-hook-runtime.js +1 -699
- package/dist/core/extensions/extension-policy.js +1 -599
- package/dist/core/extensions/extension-registries.js +1 -62
- package/dist/core/extensions/extension-runtime-helpers.js +1 -33
- package/dist/core/extensions/extension-types.js +1 -102
- package/dist/core/extensions/flag-definition-validation.js +1 -52
- package/dist/core/extensions/flag-value-types.js +1 -64
- package/dist/core/extensions/index.js +1 -526
- package/dist/core/extensions/item-field-types.js +1 -39
- package/dist/core/extensions/item-fields.js +1 -261
- package/dist/core/extensions/loader.js +1 -2223
- package/dist/core/extensions/manifest-schema.js +1 -69
- package/dist/core/extensions/module-graph-snapshot.js +1 -33
- package/dist/core/extensions/preflight-ownership.js +1 -41
- package/dist/core/extensions/registration-validation.js +1 -82
- package/dist/core/extensions/registration-values.js +1 -209
- package/dist/core/extensions/reserved-host-flags.js +1 -36
- package/dist/core/extensions/runtime-registrations.js +1 -67
- package/dist/core/extensions/service-ownership.js +1 -19
- package/dist/core/extensions/version-compat.js +1 -216
- package/dist/core/fs/fs-utils.js +2 -158
- package/dist/core/fs/host-environment-errors.js +1 -141
- package/dist/core/fs/index.js +1 -9
- package/dist/core/fs/path-utils.js +1 -17
- package/dist/core/governance/content-fields.js +1 -160
- package/dist/core/governance/issue-codes.js +1 -151
- package/dist/core/governance/metadata-coverage.js +1 -358
- package/dist/core/history/drift-cache.js +3 -72
- package/dist/core/history/drift-scan.js +1 -342
- package/dist/core/history/event-classification.js +1 -109
- package/dist/core/history/event-index.js +8 -784
- package/dist/core/history/history-compact-bulk.js +1 -104
- package/dist/core/history/history-diff.js +1 -158
- package/dist/core/history/history-rewrite.d.ts +6 -1
- package/dist/core/history/history-rewrite.js +1 -107
- package/dist/core/history/history-storage-stats.js +1 -102
- package/dist/core/history/history-stream-policy.js +1 -62
- package/dist/core/history/history.js +2 -617
- package/dist/core/history/identity.js +1 -30
- package/dist/core/history/index.js +1 -9
- package/dist/core/history/projection.js +1 -196
- package/dist/core/history/read.d.ts +9 -0
- package/dist/core/history/read.js +1 -57
- package/dist/core/history/replay.js +2 -439
- package/dist/core/history/version-address.js +1 -32
- package/dist/core/history/workspace-history.js +2 -433
- package/dist/core/io/body-file.js +1 -62
- package/dist/core/io/bulk-ids-input.js +1 -112
- package/dist/core/item/actionability.js +1 -327
- package/dist/core/item/dependency-reference.js +1 -20
- package/dist/core/item/id.js +1 -112
- package/dist/core/item/index.js +1 -12
- package/dist/core/item/item-format-version.js +1 -78
- package/dist/core/item/item-format.js +5 -1473
- package/dist/core/item/item-record.js +1 -23
- package/dist/core/item/item-type-definition.js +1 -133
- package/dist/core/item/parent-reference-policy.js +1 -57
- package/dist/core/item/parse.js +2 -603
- package/dist/core/item/plan-lifecycle.js +1 -19
- package/dist/core/item/priority.js +1 -61
- package/dist/core/item/sprint-release-format.js +1 -38
- package/dist/core/item/status-filter.js +1 -115
- package/dist/core/item/status.js +1 -43
- package/dist/core/item/toon-decode.js +1 -29
- package/dist/core/item/type-registry.js +1 -715
- package/dist/core/item/type-synonyms.js +1 -38
- package/dist/core/lock/index.js +1 -9
- package/dist/core/lock/lock-gc.js +1 -240
- package/dist/core/lock/lock.js +3 -590
- package/dist/core/output/mutation-projection.js +1 -217
- package/dist/core/output/output-control.js +1 -25
- package/dist/core/output/output.js +11 -494
- package/dist/core/output/query-summary.js +1 -58
- package/dist/core/output/tabular.js +1 -77
- package/dist/core/packages/manifest.js +1 -244
- package/dist/core/packages/root.js +1 -84
- package/dist/core/profile/profile-describe.js +1 -83
- package/dist/core/profile/profile-lint.js +1 -415
- package/dist/core/profile/profile-plan.js +0 -0
- package/dist/core/profile/profile-presets.js +1 -370
- package/dist/core/reproducibility/context.js +1 -82
- package/dist/core/schema/fields-file.js +2 -288
- package/dist/core/schema/item-types-file.js +2 -296
- package/dist/core/schema/runtime-field-filters.js +1 -49
- package/dist/core/schema/runtime-field-values.js +1 -313
- package/dist/core/schema/runtime-schema.js +2 -826
- package/dist/core/schema/status-defs-file.js +2 -227
- package/dist/core/schema/status-token.js +1 -31
- package/dist/core/schema/type-inference.js +1 -95
- package/dist/core/schema/type-presets.js +1 -87
- package/dist/core/schema/type-workflows.js +1 -104
- package/dist/core/search/background-refresh.js +2 -286
- package/dist/core/search/bm25.js +1 -146
- package/dist/core/search/cache.js +2 -534
- package/dist/core/search/corpus.js +1 -311
- package/dist/core/search/embedding-batches.js +1 -163
- package/dist/core/search/eval.js +1 -225
- package/dist/core/search/http-client.js +1 -75
- package/dist/core/search/providers.js +1 -242
- package/dist/core/search/relevance.js +1 -244
- package/dist/core/search/semantic-defaults.js +1 -199
- package/dist/core/search/staleness.js +1 -30
- package/dist/core/search/vector-stores.js +2 -664
- package/dist/core/search/vectorization-metadata.js +1 -81
- package/dist/core/sentry/helpers.js +1 -272
- package/dist/core/sentry/instrument.js +1 -387
- package/dist/core/session/session-state.js +1 -260
- package/dist/core/shared/agent-session-context.js +1 -133
- package/dist/core/shared/author.js +1 -1172
- package/dist/core/shared/command-types.js +1 -4
- package/dist/core/shared/conflict-markers.js +1 -31
- package/dist/core/shared/constants.js +1 -405
- package/dist/core/shared/errors.js +1 -20
- package/dist/core/shared/html-entity-decode.js +1 -131
- package/dist/core/shared/index.js +1 -12
- package/dist/core/shared/item-metadata-contract.js +1 -89
- package/dist/core/shared/lazy-module.js +1 -16
- package/dist/core/shared/levenshtein.js +1 -61
- package/dist/core/shared/memo.js +1 -19
- package/dist/core/shared/numeric-parsers.js +1 -20
- package/dist/core/shared/option-alias-visibility.js +1 -67
- package/dist/core/shared/primitives.js +1 -127
- package/dist/core/shared/serial-queue.js +1 -79
- package/dist/core/shared/serialization.js +1 -210
- package/dist/core/shared/split-comma-list.js +1 -30
- package/dist/core/shared/text-normalization.js +1 -38
- package/dist/core/shared/time.js +1 -306
- package/dist/core/store/index.js +1 -12
- package/dist/core/store/item-format-migration.js +1 -125
- package/dist/core/store/item-metadata-cache.js +1 -1116
- package/dist/core/store/item-metadata-query-index.js +9 -394
- package/dist/core/store/item-metadata-read-work.js +1 -43
- package/dist/core/store/item-store.js +1 -693
- package/dist/core/store/paths.d.ts +1 -1
- package/dist/core/store/paths.js +1 -214
- package/dist/core/store/settings-read-cache.js +1 -85
- package/dist/core/store/settings-validator.js +1 -421
- package/dist/core/store/settings.js +3 -1309
- package/dist/core/store/tracker-preflight.js +1 -141
- package/dist/core/telemetry/consent.js +5 -108
- package/dist/core/telemetry/observability.js +1 -246
- package/dist/core/telemetry/runtime.js +4 -1988
- package/dist/core/test/background-runs.js +4 -945
- package/dist/core/test/item-test-run-tracking.js +1 -63
- package/dist/core/test/run-selectors.js +1 -120
- package/dist/core/validate/estimate-defaults.js +1 -89
- package/dist/core/validate/fix-planning.js +1 -189
- package/dist/core/validate/linked-artifact-reference.js +1 -36
- package/dist/core/validate/missing-by-type.js +1 -34
- package/dist/core/validate/missing-link-owners.js +1 -95
- package/dist/core/validate/stale-file-classification.js +1 -82
- package/dist/mcp/http-server.js +5 -448
- package/dist/mcp/legacy-adapter.js +1 -77
- package/dist/mcp/runtime-capabilities.js +1 -200
- package/dist/mcp/server.js +4 -1233
- package/dist/mcp/tool-definitions.js +1 -804
- package/dist/sdk/actionability.js +1 -13
- package/dist/sdk/agent/closed-domain-contracts.js +1 -161
- package/dist/sdk/agent/command-recovery.js +1 -59
- package/dist/sdk/agent/command-suggestions.js +1 -66
- package/dist/sdk/agent/create-option-policy.js +1 -31
- package/dist/sdk/agent/identity-config.js +1 -106
- package/dist/sdk/agent/item-addressing.js +1 -207
- package/dist/sdk/agent/refusal-closure-census.js +1 -151
- package/dist/sdk/agent/refusal-closure.js +1 -133
- package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
- package/dist/sdk/agent/refusal-reachability.js +1 -593
- package/dist/sdk/agent/subcommand-recovery.js +1 -83
- package/dist/sdk/agent/task-transcript-contracts.js +1 -197
- package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
- package/dist/sdk/agent-capability-contracts.js +1 -428
- package/dist/sdk/agent-session-context.js +1 -9
- package/dist/sdk/annotations.js +1 -448
- package/dist/sdk/author-attribution.js +1 -468
- package/dist/sdk/authoring.js +1 -20
- package/dist/sdk/cli-bootstrap.js +1 -838
- package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
- package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
- package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
- package/dist/sdk/cli-contracts/command-aliases.js +1 -107
- package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
- package/dist/sdk/cli-contracts/commander-types.js +1 -159
- package/dist/sdk/cli-contracts/completeness.js +1 -393
- package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
- package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
- package/dist/sdk/cli-contracts/string-lists.js +1 -16
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
- package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
- package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +1 -17
- package/dist/sdk/cli-program.js +1 -49
- package/dist/sdk/command-line.d.ts +2 -5
- package/dist/sdk/command-line.js +1 -78
- package/dist/sdk/comments.js +1 -133
- package/dist/sdk/compile-cache.js +1 -73
- package/dist/sdk/completion.js +157 -837
- package/dist/sdk/compose.js +1 -1090
- package/dist/sdk/config.js +1 -1204
- package/dist/sdk/context/recency.js +1 -33
- package/dist/sdk/context/semantic-session-attribution.js +1 -82
- package/dist/sdk/context/usage-egress.js +1 -29
- package/dist/sdk/context/usage-ledger.js +3 -185
- package/dist/sdk/context-intent-contracts.js +1 -709
- package/dist/sdk/context-intent-runtime.js +1 -115
- package/dist/sdk/context-packing.js +1 -218
- package/dist/sdk/context-relevance.js +1 -503
- package/dist/sdk/context-signal-store.js +2 -426
- package/dist/sdk/context-usage.js +1 -367
- package/dist/sdk/contracts.js +1 -23
- package/dist/sdk/core-governance.js +1 -14
- package/dist/sdk/core.js +1 -14
- package/dist/sdk/corpus-shape.js +1 -401
- package/dist/sdk/define.js +1 -220
- package/dist/sdk/dependencies.js +1 -718
- package/dist/sdk/dependency-flag-validation.js +1 -156
- package/dist/sdk/dependency-provenance.js +1 -135
- package/dist/sdk/docs.js +1 -14
- package/dist/sdk/duplicates.js +1 -40
- package/dist/sdk/environment/agent-environment.js +1 -466
- package/dist/sdk/environment/host-environment-errors.js +1 -8
- package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
- package/dist/sdk/environment/source-context.js +1 -28
- package/dist/sdk/environment/tracker-preflight.js +1 -9
- package/dist/sdk/error-code-catalog.js +1 -153
- package/dist/sdk/error-runtime.js +1 -58
- package/dist/sdk/errors.js +1 -58
- package/dist/sdk/eval.js +1 -190
- package/dist/sdk/extension/author-manifest.js +1 -92
- package/dist/sdk/extension/bundled-catalog.js +1 -332
- package/dist/sdk/extension/concurrency.js +1 -25
- package/dist/sdk/extension/copy-scope.d.ts +2 -0
- package/dist/sdk/extension/copy-scope.js +2 -0
- package/dist/sdk/extension/custom-field-collisions.js +1 -30
- package/dist/sdk/extension/describe.js +3 -189
- package/dist/sdk/extension/doctor.js +1 -606
- package/dist/sdk/extension/install-plan.d.ts +69 -0
- package/dist/sdk/extension/install-plan.js +2 -0
- package/dist/sdk/extension/install-receipts.d.ts +7 -0
- package/dist/sdk/extension/install-receipts.js +2 -0
- package/dist/sdk/extension/install-runtime.js +3 -313
- package/dist/sdk/extension/install-snapshot.js +1 -66
- package/dist/sdk/extension/install-sources.js +5 -1057
- package/dist/sdk/extension/managed-state.js +2 -252
- package/dist/sdk/extension/migrations.js +2 -174
- package/dist/sdk/extension/output-ownership.js +1 -25
- package/dist/sdk/extension/runtime-summary.js +1 -18
- package/dist/sdk/extension/scaffold.js +4 -2308
- package/dist/sdk/extension/shared.js +1 -147
- package/dist/sdk/extension/source-resolution.js +1 -65
- package/dist/sdk/extension/update-check.js +1 -67
- package/dist/sdk/extension-command-context.js +1 -44
- package/dist/sdk/extension-contracts.js +1 -73
- package/dist/sdk/extension.d.ts +7 -2
- package/dist/sdk/extension.js +1 -2196
- package/dist/sdk/files.js +1 -535
- package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
- package/dist/sdk/flag-invocation-contracts.js +1 -344
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
- package/dist/sdk/generated-error-code-catalog.js +1 -16
- package/dist/sdk/governance/assurance-action-contracts.js +1 -4
- package/dist/sdk/governance/assurance-action.js +1 -411
- package/dist/sdk/governance/assurance-limits.js +1 -10
- package/dist/sdk/governance/assurance-mutation-error.js +1 -81
- package/dist/sdk/governance/assurance-presets.js +1 -135
- package/dist/sdk/governance/assurance-runtime.js +1 -238
- package/dist/sdk/governance/assurance.js +4 -1182
- package/dist/sdk/governance/boundary-fixtures.js +1 -200
- package/dist/sdk/governance/coverage-assurance.js +1 -60
- package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
- package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
- package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
- package/dist/sdk/governance/defect-recurrence.js +1 -623
- package/dist/sdk/governance/extension-host-version.js +1 -115
- package/dist/sdk/governance/gc.js +1 -368
- package/dist/sdk/governance/health.js +1 -2367
- package/dist/sdk/governance/hierarchy-validation.js +1 -108
- package/dist/sdk/governance/linked-file-report.js +1 -71
- package/dist/sdk/governance/merge-receipt-history.js +1 -206
- package/dist/sdk/governance/provenance-health.js +1 -282
- package/dist/sdk/governance/reindex.js +4 -761
- package/dist/sdk/governance/stale-work.js +1 -82
- package/dist/sdk/governance/status-role-diagnostics.js +1 -35
- package/dist/sdk/governance/storage-integrity.js +1 -280
- package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
- package/dist/sdk/governance/upgrade.js +2 -327
- package/dist/sdk/governance/validate-history-drift.js +1 -81
- package/dist/sdk/governance/validate-item-reader.js +1 -17
- package/dist/sdk/governance/validate-normalization.js +1 -36
- package/dist/sdk/governance/validate.js +1 -2261
- package/dist/sdk/governance/workspace-position.js +1 -163
- package/dist/sdk/governance.d.ts +1 -0
- package/dist/sdk/governance.js +1 -31
- package/dist/sdk/graph/adapter.js +1 -181
- package/dist/sdk/graph/analytics.js +1 -474
- package/dist/sdk/graph/assembly.js +1 -377
- package/dist/sdk/graph/cache.js +1 -160
- package/dist/sdk/graph/centrality.js +1 -258
- package/dist/sdk/graph/conformance.js +1 -130
- package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
- package/dist/sdk/graph/deadline-scheduling.js +2 -0
- package/dist/sdk/graph/durable-cache.d.ts +1 -1
- package/dist/sdk/graph/durable-cache.js +1 -361
- package/dist/sdk/graph/governance-contracts.js +1 -34
- package/dist/sdk/graph/governance.d.ts +13 -1
- package/dist/sdk/graph/governance.js +1 -735
- package/dist/sdk/graph/hierarchy-integrity.js +1 -310
- package/dist/sdk/graph/index.d.ts +3 -2
- package/dist/sdk/graph/index.js +1 -26
- package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
- package/dist/sdk/graph/lifecycle-coverage.js +2 -0
- package/dist/sdk/graph/mutation-advisory.js +1 -176
- package/dist/sdk/graph/remediation.js +1 -197
- package/dist/sdk/graph/run.d.ts +15 -1
- package/dist/sdk/graph/run.js +1 -768
- package/dist/sdk/graph/scheduling.js +1 -124
- package/dist/sdk/graph/traversal.js +1 -284
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
- package/dist/sdk/graph.js +1 -15
- package/dist/sdk/guide-topics.js +1 -707
- package/dist/sdk/guide.js +1 -279
- package/dist/sdk/history/maintenance.d.ts +71 -0
- package/dist/sdk/history/maintenance.js +2 -0
- package/dist/sdk/history/salvage.js +2 -247
- package/dist/sdk/history/subject.d.ts +19 -0
- package/dist/sdk/history/subject.js +2 -0
- package/dist/sdk/history-analytics.js +1 -282
- package/dist/sdk/history-compact.js +1 -527
- package/dist/sdk/history-mcp.js +1 -68
- package/dist/sdk/history-provenance.js +1 -182
- package/dist/sdk/history-read.js +1 -96
- package/dist/sdk/history-redact.d.ts +1 -14
- package/dist/sdk/history-redact.js +1 -643
- package/dist/sdk/history-repair.d.ts +5 -0
- package/dist/sdk/history-repair.js +1 -657
- package/dist/sdk/improvement-ledger-validation.js +1 -62
- package/dist/sdk/improvement-ledger.js +2 -257
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +1 -183
- package/dist/sdk/init-agent-guidance.js +2 -496
- package/dist/sdk/init.js +2 -820
- package/dist/sdk/invocation-author.js +1 -39
- package/dist/sdk/item-children.js +1 -90
- package/dist/sdk/item-metadata-index.js +1 -15
- package/dist/sdk/item-schedule.js +1 -27
- package/dist/sdk/item-transaction.js +1 -396
- package/dist/sdk/learnings.js +1 -29
- package/dist/sdk/lifecycle/append.js +2 -53
- package/dist/sdk/lifecycle/claim.d.ts +2 -0
- package/dist/sdk/lifecycle/claim.js +1 -242
- package/dist/sdk/lifecycle/close-many.js +1 -438
- package/dist/sdk/lifecycle/close.js +1 -468
- package/dist/sdk/lifecycle/copy.js +1 -212
- package/dist/sdk/lifecycle/create.js +1 -1949
- package/dist/sdk/lifecycle/delete.js +1 -45
- package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
- package/dist/sdk/lifecycle/focus.js +1 -91
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
- package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
- package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
- package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
- package/dist/sdk/lifecycle/mcp-actions.js +1 -51
- package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
- package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
- package/dist/sdk/lifecycle/plan.js +1 -1606
- package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
- package/dist/sdk/lifecycle/reopen.js +1 -68
- package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
- package/dist/sdk/lifecycle/restore.d.ts +1 -0
- package/dist/sdk/lifecycle/restore.js +1 -330
- package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
- package/dist/sdk/lifecycle/update-many.js +1 -861
- package/dist/sdk/lifecycle/update.js +1 -2136
- package/dist/sdk/lifecycle-completion.js +1 -92
- package/dist/sdk/lifecycle-policy.js +1 -120
- package/dist/sdk/linked-artifacts.js +1 -530
- package/dist/sdk/mcp/apps.js +4 -133
- package/dist/sdk/mcp/authorization.js +1 -404
- package/dist/sdk/mcp/discovery.js +1 -494
- package/dist/sdk/mcp/interactions.js +1 -336
- package/dist/sdk/mcp/protocol.d.ts +7 -0
- package/dist/sdk/mcp/protocol.js +1 -184
- package/dist/sdk/mcp/skills.js +1 -389
- package/dist/sdk/mcp/subscriptions.js +1 -211
- package/dist/sdk/mcp/tasks.js +2 -430
- package/dist/sdk/mcp/transport.js +1 -260
- package/dist/sdk/merge/abandoned-receipts.js +1 -46
- package/dist/sdk/merge/driver.js +1 -212
- package/dist/sdk/merge/index.js +1 -16
- package/dist/sdk/merge/install.js +3 -561
- package/dist/sdk/merge/receipt-file-boundary.js +1 -46
- package/dist/sdk/merge/receipt-operation.js +1 -96
- package/dist/sdk/merge/receipt-schema.js +1 -397
- package/dist/sdk/merge/receipts.js +4 -525
- package/dist/sdk/merge/reconcile.js +1 -352
- package/dist/sdk/merge/three-way.js +3 -775
- package/dist/sdk/merge.js +1 -10
- package/dist/sdk/mutation-events.js +1 -292
- package/dist/sdk/mutation-guard.js +1 -216
- package/dist/sdk/notes.js +1 -139
- package/dist/sdk/output-contracts.js +1 -172
- package/dist/sdk/output-projection.js +1 -430
- package/dist/sdk/output-token-accounting.js +1 -140
- package/dist/sdk/output.js +1 -64
- package/dist/sdk/ownership-source.js +1 -21
- package/dist/sdk/package-import-adapters.js +1 -442
- package/dist/sdk/package-migrations.js +1 -20
- package/dist/sdk/package-runtime-options.js +1 -80
- package/dist/sdk/pagination.js +1 -162
- package/dist/sdk/profile.js +1 -454
- package/dist/sdk/provenance.js +1 -258
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/activity.js +1 -401
- package/dist/sdk/query/aggregate.d.ts +16 -0
- package/dist/sdk/query/aggregate.js +1 -390
- package/dist/sdk/query/calendar.js +1 -964
- package/dist/sdk/query/complete-list.js +1 -215
- package/dist/sdk/query/context.js +1 -1702
- package/dist/sdk/query/duplicate-candidates.js +1 -70
- package/dist/sdk/query/get.js +1 -450
- package/dist/sdk/query/history.js +1 -186
- package/dist/sdk/query/item-filter-options.js +1 -9
- package/dist/sdk/query/light-metadata.js +1 -18
- package/dist/sdk/query/list-filter-shared.js +1 -81
- package/dist/sdk/query/list.js +1 -1304
- package/dist/sdk/query/multi-value-filters.js +1 -78
- package/dist/sdk/query/next.js +1 -513
- package/dist/sdk/query/parsers.js +1 -44
- package/dist/sdk/query/projection-contracts.js +1 -184
- package/dist/sdk/query/search-contracts.js +1 -230
- package/dist/sdk/query/search-pagination.js +1 -35
- package/dist/sdk/query/search-rendering.js +1 -105
- package/dist/sdk/query/search.js +2 -1987
- package/dist/sdk/query.js +1 -35
- package/dist/sdk/read-output/continuation.js +1 -194
- package/dist/sdk/read-output-budget.js +1 -135
- package/dist/sdk/read-output-contracts.js +1 -1225
- package/dist/sdk/read-output-rows.js +1 -186
- package/dist/sdk/read-output-session.js +1 -208
- package/dist/sdk/relationship-analytics.js +1 -410
- package/dist/sdk/relationship-context.js +1 -284
- package/dist/sdk/relationship-history.js +4 -519
- package/dist/sdk/relationship-kinds/contract.js +1 -22
- package/dist/sdk/relationship-migration.js +1 -77
- package/dist/sdk/relationships.js +1 -579
- package/dist/sdk/reproducibility/process.js +1 -87
- package/dist/sdk/runtime-action-aliases.js +1 -59
- package/dist/sdk/runtime-extended-actions.js +1 -177
- package/dist/sdk/runtime-input.js +1 -614
- package/dist/sdk/runtime-primitives.js +1 -84
- package/dist/sdk/runtime-public-contracts.js +1 -4
- package/dist/sdk/runtime-stats-options.js +1 -38
- package/dist/sdk/runtime.js +1 -1928
- package/dist/sdk/scheduling-shortcuts.js +1 -63
- package/dist/sdk/schema-migration.js +3 -856
- package/dist/sdk/schema.js +1 -1376
- package/dist/sdk/search-refresh-worker.js +1 -18
- package/dist/sdk/similarity-scoring.js +1 -53
- package/dist/sdk/similarity.js +1 -326
- package/dist/sdk/start-task-status.js +1 -14
- package/dist/sdk/stats.js +1 -270
- package/dist/sdk/structured-mutations.js +1 -580
- package/dist/sdk/telemetry-flush.js +1 -13
- package/dist/sdk/telemetry.js +1 -405
- package/dist/sdk/templates.js +2 -292
- package/dist/sdk/test/batch.js +2 -509
- package/dist/sdk/test/entry.js +1 -70
- package/dist/sdk/test/execution.js +6 -2211
- package/dist/sdk/test/linked-command-detection.js +1 -546
- package/dist/sdk/test/measurements.js +1 -91
- package/dist/sdk/test/parsers.js +1 -545
- package/dist/sdk/test/runs.js +1 -193
- package/dist/sdk/test/trust.js +2 -206
- package/dist/sdk/testing.js +4 -1391
- package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
- package/dist/sdk/traceability/source-traceability.js +1 -292
- package/dist/sdk/tracker-root-discovery.js +1 -9
- package/dist/sdk/workspace-contracts-cache.js +1 -28
- package/dist/sdk/workspace-contracts.js +1 -33
- package/dist/sdk/workspace-memory.js +2 -318
- package/dist/sdk/workspace-recipe.js +1 -71
- package/dist/sdk/workspace-snapshot.js +4 -613
- package/dist/sdk/workspace-transaction-gc.js +1 -149
- package/dist/sdk/workspace-transaction.js +2 -363
- package/dist/sdk/workspace.js +3 -127
- package/dist/types/index.js +1 -9
- package/dist/types.js +1 -245
- package/docs/AGENT_GUIDE.md +1 -1
- package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
- package/docs/EXTENSIONS.md +1 -0
- package/docs/HISTORY_MAINTENANCE.md +125 -0
- package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
- package/docs/PACKAGE_EVIDENCE.md +92 -0
- package/docs/PLANNING_MEASUREMENTS.md +183 -0
- package/docs/README.md +3 -0
- package/docs/RELEASING.md +1 -0
- package/docs/SCRIPTING.md +21 -0
- package/docs/TESTING.md +23 -0
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +5 -5
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +2 -2
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/finalize-build.mjs +45 -3
- package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
- package/dist/cli-bundle/chunks/chunk-BAX2BYUW.js +0 -2111
- package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
- package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
- package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
- package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
- package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
- package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
- package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
- package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
- package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
- package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
- package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
- package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
|
@@ -1,469 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0e166cbb-ef9c-5016-89a6-07f287e00a2e")}catch(e){}}();
|
|
3
|
-
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
4
|
-
import { toItemRecord, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, buildItemNotFoundError, listAllItemMetadataLight, locateItem, mutateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, resolveIsoOrRelative, shouldCompletePlanOnClose, getActiveExtensionRegistrations, } from "../runtime-primitives.js";
|
|
5
|
-
import { collectBlockedByIds, indexBlockedByIds } from "../actionability.js";
|
|
6
|
-
import { applyTerminalOrderingPolicy, requireTerminalReason, } from "../lifecycle-policy.js";
|
|
7
|
-
import { nowIso } from "../../core/shared/time.js";
|
|
8
|
-
import { renderPmCommand } from "../command-line.js";
|
|
9
|
-
const CLOSE_VALIDATION_FIELDS = [
|
|
10
|
-
{ key: "resolution", label: "resolution (--resolution)" },
|
|
11
|
-
{
|
|
12
|
-
key: "expected_result",
|
|
13
|
-
label: "expected_result (--expected-result)",
|
|
14
|
-
},
|
|
15
|
-
{ key: "actual_result", label: "actual_result (--actual-result)" },
|
|
16
|
-
];
|
|
17
|
-
function parseValidateCloseMode(raw) {
|
|
18
|
-
if (raw === undefined) {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
const normalized = raw.trim().toLowerCase();
|
|
22
|
-
if (normalized.length === 0 || normalized === "warn") {
|
|
23
|
-
return "warn";
|
|
24
|
-
}
|
|
25
|
-
if (normalized === "off" ||
|
|
26
|
-
normalized === "none" ||
|
|
27
|
-
normalized === "disabled") {
|
|
28
|
-
return "off";
|
|
29
|
-
}
|
|
30
|
-
if (normalized === "strict") {
|
|
31
|
-
return "strict";
|
|
32
|
-
}
|
|
33
|
-
throw new PmCliError(`Invalid --validate-close mode "${raw}" (expected "off", "warn", or "strict")`, EXIT_CODE.USAGE);
|
|
34
|
-
}
|
|
35
|
-
function findMissingCloseValidationFields(itemMetadata) {
|
|
36
|
-
const missing = [];
|
|
37
|
-
for (const field of CLOSE_VALIDATION_FIELDS) {
|
|
38
|
-
const rawValue = itemMetadata[field.key];
|
|
39
|
-
if (typeof rawValue !== "string" || rawValue.trim().length === 0) {
|
|
40
|
-
missing.push(field);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return missing;
|
|
44
|
-
}
|
|
45
|
-
/** Build an argv-safe update that appends acceptance evidence without repeating a terminal transition. */
|
|
46
|
-
function closeEvidenceRecovery(metadata, pmRoot, options = {}) {
|
|
47
|
-
const missing = findMissingCloseValidationFields(metadata);
|
|
48
|
-
if (missing.length === 0)
|
|
49
|
-
return undefined;
|
|
50
|
-
const values = { resolution: options.resolution, expected_result: options.expectedResult, actual_result: options.actualResult };
|
|
51
|
-
const missingFlags = missing.map((field) => `--${field.key.replaceAll("_", "-")}`);
|
|
52
|
-
const args = ["--pm-path", pmRoot, "update", metadata.id, ...missing.flatMap((field, index) => [missingFlags[index], values[field.key]?.trim() || "<value>"])];
|
|
53
|
-
return { missing: missingFlags, suggested_retry: renderPmCommand(args), suggested_retry_args: args };
|
|
54
|
-
}
|
|
55
|
-
async function duplicateChainReferencesClosingItem(loadItemById, initialDuplicateOf, closingId) {
|
|
56
|
-
const visited = new Set();
|
|
57
|
-
let current = initialDuplicateOf;
|
|
58
|
-
while (typeof current === "string" && current.trim().length > 0) {
|
|
59
|
-
const currentId = current.trim();
|
|
60
|
-
if (currentId === closingId) {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
if (visited.has(currentId)) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
visited.add(currentId);
|
|
67
|
-
current = (await loadItemById(currentId))?.duplicate_of;
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
function shouldApplyDuplicateFallback(value) {
|
|
72
|
-
return typeof value !== "string" || value.trim().length === 0;
|
|
73
|
-
}
|
|
74
|
-
async function assertDuplicateTargetExists(pmRoot, settings, duplicateOf, closingId) {
|
|
75
|
-
const rawTarget = duplicateOf?.trim();
|
|
76
|
-
if (!rawTarget) {
|
|
77
|
-
return undefined;
|
|
78
|
-
}
|
|
79
|
-
if (rawTarget === closingId) {
|
|
80
|
-
throw new PmCliError("An item cannot be closed as a duplicate of itself.", EXIT_CODE.USAGE, {
|
|
81
|
-
code: "duplicate_target_self",
|
|
82
|
-
why: "--duplicate-of must identify the canonical item that should remain open or already represent the work.",
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
|
|
86
|
-
const itemCache = new Map();
|
|
87
|
-
const loadItemById = async (id) => {
|
|
88
|
-
if (itemCache.has(id)) {
|
|
89
|
-
return itemCache.get(id) ?? null;
|
|
90
|
-
}
|
|
91
|
-
const located = await locateItem(pmRoot, id, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
|
|
92
|
-
if (!located) {
|
|
93
|
-
itemCache.set(id, null);
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
const { document } = await readLocatedItem(located, {
|
|
97
|
-
schema: settings.schema,
|
|
98
|
-
});
|
|
99
|
-
itemCache.set(id, document.metadata);
|
|
100
|
-
return document.metadata;
|
|
101
|
-
};
|
|
102
|
-
const target = await loadItemById(rawTarget);
|
|
103
|
-
if (!target) {
|
|
104
|
-
throw new PmCliError(`Duplicate target "${rawTarget}" was not found. Create or locate the canonical item first.`, EXIT_CODE.USAGE, {
|
|
105
|
-
code: "duplicate_target_missing",
|
|
106
|
-
why: "Duplicate closure should point at a real canonical pm item so future dedupe and changelog tooling can trace the relationship.",
|
|
107
|
-
examples: [
|
|
108
|
-
`pm close ${closingId} "Duplicate of ${rawTarget}" --duplicate-of ${rawTarget}`,
|
|
109
|
-
],
|
|
110
|
-
nextSteps: [
|
|
111
|
-
"Run pm search/list to find the canonical item, then retry with --duplicate-of <id>.",
|
|
112
|
-
],
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
if (await duplicateChainReferencesClosingItem(loadItemById, target.duplicate_of, closingId)) {
|
|
116
|
-
throw new PmCliError(`Circular duplicate reference detected. Target "${rawTarget}" points back to "${closingId}".`, EXIT_CODE.USAGE, {
|
|
117
|
-
code: "duplicate_target_circular",
|
|
118
|
-
why: "Circular duplicate relationships create loops for dedupe and status propagation tooling.",
|
|
119
|
-
nextSteps: [
|
|
120
|
-
"Choose the existing canonical item, or clear the target duplicate_of metadata before closing this item as a duplicate.",
|
|
121
|
-
],
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
if (typeof target.duplicate_of === "string" &&
|
|
125
|
-
target.duplicate_of.trim().length > 0) {
|
|
126
|
-
throw new PmCliError(`Duplicate target "${rawTarget}" is already marked as a duplicate of "${target.duplicate_of.trim()}".`, EXIT_CODE.USAGE, {
|
|
127
|
-
code: "duplicate_target_is_duplicate",
|
|
128
|
-
why: "Duplicate closure should point directly at the canonical item, not another duplicate.",
|
|
129
|
-
examples: [
|
|
130
|
-
`pm close ${closingId} "Duplicate of ${target.duplicate_of.trim()}" --duplicate-of ${target.duplicate_of.trim()}`,
|
|
131
|
-
],
|
|
132
|
-
nextSteps: [
|
|
133
|
-
"Use the canonical item referenced by duplicate_of as the --duplicate-of target.",
|
|
134
|
-
],
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
return target.id;
|
|
138
|
-
}
|
|
139
|
-
function findActiveChildIds(items, parentId, statusRegistry) {
|
|
140
|
-
return items
|
|
141
|
-
.filter((item) => item.parent === parentId &&
|
|
142
|
-
!isTerminalStatus(item.status, statusRegistry))
|
|
143
|
-
.map((item) => item.id)
|
|
144
|
-
.sort((left, right) => left.localeCompare(right));
|
|
145
|
-
}
|
|
146
|
-
function findAutoUnblockCandidates(items, closedId, statusRegistry) {
|
|
147
|
-
const itemsById = new Map(items.map((item) => [item.id.trim().toLowerCase(), item]));
|
|
148
|
-
const blockerIdsByItem = indexBlockedByIds(items);
|
|
149
|
-
const normalizedClosedId = closedId.trim().toLowerCase();
|
|
150
|
-
const blockedStatuses = statusRegistry.blocked_statuses;
|
|
151
|
-
return items
|
|
152
|
-
.filter((item) => blockedStatuses.has(item.status))
|
|
153
|
-
.map((item) => ({
|
|
154
|
-
item,
|
|
155
|
-
blockerIds: blockerIdsByItem.get(item.id.trim().toLowerCase()),
|
|
156
|
-
}))
|
|
157
|
-
.filter(({ blockerIds }) => blockerIds.includes(normalizedClosedId))
|
|
158
|
-
.filter(({ blockerIds }) => blockerIds.every((blockerId) => {
|
|
159
|
-
if (blockerId === normalizedClosedId) {
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
const blocker = itemsById.get(blockerId);
|
|
163
|
-
return (blocker !== undefined &&
|
|
164
|
-
isTerminalStatus(blocker.status, statusRegistry));
|
|
165
|
-
}))
|
|
166
|
-
.map(({ item, blockerIds }) => ({ id: item.id, blocker_ids: blockerIds }))
|
|
167
|
-
.sort((left, right) => left.id.localeCompare(right.id));
|
|
168
|
-
}
|
|
169
|
-
async function autoUnblockResolvedDependents(pmRoot, settings, items, closedId, author, statusRegistry) {
|
|
170
|
-
const candidates = findAutoUnblockCandidates(items, closedId, statusRegistry);
|
|
171
|
-
const warnings = [];
|
|
172
|
-
for (const candidate of candidates) {
|
|
173
|
-
try {
|
|
174
|
-
const unblocked = await mutateItem({
|
|
175
|
-
pmRoot,
|
|
176
|
-
settings,
|
|
177
|
-
id: candidate.id,
|
|
178
|
-
op: "update",
|
|
179
|
-
author,
|
|
180
|
-
message: `Auto-unblocked after blocker ${closedId} closed`,
|
|
181
|
-
mutate(document) {
|
|
182
|
-
/* c8 ignore start -- normal auto-unblock candidates carry dependency metadata; fallback preserves hand-edited scalar-only blockers. */
|
|
183
|
-
const dependencies = document.metadata.dependencies ?? [];
|
|
184
|
-
/* c8 ignore stop */
|
|
185
|
-
const remainingDependencies = dependencies.filter((dependency) => {
|
|
186
|
-
const dependencyId = dependency.id.trim().toLowerCase();
|
|
187
|
-
return (dependency.kind !== "blocked_by" ||
|
|
188
|
-
!candidate.blocker_ids.includes(dependencyId));
|
|
189
|
-
});
|
|
190
|
-
document.metadata.status = statusRegistry.open_status;
|
|
191
|
-
delete document.metadata.blocked_by;
|
|
192
|
-
delete document.metadata.blocked_reason;
|
|
193
|
-
document.metadata.unblock_note = `Auto-unblocked after blocker ${closedId} closed; all blockers resolved (${candidate.blocker_ids.join(", ")}).`;
|
|
194
|
-
if (remainingDependencies.length > 0) {
|
|
195
|
-
document.metadata.dependencies = remainingDependencies;
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
delete document.metadata.dependencies;
|
|
199
|
-
}
|
|
200
|
-
const changedFields = [
|
|
201
|
-
"status",
|
|
202
|
-
"blocked_by",
|
|
203
|
-
"blocked_reason",
|
|
204
|
-
"unblock_note",
|
|
205
|
-
];
|
|
206
|
-
if (remainingDependencies.length !== dependencies.length) {
|
|
207
|
-
changedFields.push("dependencies");
|
|
208
|
-
}
|
|
209
|
-
return {
|
|
210
|
-
changedFields,
|
|
211
|
-
};
|
|
212
|
-
},
|
|
213
|
-
});
|
|
214
|
-
warnings.push(`auto_unblocked:${unblocked.item.id}:resolved_blockers=${candidate.blocker_ids.join(",")}`);
|
|
215
|
-
/* c8 ignore start -- defensive fan-out failure path; normal lock/claim state is auditable and still unblocks. */
|
|
216
|
-
}
|
|
217
|
-
catch (error) {
|
|
218
|
-
const reason = error instanceof Error
|
|
219
|
-
? error.message.replace(/\s+/g, " ").trim()
|
|
220
|
-
: "unknown";
|
|
221
|
-
warnings.push(`auto_unblock_failed:${candidate.id}:${reason}`);
|
|
222
|
-
}
|
|
223
|
-
/* c8 ignore stop */
|
|
224
|
-
}
|
|
225
|
-
return warnings;
|
|
226
|
-
}
|
|
227
|
-
function applyInlineCloseFields(metadata, options) {
|
|
228
|
-
const changedFields = [];
|
|
229
|
-
const inlineCloseFields = [
|
|
230
|
-
{ option: options.resolution, key: "resolution" },
|
|
231
|
-
{ option: options.expectedResult, key: "expected_result" },
|
|
232
|
-
{ option: options.actualResult, key: "actual_result" },
|
|
233
|
-
];
|
|
234
|
-
for (const { option, key } of inlineCloseFields) {
|
|
235
|
-
if (typeof option !== "string") {
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
const trimmed = option.trim();
|
|
239
|
-
if (trimmed.length === 0) {
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
metadata[key] = trimmed;
|
|
243
|
-
changedFields.push(key);
|
|
244
|
-
}
|
|
245
|
-
return changedFields;
|
|
246
|
-
}
|
|
247
|
-
function applyDuplicateCloseMetadata(metadata, duplicateOf) {
|
|
248
|
-
if (duplicateOf === undefined) {
|
|
249
|
-
return [];
|
|
250
|
-
}
|
|
251
|
-
metadata.duplicate_of = duplicateOf;
|
|
252
|
-
const duplicateFallbackFields = [];
|
|
253
|
-
const fallbackValues = [
|
|
254
|
-
{ key: "resolution", value: `Duplicate of ${duplicateOf}` },
|
|
255
|
-
{
|
|
256
|
-
key: "expected_result",
|
|
257
|
-
value: `Canonical item ${duplicateOf} tracks the work.`,
|
|
258
|
-
},
|
|
259
|
-
{ key: "actual_result", value: `Closed as duplicate of ${duplicateOf}.` },
|
|
260
|
-
];
|
|
261
|
-
for (const { key, value } of fallbackValues) {
|
|
262
|
-
if (shouldApplyDuplicateFallback(metadata[key])) {
|
|
263
|
-
metadata[key] = value;
|
|
264
|
-
duplicateFallbackFields.push(key);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return duplicateFallbackFields;
|
|
268
|
-
}
|
|
269
|
-
function collectCloseValidationWarnings(metadata, validateCloseMode, activeChildIds, pmRoot) {
|
|
270
|
-
const warnings = [];
|
|
271
|
-
if (validateCloseMode !== "off") {
|
|
272
|
-
const missingFields = findMissingCloseValidationFields(metadata);
|
|
273
|
-
if (missingFields.length > 0) {
|
|
274
|
-
const missingLabels = missingFields.map((field) => field.label);
|
|
275
|
-
if (validateCloseMode === "strict") {
|
|
276
|
-
const missingFlags = missingFields.map((field) => `--${field.key.replaceAll("_", "-")}`);
|
|
277
|
-
const updateTokens = [
|
|
278
|
-
"--pm-path",
|
|
279
|
-
pmRoot,
|
|
280
|
-
"update",
|
|
281
|
-
metadata.id,
|
|
282
|
-
...missingFlags.flatMap((flag) => [flag, "<value>"]),
|
|
283
|
-
];
|
|
284
|
-
throw new PmCliError(`Cannot close item ${metadata.id}: missing ${missingLabels.join(", ")}. Populate fields or use --validate-close warn.`, EXIT_CODE.USAGE, {
|
|
285
|
-
code: "close_validation_missing_fields",
|
|
286
|
-
recovery: {
|
|
287
|
-
missing: missingFlags,
|
|
288
|
-
suggested_retry: renderPmCommand(updateTokens),
|
|
289
|
-
},
|
|
290
|
-
nextSteps: [
|
|
291
|
-
"Run the suggested pm update, then retry the original pm close invocation.",
|
|
292
|
-
"Use --validate-close warn only when governance permits an evidenced exception.",
|
|
293
|
-
],
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
warnings.push(`close_validation_missing_fields:${metadata.id}:${missingLabels.join(",")}`);
|
|
297
|
-
}
|
|
298
|
-
if (activeChildIds.length > 0) {
|
|
299
|
-
if (validateCloseMode === "strict") {
|
|
300
|
-
throw new PmCliError(`Cannot close item ${metadata.id}: active child items remain open (${activeChildIds.join(", ")}). Close, cancel, or re-parent them first, or use --validate-close warn.`, EXIT_CODE.USAGE);
|
|
301
|
-
}
|
|
302
|
-
warnings.push(`close_validation_active_children:${metadata.id}:${activeChildIds.join(",")}`);
|
|
303
|
-
}
|
|
304
|
-
return warnings;
|
|
305
|
-
}
|
|
306
|
-
if (activeChildIds.length > 0) {
|
|
307
|
-
warnings.push(`closed_with_active_children:${metadata.id}:${activeChildIds.join(",")}`);
|
|
308
|
-
}
|
|
309
|
-
return warnings;
|
|
310
|
-
}
|
|
311
|
-
function applyCloseReason(metadata, closeReason) {
|
|
312
|
-
if (closeReason !== undefined) {
|
|
313
|
-
metadata.close_reason = closeReason;
|
|
314
|
-
return ["close_reason"];
|
|
315
|
-
}
|
|
316
|
-
return [];
|
|
317
|
-
}
|
|
318
|
-
function clearCloseAssignee(metadata) {
|
|
319
|
-
if (metadata.assignee === undefined) {
|
|
320
|
-
return [];
|
|
321
|
-
}
|
|
322
|
-
delete metadata.assignee;
|
|
323
|
-
return ["assignee"];
|
|
324
|
-
}
|
|
325
|
-
/** Enforce terminal and closure policies before applying acceptance fields and the atomic lifecycle transition. */
|
|
326
|
-
function mutateCloseMetadata(metadata, context) {
|
|
327
|
-
if (isTerminalStatus(metadata.status, context.statusRegistry) &&
|
|
328
|
-
!context.force) {
|
|
329
|
-
throw new PmCliError(`Item ${metadata.id} is already terminal; use pm update to append acceptance evidence, or --force only for an intentional repeat closure.`, EXIT_CODE.CONFLICT, { recovery: closeEvidenceRecovery(metadata, context.pmRoot, context.options) });
|
|
330
|
-
}
|
|
331
|
-
const inlineChangedFields = applyInlineCloseFields(metadata, context.options);
|
|
332
|
-
const duplicateFallbackFields = applyDuplicateCloseMetadata(metadata, context.duplicateOf);
|
|
333
|
-
const mutationWarnings = collectCloseValidationWarnings(metadata, context.validateCloseMode, context.activeChildIds, context.pmRoot);
|
|
334
|
-
metadata.status = context.statusRegistry.close_status;
|
|
335
|
-
metadata.closed_at = context.closedAt;
|
|
336
|
-
const shouldWriteCompletedAt = context.options.completedAt !== undefined ||
|
|
337
|
-
metadata.completed_at === undefined;
|
|
338
|
-
if (shouldWriteCompletedAt) {
|
|
339
|
-
metadata.completed_at = context.completedAt;
|
|
340
|
-
}
|
|
341
|
-
const changedFields = [
|
|
342
|
-
"status",
|
|
343
|
-
"closed_at",
|
|
344
|
-
...(shouldWriteCompletedAt ? ["completed_at"] : []),
|
|
345
|
-
...applyCloseReason(metadata, context.closeReason),
|
|
346
|
-
...inlineChangedFields,
|
|
347
|
-
];
|
|
348
|
-
if (shouldCompletePlanOnClose(metadata)) {
|
|
349
|
-
metadata.plan_mode = "completed";
|
|
350
|
-
changedFields.push("plan_mode");
|
|
351
|
-
}
|
|
352
|
-
if (context.duplicateOf !== undefined) {
|
|
353
|
-
changedFields.push("duplicate_of");
|
|
354
|
-
for (const key of duplicateFallbackFields) {
|
|
355
|
-
/* v8 ignore start -- duplicate fallback keys are already pre-deduped by applyDuplicateCloseMetadata in covered close paths */
|
|
356
|
-
if (!changedFields.includes(key)) {
|
|
357
|
-
changedFields.push(key);
|
|
358
|
-
}
|
|
359
|
-
/* v8 ignore stop */
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
changedFields.push(...clearCloseAssignee(metadata));
|
|
363
|
-
const blockerCleanup = applyTerminalOrderingPolicy(metadata, context.lifecyclePolicy);
|
|
364
|
-
changedFields.push(...blockerCleanup.changedFields);
|
|
365
|
-
mutationWarnings.push(...blockerCleanup.warnings);
|
|
366
|
-
return {
|
|
367
|
-
changedFields,
|
|
368
|
-
...(mutationWarnings.length > 0 ? { warnings: mutationWarnings } : {}),
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
/** Public contract for test only close command, shared by SDK and presentation-layer consumers. */
|
|
372
|
-
export const _testOnlyCloseCommand = {
|
|
373
|
-
blockedByIds: collectBlockedByIds,
|
|
374
|
-
};
|
|
375
|
-
/** Close one item through the SDK-owned lifecycle transaction and policy. */
|
|
376
|
-
export async function closeItem(id, closeReasonText, options, global) {
|
|
377
|
-
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
378
|
-
await assertInitializedTracker(pmRoot);
|
|
379
|
-
const settings = await readSettings(pmRoot);
|
|
380
|
-
const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
|
|
381
|
-
const author = resolveAuthor(options.author, settings.author_default);
|
|
382
|
-
// GH-250: verify the target item EXISTS before the governance close-reason
|
|
383
|
-
// gate fires. Otherwise closing a typo'd id with no reason reports
|
|
384
|
-
// "Close reason text is required" and hides the real cause (bad id) until a
|
|
385
|
-
// reason is supplied. Existence is the more fundamental precondition, so it
|
|
386
|
-
// is validated first regardless of whether a reason was provided.
|
|
387
|
-
const typeToFolder = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations()).type_to_folder;
|
|
388
|
-
const located = await locateItem(pmRoot, id, settings.id_prefix, settings.item_format, typeToFolder);
|
|
389
|
-
if (!located) {
|
|
390
|
-
throw await buildItemNotFoundError(pmRoot, id, settings.id_prefix, typeToFolder);
|
|
391
|
-
}
|
|
392
|
-
// GH-204: resolve the duplicate target BEFORE reason validation so
|
|
393
|
-
// `pm close <id> --duplicate-of <canonical>` succeeds under
|
|
394
|
-
// governance.require_close_reason without a manual reason — when no
|
|
395
|
-
// positional/--reason text is provided the reason defaults to
|
|
396
|
-
// "Duplicate of <id>" (mirroring the auto-filled closure metadata).
|
|
397
|
-
// Explicit reason text still wins.
|
|
398
|
-
const duplicateOf = await assertDuplicateTargetExists(pmRoot, settings, options.duplicateOf, located.id);
|
|
399
|
-
// pm-7x8d / pm-9hry / GH-204: when no explicit positional/--reason text is given, derive
|
|
400
|
-
// the close reason from the next-best closure signal instead of hard-blocking
|
|
401
|
-
// under governance.require_close_reason. Precedence: explicit reason text >
|
|
402
|
-
// --duplicate-of ("Duplicate of <id>") > --resolution summary > --message.
|
|
403
|
-
// Resolution still writes metadata.resolution below; message still writes the
|
|
404
|
-
// history entry through mutateItem. Reusing either as the close reason just lets
|
|
405
|
-
// a single agent-authored close command succeed when it already supplied a
|
|
406
|
-
// closure summary through another structured option.
|
|
407
|
-
const lifecyclePolicy = {
|
|
408
|
-
requireCloseReason: options.lifecyclePolicy?.requireCloseReason ??
|
|
409
|
-
settings.governance.require_close_reason,
|
|
410
|
-
orderingEdges: options.lifecyclePolicy?.orderingEdges ?? "preserve",
|
|
411
|
-
};
|
|
412
|
-
const closeReason = requireTerminalReason({
|
|
413
|
-
explicit: closeReasonText,
|
|
414
|
-
duplicateOf,
|
|
415
|
-
resolution: options.resolution,
|
|
416
|
-
message: options.message,
|
|
417
|
-
}, lifecyclePolicy.requireCloseReason).closeReason;
|
|
418
|
-
const validateCloseMode = parseValidateCloseMode(options.validateClose) ??
|
|
419
|
-
settings.governance.close_validation_default;
|
|
420
|
-
// C3 (pm-fu5d): scan for active children even under minimal governance so
|
|
421
|
-
// closing a parent is never silently orphaning — off mode emits an
|
|
422
|
-
// informational note instead of the warn/strict validation warning.
|
|
423
|
-
const trackerItems = await listAllItemMetadataLight(pmRoot, settings.item_format, typeToFolder, undefined, settings.schema);
|
|
424
|
-
const activeChildIds = findActiveChildIds(trackerItems, located.id, statusRegistry);
|
|
425
|
-
const closedAt = nowIso();
|
|
426
|
-
const completedAt = options.completedAt === undefined
|
|
427
|
-
? closedAt
|
|
428
|
-
: resolveIsoOrRelative(options.completedAt, new Date(closedAt), "completed-at");
|
|
429
|
-
const result = await mutateItem({
|
|
430
|
-
pmRoot,
|
|
431
|
-
settings,
|
|
432
|
-
id: located.id,
|
|
433
|
-
op: "close",
|
|
434
|
-
author,
|
|
435
|
-
message: options.message,
|
|
436
|
-
force: options.force,
|
|
437
|
-
mutate(document) {
|
|
438
|
-
return mutateCloseMetadata(document.metadata, {
|
|
439
|
-
pmRoot,
|
|
440
|
-
statusRegistry,
|
|
441
|
-
force: options.force,
|
|
442
|
-
options,
|
|
443
|
-
duplicateOf,
|
|
444
|
-
validateCloseMode,
|
|
445
|
-
activeChildIds,
|
|
446
|
-
closeReason,
|
|
447
|
-
closedAt,
|
|
448
|
-
completedAt,
|
|
449
|
-
lifecyclePolicy,
|
|
450
|
-
});
|
|
451
|
-
},
|
|
452
|
-
});
|
|
453
|
-
const recovery = validateCloseMode === "warn" ? closeEvidenceRecovery(result.item, pmRoot) : undefined;
|
|
454
|
-
return {
|
|
455
|
-
item: toItemRecord(result.item),
|
|
456
|
-
changed_fields: result.changedFields,
|
|
457
|
-
...(recovery ? { recovery } : {}),
|
|
458
|
-
warnings: [
|
|
459
|
-
...result.warnings,
|
|
460
|
-
...(await autoUnblockResolvedDependents(pmRoot, settings, trackerItems, located.id, author, statusRegistry)),
|
|
461
|
-
],
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
/** Compatibility command-shaped wrapper over the SDK-owned close operation. */
|
|
465
|
-
export function runClose(id, closeReasonText, options, global) {
|
|
466
|
-
return closeItem(id, closeReasonText, options, global);
|
|
467
|
-
}
|
|
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]="49e375b7-49a8-5b6f-89c8-be70d334b78f")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{toItemRecord,isTerminalStatus,resolveItemTypeRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,PmCliError,buildItemNotFoundError,listAllItemMetadataLight,locateItem,mutateItem,readLocatedItem,resolvePmRoot,readSettings,resolveAuthor,resolveIsoOrRelative,shouldCompletePlanOnClose,getActiveExtensionRegistrations}from"../runtime-primitives.js";import{collectBlockedByIds,indexBlockedByIds}from"../actionability.js";import{applyTerminalOrderingPolicy,requireTerminalReason}from"../lifecycle-policy.js";import{nowIso}from"../../core/shared/time.js";import{renderPmCommand}from"../command-line.js";const CLOSE_VALIDATION_FIELDS=[{key:"resolution",label:"resolution (--resolution)"},{key:"expected_result",label:"expected_result (--expected-result)"},{key:"actual_result",label:"actual_result (--actual-result)"}];function parseValidateCloseMode(raw){if(raw===void 0){return void 0}const normalized=raw.trim().toLowerCase();if(normalized.length===0||normalized==="warn"){return"warn"}if(normalized==="off"||normalized==="none"||normalized==="disabled"){return"off"}if(normalized==="strict"){return"strict"}throw new PmCliError(`Invalid --validate-close mode "${raw}" (expected "off", "warn", or "strict")`,EXIT_CODE.USAGE)}function findMissingCloseValidationFields(itemMetadata){const missing=[];for(const field of CLOSE_VALIDATION_FIELDS){const rawValue=itemMetadata[field.key];if(typeof rawValue!=="string"||rawValue.trim().length===0){missing.push(field)}}return missing}function closeEvidenceRecovery(metadata,pmRoot,options={}){const missing=findMissingCloseValidationFields(metadata);if(missing.length===0)return void 0;const values={resolution:options.resolution,expected_result:options.expectedResult,actual_result:options.actualResult};const missingFlags=missing.map(field=>`--${field.key.replaceAll("_","-")}`);const args=["--pm-path",pmRoot,"update",metadata.id,...missing.flatMap((field,index)=>[missingFlags[index],values[field.key]?.trim()||"<value>"])];return{missing:missingFlags,suggested_retry:renderPmCommand(args),suggested_retry_args:args}}async function duplicateChainReferencesClosingItem(loadItemById,initialDuplicateOf,closingId){const visited=new Set;let current=initialDuplicateOf;while(typeof current==="string"&¤t.trim().length>0){const currentId=current.trim();if(currentId===closingId){return true}if(visited.has(currentId)){return false}visited.add(currentId);current=(await loadItemById(currentId))?.duplicate_of}return false}function shouldApplyDuplicateFallback(value){return typeof value!=="string"||value.trim().length===0}async function assertDuplicateTargetExists(pmRoot,settings,duplicateOf,closingId){const rawTarget=duplicateOf?.trim();if(!rawTarget){return void 0}if(rawTarget===closingId){throw new PmCliError("An item cannot be closed as a duplicate of itself.",EXIT_CODE.USAGE,{code:"duplicate_target_self",why:"--duplicate-of must identify the canonical item that should remain open or already represent the work."})}const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());const itemCache=new Map;const loadItemById=async id=>{if(itemCache.has(id)){return itemCache.get(id)??null}const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);if(!located){itemCache.set(id,null);return null}const{document}=await readLocatedItem(located,{schema:settings.schema});itemCache.set(id,document.metadata);return document.metadata};const target=await loadItemById(rawTarget);if(!target){throw new PmCliError(`Duplicate target "${rawTarget}" was not found. Create or locate the canonical item first.`,EXIT_CODE.USAGE,{code:"duplicate_target_missing",why:"Duplicate closure should point at a real canonical pm item so future dedupe and changelog tooling can trace the relationship.",examples:[`pm close ${closingId} "Duplicate of ${rawTarget}" --duplicate-of ${rawTarget}`],nextSteps:["Run pm search/list to find the canonical item, then retry with --duplicate-of <id>."]})}if(await duplicateChainReferencesClosingItem(loadItemById,target.duplicate_of,closingId)){throw new PmCliError(`Circular duplicate reference detected. Target "${rawTarget}" points back to "${closingId}".`,EXIT_CODE.USAGE,{code:"duplicate_target_circular",why:"Circular duplicate relationships create loops for dedupe and status propagation tooling.",nextSteps:["Choose the existing canonical item, or clear the target duplicate_of metadata before closing this item as a duplicate."]})}if(typeof target.duplicate_of==="string"&&target.duplicate_of.trim().length>0){throw new PmCliError(`Duplicate target "${rawTarget}" is already marked as a duplicate of "${target.duplicate_of.trim()}".`,EXIT_CODE.USAGE,{code:"duplicate_target_is_duplicate",why:"Duplicate closure should point directly at the canonical item, not another duplicate.",examples:[`pm close ${closingId} "Duplicate of ${target.duplicate_of.trim()}" --duplicate-of ${target.duplicate_of.trim()}`],nextSteps:["Use the canonical item referenced by duplicate_of as the --duplicate-of target."]})}return target.id}function findActiveChildIds(items,parentId,statusRegistry){return items.filter(item=>item.parent===parentId&&!isTerminalStatus(item.status,statusRegistry)).map(item=>item.id).sort((left,right)=>left.localeCompare(right))}function findAutoUnblockCandidates(items,closedId,statusRegistry){const itemsById=new Map(items.map(item=>[item.id.trim().toLowerCase(),item]));const blockerIdsByItem=indexBlockedByIds(items);const normalizedClosedId=closedId.trim().toLowerCase();const blockedStatuses=statusRegistry.blocked_statuses;return items.filter(item=>blockedStatuses.has(item.status)).map(item=>({item,blockerIds:blockerIdsByItem.get(item.id.trim().toLowerCase())})).filter(({blockerIds})=>blockerIds.includes(normalizedClosedId)).filter(({blockerIds})=>blockerIds.every(blockerId=>{if(blockerId===normalizedClosedId){return true}const blocker=itemsById.get(blockerId);return blocker!==void 0&&isTerminalStatus(blocker.status,statusRegistry)})).map(({item,blockerIds})=>({id:item.id,blocker_ids:blockerIds})).sort((left,right)=>left.id.localeCompare(right.id))}async function autoUnblockResolvedDependents(pmRoot,settings,items,closedId,author,statusRegistry){const candidates=findAutoUnblockCandidates(items,closedId,statusRegistry);const warnings=[];for(const candidate of candidates){try{const unblocked=await mutateItem({pmRoot,settings,id:candidate.id,op:"update",author,message:`Auto-unblocked after blocker ${closedId} closed`,mutate(document){const dependencies=document.metadata.dependencies??[];const remainingDependencies=dependencies.filter(dependency=>{const dependencyId=dependency.id.trim().toLowerCase();return dependency.kind!=="blocked_by"||!candidate.blocker_ids.includes(dependencyId)});document.metadata.status=statusRegistry.open_status;delete document.metadata.blocked_by;delete document.metadata.blocked_reason;document.metadata.unblock_note=`Auto-unblocked after blocker ${closedId} closed; all blockers resolved (${candidate.blocker_ids.join(", ")}).`;if(remainingDependencies.length>0){document.metadata.dependencies=remainingDependencies}else{delete document.metadata.dependencies}const changedFields=["status","blocked_by","blocked_reason","unblock_note"];if(remainingDependencies.length!==dependencies.length){changedFields.push("dependencies")}return{changedFields}}});warnings.push(`auto_unblocked:${unblocked.item.id}:resolved_blockers=${candidate.blocker_ids.join(",")}`)}catch(error){const reason=error instanceof Error?error.message.replace(/\s+/g," ").trim():"unknown";warnings.push(`auto_unblock_failed:${candidate.id}:${reason}`)}}return warnings}function applyInlineCloseFields(metadata,options){const changedFields=[];const inlineCloseFields=[{option:options.resolution,key:"resolution"},{option:options.expectedResult,key:"expected_result"},{option:options.actualResult,key:"actual_result"}];for(const{option,key}of inlineCloseFields){if(typeof option!=="string"){continue}const trimmed=option.trim();if(trimmed.length===0){continue}metadata[key]=trimmed;changedFields.push(key)}return changedFields}function applyDuplicateCloseMetadata(metadata,duplicateOf){if(duplicateOf===void 0){return[]}metadata.duplicate_of=duplicateOf;const duplicateFallbackFields=[];const fallbackValues=[{key:"resolution",value:`Duplicate of ${duplicateOf}`},{key:"expected_result",value:`Canonical item ${duplicateOf} tracks the work.`},{key:"actual_result",value:`Closed as duplicate of ${duplicateOf}.`}];for(const{key,value}of fallbackValues){if(shouldApplyDuplicateFallback(metadata[key])){metadata[key]=value;duplicateFallbackFields.push(key)}}return duplicateFallbackFields}function collectCloseValidationWarnings(metadata,validateCloseMode,activeChildIds,pmRoot){const warnings=[];if(validateCloseMode!=="off"){const missingFields=findMissingCloseValidationFields(metadata);if(missingFields.length>0){const missingLabels=missingFields.map(field=>field.label);if(validateCloseMode==="strict"){const missingFlags=missingFields.map(field=>`--${field.key.replaceAll("_","-")}`);const updateTokens=["--pm-path",pmRoot,"update",metadata.id,...missingFlags.flatMap(flag=>[flag,"<value>"])];throw new PmCliError(`Cannot close item ${metadata.id}: missing ${missingLabels.join(", ")}. Populate fields or use --validate-close warn.`,EXIT_CODE.USAGE,{code:"close_validation_missing_fields",recovery:{missing:missingFlags,suggested_retry:renderPmCommand(updateTokens)},nextSteps:["Run the suggested pm update, then retry the original pm close invocation.","Use --validate-close warn only when governance permits an evidenced exception."]})}warnings.push(`close_validation_missing_fields:${metadata.id}:${missingLabels.join(",")}`)}if(activeChildIds.length>0){if(validateCloseMode==="strict"){throw new PmCliError(`Cannot close item ${metadata.id}: active child items remain open (${activeChildIds.join(", ")}). Close, cancel, or re-parent them first, or use --validate-close warn.`,EXIT_CODE.USAGE)}warnings.push(`close_validation_active_children:${metadata.id}:${activeChildIds.join(",")}`)}return warnings}if(activeChildIds.length>0){warnings.push(`closed_with_active_children:${metadata.id}:${activeChildIds.join(",")}`)}return warnings}function applyCloseReason(metadata,closeReason){if(closeReason!==void 0){metadata.close_reason=closeReason;return["close_reason"]}return[]}function clearCloseAssignee(metadata){if(metadata.assignee===void 0){return[]}delete metadata.assignee;return["assignee"]}function mutateCloseMetadata(metadata,context){if(isTerminalStatus(metadata.status,context.statusRegistry)&&!context.force){throw new PmCliError(`Item ${metadata.id} is already terminal; use pm update to append acceptance evidence, or --force only for an intentional repeat closure.`,EXIT_CODE.CONFLICT,{recovery:closeEvidenceRecovery(metadata,context.pmRoot,context.options)})}const inlineChangedFields=applyInlineCloseFields(metadata,context.options);const duplicateFallbackFields=applyDuplicateCloseMetadata(metadata,context.duplicateOf);const mutationWarnings=collectCloseValidationWarnings(metadata,context.validateCloseMode,context.activeChildIds,context.pmRoot);metadata.status=context.statusRegistry.close_status;metadata.closed_at=context.closedAt;const shouldWriteCompletedAt=context.options.completedAt!==void 0||metadata.completed_at===void 0;if(shouldWriteCompletedAt){metadata.completed_at=context.completedAt}const changedFields=["status","closed_at",...shouldWriteCompletedAt?["completed_at"]:[],...applyCloseReason(metadata,context.closeReason),...inlineChangedFields];if(shouldCompletePlanOnClose(metadata)){metadata.plan_mode="completed";changedFields.push("plan_mode")}if(context.duplicateOf!==void 0){changedFields.push("duplicate_of");for(const key of duplicateFallbackFields){if(!changedFields.includes(key)){changedFields.push(key)}}}changedFields.push(...clearCloseAssignee(metadata));const blockerCleanup=applyTerminalOrderingPolicy(metadata,context.lifecyclePolicy);changedFields.push(...blockerCleanup.changedFields);mutationWarnings.push(...blockerCleanup.warnings);return{changedFields,...mutationWarnings.length>0?{warnings:mutationWarnings}:{}}}const _testOnlyCloseCommand={blockedByIds:collectBlockedByIds};async function closeItem(id,closeReasonText,options,global2){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);const statusRegistry=resolveRuntimeStatusRegistry(settings.schema);const author=resolveAuthor(options.author,settings.author_default);const typeToFolder=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations()).type_to_folder;const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeToFolder);if(!located){throw await buildItemNotFoundError(pmRoot,id,settings.id_prefix,typeToFolder)}const duplicateOf=await assertDuplicateTargetExists(pmRoot,settings,options.duplicateOf,located.id);const lifecyclePolicy={requireCloseReason:options.lifecyclePolicy?.requireCloseReason??settings.governance.require_close_reason,orderingEdges:options.lifecyclePolicy?.orderingEdges??"preserve"};const closeReason=requireTerminalReason({explicit:closeReasonText,duplicateOf,resolution:options.resolution,message:options.message},lifecyclePolicy.requireCloseReason).closeReason;const validateCloseMode=parseValidateCloseMode(options.validateClose)??settings.governance.close_validation_default;const trackerItems=await listAllItemMetadataLight(pmRoot,settings.item_format,typeToFolder,void 0,settings.schema);const activeChildIds=findActiveChildIds(trackerItems,located.id,statusRegistry);const closedAt=nowIso();const completedAt=options.completedAt===void 0?closedAt:resolveIsoOrRelative(options.completedAt,new Date(closedAt),"completed-at");const result=await mutateItem({pmRoot,settings,id:located.id,op:"close",author,message:options.message,force:options.force,mutate(document){return mutateCloseMetadata(document.metadata,{pmRoot,statusRegistry,force:options.force,options,duplicateOf,validateCloseMode,activeChildIds,closeReason,closedAt,completedAt,lifecyclePolicy})}});const recovery=validateCloseMode==="warn"?closeEvidenceRecovery(result.item,pmRoot):void 0;return{item:toItemRecord(result.item),changed_fields:result.changedFields,...recovery?{recovery}:{},warnings:[...result.warnings,...await autoUnblockResolvedDependents(pmRoot,settings,trackerItems,located.id,author,statusRegistry)]}}function runClose(id,closeReasonText,options,global2){return closeItem(id,closeReasonText,options,global2)}export{_testOnlyCloseCommand,closeItem,runClose};
|
|
468
2
|
//# sourceMappingURL=close.js.map
|
|
469
|
-
//# debugId=0e166cbb-ef9c-5016-89a6-07f287e00a2e
|