@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,563 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
* @module sdk/merge/install
|
|
3
|
-
*
|
|
4
|
-
* Installs the tracker's git merge configuration into a repository: a fenced
|
|
5
|
-
* `.gitattributes` block mapping every mergeable tracker artifact class to a
|
|
6
|
-
* pm merge driver, plus the local `git config` driver definitions that make
|
|
7
|
-
* those attributes effective. Idempotent and re-runnable; schema type
|
|
8
|
-
* mutations refresh the fenced block automatically once it is installed.
|
|
9
|
-
*/
|
|
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]="0200a3f7-93f5-5aaf-a6e8-2239e5b2ec3a")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isFileMissingError}from"../../core/fs/fs-utils.js";import{readFile,realpath,writeFile}from"node:fs/promises";import{execFile}from"node:child_process";import path from"node:path";import{promisify}from"node:util";import{pathExists}from"../../core/fs/fs-utils.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{acquireLock}from"../../core/lock/lock.js";import{resolvePmPackageRootFromModule}from"../../core/packages/root.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolveAuthor}from"../../core/shared/author.js";import{nowIso}from"../../core/shared/time.js";import{resolvePmRoot}from"../../core/store/paths.js";import{readSettings,resolveGovernanceKnobs}from"../../core/store/settings.js";import{isPathOutsideRoot}from"../workspace.js";import{resolveSourceContextWritePolicy}from"../environment/source-context.js";const execFileAsync=promisify(execFile);const PM_GITATTRIBUTES_START="# pm-cli:merge-drivers:start";const PM_GITATTRIBUTES_END="# pm-cli:merge-drivers:end";const PM_GITATTRIBUTES_V2_START="# pm-cli:merge-drivers:v2:start";const PM_GITATTRIBUTES_V2_END="# pm-cli:merge-drivers:v2:end";const MERGE_FENCE_LOCK_ID="merge-fence";function quoteMergeDriverArgument(value){return`'${value.replaceAll("'",`'"'"'`)}'`}function resolveMergeDriverCliCommand(){const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);return`${quoteMergeDriverArgument(process.execPath)} ${quoteMergeDriverArgument(path.join(packageRoot,"dist","cli.js"))}`}const MERGE_DRIVER_DEFINITIONS=[{key:"pm-item-toon",name:"pm field-aware TOON item document merge",artifact:"item",itemPath:"%P"},{key:"pm-item-markdown",name:"pm field-aware JSON-markdown item document merge",artifact:"item",itemPath:"%P"},{key:"pm-history",name:"pm append-only history stream merge",artifact:"history",itemPath:void 0},{key:"pm-relationship",name:"pm append-only relationship event store merge",artifact:"relationship",itemPath:void 0},{key:"pm-json",name:"pm key-level JSON config merge",artifact:"json",itemPath:void 0}];function resolveMergeInstallContext(options){const explicitPath=options.explicitPath?.trim();const sourceWorkspaceRoot=options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim();const sourcePmRoot=options.environment.PM_SOURCE_PM_PATH?.trim();const sourcePolicy=resolveSourceContextWritePolicy(options.environment);const sourceCoordinatesAvailable=Boolean(sourceWorkspaceRoot&&sourcePmRoot);const sourceContextSelected=explicitPath===void 0&&sourceCoordinatesAvailable&&(options.dryRun||sourcePolicy.source_writes_allowed);if(explicitPath!==void 0){const pmRoot=resolvePmRoot(options.cwd,explicitPath);return{pm_root:pmRoot,workspace_start:pmRoot,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}if(sourceContextSelected){return{pm_root:path.resolve(sourcePmRoot),workspace_start:path.resolve(sourceWorkspaceRoot),source_coordinates_available:true,source_context_selected:true,source_policy:sourcePolicy}}return{pm_root:sourceCoordinatesAvailable?resolvePmRoot(options.cwd,".agents/pm"):resolvePmRoot(options.cwd),workspace_start:options.cwd,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}async function findGitWorkspaceRoot(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--show-toplevel"],{cwd,encoding:"utf8",windowsHide:true,timeout:1e4});return await realpath(stdout.trim())}catch{return null}}async function resolveGitWorkspaceRoot(cwd){const workspaceRoot=await findGitWorkspaceRoot(cwd);if(workspaceRoot===null){throw new PmCliError("pm merge install requires a git repository (merge drivers are git configuration).",EXIT_CODE.USAGE)}return workspaceRoot}function toPosixRelative(fromPath,toPath){return path.relative(fromPath,toPath).replaceAll("\\","/")}function quoteGitAttributePattern(value){return`"${value.replaceAll("\\","\\\\").replaceAll('"','\\"')}"`}function readSingleQuotedArgument(command,offset){if(command[offset]!=="'"){return null}let value="";for(let index=offset+1;index<command.length;index+=1){if(command.startsWith(`'"'"'`,index)){value+="'";index+=4;continue}if(command[index]==="'"){return{value,nextOffset:index+1}}value+=command[index]}return null}async function isPortableMergeDriverCommand(configured,expectedSuffix){const nodeArgument=readSingleQuotedArgument(configured,0);if(nodeArgument===null||configured[nodeArgument.nextOffset]!==" "){return false}const cliArgument=readSingleQuotedArgument(configured,nodeArgument.nextOffset+1);if(cliArgument===null||configured.slice(cliArgument.nextOffset)!==expectedSuffix||!/^node(?:\.exe)?$/iu.test(path.basename(nodeArgument.value))||path.basename(cliArgument.value)!=="cli.js"||path.basename(path.dirname(cliArgument.value))!=="dist"){return false}if(!await pathExists(nodeArgument.value)||!await pathExists(cliArgument.value)){return false}try{const packageRoot=path.dirname(path.dirname(cliArgument.value));const manifest=JSON.parse(await readFile(path.join(packageRoot,"package.json"),"utf8"));const pmBin=typeof manifest.bin==="object"&&manifest.bin!==null&&"pm"in manifest.bin?manifest.bin.pm:void 0;return manifest.name==="@unbrained/pm-cli"&&(manifest.bin==="dist/cli.js"||pmBin==="dist/cli.js")}catch{return false}}function buildMergeAttributePatterns(trackerRelativeRoot,typeFolders){const prefix=trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"";const patterns=[`${quoteGitAttributePattern(`${prefix}**/*.toon`)} merge=pm-item-toon`,`${quoteGitAttributePattern(`${prefix}**/*.md`)} merge=pm-item-markdown`];for(const folder of typeFolders){patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.toon`)} merge=pm-item-toon`);patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.md`)} merge=pm-item-markdown`)}patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.jsonl`)} merge=pm-relationship`);patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`);patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`);patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.json`)} merge=pm-json`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/**`)} -merge`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);return patterns}function removeManagedBlock(content,startMarker,endMarker){const start=content.indexOf(startMarker);const end=content.indexOf(endMarker);return start>=0&&end>start?`${content.slice(0,start)}${content.slice(end+endMarker.length)}`:content.replace(startMarker,"").replace(endMarker,"")}async function reconcileGitattributesBlock(workspaceRoot,patterns,dryRun){const gitattributesPath=path.join(workspaceRoot,".gitattributes");let current="";try{current=await readFile(gitattributesPath,"utf8")}catch(error){if(!(error instanceof Error&&"code"in error&&isFileMissingError(error))){throw error}}const block=[PM_GITATTRIBUTES_V2_START,...patterns,PM_GITATTRIBUTES_V2_END].join("\n");const withoutManagedBlock=removeManagedBlock(removeManagedBlock(current,PM_GITATTRIBUTES_V2_START,PM_GITATTRIBUTES_V2_END),PM_GITATTRIBUTES_START,PM_GITATTRIBUTES_END);const prefix=withoutManagedBlock.trimEnd();const next=`${prefix.length>0?`${prefix}
|
|
10
2
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { isFileMissingError } from "../../core/fs/fs-utils.js";
|
|
14
|
-
import { readFile, realpath, writeFile } from "node:fs/promises";
|
|
15
|
-
import { execFile } from "node:child_process";
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import { promisify } from "node:util";
|
|
18
|
-
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
19
|
-
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
20
|
-
import { acquireLock } from "../../core/lock/lock.js";
|
|
21
|
-
import { resolvePmPackageRootFromModule } from "../../core/packages/root.js";
|
|
22
|
-
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
23
|
-
import { PmCliError } from "../../core/shared/errors.js";
|
|
24
|
-
import { resolveAuthor } from "../../core/shared/author.js";
|
|
25
|
-
import { nowIso } from "../../core/shared/time.js";
|
|
26
|
-
import { resolvePmRoot } from "../../core/store/paths.js";
|
|
27
|
-
import { readSettings, resolveGovernanceKnobs, } from "../../core/store/settings.js";
|
|
28
|
-
import { isPathOutsideRoot } from "../workspace.js";
|
|
29
|
-
import { resolveSourceContextWritePolicy } from "../environment/source-context.js";
|
|
30
|
-
const execFileAsync = promisify(execFile);
|
|
31
|
-
/** Opening marker for the pm-owned merge-driver `.gitattributes` block. */
|
|
32
|
-
export const PM_GITATTRIBUTES_START = "# pm-cli:merge-drivers:start";
|
|
33
|
-
/** Closing marker for the pm-owned merge-driver `.gitattributes` block. */
|
|
34
|
-
export const PM_GITATTRIBUTES_END = "# pm-cli:merge-drivers:end";
|
|
35
|
-
/** Opening marker for the versioned fence that older releases leave untouched. */
|
|
36
|
-
export const PM_GITATTRIBUTES_V2_START = "# pm-cli:merge-drivers:v2:start";
|
|
37
|
-
/** Closing marker for the versioned fence that older releases leave untouched. */
|
|
38
|
-
export const PM_GITATTRIBUTES_V2_END = "# pm-cli:merge-drivers:v2:end";
|
|
39
|
-
const MERGE_FENCE_LOCK_ID = "merge-fence";
|
|
40
|
-
/**
|
|
41
|
-
* Quote one argument for the shell used by Git merge-driver configuration.
|
|
42
|
-
*
|
|
43
|
-
* Git executes configured driver strings through a shell even when the
|
|
44
|
-
* original `pm merge install` process was launched directly. Single-quoting
|
|
45
|
-
* both the Node executable and bundled CLI path prevents spaces or shell
|
|
46
|
-
* metacharacters in either installation path from changing the command.
|
|
47
|
-
*/
|
|
48
|
-
function quoteMergeDriverArgument(value) {
|
|
49
|
-
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
50
|
-
}
|
|
51
|
-
/** Resolve the installed CLI without relying on the collaborator's PATH. */
|
|
52
|
-
function resolveMergeDriverCliCommand() {
|
|
53
|
-
const packageRoot = resolvePmPackageRootFromModule(import.meta.url, [
|
|
54
|
-
"../../..",
|
|
55
|
-
]);
|
|
56
|
-
return `${quoteMergeDriverArgument(process.execPath)} ${quoteMergeDriverArgument(path.join(packageRoot, "dist", "cli.js"))}`;
|
|
57
|
-
}
|
|
58
|
-
const MERGE_DRIVER_DEFINITIONS = [
|
|
59
|
-
{
|
|
60
|
-
key: "pm-item-toon",
|
|
61
|
-
name: "pm field-aware TOON item document merge",
|
|
62
|
-
artifact: "item",
|
|
63
|
-
itemPath: "%P",
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
key: "pm-item-markdown",
|
|
67
|
-
name: "pm field-aware JSON-markdown item document merge",
|
|
68
|
-
artifact: "item",
|
|
69
|
-
itemPath: "%P",
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
key: "pm-history",
|
|
73
|
-
name: "pm append-only history stream merge",
|
|
74
|
-
artifact: "history",
|
|
75
|
-
itemPath: undefined,
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
key: "pm-relationship",
|
|
79
|
-
name: "pm append-only relationship event store merge",
|
|
80
|
-
artifact: "relationship",
|
|
81
|
-
itemPath: undefined,
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
key: "pm-json",
|
|
85
|
-
name: "pm key-level JSON config merge",
|
|
86
|
-
artifact: "json",
|
|
87
|
-
itemPath: undefined,
|
|
88
|
-
},
|
|
89
|
-
];
|
|
90
|
-
/** Resolve explicit, inherited-source, and current-workspace precedence without I/O. */
|
|
91
|
-
export function resolveMergeInstallContext(options) {
|
|
92
|
-
const explicitPath = options.explicitPath?.trim();
|
|
93
|
-
const sourceWorkspaceRoot = options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim();
|
|
94
|
-
const sourcePmRoot = options.environment.PM_SOURCE_PM_PATH?.trim();
|
|
95
|
-
const sourcePolicy = resolveSourceContextWritePolicy(options.environment);
|
|
96
|
-
const sourceCoordinatesAvailable = Boolean(sourceWorkspaceRoot && sourcePmRoot);
|
|
97
|
-
const sourceContextSelected = explicitPath === undefined &&
|
|
98
|
-
sourceCoordinatesAvailable &&
|
|
99
|
-
(options.dryRun || sourcePolicy.source_writes_allowed);
|
|
100
|
-
if (explicitPath !== undefined) {
|
|
101
|
-
const pmRoot = resolvePmRoot(options.cwd, explicitPath);
|
|
102
|
-
return {
|
|
103
|
-
pm_root: pmRoot,
|
|
104
|
-
workspace_start: pmRoot,
|
|
105
|
-
source_coordinates_available: sourceCoordinatesAvailable,
|
|
106
|
-
source_context_selected: false,
|
|
107
|
-
source_policy: sourcePolicy,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
if (sourceContextSelected) {
|
|
111
|
-
return {
|
|
112
|
-
pm_root: path.resolve(sourcePmRoot),
|
|
113
|
-
workspace_start: path.resolve(sourceWorkspaceRoot),
|
|
114
|
-
source_coordinates_available: true,
|
|
115
|
-
source_context_selected: true,
|
|
116
|
-
source_policy: sourcePolicy,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
pm_root: sourceCoordinatesAvailable
|
|
121
|
-
? resolvePmRoot(options.cwd, ".agents/pm")
|
|
122
|
-
: resolvePmRoot(options.cwd),
|
|
123
|
-
workspace_start: options.cwd,
|
|
124
|
-
source_coordinates_available: sourceCoordinatesAvailable,
|
|
125
|
-
source_context_selected: false,
|
|
126
|
-
source_policy: sourcePolicy,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
/** Resolve the enclosing Git worktree root or return null outside Git. */
|
|
130
|
-
export async function findGitWorkspaceRoot(cwd) {
|
|
131
|
-
try {
|
|
132
|
-
const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8", windowsHide: true, timeout: 10_000 });
|
|
133
|
-
return await realpath(stdout.trim());
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
async function resolveGitWorkspaceRoot(cwd) {
|
|
140
|
-
const workspaceRoot = await findGitWorkspaceRoot(cwd);
|
|
141
|
-
if (workspaceRoot === null) {
|
|
142
|
-
throw new PmCliError("pm merge install requires a git repository (merge drivers are git configuration).", EXIT_CODE.USAGE);
|
|
143
|
-
}
|
|
144
|
-
return workspaceRoot;
|
|
145
|
-
}
|
|
146
|
-
function toPosixRelative(fromPath, toPath) {
|
|
147
|
-
return path.relative(fromPath, toPath).replaceAll("\\", "/");
|
|
148
|
-
}
|
|
149
|
-
/** Encode one Git attributes pattern with C-style quoting so whitespace, backslashes, and quotation marks remain part of the repository path instead of being parsed as attribute separators. */
|
|
150
|
-
function quoteGitAttributePattern(value) {
|
|
151
|
-
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
152
|
-
}
|
|
153
|
-
function readSingleQuotedArgument(command, offset) {
|
|
154
|
-
if (command[offset] !== "'") {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
let value = "";
|
|
158
|
-
for (let index = offset + 1; index < command.length; index += 1) {
|
|
159
|
-
if (command.startsWith(`'"'"'`, index)) {
|
|
160
|
-
value += "'";
|
|
161
|
-
index += 4;
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
if (command[index] === "'") {
|
|
165
|
-
return { value, nextOffset: index + 1 };
|
|
166
|
-
}
|
|
167
|
-
value += command[index];
|
|
168
|
-
}
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
async function isPortableMergeDriverCommand(configured, expectedSuffix) {
|
|
172
|
-
const nodeArgument = readSingleQuotedArgument(configured, 0);
|
|
173
|
-
if (nodeArgument === null || configured[nodeArgument.nextOffset] !== " ") {
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
const cliArgument = readSingleQuotedArgument(configured, nodeArgument.nextOffset + 1);
|
|
177
|
-
if (cliArgument === null ||
|
|
178
|
-
configured.slice(cliArgument.nextOffset) !== expectedSuffix ||
|
|
179
|
-
!/^node(?:\.exe)?$/iu.test(path.basename(nodeArgument.value)) ||
|
|
180
|
-
path.basename(cliArgument.value) !== "cli.js" ||
|
|
181
|
-
path.basename(path.dirname(cliArgument.value)) !== "dist") {
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
if (!(await pathExists(nodeArgument.value)) ||
|
|
185
|
-
!(await pathExists(cliArgument.value))) {
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
try {
|
|
189
|
-
const packageRoot = path.dirname(path.dirname(cliArgument.value));
|
|
190
|
-
const manifest = JSON.parse(await readFile(path.join(packageRoot, "package.json"), "utf8"));
|
|
191
|
-
const pmBin = typeof manifest.bin === "object" &&
|
|
192
|
-
manifest.bin !== null &&
|
|
193
|
-
"pm" in manifest.bin
|
|
194
|
-
? manifest.bin.pm
|
|
195
|
-
: undefined;
|
|
196
|
-
return (manifest.name === "@unbrained/pm-cli" &&
|
|
197
|
-
(manifest.bin === "dist/cli.js" || pmBin === "dist/cli.js"));
|
|
198
|
-
}
|
|
199
|
-
catch {
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Build the complete fenced `.gitattributes` pattern list for a tracker rooted
|
|
205
|
-
* at `trackerRelativeRoot` (git-root-relative POSIX path, empty when the
|
|
206
|
-
* tracker root IS the git root). This is the single coverage contract shared
|
|
207
|
-
* by `pm merge install` (which writes the fence) and the validate
|
|
208
|
-
* merge-fence-drift detection (which compares the committed fence against the
|
|
209
|
-
* active schema's type folders), so schema-added custom types can never
|
|
210
|
-
* silently diverge from the installed fence without a warning.
|
|
211
|
-
*/
|
|
212
|
-
export function buildMergeAttributePatterns(trackerRelativeRoot, typeFolders) {
|
|
213
|
-
const prefix = trackerRelativeRoot.length > 0 ? `${trackerRelativeRoot}/` : "";
|
|
214
|
-
// Package-owned types can register folders at runtime, and a branch can
|
|
215
|
-
// contain their items before the receiving branch has installed the package.
|
|
216
|
-
// Fence every tracker TOON/Markdown item first; the explicit per-type rows
|
|
217
|
-
// below remain useful diagnostics for registry drift and override nothing.
|
|
218
|
-
const patterns = [
|
|
219
|
-
`${quoteGitAttributePattern(`${prefix}**/*.toon`)} merge=pm-item-toon`,
|
|
220
|
-
`${quoteGitAttributePattern(`${prefix}**/*.md`)} merge=pm-item-markdown`,
|
|
221
|
-
];
|
|
222
|
-
for (const folder of typeFolders) {
|
|
223
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.toon`)} merge=pm-item-toon`);
|
|
224
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.md`)} merge=pm-item-markdown`);
|
|
225
|
-
}
|
|
226
|
-
// RelationshipEventStore deliberately accepts a caller-chosen relativePath
|
|
227
|
-
// anywhere below the tracker root. Cover all tracker JSONL first, then let
|
|
228
|
-
// the more-specific history rule below override it. This keeps custom event
|
|
229
|
-
// stores protected without guessing package-owned paths.
|
|
230
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.jsonl`)} merge=pm-relationship`);
|
|
231
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`);
|
|
232
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`);
|
|
233
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.json`)} merge=pm-json`);
|
|
234
|
-
// Extensions are package assets, not tracker item streams. The broad
|
|
235
|
-
// fallback patterns above intentionally protect unknown contributed item
|
|
236
|
-
// folders, so this last-match escape hatch must explicitly unset merge for
|
|
237
|
-
// every file beneath the reserved extension package root.
|
|
238
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/**`)} -merge`);
|
|
239
|
-
// The managed extension inventory is tracker state rather than package
|
|
240
|
-
// content, so restore its structured JSON driver after the asset exclusion.
|
|
241
|
-
patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);
|
|
242
|
-
return patterns;
|
|
243
|
-
}
|
|
244
|
-
function removeManagedBlock(content, startMarker, endMarker) {
|
|
245
|
-
const start = content.indexOf(startMarker);
|
|
246
|
-
const end = content.indexOf(endMarker);
|
|
247
|
-
return start >= 0 && end > start
|
|
248
|
-
? `${content.slice(0, start)}${content.slice(end + endMarker.length)}`
|
|
249
|
-
: content.replace(startMarker, "").replace(endMarker, "");
|
|
250
|
-
}
|
|
251
|
-
async function reconcileGitattributesBlock(workspaceRoot, patterns, dryRun) {
|
|
252
|
-
const gitattributesPath = path.join(workspaceRoot, ".gitattributes");
|
|
253
|
-
let current = "";
|
|
254
|
-
try {
|
|
255
|
-
current = await readFile(gitattributesPath, "utf8");
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
if (!(error instanceof Error && "code" in error && isFileMissingError(error))) {
|
|
259
|
-
throw error;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
const block = [
|
|
263
|
-
PM_GITATTRIBUTES_V2_START,
|
|
264
|
-
...patterns,
|
|
265
|
-
PM_GITATTRIBUTES_V2_END,
|
|
266
|
-
].join("\n");
|
|
267
|
-
const withoutManagedBlock = removeManagedBlock(removeManagedBlock(current, PM_GITATTRIBUTES_V2_START, PM_GITATTRIBUTES_V2_END), PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_END);
|
|
268
|
-
const prefix = withoutManagedBlock.trimEnd();
|
|
269
|
-
const next = `${prefix.length > 0 ? `${prefix}\n\n` : ""}${block}\n`;
|
|
270
|
-
if (next === current) {
|
|
271
|
-
return { path: gitattributesPath, changed: false };
|
|
272
|
-
}
|
|
273
|
-
if (!dryRun) {
|
|
274
|
-
await writeFile(gitattributesPath, next, "utf8");
|
|
275
|
-
}
|
|
276
|
-
return { path: gitattributesPath, changed: true };
|
|
277
|
-
}
|
|
278
|
-
/** Resolve merge-fence folders from built-ins plus persisted project schema only. */
|
|
279
|
-
export function resolveProjectMergeTypeFolders(settings) {
|
|
280
|
-
const registry = resolveItemTypeRegistry(settings, null);
|
|
281
|
-
return [...new Set(Object.values(registry.type_to_folder))].sort((left, right) => left.localeCompare(right));
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Audit the committed `.gitattributes` merge fence against the coverage the
|
|
285
|
-
* active schema requires, without touching git configuration. The fence file
|
|
286
|
-
* is discovered by walking up from the tracker root (bounded), so the audit
|
|
287
|
-
* stays filesystem-only and safe to run inside `pm validate`. A `drift`
|
|
288
|
-
* result means items of some type folder (or a tracker JSONL store) would
|
|
289
|
-
* merge under git's default text driver despite the fence being installed.
|
|
290
|
-
*/
|
|
291
|
-
export async function auditMergeAttributeFence(pmRoot, typeFolders) {
|
|
292
|
-
const resolvedRoot = path.resolve(pmRoot);
|
|
293
|
-
let fenceDirectory = null;
|
|
294
|
-
let fenceContent = "";
|
|
295
|
-
let directory = resolvedRoot;
|
|
296
|
-
for (let depth = 0; depth < 8; depth += 1) {
|
|
297
|
-
const candidate = path.join(directory, ".gitattributes");
|
|
298
|
-
try {
|
|
299
|
-
const raw = await readFile(candidate, "utf8");
|
|
300
|
-
if (raw.includes(PM_GITATTRIBUTES_V2_START) ||
|
|
301
|
-
raw.includes(PM_GITATTRIBUTES_START)) {
|
|
302
|
-
fenceDirectory = directory;
|
|
303
|
-
fenceContent = raw;
|
|
304
|
-
break;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
catch {
|
|
308
|
-
// No .gitattributes at this level; keep walking up.
|
|
309
|
-
}
|
|
310
|
-
const parent = path.dirname(directory);
|
|
311
|
-
if (parent === directory) {
|
|
312
|
-
break;
|
|
313
|
-
}
|
|
314
|
-
directory = parent;
|
|
315
|
-
}
|
|
316
|
-
if (fenceDirectory === null) {
|
|
317
|
-
return {
|
|
318
|
-
status: "not_installed",
|
|
319
|
-
missing_patterns: [],
|
|
320
|
-
stale_patterns: [],
|
|
321
|
-
schema_scope: "project",
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
const fencePath = path.join(fenceDirectory, ".gitattributes");
|
|
325
|
-
const usesV2 = fenceContent.includes(PM_GITATTRIBUTES_V2_START);
|
|
326
|
-
const startMarker = usesV2
|
|
327
|
-
? PM_GITATTRIBUTES_V2_START
|
|
328
|
-
: PM_GITATTRIBUTES_START;
|
|
329
|
-
const endMarker = usesV2 ? PM_GITATTRIBUTES_V2_END : PM_GITATTRIBUTES_END;
|
|
330
|
-
const start = fenceContent.indexOf(startMarker);
|
|
331
|
-
const end = fenceContent.indexOf(endMarker);
|
|
332
|
-
const committed = end > start
|
|
333
|
-
? fenceContent
|
|
334
|
-
.slice(start + startMarker.length, end)
|
|
335
|
-
.split("\n")
|
|
336
|
-
.map((line) => line.trim())
|
|
337
|
-
.filter((line) => line.length > 0)
|
|
338
|
-
: [];
|
|
339
|
-
const expected = buildMergeAttributePatterns(toPosixRelative(fenceDirectory, resolvedRoot), typeFolders);
|
|
340
|
-
const committedSet = new Set(committed);
|
|
341
|
-
const expectedSet = new Set(expected);
|
|
342
|
-
const missing = expected.filter((line) => !committedSet.has(line));
|
|
343
|
-
const stale = committed.filter((line) => !expectedSet.has(line));
|
|
344
|
-
return {
|
|
345
|
-
status: missing.length > 0 || stale.length > 0 ? "drift" : "ok",
|
|
346
|
-
path: fencePath,
|
|
347
|
-
missing_patterns: missing,
|
|
348
|
-
stale_patterns: stale,
|
|
349
|
-
schema_scope: "project",
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
/** Audit the clone-local Git driver commands without executing a merge. */
|
|
353
|
-
export async function auditMergeDriverConfiguration(workspaceRoot) {
|
|
354
|
-
const cliCommand = resolveMergeDriverCliCommand();
|
|
355
|
-
const missingKeys = [];
|
|
356
|
-
const driftedKeys = [];
|
|
357
|
-
for (const definition of MERGE_DRIVER_DEFINITIONS) {
|
|
358
|
-
const key = `merge.${definition.key}.driver`;
|
|
359
|
-
const expectedSuffix = ` merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath === undefined ? "" : ` --item-path ${definition.itemPath}`}`;
|
|
360
|
-
const expected = `${cliCommand}${expectedSuffix}`;
|
|
361
|
-
try {
|
|
362
|
-
const { stdout } = await execFileAsync("git", ["config", "--local", "--get", key], {
|
|
363
|
-
cwd: workspaceRoot,
|
|
364
|
-
encoding: "utf8",
|
|
365
|
-
windowsHide: true,
|
|
366
|
-
timeout: 10_000,
|
|
367
|
-
});
|
|
368
|
-
const configured = stdout.trim();
|
|
369
|
-
if (configured !== expected &&
|
|
370
|
-
!(await isPortableMergeDriverCommand(configured, expectedSuffix))) {
|
|
371
|
-
driftedKeys.push(key);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
catch {
|
|
375
|
-
missingKeys.push(key);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
return {
|
|
379
|
-
status: missingKeys.length > 0
|
|
380
|
-
? "missing"
|
|
381
|
-
: driftedKeys.length > 0
|
|
382
|
-
? "drift"
|
|
383
|
-
: "ok",
|
|
384
|
-
missing_keys: missingKeys,
|
|
385
|
-
drifted_keys: driftedKeys,
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Refresh the fenced `.gitattributes` merge-driver block after a schema type
|
|
390
|
-
* mutation, but only when `pm merge install` already ran (the fence markers
|
|
391
|
-
* are present). Without this, custom item types registered after install
|
|
392
|
-
* would write items into folders with no merge attribute — silently
|
|
393
|
-
* reintroducing the whole-file conflict class for exactly those items. Repos
|
|
394
|
-
* that never installed the fence get a `not_installed` outcome so callers can
|
|
395
|
-
* surface an actionable hint instead of mutating git configuration nobody
|
|
396
|
-
* asked for.
|
|
397
|
-
*/
|
|
398
|
-
export async function refreshMergeAttributeFenceIfInstalled(pmRoot) {
|
|
399
|
-
let workspaceRoot;
|
|
400
|
-
try {
|
|
401
|
-
workspaceRoot = await resolveGitWorkspaceRoot(path.resolve(pmRoot));
|
|
402
|
-
}
|
|
403
|
-
catch {
|
|
404
|
-
return { status: "no_git" };
|
|
405
|
-
}
|
|
406
|
-
const trackerRelativeRoot = toPosixRelative(workspaceRoot, path.resolve(pmRoot));
|
|
407
|
-
const lockSettings = await readSettings(pmRoot);
|
|
408
|
-
const owner = resolveAuthor(undefined, lockSettings.author_default);
|
|
409
|
-
const releaseLock = await acquireLock(pmRoot, MERGE_FENCE_LOCK_ID, lockSettings.locks.ttl_seconds, owner, false, resolveGovernanceKnobs(lockSettings).force_required_for_stale_lock, lockSettings.locks.wait_ms);
|
|
410
|
-
try {
|
|
411
|
-
const gitattributesPath = path.join(workspaceRoot, ".gitattributes");
|
|
412
|
-
let current;
|
|
413
|
-
try {
|
|
414
|
-
current = await readFile(gitattributesPath, "utf8");
|
|
415
|
-
}
|
|
416
|
-
catch (error) {
|
|
417
|
-
if (error instanceof Error &&
|
|
418
|
-
"code" in error &&
|
|
419
|
-
isFileMissingError(error)) {
|
|
420
|
-
return { status: "not_installed", path: gitattributesPath };
|
|
421
|
-
}
|
|
422
|
-
throw error;
|
|
423
|
-
}
|
|
424
|
-
if (!current.includes(PM_GITATTRIBUTES_V2_START) &&
|
|
425
|
-
!current.includes(PM_GITATTRIBUTES_START)) {
|
|
426
|
-
return { status: "not_installed", path: gitattributesPath };
|
|
427
|
-
}
|
|
428
|
-
// Re-read after acquiring the dedicated fence lock so every concurrent
|
|
429
|
-
// refresher computes from the latest committed type registry.
|
|
430
|
-
const settings = await readSettings(pmRoot);
|
|
431
|
-
const typeFolders = resolveProjectMergeTypeFolders(settings);
|
|
432
|
-
const outcome = await reconcileGitattributesBlock(workspaceRoot, buildMergeAttributePatterns(trackerRelativeRoot, typeFolders), false);
|
|
433
|
-
return {
|
|
434
|
-
status: outcome.changed ? "refreshed" : "unchanged",
|
|
435
|
-
path: outcome.path,
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
finally {
|
|
439
|
-
await releaseLock();
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* Install (or preview) the repository merge configuration for tracker data:
|
|
444
|
-
* writes the fenced merge-driver block into `.gitattributes` (committed and
|
|
445
|
-
* shared with every branch) and defines the `merge.pm-*.driver` entries in the
|
|
446
|
-
* repository-local git config (per-clone, so every collaborator runs this once
|
|
447
|
-
* per checkout). Requires an initialized tracker and a git repository.
|
|
448
|
-
*/
|
|
449
|
-
export async function runMergeInstall(options, global) {
|
|
450
|
-
const context = resolveMergeInstallContext({
|
|
451
|
-
cwd: process.cwd(),
|
|
452
|
-
explicitPath: global.path,
|
|
453
|
-
dryRun: options.dryRun === true,
|
|
454
|
-
environment: process.env,
|
|
455
|
-
});
|
|
456
|
-
const pmRoot = context.pm_root;
|
|
457
|
-
await assertInitializedTracker(pmRoot);
|
|
458
|
-
const workspaceRoot = await resolveGitWorkspaceRoot(context.workspace_start);
|
|
459
|
-
return installMergeFence({
|
|
460
|
-
pmRoot,
|
|
461
|
-
workspaceRoot,
|
|
462
|
-
dryRun: options.dryRun === true,
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Install merge safety for an initialized tracker without depending on the
|
|
467
|
-
* caller's cwd or global CLI path resolution. This is the SDK primitive used
|
|
468
|
-
* by fresh init and by the `pm merge install` adapter.
|
|
469
|
-
*/
|
|
470
|
-
export async function installMergeFence(options) {
|
|
471
|
-
const pmRoot = path.resolve(options.pmRoot);
|
|
472
|
-
const workspaceRoot = path.resolve(options.workspaceRoot);
|
|
473
|
-
const dryRun = options.dryRun === true;
|
|
474
|
-
// Git for Windows may report a worktree through an 8.3 short path while
|
|
475
|
-
// Node resolves the tracker through its long path. Compare filesystem
|
|
476
|
-
// identities rather than those two equivalent spellings so a valid
|
|
477
|
-
// in-repository tracker is not rejected as external.
|
|
478
|
-
let canonicalPmRoot;
|
|
479
|
-
let canonicalWorkspaceRoot;
|
|
480
|
-
try {
|
|
481
|
-
[canonicalPmRoot, canonicalWorkspaceRoot] = await Promise.all([
|
|
482
|
-
realpath(pmRoot),
|
|
483
|
-
realpath(workspaceRoot),
|
|
484
|
-
]);
|
|
485
|
-
}
|
|
486
|
-
catch (error) {
|
|
487
|
-
throw new PmCliError(`Cannot resolve tracker root ${pmRoot} or workspace root ${workspaceRoot}: ${String(error)}`, EXIT_CODE.NOT_FOUND, {
|
|
488
|
-
code: "merge_root_not_found",
|
|
489
|
-
nextSteps: [
|
|
490
|
-
"Initialize the tracker and ensure both paths are accessible.",
|
|
491
|
-
'Retry "pm merge install" from the repository workspace.',
|
|
492
|
-
],
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
const trackerRelativeRoot = toPosixRelative(canonicalWorkspaceRoot, canonicalPmRoot);
|
|
496
|
-
if (isPathOutsideRoot(trackerRelativeRoot)) {
|
|
497
|
-
throw new PmCliError(`Tracker root ${pmRoot} is outside the git repository ${workspaceRoot}; there is nothing to configure for this repository.`, EXIT_CODE.USAGE);
|
|
498
|
-
}
|
|
499
|
-
const settings = await readSettings(canonicalPmRoot);
|
|
500
|
-
const typeFolders = resolveProjectMergeTypeFolders(settings);
|
|
501
|
-
const patterns = buildMergeAttributePatterns(trackerRelativeRoot, typeFolders);
|
|
502
|
-
const gitConfigEntries = [];
|
|
503
|
-
const cliCommand = resolveMergeDriverCliCommand();
|
|
504
|
-
for (const definition of MERGE_DRIVER_DEFINITIONS) {
|
|
505
|
-
gitConfigEntries.push({
|
|
506
|
-
key: `merge.${definition.key}.name`,
|
|
507
|
-
value: definition.name,
|
|
508
|
-
});
|
|
509
|
-
gitConfigEntries.push({
|
|
510
|
-
key: `merge.${definition.key}.driver`,
|
|
511
|
-
value: `${cliCommand} merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath === undefined ? "" : ` --item-path ${definition.itemPath}`}`,
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
if (!dryRun) {
|
|
515
|
-
try {
|
|
516
|
-
for (const entry of gitConfigEntries) {
|
|
517
|
-
await execFileAsync("git", ["config", "--local", entry.key, entry.value], {
|
|
518
|
-
cwd: canonicalWorkspaceRoot,
|
|
519
|
-
encoding: "utf8",
|
|
520
|
-
windowsHide: true,
|
|
521
|
-
timeout: 10_000,
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
catch {
|
|
526
|
-
throw new PmCliError(`Cannot install repository-local merge drivers in ${canonicalWorkspaceRoot}. Ensure the repository Git config is writable and no other Git process holds its lock, then retry.`, EXIT_CODE.DEPENDENCY_FAILED, {
|
|
527
|
-
code: "merge_git_config_unwritable",
|
|
528
|
-
why: "pm merge install must persist clone-local driver commands before publishing their shared .gitattributes mappings.",
|
|
529
|
-
nextSteps: [
|
|
530
|
-
"Make the repository Git config writable or wait for the process holding its lock to finish.",
|
|
531
|
-
'Retry "pm merge install"; the operation is idempotent.',
|
|
532
|
-
'Use "pm merge install --dry-run --json" when the workspace is intentionally read-only.',
|
|
533
|
-
],
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
// Publish the shared attribute fence only after the clone-local commands are
|
|
538
|
-
// usable. A read-only or locked Git config therefore cannot leave a newly
|
|
539
|
-
// activated fence pointing at drivers that this clone has not installed.
|
|
540
|
-
const gitattributes = await reconcileGitattributesBlock(canonicalWorkspaceRoot, patterns, dryRun);
|
|
541
|
-
return {
|
|
542
|
-
ok: true,
|
|
543
|
-
dry_run: dryRun,
|
|
544
|
-
workspace_root: canonicalWorkspaceRoot,
|
|
545
|
-
pm_root: canonicalPmRoot,
|
|
546
|
-
gitattributes: {
|
|
547
|
-
path: gitattributes.path,
|
|
548
|
-
changed: gitattributes.changed,
|
|
549
|
-
patterns,
|
|
550
|
-
schema_scope: "project",
|
|
551
|
-
},
|
|
552
|
-
git_config: gitConfigEntries,
|
|
553
|
-
guidance: [
|
|
554
|
-
"Commit .gitattributes so every branch and collaborator shares the merge mapping.",
|
|
555
|
-
'git config is per-clone: each collaborator (and each fresh worktree/clone) runs "pm merge install" once.',
|
|
556
|
-
'After merging branches, run "pm merge reconcile --dry-run" to inspect the complete receipt and history repair, then apply "pm merge reconcile"; use --force only after explicitly accepting any discarded values.',
|
|
557
|
-
"Custom item types registered later refresh this fence automatically (pm schema add-type/remove-type); rerun pm merge install only after out-of-band type-folder edits.",
|
|
558
|
-
],
|
|
559
|
-
generated_at: nowIso(),
|
|
560
|
-
};
|
|
561
|
-
}
|
|
3
|
+
`:""}${block}
|
|
4
|
+
`;if(next===current){return{path:gitattributesPath,changed:false}}if(!dryRun){await writeFile(gitattributesPath,next,"utf8")}return{path:gitattributesPath,changed:true}}function resolveProjectMergeTypeFolders(settings){const registry=resolveItemTypeRegistry(settings,null);return[...new Set(Object.values(registry.type_to_folder))].sort((left,right)=>left.localeCompare(right))}async function auditMergeAttributeFence(pmRoot,typeFolders){const resolvedRoot=path.resolve(pmRoot);let fenceDirectory=null;let fenceContent="";let directory=resolvedRoot;for(let depth=0;depth<8;depth+=1){const candidate=path.join(directory,".gitattributes");try{const raw=await readFile(candidate,"utf8");if(raw.includes(PM_GITATTRIBUTES_V2_START)||raw.includes(PM_GITATTRIBUTES_START)){fenceDirectory=directory;fenceContent=raw;break}}catch{}const parent=path.dirname(directory);if(parent===directory){break}directory=parent}if(fenceDirectory===null){return{status:"not_installed",missing_patterns:[],stale_patterns:[],schema_scope:"project"}}const fencePath=path.join(fenceDirectory,".gitattributes");const usesV2=fenceContent.includes(PM_GITATTRIBUTES_V2_START);const startMarker=usesV2?PM_GITATTRIBUTES_V2_START:PM_GITATTRIBUTES_START;const endMarker=usesV2?PM_GITATTRIBUTES_V2_END:PM_GITATTRIBUTES_END;const start=fenceContent.indexOf(startMarker);const end=fenceContent.indexOf(endMarker);const committed=end>start?fenceContent.slice(start+startMarker.length,end).split("\n").map(line=>line.trim()).filter(line=>line.length>0):[];const expected=buildMergeAttributePatterns(toPosixRelative(fenceDirectory,resolvedRoot),typeFolders);const committedSet=new Set(committed);const expectedSet=new Set(expected);const missing=expected.filter(line=>!committedSet.has(line));const stale=committed.filter(line=>!expectedSet.has(line));return{status:missing.length>0||stale.length>0?"drift":"ok",path:fencePath,missing_patterns:missing,stale_patterns:stale,schema_scope:"project"}}async function auditMergeDriverConfiguration(workspaceRoot){const cliCommand=resolveMergeDriverCliCommand();const missingKeys=[];const driftedKeys=[];for(const definition of MERGE_DRIVER_DEFINITIONS){const key=`merge.${definition.key}.driver`;const expectedSuffix=` merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`;const expected=`${cliCommand}${expectedSuffix}`;try{const{stdout}=await execFileAsync("git",["config","--local","--get",key],{cwd:workspaceRoot,encoding:"utf8",windowsHide:true,timeout:1e4});const configured=stdout.trim();if(configured!==expected&&!await isPortableMergeDriverCommand(configured,expectedSuffix)){driftedKeys.push(key)}}catch{missingKeys.push(key)}}return{status:missingKeys.length>0?"missing":driftedKeys.length>0?"drift":"ok",missing_keys:missingKeys,drifted_keys:driftedKeys}}async function refreshMergeAttributeFenceIfInstalled(pmRoot){let workspaceRoot;try{workspaceRoot=await resolveGitWorkspaceRoot(path.resolve(pmRoot))}catch{return{status:"no_git"}}const trackerRelativeRoot=toPosixRelative(workspaceRoot,path.resolve(pmRoot));const lockSettings=await readSettings(pmRoot);const owner=resolveAuthor(void 0,lockSettings.author_default);const releaseLock=await acquireLock(pmRoot,MERGE_FENCE_LOCK_ID,lockSettings.locks.ttl_seconds,owner,false,resolveGovernanceKnobs(lockSettings).force_required_for_stale_lock,lockSettings.locks.wait_ms);try{const gitattributesPath=path.join(workspaceRoot,".gitattributes");let current;try{current=await readFile(gitattributesPath,"utf8")}catch(error){if(error instanceof Error&&"code"in error&&isFileMissingError(error)){return{status:"not_installed",path:gitattributesPath}}throw error}if(!current.includes(PM_GITATTRIBUTES_V2_START)&&!current.includes(PM_GITATTRIBUTES_START)){return{status:"not_installed",path:gitattributesPath}}const settings=await readSettings(pmRoot);const typeFolders=resolveProjectMergeTypeFolders(settings);const outcome=await reconcileGitattributesBlock(workspaceRoot,buildMergeAttributePatterns(trackerRelativeRoot,typeFolders),false);return{status:outcome.changed?"refreshed":"unchanged",path:outcome.path}}finally{await releaseLock()}}async function runMergeInstall(options,global2){const context=resolveMergeInstallContext({cwd:process.cwd(),explicitPath:global2.path,dryRun:options.dryRun===true,environment:process.env});const pmRoot=context.pm_root;await assertInitializedTracker(pmRoot);const workspaceRoot=await resolveGitWorkspaceRoot(context.workspace_start);return installMergeFence({pmRoot,workspaceRoot,dryRun:options.dryRun===true})}async function installMergeFence(options){const pmRoot=path.resolve(options.pmRoot);const workspaceRoot=path.resolve(options.workspaceRoot);const dryRun=options.dryRun===true;let canonicalPmRoot;let canonicalWorkspaceRoot;try{[canonicalPmRoot,canonicalWorkspaceRoot]=await Promise.all([realpath(pmRoot),realpath(workspaceRoot)])}catch(error){throw new PmCliError(`Cannot resolve tracker root ${pmRoot} or workspace root ${workspaceRoot}: ${String(error)}`,EXIT_CODE.NOT_FOUND,{code:"merge_root_not_found",nextSteps:["Initialize the tracker and ensure both paths are accessible.",'Retry "pm merge install" from the repository workspace.']})}const trackerRelativeRoot=toPosixRelative(canonicalWorkspaceRoot,canonicalPmRoot);if(isPathOutsideRoot(trackerRelativeRoot)){throw new PmCliError(`Tracker root ${pmRoot} is outside the git repository ${workspaceRoot}; there is nothing to configure for this repository.`,EXIT_CODE.USAGE)}const settings=await readSettings(canonicalPmRoot);const typeFolders=resolveProjectMergeTypeFolders(settings);const patterns=buildMergeAttributePatterns(trackerRelativeRoot,typeFolders);const gitConfigEntries=[];const cliCommand=resolveMergeDriverCliCommand();for(const definition of MERGE_DRIVER_DEFINITIONS){gitConfigEntries.push({key:`merge.${definition.key}.name`,value:definition.name});gitConfigEntries.push({key:`merge.${definition.key}.driver`,value:`${cliCommand} merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`})}if(!dryRun){try{for(const entry of gitConfigEntries){await execFileAsync("git",["config","--local",entry.key,entry.value],{cwd:canonicalWorkspaceRoot,encoding:"utf8",windowsHide:true,timeout:1e4})}}catch{throw new PmCliError(`Cannot install repository-local merge drivers in ${canonicalWorkspaceRoot}. Ensure the repository Git config is writable and no other Git process holds its lock, then retry.`,EXIT_CODE.DEPENDENCY_FAILED,{code:"merge_git_config_unwritable",why:"pm merge install must persist clone-local driver commands before publishing their shared .gitattributes mappings.",nextSteps:["Make the repository Git config writable or wait for the process holding its lock to finish.",'Retry "pm merge install"; the operation is idempotent.','Use "pm merge install --dry-run --json" when the workspace is intentionally read-only.']})}}const gitattributes=await reconcileGitattributesBlock(canonicalWorkspaceRoot,patterns,dryRun);return{ok:true,dry_run:dryRun,workspace_root:canonicalWorkspaceRoot,pm_root:canonicalPmRoot,gitattributes:{path:gitattributes.path,changed:gitattributes.changed,patterns,schema_scope:"project"},git_config:gitConfigEntries,guidance:["Commit .gitattributes so every branch and collaborator shares the merge mapping.",'git config is per-clone: each collaborator (and each fresh worktree/clone) runs "pm merge install" once.','After merging branches, run "pm merge reconcile --dry-run" to inspect the complete receipt and history repair, then apply "pm merge reconcile"; use --force only after explicitly accepting any discarded values.',"Custom item types registered later refresh this fence automatically (pm schema add-type/remove-type); rerun pm merge install only after out-of-band type-folder edits."],generated_at:nowIso()}}export{PM_GITATTRIBUTES_END,PM_GITATTRIBUTES_START,PM_GITATTRIBUTES_V2_END,PM_GITATTRIBUTES_V2_START,auditMergeAttributeFence,auditMergeDriverConfiguration,buildMergeAttributePatterns,findGitWorkspaceRoot,installMergeFence,refreshMergeAttributeFenceIfInstalled,resolveMergeInstallContext,resolveProjectMergeTypeFolders,runMergeInstall};
|
|
562
5
|
//# sourceMappingURL=install.js.map
|
|
563
|
-
//# debugId=dea4137f-adbd-5dca-bfc7-b56c99c7aa79
|
|
@@ -1,47 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* @module sdk/merge/receipt-file-boundary
|
|
3
|
-
*
|
|
4
|
-
* Reads untrusted receipt candidates through a bounded, no-follow file
|
|
5
|
-
* boundary whose race and short-read behavior can be exercised directly.
|
|
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]="6ece0e15-aff5-5e2d-b18a-16ffaa0fe2ea")}catch(e){}}();
|
|
9
|
-
import { constants as fsConstants } from "node:fs";
|
|
10
|
-
import { lstat, open } from "node:fs/promises";
|
|
11
|
-
const NODE_RECEIPT_FILE_BOUNDARY = { lstat, open };
|
|
12
|
-
/** Resolve the platform no-follow flag, falling back only where Node omits it. */
|
|
13
|
-
export function resolveReceiptNoFollowFlag(constants) {
|
|
14
|
-
return constants.O_NOFOLLOW ?? 0;
|
|
15
|
-
}
|
|
16
|
-
/** Read one regular file only when its opened identity remains bounded and stable. */
|
|
17
|
-
export async function readBoundedRegularFile(receiptPath, maximumBytes, boundary = NODE_RECEIPT_FILE_BOUNDARY) {
|
|
18
|
-
const pathStats = await boundary.lstat(receiptPath);
|
|
19
|
-
if (pathStats.isSymbolicLink() ||
|
|
20
|
-
!pathStats.isFile() ||
|
|
21
|
-
pathStats.size > maximumBytes) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
const handle = await boundary.open(receiptPath, fsConstants.O_RDONLY | resolveReceiptNoFollowFlag(fsConstants));
|
|
25
|
-
try {
|
|
26
|
-
const openedStats = await handle.stat();
|
|
27
|
-
if (!openedStats.isFile() || openedStats.size > maximumBytes)
|
|
28
|
-
return null;
|
|
29
|
-
const buffer = Buffer.alloc(openedStats.size);
|
|
30
|
-
let offset = 0;
|
|
31
|
-
while (offset < buffer.length) {
|
|
32
|
-
const { bytesRead } = await handle.read(buffer, offset, buffer.length - offset, offset);
|
|
33
|
-
if (bytesRead === 0)
|
|
34
|
-
break;
|
|
35
|
-
offset += bytesRead;
|
|
36
|
-
}
|
|
37
|
-
const finalStats = await handle.stat();
|
|
38
|
-
return finalStats.size === openedStats.size && offset === openedStats.size
|
|
39
|
-
? buffer.toString("utf8", 0, offset)
|
|
40
|
-
: null;
|
|
41
|
-
}
|
|
42
|
-
finally {
|
|
43
|
-
await handle.close();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
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]="b8cf81eb-6afd-5d5a-8a4d-b5b5fbd51ace")}catch(e2){}})();import{constants as fsConstants}from"node:fs";import{lstat,open}from"node:fs/promises";const NODE_RECEIPT_FILE_BOUNDARY={lstat,open};function resolveReceiptNoFollowFlag(constants){return constants.O_NOFOLLOW??0}async function readBoundedRegularFile(receiptPath,maximumBytes,boundary=NODE_RECEIPT_FILE_BOUNDARY){const pathStats=await boundary.lstat(receiptPath);if(pathStats.isSymbolicLink()||!pathStats.isFile()||pathStats.size>maximumBytes){return null}const handle=await boundary.open(receiptPath,fsConstants.O_RDONLY|resolveReceiptNoFollowFlag(fsConstants));try{const openedStats=await handle.stat();if(!openedStats.isFile()||openedStats.size>maximumBytes)return null;const buffer=Buffer.alloc(openedStats.size);let offset=0;while(offset<buffer.length){const{bytesRead}=await handle.read(buffer,offset,buffer.length-offset,offset);if(bytesRead===0)break;offset+=bytesRead}const finalStats=await handle.stat();return finalStats.size===openedStats.size&&offset===openedStats.size?buffer.toString("utf8",0,offset):null}finally{await handle.close()}}export{readBoundedRegularFile,resolveReceiptNoFollowFlag};
|
|
46
2
|
//# sourceMappingURL=receipt-file-boundary.js.map
|
|
47
|
-
//# debugId=6ece0e15-aff5-5e2d-b18a-16ffaa0fe2ea
|