@unbrained/pm-cli 2026.10.4 → 2026.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +11 -0
- package/dist/cli/after-command-context-usage.js +1 -1
- package/dist/cli/argv-utils.js +1 -1
- package/dist/cli/bootstrap-args.js +1 -1
- package/dist/cli/bundle-integrity.js +2 -2
- package/dist/cli/command-namespaces.js +1 -1
- package/dist/cli/commander-usage.d.ts +1 -1
- package/dist/cli/commander-usage.js +7 -4
- package/dist/cli/commands/annotations/comments.js +1 -1
- package/dist/cli/commands/annotations/docs.js +1 -1
- package/dist/cli/commands/annotations/files.js +1 -1
- package/dist/cli/commands/annotations/learnings.js +1 -1
- package/dist/cli/commands/annotations/notes.js +1 -1
- package/dist/cli/commands/extension/describe.js +1 -1
- package/dist/cli/commands/extension/extension.js +1 -1
- package/dist/cli/commands/extension/scaffold.js +1 -1
- package/dist/cli/commands/extension/shared.js +1 -1
- package/dist/cli/commands/governance/gc.js +1 -1
- package/dist/cli/commands/governance/health.js +1 -1
- package/dist/cli/commands/governance/telemetry.js +1 -1
- package/dist/cli/commands/governance/validate.js +1 -1
- package/dist/cli/commands/history/activity.js +1 -1
- package/dist/cli/commands/history/history-compact.js +1 -1
- package/dist/cli/commands/history/history-redact.js +1 -1
- package/dist/cli/commands/history/history-repair.js +1 -1
- package/dist/cli/commands/history/history.js +1 -1
- package/dist/cli/commands/history/restore.js +1 -1
- package/dist/cli/commands/lifecycle/append.js +1 -1
- package/dist/cli/commands/lifecycle/claim.js +1 -1
- package/dist/cli/commands/lifecycle/close-many.js +1 -1
- package/dist/cli/commands/lifecycle/close.js +1 -1
- package/dist/cli/commands/lifecycle/copy.js +1 -1
- package/dist/cli/commands/lifecycle/create.js +1 -1
- package/dist/cli/commands/lifecycle/delete.js +1 -1
- package/dist/cli/commands/lifecycle/focus.js +1 -1
- package/dist/cli/commands/lifecycle/plan.js +1 -1
- package/dist/cli/commands/lifecycle/update-many.js +1 -1
- package/dist/cli/commands/lifecycle/update.js +1 -1
- package/dist/cli/commands/query/aggregate.js +1 -1
- package/dist/cli/commands/query/context.js +1 -1
- package/dist/cli/commands/query/deps.js +1 -1
- package/dist/cli/commands/query/duplicates.js +1 -1
- package/dist/cli/commands/query/eval.js +1 -1
- package/dist/cli/commands/query/get.js +1 -1
- package/dist/cli/commands/query/graph.js +1 -1
- package/dist/cli/commands/query/list.js +1 -1
- package/dist/cli/commands/query/next.js +1 -1
- package/dist/cli/commands/query/search.js +1 -1
- package/dist/cli/commands/query/stats.js +1 -1
- package/dist/cli/commands/test/test-all.js +1 -1
- package/dist/cli/commands/test/test-runs.js +1 -1
- package/dist/cli/commands/test/test.js +1 -1
- package/dist/cli/commands/workspace/config.js +1 -1
- package/dist/cli/commands/workspace/contracts.js +1 -1
- package/dist/cli/commands/workspace/init.js +1 -1
- package/dist/cli/commands/workspace/merge.js +1 -1
- package/dist/cli/commands/workspace/profile.js +1 -1
- package/dist/cli/commands/workspace/schema.js +1 -1
- package/dist/cli/commands/workspace/upgrade.js +1 -1
- package/dist/cli/context-intent-invocation.js +1 -1
- package/dist/cli/description-stdin.js +1 -1
- package/dist/cli/error-guidance.js +3 -1
- package/dist/cli/extension-command-help.js +5 -3
- package/dist/cli/extension-command-options.js +1 -1
- package/dist/cli/extension-recovery.js +1 -1
- package/dist/cli/help-content.js +5 -2
- package/dist/cli/help-json-payload.js +6 -3
- package/dist/cli/invocation-profile.js +2 -2
- package/dist/cli/main.js +5 -5
- package/dist/cli/migration-gates.js +1 -1
- package/dist/cli/option-values.js +1 -1
- package/dist/cli/public.js +1 -1
- package/dist/cli/register-annotations.js +1 -1
- package/dist/cli/register-assurance.js +1 -1
- package/dist/cli/register-files-lookup.js +1 -1
- package/dist/cli/register-history-activity.js +1 -1
- package/dist/cli/register-history-author.js +1 -1
- package/dist/cli/register-history-maintenance.js +2 -2
- package/dist/cli/register-list-query.js +10 -10
- package/dist/cli/register-mutation-options.js +1 -1
- package/dist/cli/register-mutation.js +2 -2
- package/dist/cli/register-operations.js +1 -1
- package/dist/cli/register-setup.js +1 -1
- package/dist/cli/register-structured-mutation.js +1 -1
- package/dist/cli/registration-helpers.js +1 -1
- package/dist/cli/runtime/activation.js +1 -1
- package/dist/cli/runtime/invocation-options.js +1 -1
- package/dist/cli/runtime/projection-retry.js +1 -1
- package/dist/cli/runtime/selection.js +1 -1
- package/dist/cli/runtime/telemetry-outcome.js +1 -1
- package/dist/cli/runtime-compatibility-boundary.js +4 -4
- package/dist/cli/schema/registration.js +2 -2
- package/dist/cli/schema-registration-helpers.js +1 -1
- package/dist/cli/search-refresh.js +1 -1
- package/dist/cli/stats-analytics-json.js +1 -1
- package/dist/cli/telemetry-flush.js +1 -1
- package/dist/cli-bundle/bundle-manifest.json +163 -163
- package/dist/cli-bundle/chunks/chunk-3CYOBJUK.js +3 -0
- package/dist/cli-bundle/chunks/chunk-5MNOWZPN.js +3 -0
- package/dist/cli-bundle/chunks/chunk-AJ7H6XUF.js +20 -0
- package/dist/cli-bundle/chunks/chunk-D332RXZ7.js +80 -0
- package/dist/cli-bundle/chunks/chunk-HRJ6G6ZG.js +31 -0
- package/dist/cli-bundle/chunks/chunk-KRVI56QE.js +6 -0
- package/dist/cli-bundle/chunks/chunk-N4YGSG6F.js +238 -0
- package/dist/cli-bundle/chunks/{chunk-7CE2DJMA.js → chunk-OOLYASYJ.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-R7CG2DB7.js +2 -0
- package/dist/cli-bundle/chunks/chunk-TGMONGWX.js +2 -0
- package/dist/cli-bundle/chunks/chunk-UZ7BIUCI.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-GZMWISWW.js → chunk-VZ63DEVJ.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-WFZ4UEOB.js +2 -0
- package/dist/cli-bundle/chunks/chunk-YVBRASXO.js +8 -0
- package/dist/cli-bundle/chunks/{chunk-SMKHR6BM.js → chunk-Z66DWDAU.js} +87 -87
- package/dist/cli-bundle/chunks/{register-list-query-QBGXO5JJ.js → register-list-query-75QXHIFH.js} +11 -11
- package/dist/cli-bundle/chunks/register-mutation-YS54SCHG.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-6KHZQSYJ.js +2 -0
- package/dist/cli-bundle/chunks/register-setup-RTATEN2M.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-Q6DJ5DFQ.js → chunk-2CVX3KR3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-5C3IDDW7.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-467EW5RL.js → chunk-ABV67XCC.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-B5RSLVE6.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-C224METM.js +20 -0
- package/dist/cli-bundle/focused-chunks/chunk-CLDPTMQY.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-DDRN42PB.js +8 -0
- package/dist/cli-bundle/focused-chunks/{chunk-7O4NUJVO.js → chunk-DOVTUKJQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-ECBOPEJE.js +75 -0
- package/dist/cli-bundle/focused-chunks/chunk-GITOYRUW.js +165 -0
- package/dist/cli-bundle/focused-chunks/chunk-GUIF3WVC.js +30 -0
- package/dist/cli-bundle/focused-chunks/chunk-LE4JUCRR.js +3 -0
- package/dist/cli-bundle/focused-chunks/{chunk-HFAW3FJQ.js → chunk-PSXFFQFT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-RHIH6XIW.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-UDYRVBOZ.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-XV5RV4ZT.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-JCVMOSWQ.js → chunk-YMU42COG.js} +2 -2
- package/dist/cli-bundle/main.js +27 -27
- 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 +32 -32
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +55 -55
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +10 -10
- package/dist/cli.js +1 -1
- package/dist/core/checkpoint/checkpoint-gc.js +1 -1
- package/dist/core/checkpoint/mutation-checkpoint.js +2 -2
- package/dist/core/config/nested-settings.js +1 -1
- package/dist/core/config/positional-value.js +1 -1
- package/dist/core/diagnostics/remediation.js +1 -1
- package/dist/core/extensions/activation-summary-markdown.js +2 -1
- package/dist/core/extensions/activation-summary.js +1 -1
- package/dist/core/extensions/activation-transaction.js +1 -1
- package/dist/core/extensions/capability-usage.js +1 -1
- package/dist/core/extensions/command-hook-context.js +1 -1
- package/dist/core/extensions/command-metadata-contract.js +1 -1
- package/dist/core/extensions/command-visibility-tier.js +1 -1
- package/dist/core/extensions/contribution-inventory.js +1 -1
- package/dist/core/extensions/exporter-output-contract.js +1 -1
- package/dist/core/extensions/extension-candidate.js +1 -1
- package/dist/core/extensions/extension-capability-aliases.js +1 -1
- package/dist/core/extensions/extension-hook-runtime.js +1 -1
- package/dist/core/extensions/extension-policy.js +1 -1
- package/dist/core/extensions/extension-registries.js +1 -1
- package/dist/core/extensions/extension-runtime-helpers.js +1 -1
- package/dist/core/extensions/extension-types.js +1 -1
- package/dist/core/extensions/flag-definition-validation.js +1 -1
- package/dist/core/extensions/flag-value-types.js +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/item-field-types.js +1 -1
- package/dist/core/extensions/item-fields.js +1 -1
- package/dist/core/extensions/loader.js +1 -1
- package/dist/core/extensions/manifest-parser.js +1 -1
- package/dist/core/extensions/manifest-schema.js +1 -1
- package/dist/core/extensions/module-graph-snapshot.js +1 -1
- package/dist/core/extensions/preflight-ownership.js +1 -1
- package/dist/core/extensions/registration-contracts.js +1 -1
- package/dist/core/extensions/registration-validation.js +1 -1
- package/dist/core/extensions/registration-values.js +1 -1
- package/dist/core/extensions/reserved-host-flags.js +1 -1
- package/dist/core/extensions/runtime-registrations.js +1 -1
- package/dist/core/extensions/service-ownership.js +1 -1
- package/dist/core/extensions/version-compat.js +1 -1
- package/dist/core/fs/atomic-create.js +1 -1
- package/dist/core/fs/fs-utils.js +2 -2
- package/dist/core/fs/host-environment-errors.js +1 -1
- package/dist/core/fs/index.js +1 -1
- package/dist/core/fs/path-utils.js +1 -1
- package/dist/core/governance/content-fields.js +1 -1
- package/dist/core/governance/issue-codes.js +1 -1
- package/dist/core/governance/metadata-coverage.js +1 -1
- package/dist/core/history/digest.js +1 -1
- package/dist/core/history/drift-cache.js +3 -3
- package/dist/core/history/drift-scan.d.ts +4 -0
- package/dist/core/history/drift-scan.js +1 -1
- package/dist/core/history/event-classification.js +1 -1
- package/dist/core/history/event-index.js +8 -7
- package/dist/core/history/history-compact-bulk.js +1 -1
- package/dist/core/history/history-diff.js +1 -1
- package/dist/core/history/history-rewrite.js +1 -1
- package/dist/core/history/history-storage-stats.js +1 -1
- package/dist/core/history/history-stream-policy.js +1 -1
- package/dist/core/history/history.js +2 -2
- package/dist/core/history/identity.js +1 -1
- package/dist/core/history/index.js +1 -1
- package/dist/core/history/operation-contract.js +1 -1
- package/dist/core/history/projection.js +1 -1
- package/dist/core/history/read.js +1 -1
- package/dist/core/history/replay.js +2 -1
- package/dist/core/history/tombstone.js +1 -1
- package/dist/core/history/version-address.js +1 -1
- package/dist/core/history/workspace-history.js +2 -2
- package/dist/core/io/body-file.js +1 -1
- package/dist/core/io/bulk-ids-input.js +2 -1
- package/dist/core/item/actionability.js +1 -1
- package/dist/core/item/dependency-reference.js +1 -1
- package/dist/core/item/id.js +1 -1
- package/dist/core/item/index.js +1 -1
- package/dist/core/item/item-format-version.js +1 -1
- package/dist/core/item/item-format.js +6 -4
- package/dist/core/item/item-record.js +1 -1
- package/dist/core/item/item-type-definition.js +1 -1
- package/dist/core/item/parent-reference-policy.js +1 -1
- package/dist/core/item/parse.js +8 -2
- package/dist/core/item/plan-lifecycle.js +1 -1
- package/dist/core/item/priority.js +1 -1
- package/dist/core/item/sprint-release-format.js +1 -1
- package/dist/core/item/status-filter.js +1 -1
- package/dist/core/item/status.js +1 -1
- package/dist/core/item/toon-decode.js +1 -1
- package/dist/core/item/type-registry.js +1 -1
- package/dist/core/item/type-synonyms.js +1 -1
- package/dist/core/lock/index.js +1 -1
- package/dist/core/lock/lock-gc.js +1 -1
- package/dist/core/lock/lock.js +3 -3
- package/dist/core/output/mutation-projection.js +1 -1
- package/dist/core/output/output-control.js +1 -1
- package/dist/core/output/output.js +22 -10
- package/dist/core/output/query-summary.js +1 -1
- package/dist/core/output/tabular.js +3 -1
- package/dist/core/packages/manifest.js +1 -1
- package/dist/core/packages/root.js +1 -1
- package/dist/core/policy/workflow-policy-schema.js +1 -1
- package/dist/core/policy/workflow-policy-store.js +1 -1
- package/dist/core/policy/workflow-policy.js +1 -1
- package/dist/core/profile/profile-describe.js +1 -1
- package/dist/core/profile/profile-lint.js +1 -1
- package/dist/core/profile/profile-plan.js +1 -1
- package/dist/core/profile/profile-presets.js +25 -1
- package/dist/core/reproducibility/context.js +1 -1
- package/dist/core/schema/fields-file.js +2 -2
- package/dist/core/schema/item-types-file.js +2 -2
- package/dist/core/schema/runtime-field-filters.js +1 -1
- package/dist/core/schema/runtime-field-values.js +1 -1
- package/dist/core/schema/runtime-schema.js +2 -2
- package/dist/core/schema/status-defs-file.js +2 -2
- package/dist/core/schema/status-token.js +1 -1
- package/dist/core/schema/type-inference.js +1 -1
- package/dist/core/schema/type-presets.js +1 -1
- package/dist/core/schema/type-workflows.js +1 -1
- package/dist/core/search/background-refresh.js +2 -2
- package/dist/core/search/bm25.js +1 -1
- package/dist/core/search/cache.js +2 -2
- package/dist/core/search/corpus.js +1 -1
- package/dist/core/search/embedding-batches.js +1 -1
- package/dist/core/search/eval-thresholds.js +1 -1
- package/dist/core/search/eval.js +1 -1
- package/dist/core/search/http-client.js +1 -1
- package/dist/core/search/providers.js +1 -1
- package/dist/core/search/relevance.js +1 -1
- package/dist/core/search/semantic-defaults.js +1 -1
- package/dist/core/search/staleness.js +1 -1
- package/dist/core/search/vector-stores.js +2 -2
- package/dist/core/search/vectorization-metadata.js +1 -1
- package/dist/core/sentry/helpers.js +1 -1
- package/dist/core/sentry/instrument.js +1 -1
- package/dist/core/session/session-state.js +1 -1
- package/dist/core/shared/agent-session-context.js +1 -1
- package/dist/core/shared/author.js +5 -1
- package/dist/core/shared/command-line.js +1 -1
- package/dist/core/shared/command-types.js +1 -1
- package/dist/core/shared/conflict-markers.js +1 -1
- package/dist/core/shared/constants.js +1 -1
- package/dist/core/shared/errors.js +1 -1
- package/dist/core/shared/html-entity-decode.js +1 -1
- package/dist/core/shared/index.js +1 -1
- package/dist/core/shared/item-metadata-contract.js +1 -1
- package/dist/core/shared/lazy-module.js +1 -1
- package/dist/core/shared/levenshtein.js +1 -1
- package/dist/core/shared/memo.js +1 -1
- package/dist/core/shared/numeric-parsers.js +1 -1
- package/dist/core/shared/option-alias-visibility.js +1 -1
- package/dist/core/shared/primitives.js +1 -1
- package/dist/core/shared/secret-rules.js +1 -1
- package/dist/core/shared/serial-queue.js +1 -1
- package/dist/core/shared/serialization.js +1 -1
- package/dist/core/shared/split-comma-list.js +1 -1
- package/dist/core/shared/text-normalization.js +1 -1
- package/dist/core/shared/time.js +2 -1
- package/dist/core/store/index.js +1 -1
- package/dist/core/store/item-format-migration.js +1 -1
- package/dist/core/store/item-metadata-cache.js +1 -1
- package/dist/core/store/item-metadata-query-index.js +7 -7
- package/dist/core/store/item-metadata-read-work.js +1 -1
- package/dist/core/store/item-store.js +1 -1
- package/dist/core/store/paths.js +1 -1
- package/dist/core/store/settings-concurrency.js +1 -1
- package/dist/core/store/settings-read-cache.js +1 -1
- package/dist/core/store/settings-validator.js +1 -1
- package/dist/core/store/settings.js +3 -3
- package/dist/core/store/tracker-preflight.js +1 -1
- package/dist/core/telemetry/consent.js +2 -2
- package/dist/core/telemetry/observability.js +1 -1
- package/dist/core/telemetry/policy.js +1 -1
- package/dist/core/telemetry/read-sampling.js +2 -2
- package/dist/core/telemetry/runtime.js +9 -5
- package/dist/core/test/background-runs.js +3 -3
- package/dist/core/test/item-test-run-tracking.js +1 -1
- package/dist/core/test/run-selectors.js +1 -1
- package/dist/core/validate/estimate-defaults.js +1 -1
- package/dist/core/validate/fix-planning.js +1 -1
- package/dist/core/validate/linked-artifact-reference.js +1 -1
- package/dist/core/validate/missing-by-type.js +1 -1
- package/dist/core/validate/missing-link-owners.js +1 -1
- package/dist/core/validate/stale-file-classification.js +1 -1
- package/dist/mcp/http-server.js +6 -4
- package/dist/mcp/legacy-adapter.js +1 -1
- package/dist/mcp/runtime-capabilities.js +1 -1
- package/dist/mcp/server.js +4 -4
- package/dist/mcp/tool-definitions.js +1 -1
- package/dist/sdk/actionability.js +1 -1
- package/dist/sdk/agent/closed-domain-contracts.js +1 -1
- package/dist/sdk/agent/command-recovery.js +1 -1
- package/dist/sdk/agent/command-suggestions.js +1 -1
- package/dist/sdk/agent/create-option-policy.js +1 -1
- package/dist/sdk/agent/identity-config.js +1 -1
- package/dist/sdk/agent/item-addressing.js +1 -1
- package/dist/sdk/agent/refusal-closure-census.js +2 -1
- package/dist/sdk/agent/refusal-closure.js +1 -1
- package/dist/sdk/agent/refusal-corpus-contracts.js +1 -1
- package/dist/sdk/agent/refusal-reachability.js +3 -1
- package/dist/sdk/agent/subcommand-recovery.js +1 -1
- package/dist/sdk/agent/task-transcript-contracts.js +1 -1
- package/dist/sdk/agent/tracker-preflight-contracts.js +1 -1
- package/dist/sdk/agent-capability-contracts.js +3 -1
- package/dist/sdk/agent-session-context.js +1 -1
- package/dist/sdk/annotations.js +1 -1
- package/dist/sdk/author-attribution.js +1 -1
- package/dist/sdk/authoring.js +1 -1
- package/dist/sdk/cli-bootstrap.js +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +5 -3
- package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -1
- package/dist/sdk/cli-contracts/command-aliases.js +1 -1
- package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -1
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1
- package/dist/sdk/cli-contracts/commander-types.js +1 -1
- package/dist/sdk/cli-contracts/completeness.js +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.js +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +2 -1
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
- package/dist/sdk/cli-contracts/registration-helpers.js +7 -7
- package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -1
- package/dist/sdk/cli-contracts/string-lists.js +1 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1
- package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -1
- package/dist/sdk/cli-contracts.js +1 -1
- package/dist/sdk/cli-program.js +1 -1
- package/dist/sdk/command-line.js +1 -1
- package/dist/sdk/comments.js +1 -1
- package/dist/sdk/compile-cache.js +1 -1
- package/dist/sdk/completion/bash.js +2 -1
- package/dist/sdk/completion/fish.js +13 -7
- package/dist/sdk/completion/shared.js +1 -1
- package/dist/sdk/completion/zsh.js +14 -8
- package/dist/sdk/completion.js +1 -1
- package/dist/sdk/compose.js +1 -1
- package/dist/sdk/config.js +1 -1
- package/dist/sdk/context/recency.js +1 -1
- package/dist/sdk/context/semantic-session-attribution.js +1 -1
- package/dist/sdk/context/usage-egress.js +1 -1
- package/dist/sdk/context/usage-ledger.js +6 -3
- package/dist/sdk/context-intent-contracts.js +1 -1
- package/dist/sdk/context-intent-runtime.js +1 -1
- package/dist/sdk/context-packing.js +1 -1
- package/dist/sdk/context-relevance.js +1 -1
- package/dist/sdk/context-signal-store.js +2 -2
- package/dist/sdk/context-usage.js +1 -1
- package/dist/sdk/contracts.js +1 -1
- package/dist/sdk/core-governance.js +1 -1
- package/dist/sdk/core.js +1 -1
- package/dist/sdk/corpus-shape.js +1 -1
- package/dist/sdk/define.js +1 -1
- package/dist/sdk/dependencies.js +1 -1
- package/dist/sdk/dependency-flag-validation.js +1 -1
- package/dist/sdk/dependency-provenance.js +1 -1
- package/dist/sdk/docs.js +1 -1
- package/dist/sdk/duplicates.js +1 -1
- package/dist/sdk/environment/agent-environment.js +1 -1
- package/dist/sdk/environment/host-environment-errors.js +1 -1
- package/dist/sdk/environment/project-runtime-compatibility.js +2 -1
- package/dist/sdk/environment/source-context.js +1 -1
- package/dist/sdk/environment/tracker-preflight.js +1 -1
- package/dist/sdk/error-code-catalog.js +1 -1
- package/dist/sdk/error-runtime.js +1 -1
- package/dist/sdk/errors.js +1 -1
- package/dist/sdk/eval.js +1 -1
- package/dist/sdk/extension/author-manifest.js +1 -1
- package/dist/sdk/extension/bundled-catalog.js +1 -1
- package/dist/sdk/extension/concurrency.js +1 -1
- package/dist/sdk/extension/copy-scope.js +1 -1
- package/dist/sdk/extension/custom-field-collisions.js +1 -1
- package/dist/sdk/extension/describe.js +4 -2
- package/dist/sdk/extension/doctor.js +1 -1
- package/dist/sdk/extension/install-plan.js +1 -1
- package/dist/sdk/extension/install-receipts.js +1 -1
- package/dist/sdk/extension/install-runtime.js +3 -3
- package/dist/sdk/extension/install-snapshot.js +1 -1
- package/dist/sdk/extension/install-sources.js +5 -5
- package/dist/sdk/extension/managed-state.js +2 -2
- package/dist/sdk/extension/migrations.js +2 -2
- package/dist/sdk/extension/output-ownership.js +1 -1
- package/dist/sdk/extension/runtime-summary.js +1 -1
- package/dist/sdk/extension/scaffold.js +11 -4
- package/dist/sdk/extension/shared.js +1 -1
- package/dist/sdk/extension/source-resolution.js +1 -1
- package/dist/sdk/extension/static-inventory.js +1 -1
- package/dist/sdk/extension/update-check.js +1 -1
- package/dist/sdk/extension-command-context.js +1 -1
- package/dist/sdk/extension-contracts.js +1 -1
- package/dist/sdk/extension.js +1 -1
- package/dist/sdk/files.js +1 -1
- package/dist/sdk/flag-invocation-contracts.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
- package/dist/sdk/generated-error-code-catalog.js +1 -1
- package/dist/sdk/governance/assurance-action-contracts.js +1 -1
- package/dist/sdk/governance/assurance-action.js +1 -1
- package/dist/sdk/governance/assurance-limits.js +1 -1
- package/dist/sdk/governance/assurance-mutation-error.js +1 -1
- package/dist/sdk/governance/assurance-presets.js +1 -1
- package/dist/sdk/governance/assurance-runtime.js +1 -1
- package/dist/sdk/governance/assurance.js +4 -4
- package/dist/sdk/governance/boundary-fixtures.js +1 -1
- package/dist/sdk/governance/closure-timestamps.js +1 -1
- package/dist/sdk/governance/coverage-assurance.js +1 -1
- package/dist/sdk/governance/defect-recurrence-coverage.js +1 -1
- package/dist/sdk/governance/defect-recurrence-graph.js +1 -1
- package/dist/sdk/governance/defect-recurrence-signals.js +1 -1
- package/dist/sdk/governance/defect-recurrence.js +1 -1
- package/dist/sdk/governance/extension-host-version.js +1 -1
- package/dist/sdk/governance/gc.js +1 -1
- package/dist/sdk/governance/health-merge-evidence.js +1 -1
- package/dist/sdk/governance/health.js +2 -1
- package/dist/sdk/governance/hierarchy-validation.js +1 -1
- package/dist/sdk/governance/linked-file-report.js +1 -1
- package/dist/sdk/governance/merge-receipt-history.js +1 -1
- package/dist/sdk/governance/provenance-health.js +4 -1
- package/dist/sdk/governance/reindex.js +5 -4
- package/dist/sdk/governance/stale-work.js +1 -1
- package/dist/sdk/governance/status-role-diagnostics.js +1 -1
- package/dist/sdk/governance/storage-integrity.js +1 -1
- package/dist/sdk/governance/tracked-runtime-cache.js +1 -1
- package/dist/sdk/governance/upgrade.js +2 -2
- package/dist/sdk/governance/validate-history-drift.js +1 -1
- package/dist/sdk/governance/validate-item-reader.js +1 -1
- package/dist/sdk/governance/validate-normalization.js +1 -1
- package/dist/sdk/governance/validate.js +1 -1
- package/dist/sdk/governance/workflow-completeness.js +1 -1
- package/dist/sdk/governance/workflow-policy.js +3 -3
- package/dist/sdk/governance/workspace-position.js +2 -1
- package/dist/sdk/governance.js +1 -1
- package/dist/sdk/graph/adapter.js +1 -1
- package/dist/sdk/graph/analytics.js +1 -1
- package/dist/sdk/graph/assembly.js +1 -1
- package/dist/sdk/graph/cache.js +1 -1
- package/dist/sdk/graph/centrality.js +1 -1
- package/dist/sdk/graph/conformance.js +1 -1
- package/dist/sdk/graph/deadline-scheduling.js +1 -1
- package/dist/sdk/graph/durable-cache.js +1 -1
- package/dist/sdk/graph/governance-contracts.js +1 -1
- package/dist/sdk/graph/governance.js +1 -1
- package/dist/sdk/graph/hierarchy-integrity.js +1 -1
- package/dist/sdk/graph/index.js +1 -1
- package/dist/sdk/graph/lifecycle-coverage.js +1 -1
- package/dist/sdk/graph/mutation-advisory.js +1 -1
- package/dist/sdk/graph/query-contracts.js +1 -1
- package/dist/sdk/graph/remediation.js +1 -1
- package/dist/sdk/graph/run.js +1 -1
- package/dist/sdk/graph/scheduling.js +1 -1
- package/dist/sdk/graph/traversal.js +1 -1
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -1
- package/dist/sdk/graph.js +1 -1
- package/dist/sdk/guide-topics.js +1 -1
- package/dist/sdk/guide.js +8 -1
- package/dist/sdk/history/attestation-command.js +1 -1
- package/dist/sdk/history/attestation-contract.js +1 -1
- package/dist/sdk/history/attestation-scan.js +1 -1
- package/dist/sdk/history/attestation.js +1 -1
- package/dist/sdk/history/maintenance.js +1 -1
- package/dist/sdk/history/salvage.js +3 -2
- package/dist/sdk/history/subject.js +1 -1
- package/dist/sdk/history-analytics.js +1 -1
- package/dist/sdk/history-compact.js +1 -1
- package/dist/sdk/history-mcp.js +1 -1
- package/dist/sdk/history-provenance.js +1 -1
- package/dist/sdk/history-read.js +1 -1
- package/dist/sdk/history-redact.js +1 -1
- package/dist/sdk/history-repair.js +1 -1
- package/dist/sdk/improvement-ledger-validation.js +1 -1
- package/dist/sdk/improvement-ledger.js +2 -2
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/init-agent-guidance.js +16 -2
- package/dist/sdk/init.js +16 -2
- package/dist/sdk/invocation-author.js +1 -1
- package/dist/sdk/item-children.js +1 -1
- package/dist/sdk/item-metadata-index.js +1 -1
- package/dist/sdk/item-schedule.js +1 -1
- package/dist/sdk/item-transaction.js +1 -1
- package/dist/sdk/learnings.js +1 -1
- package/dist/sdk/lifecycle/append.js +4 -2
- package/dist/sdk/lifecycle/claim.js +1 -1
- package/dist/sdk/lifecycle/close-many.js +1 -1
- package/dist/sdk/lifecycle/close.js +1 -1
- package/dist/sdk/lifecycle/copy.js +1 -1
- package/dist/sdk/lifecycle/create.js +1 -1
- package/dist/sdk/lifecycle/delete.js +1 -1
- package/dist/sdk/lifecycle/event-validation-messages.js +1 -1
- package/dist/sdk/lifecycle/focus.js +1 -1
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -1
- package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -1
- package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -1
- package/dist/sdk/lifecycle/mcp-actions.js +1 -1
- package/dist/sdk/lifecycle/metadata-normalizers.js +1 -1
- package/dist/sdk/lifecycle/mutation-command-options.js +1 -1
- package/dist/sdk/lifecycle/plan-mutation-receipt.js +1 -1
- package/dist/sdk/lifecycle/plan.js +1 -1
- package/dist/sdk/lifecycle/recurrence-parsers.js +1 -1
- package/dist/sdk/lifecycle/reopen.js +1 -1
- package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +2 -1
- package/dist/sdk/lifecycle/restore.js +1 -1
- package/dist/sdk/lifecycle/shared-unset-fields.js +1 -1
- package/dist/sdk/lifecycle/task-composition.js +1 -1
- package/dist/sdk/lifecycle/update-many.js +1 -1
- package/dist/sdk/lifecycle/update.js +2 -1
- package/dist/sdk/lifecycle-completion.js +1 -1
- package/dist/sdk/lifecycle-policy.js +1 -1
- package/dist/sdk/linked-artifacts.js +2 -1
- package/dist/sdk/mcp/apps.js +1 -1
- package/dist/sdk/mcp/authorization.js +1 -1
- package/dist/sdk/mcp/discovery.js +1 -1
- package/dist/sdk/mcp/interactions.js +1 -1
- package/dist/sdk/mcp/protocol.js +1 -1
- package/dist/sdk/mcp/skills.js +3 -1
- package/dist/sdk/mcp/subscriptions.js +1 -1
- package/dist/sdk/mcp/tasks.js +2 -2
- package/dist/sdk/mcp/transport.js +1 -1
- package/dist/sdk/merge/abandoned-receipts.js +1 -1
- package/dist/sdk/merge/driver.js +1 -1
- package/dist/sdk/merge/index.js +1 -1
- package/dist/sdk/merge/install.js +4 -2
- package/dist/sdk/merge/receipt-file-boundary.js +1 -1
- package/dist/sdk/merge/receipt-operation.js +1 -1
- package/dist/sdk/merge/receipt-schema.js +1 -1
- package/dist/sdk/merge/receipts.js +4 -4
- package/dist/sdk/merge/reconcile.js +1 -1
- package/dist/sdk/merge/three-way.js +3 -2
- package/dist/sdk/merge/worktree-config.js +1 -1
- package/dist/sdk/merge.js +1 -1
- package/dist/sdk/mutation-events.js +1 -1
- package/dist/sdk/mutation-guard.js +1 -1
- package/dist/sdk/notes.js +1 -1
- package/dist/sdk/output-contracts.js +1 -1
- package/dist/sdk/output-projection.js +1 -1
- package/dist/sdk/output-token-accounting.js +1 -1
- package/dist/sdk/output.js +2 -1
- package/dist/sdk/ownership-source.js +1 -1
- package/dist/sdk/package-import-adapters.js +1 -1
- package/dist/sdk/package-migrations.js +1 -1
- package/dist/sdk/package-runtime-options.js +1 -1
- package/dist/sdk/pagination.js +1 -1
- package/dist/sdk/profile.js +5 -1
- package/dist/sdk/provenance.js +1 -1
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/activity.js +1 -1
- package/dist/sdk/query/aggregate.js +1 -1
- package/dist/sdk/query/calendar.js +4 -1
- package/dist/sdk/query/complete-list.js +1 -1
- package/dist/sdk/query/context.js +2 -1
- package/dist/sdk/query/duplicate-candidates.js +1 -1
- package/dist/sdk/query/get.d.ts +14 -2
- package/dist/sdk/query/get.js +1 -1
- package/dist/sdk/query/history.js +1 -1
- package/dist/sdk/query/item-filter-options.js +1 -1
- package/dist/sdk/query/light-metadata.js +1 -1
- package/dist/sdk/query/list-filter-shared.js +1 -1
- package/dist/sdk/query/list.js +1 -1
- package/dist/sdk/query/multi-value-filters.js +1 -1
- package/dist/sdk/query/next-ready-budget.js +1 -1
- package/dist/sdk/query/next.js +2 -1
- package/dist/sdk/query/parsers.js +1 -1
- package/dist/sdk/query/projection-contracts.js +1 -1
- package/dist/sdk/query/search/corpus.js +2 -1
- package/dist/sdk/query/search/filters.js +1 -1
- package/dist/sdk/query/search/input.js +1 -1
- package/dist/sdk/query/search/lexical.js +1 -1
- package/dist/sdk/query/search/response.js +1 -1
- package/dist/sdk/query/search/semantic.js +3 -2
- package/dist/sdk/query/search/types.js +1 -1
- package/dist/sdk/query/search-contracts.js +1 -1
- package/dist/sdk/query/search-pagination.js +1 -1
- package/dist/sdk/query/search-rendering.js +1 -1
- package/dist/sdk/query/search.js +1 -1
- package/dist/sdk/query/workspace-contracts.js +1 -1
- package/dist/sdk/query.js +1 -1
- package/dist/sdk/read-output/continuation.js +1 -1
- package/dist/sdk/read-output/options.js +1 -1
- package/dist/sdk/read-output/provenance.js +1 -1
- package/dist/sdk/read-output-budget.js +1 -1
- package/dist/sdk/read-output-contracts.js +1 -1
- package/dist/sdk/read-output-rows.js +1 -1
- package/dist/sdk/read-output-session.js +1 -1
- package/dist/sdk/relationship-analytics.js +1 -1
- package/dist/sdk/relationship-context.js +1 -1
- package/dist/sdk/relationship-history.js +7 -4
- package/dist/sdk/relationship-kinds/contract.js +1 -1
- package/dist/sdk/relationship-migration.js +1 -1
- package/dist/sdk/relationships.js +1 -1
- package/dist/sdk/reproducibility/process.js +1 -1
- package/dist/sdk/runtime/actions.js +1 -1
- package/dist/sdk/runtime/context.js +1 -1
- package/dist/sdk/runtime/schema-preview.js +1 -1
- package/dist/sdk/runtime/schema.js +1 -1
- package/dist/sdk/runtime-action-aliases.js +1 -1
- package/dist/sdk/runtime-extended-actions.js +1 -1
- package/dist/sdk/runtime-input.js +1 -1
- package/dist/sdk/runtime-primitives.js +1 -1
- package/dist/sdk/runtime-public-contracts.js +1 -1
- package/dist/sdk/runtime-stats-options.js +1 -1
- package/dist/sdk/runtime.js +1 -1
- package/dist/sdk/scheduling-shortcuts.js +1 -1
- package/dist/sdk/schema-migration.js +4 -3
- package/dist/sdk/schema.js +7 -1
- package/dist/sdk/search-refresh-worker.js +1 -1
- package/dist/sdk/similarity-scoring.js +1 -1
- package/dist/sdk/similarity.js +1 -1
- package/dist/sdk/start-task-status.js +1 -1
- package/dist/sdk/stats.js +1 -1
- package/dist/sdk/structured-mutations.js +1 -1
- package/dist/sdk/telemetry-flush.js +1 -1
- package/dist/sdk/telemetry.js +4 -3
- package/dist/sdk/templates.js +26 -2
- package/dist/sdk/test/batch.js +2 -2
- package/dist/sdk/test/entry.js +1 -1
- package/dist/sdk/test/execution.js +6 -5
- package/dist/sdk/test/json-path.js +1 -1
- package/dist/sdk/test/linked-command-detection.js +1 -1
- package/dist/sdk/test/measurements.js +1 -1
- package/dist/sdk/test/parsers.js +1 -1
- package/dist/sdk/test/runs.js +1 -1
- package/dist/sdk/test/trust.js +2 -2
- package/dist/sdk/test/workspace-snapshot.js +1 -1
- package/dist/sdk/testing.js +7 -4
- package/dist/sdk/traceability/runtime-files-lookup.js +1 -1
- package/dist/sdk/traceability/source-traceability.js +2 -1
- package/dist/sdk/tracker-root-discovery.js +1 -1
- package/dist/sdk/workspace-contracts-cache.js +1 -1
- package/dist/sdk/workspace-contracts.js +1 -1
- package/dist/sdk/workspace-memory.js +2 -2
- package/dist/sdk/workspace-recipe.js +1 -1
- package/dist/sdk/workspace-snapshot.js +5 -4
- package/dist/sdk/workspace-transaction-gc.js +1 -1
- package/dist/sdk/workspace-transaction.js +2 -2
- package/dist/sdk/workspace.js +3 -2
- package/dist/types/index.js +1 -1
- package/dist/types.js +1 -1
- package/docs/AGENT_EVIDENCE_CONSISTENCY.md +88 -0
- package/docs/GET_READ_EVIDENCE.md +68 -0
- package/docs/README.md +2 -0
- 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/extensions/vcs/index.ts +4 -2
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/package.json +2 -2
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/package.json +2 -2
- package/plugins/pm-codex/plugin.json +1 -1
- package/scripts/finalize-build.mjs +3 -2
- package/dist/cli-bundle/chunks/chunk-7UVXKI7K.js +0 -2
- package/dist/cli-bundle/chunks/chunk-D7Z2ZMJL.js +0 -3
- package/dist/cli-bundle/chunks/chunk-DEZPZOQ7.js +0 -2
- package/dist/cli-bundle/chunks/chunk-J52QIRRZ.js +0 -80
- package/dist/cli-bundle/chunks/chunk-JDKD3WGG.js +0 -6
- package/dist/cli-bundle/chunks/chunk-JQ7DW663.js +0 -2
- package/dist/cli-bundle/chunks/chunk-QXIDOOWT.js +0 -20
- package/dist/cli-bundle/chunks/chunk-SGFQQXFD.js +0 -2
- package/dist/cli-bundle/chunks/chunk-V3U77H3V.js +0 -31
- package/dist/cli-bundle/chunks/chunk-XZDWAYJC.js +0 -3
- package/dist/cli-bundle/chunks/chunk-Y6VRBTP3.js +0 -238
- package/dist/cli-bundle/chunks/chunk-YAAFYFS4.js +0 -8
- package/dist/cli-bundle/chunks/register-mutation-53ZLT4RX.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-OBK2FXUU.js +0 -2
- package/dist/cli-bundle/chunks/register-setup-HM3OCBH2.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-2JFYR56O.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-32EVUSS4.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-5GUSO2P4.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-6XBRADQQ.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-CURTIIQT.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-IJUWEEEB.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-JMJK2L4Z.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-KG3H4UZZ.js +0 -30
- package/dist/cli-bundle/focused-chunks/chunk-MHQ2XICU.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-RJV6QVJE.js +0 -75
- package/dist/cli-bundle/focused-chunks/chunk-ZE2JZ7R6.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-ZLEN4HZD.js +0 -165
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
`
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6d50733c-ced5-5ec8-b82e-2391a974ad0f")}catch{}})();import{describeExtensionActivation}from"../../core/extensions/activation-summary.js";import{renderExtensionSurfaceMarkdown}from"../../core/extensions/activation-summary-markdown.js";import{normalizeExtensionNameForMatch}from"./shared.js";function layerNameKey(layer,name){return`${layer}:${normalizeExtensionNameForMatch(name)}`}function buildExtensionCommandOwnership(activationResult,matchedNames){const rows=[];for(const[surface,entries]of[["handler",activationResult.commands.handlers],["override",activationResult.commands.overrides]]){const byCommand=new Map;for(const entry of entries){const bucket=byCommand.get(entry.command)??[];byCommand.set(entry.command,[...bucket,entry])}for(const[command,claimants]of byCommand){if(matchedNames!==null&&!claimants.some(entry=>matchedNames.has(normalizeExtensionNameForMatch(entry.name))))continue;const winner=claimants.at(-1);rows.push({command,surface,policy:"last_activated_wins",collision:claimants.length>1,claimants:claimants.map(entry=>({name:entry.name,layer:entry.layer,winner:entry===winner}))})}}return rows.sort((left,right)=>left.command.localeCompare(right.command)||left.surface.localeCompare(right.surface))}function buildExtensionDescribeResult(target,loadResult,activationResult){const activationFailedKeys=new Set(activationResult.failed.map(entry=>layerNameKey(entry.layer,entry.name))),candidates=[...loadResult.loaded.map(entry=>({name:entry.name,layer:entry.layer,version:entry.version,activation_status:activationFailedKeys.has(layerNameKey(entry.layer,entry.name))?"failed":"ok",surfaces:describeExtensionActivation(activationResult,{extensionName:entry.name})})),...loadResult.failed.map(entry=>({name:entry.name,layer:entry.layer,version:"unknown",activation_status:"not_loaded",surfaces:describeExtensionActivation(activationResult,{extensionName:entry.name})}))].sort((left,right)=>left.name.localeCompare(right.name)||left.layer.localeCompare(right.layer)),normalizedTarget=typeof target=="string"?normalizeExtensionNameForMatch(target):null,matchedNames=normalizedTarget===null?null:new Set(loadResult.loaded.filter(entry=>normalizeExtensionNameForMatch(entry.name)===normalizedTarget||typeof entry.source_package=="string"&&normalizeExtensionNameForMatch(entry.source_package)===normalizedTarget||(entry.source_aliases??[]).some(alias=>normalizeExtensionNameForMatch(alias)===normalizedTarget)).map(entry=>normalizeExtensionNameForMatch(entry.name)).concat(normalizedTarget)),extensions=matchedNames===null?candidates:candidates.filter(entry=>matchedNames.has(normalizeExtensionNameForMatch(entry.name))),unionOptions=matchedNames===null?{}:{extensionNames:[...matchedNames]};return{target:typeof target=="string"?target.trim():null,total:extensions.length,extensions,union:describeExtensionActivation(activationResult,unionOptions),command_ownership:buildExtensionCommandOwnership(activationResult,matchedNames)}}const ACTIVATION_STATUS_LABELS={ok:"loaded",failed:"activation failed",not_loaded:"not loaded"};function renderExtensionDescribeMarkdown(result,noun){const lines=[`# ${`${noun[0].toUpperCase()}${noun.slice(1)}`} surface reference`,""];if(lines.push(result.target===null?`Scope: all loaded ${noun}s`:`Scope: \`${result.target}\``),lines.push(`Described: ${result.total} ${noun}${result.total===1?"":"s"}`,""),(result.command_ownership?.length??0)>0){lines.push("## Command ownership","");for(const ownership of result.command_ownership){const winner=ownership.claimants.find(claimant=>claimant.winner),claimantNames=ownership.claimants.map(claimant=>`${claimant.layer}:${claimant.name}`).join(", ");lines.push(`- \`${ownership.command}\` (${ownership.surface}): ${winner.layer}:${winner.name}; policy=${ownership.policy}; collision=${String(ownership.collision)}; claimants=${claimantNames}`)}lines.push("")}if(result.extensions.length===0)return lines.push(`_No ${noun}s are loaded._`,""),`${lines.join(`
|
|
2
|
+
`).trimEnd()}
|
|
3
|
+
`;for(const entry of result.extensions){const title=`${entry.name} (${entry.layer} v${entry.version}, ${ACTIVATION_STATUS_LABELS[entry.activation_status]})`;lines.push(renderExtensionSurfaceMarkdown(entry.surfaces,{title,headingLevel:2}))}return result.extensions.length>1&&lines.push(renderExtensionSurfaceMarkdown(result.union,{title:`Union across all described ${noun}s`,headingLevel:2})),`${lines.join(`
|
|
4
|
+
`).trimEnd()}
|
|
3
5
|
`}export{buildExtensionDescribeResult,renderExtensionDescribeMarkdown};
|
|
4
6
|
//# sourceMappingURL=describe.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="df60255d-fdd6-594a-9e17-547d53f7b3bb")}catch(e2){}})();import{reconcileExtensionCapabilityUsage}from"../../core/extensions/index.js";import{EXTENSION_CAPABILITY_CONTRACT,KNOWN_EXTENSION_CAPABILITIES,parseLegacyExtensionCapabilityAliasWarning,parseUnknownExtensionCapabilityWarning}from"../../core/extensions/loader.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{normalizeExtensionNameForMatch}from"./shared.js";function summarizeExtensionFailures(failures){return failures.map(({layer,name,error})=>({layer,name,error}))}function addRuntimePath(pathsByExtension,extensionName,pathValue){const normalizedName=normalizeExtensionNameForMatch(extensionName);const normalizedPath=pathValue.trim();if(normalizedName.length===0||normalizedPath.length===0){return}const existing=pathsByExtension.get(normalizedName)??new Set;existing.add(normalizedPath);pathsByExtension.set(normalizedName,existing)}function collectRuntimeActivationPaths(activationResult){const commandPathsByExtension=new Map;const actionPathsByExtension=new Map;for(const registration of activationResult.registrations.commands){addRuntimePath(commandPathsByExtension,registration.name,registration.command);addRuntimePath(actionPathsByExtension,registration.name,registration.action)}for(const handler of activationResult.commands.handlers){addRuntimePath(commandPathsByExtension,handler.name,handler.command)}for(const override of activationResult.commands.overrides){addRuntimePath(commandPathsByExtension,override.name,override.command)}return{commandPathsByExtension,actionPathsByExtension}}function sortedRuntimePaths(values){if(!values||values.size===0){return void 0}return[...values].sort((left,right)=>left.localeCompare(right))}function resolveDoctorActivationStatus(params){const{enabled,normalizedName,loadedNames,loadFailedNames,activationFailedNames}=params;if(!enabled){return{runtime_active:false,activation_status:"not_loaded"}}if(loadFailedNames.has(normalizedName)||activationFailedNames.has(normalizedName)){return{runtime_active:false,activation_status:"failed"}}if(loadedNames.has(normalizedName)){return{runtime_active:true,activation_status:"ok"}}return{runtime_active:false,activation_status:"not_loaded"}}function applyDoctorRuntimeActivationState(extensions,loadResult,activationResult){const loadedNames=new Set(loadResult.loaded.map(entry=>normalizeExtensionNameForMatch(entry.name)));const loadFailedNames=new Set(loadResult.failed.map(entry=>normalizeExtensionNameForMatch(entry.name)));const activationFailedNames=new Set(activationResult.failed.map(entry=>normalizeExtensionNameForMatch(entry.name)));const{commandPathsByExtension,actionPathsByExtension}=collectRuntimeActivationPaths(activationResult);return extensions.map(entry=>{const normalizedName=normalizeExtensionNameForMatch(entry.name);const commandPaths=sortedRuntimePaths(commandPathsByExtension.get(normalizedName));const actionPaths=sortedRuntimePaths(actionPathsByExtension.get(normalizedName));const runtimeMetadata={...commandPaths?{command_paths:commandPaths}:{},...actionPaths?{action_paths:actionPaths}:{}};const activationStatus=resolveDoctorActivationStatus({enabled:entry.enabled,normalizedName,loadedNames,loadFailedNames,activationFailedNames});return{...entry,...activationStatus,...runtimeMetadata}})}function summarizePolicyWarnings(warnings){let warningCount=0;let violationCount=0;let blockedCount=0;for(const warning of warnings){if(!warning.startsWith("extension_policy_")){continue}warningCount+=1;if(warning.startsWith("extension_policy_violation_")){violationCount+=1;continue}if(warning.startsWith("extension_policy_blocked_")){blockedCount+=1}}return{warning_count:warningCount,violation_count:violationCount,blocked_count:blockedCount}}function lifecycleFlagCommand(options,action){return options.vocabulary==="package"?`pm package --${action}`:`pm extension --${action}`}const REGISTRATION_COLLISION_WARNING_CODES=new Set(["extension_command_handler_collision","extension_command_override_collision","extension_command_override_handler_overlap","extension_parser_override_collision","extension_preflight_override_collision","extension_renderer_collision","extension_service_override_collision"]);function isRegistrationCollisionWarning(warning){return REGISTRATION_COLLISION_WARNING_CODES.has(warningCode(warning))}function isExtensionLayer(value){return value==="project"||value==="global"}function parseRegistrationCollisionWarning(warning){const parts=warning.split(":");const code=parts[0];if(!code||!REGISTRATION_COLLISION_WARNING_CODES.has(code)){return null}const winnerLayer=parts.at(-4);const winnerName=parts.at(-3)?.trim();const displacedLayer=parts.at(-2);const displacedName=parts.at(-1)?.trim();if(!isExtensionLayer(winnerLayer)||!isExtensionLayer(displacedLayer)||!winnerName||!displacedName){return null}return{code,surface:parts.slice(1,-4).join(":")||"global",winner:{layer:winnerLayer,name:winnerName},displaced:{layer:displacedLayer,name:displacedName}}}function collectRegistrationCollisionExtensionNames(warnings){const names=new Set;for(const warning of warnings){const parsed=parseRegistrationCollisionWarning(warning);if(!parsed){continue}names.add(parsed.winner.name);names.add(parsed.displaced.name)}return[...names].sort((left,right)=>left.localeCompare(right))}function buildRegistrationCollisionRemediation(warnings,commands){const registrationCollisionWarnings=warnings.filter(isRegistrationCollisionWarning);if(registrationCollisionWarnings.length===0){return null}const collisionNames=collectRegistrationCollisionExtensionNames(registrationCollisionWarnings);const collisionNameText=collisionNames.length>0?` Conflicting extensions: ${collisionNames.join(", ")}.`:"";return`Extension registration collisions or handler/override overlaps detected.${collisionNameText} Single-winner surfaces can hide earlier package behavior. Deactivate one conflicting package with ${commands.deactivate}, or scope registration surfaces in extensions.policy.extension_overrides, then rerun ${commands.doctor}.`}function buildRegistrationCollisionPlan(scope,warnings,extensions,options){const collisions=warnings.map(warning=>parseRegistrationCollisionWarning(warning)).filter(entry=>entry!==null).sort((left,right)=>`${left.code}:${left.surface}:${left.winner.name}:${left.displaced.name}`.localeCompare(`${right.code}:${right.surface}:${right.winner.name}:${right.displaced.name}`));if(collisions.length===0){return void 0}const scopeFlag=scope==="global"?"--global":"--project";const deactivatePrefix=lifecycleFlagCommand(options,"deactivate");const doctorCommand=`${lifecycleFlagCommand(options,"doctor")} ${scopeFlag} --detail deep --trace`;const extensionByName=new Map(extensions.map(entry=>[normalizeExtensionNameForMatch(entry.name),entry]));const affectedByName=new Map;for(const collision of collisions){for(const name of[collision.winner.name,collision.displaced.name]){const normalizedName=normalizeExtensionNameForMatch(name);affectedByName.set(normalizedName,(affectedByName.get(normalizedName)??0)+1)}}const remediationCandidates=[...affectedByName.entries()].map(([normalizedName,affectedCollisions])=>{const extension=extensionByName.get(normalizedName);const extensionName=extension?.name??normalizedName;const commandPaths=extension?.command_paths??[];const actionPaths=extension?.action_paths??[];return{action:"deactivate",extension:extensionName,command:`${deactivatePrefix} ${extensionName} ${scopeFlag}`,affected_collisions:affectedCollisions,feature_loss:{command_paths:[...commandPaths].sort((left,right)=>left.localeCompare(right)),action_paths:[...actionPaths].sort((left,right)=>left.localeCompare(right))}}}).sort((left,right)=>{const affectedDelta=right.affected_collisions-left.affected_collisions;if(affectedDelta!==0){return affectedDelta}const leftSurfaceCount=left.feature_loss.command_paths.length+left.feature_loss.action_paths.length;const rightSurfaceCount=right.feature_loss.command_paths.length+right.feature_loss.action_paths.length;if(leftSurfaceCount!==rightSurfaceCount){return leftSurfaceCount-rightSurfaceCount}return left.extension.localeCompare(right.extension)});return{status:"conflicts_detected",collision_count:collisions.length,extension_count:affectedByName.size,next_best_command:doctorCommand,collisions,remediation_candidates:remediationCandidates}}function classifyDoctorLoadFailureWarnings(loadFailures){const warnings=[];for(const failure of loadFailures){const normalizedError=failure.error.toLowerCase();if(normalizedError.includes("cannot find package '@unbrained/pm-cli'")||normalizedError.includes('cannot find module "@unbrained/pm-cli"')||normalizedError.includes("cannot find module '@unbrained/pm-cli'")){warnings.push(`extension_load_failed_sdk_dependency_missing:${failure.name}`)}if(normalizedError.includes("cannot use import statement outside a module")||normalizedError.includes("to load an es module")||normalizedError.includes("must use import to load es module")){warnings.push(`extension_load_failed_module_mode_mismatch:${failure.name}`)}}return[...new Set(warnings)].sort((left,right)=>left.localeCompare(right))}function classifyDoctorActivationFailureWarnings(activationFailures=[]){const failures=Array.isArray(activationFailures)?activationFailures:[];const warnings=[];for(const failure of failures){if(!failure||typeof failure.name!=="string"){continue}const missingCapability=failure.trace?.missing_capability??failure.trace?.capability;if(typeof missingCapability==="string"&&missingCapability.trim().length>0){warnings.push(`extension_capability_missing:${failure.name}:${missingCapability.trim().toLowerCase()}`)}}return[...new Set(warnings)].sort((left,right)=>left.localeCompare(right))}function classifyUnusedCapabilityWarnings(loadResult,activationResult){const warnings=[];for(const entry of reconcileExtensionCapabilityUsage(loadResult.loaded,activationResult)){for(const capability of entry.unused){warnings.push(`extension_capability_unused:${entry.layer}:${entry.name}:${capability}`)}}return[...new Set(warnings)].sort((left,right)=>left.localeCompare(right))}const TRIAGE_REMEDIATION_RULES=[{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_manifest_")),build:ctx=>`Run ${lifecycleFlagCommand(ctx.options,"explore")} ${ctx.scopeFlag} to inspect discovered manifests and directories.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_unknown:")),build:()=>`Unknown extension capabilities detected. Allowed capabilities: ${KNOWN_EXTENSION_CAPABILITIES.join(", ")}. Review extension_capability_unknown warning details for suggested replacements.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_legacy_alias:")),build:()=>"Legacy extension capability aliases were auto-remapped to canonical capabilities. Update manifests to canonical names (migration/validation -> schema)."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_missing:")),build:ctx=>`Extension activation failed because code registered a surface missing from manifest capabilities. Run ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag} --detail deep --trace and add the reported missing_capability to manifest.json before publishing.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_unused:")),build:ctx=>`Extension manifests declare capabilities that are never registered against. Remove each reported unused capability from manifest.json to keep least privilege, or add the matching registration. Run ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag} --detail deep --trace for per-extension registration counts.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_command_definition_legacy_handler_alias:")),build:()=>"Extension command definitions using legacy handler were auto-remapped. Update command definitions to use run: (context) => ... for forward compatibility."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_output_service_override_global:")||warning.startsWith("extension_output_renderer_override_global:")),build:()=>"Global output service/renderer overrides are active. For output_format, return context.payload/null/undefined unless the extension owns the command. For renderers, return null for unrelated payloads so pm falls back to native rendering."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_schema_narrow_activation:")),build:()=>"A package registers custom item types/fields (a GLOBAL schema contribution) but also declares narrow activation.commands, so it never activates for built-in commands like pm create <type> and the custom type silently fails to register. Remove activation.commands from manifest.json so pm activates the package for every command, or \u2014 if the schema is intentionally command-scoped \u2014 knowingly ignore this advisory."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_load_failed_sdk_dependency_missing:")),build:ctx=>`Detected extension load failures caused by missing SDK dependency resolution. Ensure extension package dependencies include "@unbrained/pm-cli" and reinstall dependencies before running ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag}.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_load_failed_module_mode_mismatch:")),build:ctx=>`Detected extension module-mode mismatches. For ESM-based extension entries/imports, set package.json "type": "module" or use an explicit .mjs entry and rerun ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag}.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_pm_min_version_")||warning.startsWith("extension_pm_max_version_")),build:ctx=>`Extension pm version-bound warnings detected. Align each package manifest's pm_min_version/pm_max_version with the installed pm CLI version (see the warning's required/allowed=...:current=... details), or upgrade/downgrade the pm CLI to satisfy the declared bounds, then rerun ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag}.`},{matches:(_warnings,ctx)=>ctx.updateCheckFailedTotal>0,build:ctx=>`Run ${lifecycleFlagCommand(ctx.options,"manage")} ${ctx.scopeFlag} after validating network and repository access.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_manager_state_")),build:ctx=>`Review and repair ${ctx.scope} managed extension state file if schema/read warnings persist.`},{matches:(_warnings,ctx)=>ctx.policyWarningCount>0,build:()=>"Extension governance policy warnings detected. Review settings.extensions.policy mode and allow/block lists to confirm intended capabilities and registration surfaces."}];function buildExtensionTriageRemediation(params){const{normalizedWarnings,options,scope,scopeFlag,updateCheckFailedTotal,policyWarningCount,unmanagedActionRequiredTotal,notCheckedTotal,skippedNonGithubTotal,updateAvailableTotal}=params;const remediation=[];const ctx={options,scope,scopeFlag,updateCheckFailedTotal,policyWarningCount};if(normalizedWarnings.length>0){const registrationCollisionRemediation=buildRegistrationCollisionRemediation(normalizedWarnings,{deactivate:`${lifecycleFlagCommand(options,"deactivate")} <name> ${scopeFlag}`,doctor:`${lifecycleFlagCommand(options,"doctor")} ${scopeFlag} --detail deep --trace`});if(registrationCollisionRemediation){remediation.push(registrationCollisionRemediation)}for(const rule of TRIAGE_REMEDIATION_RULES){if(rule.matches(normalizedWarnings,ctx)){remediation.push(rule.build(ctx))}}}if(unmanagedActionRequiredTotal>0){remediation.push(`Update-check coverage is partial because unmanaged extensions need adoption. Adopt existing installs via ${lifecycleFlagCommand(options,"manage")} ${scopeFlag} --fix-managed-state (or ${lifecycleFlagCommand(options,"adopt-all")} ${scopeFlag}, ${lifecycleFlagCommand(options,"adopt")} <name> ${scopeFlag}, or reinstall via ${lifecycleFlagCommand(options,"install")} ${scopeFlag} <source>).`)}if(skippedNonGithubTotal>0){remediation.push("Update-check coverage is partial: non-GitHub managed sources were not checked. Inspect their registry or source directly; zero detected updates does not mean these packages are current. Runtime activation health is independent.")}if(notCheckedTotal>0){remediation.push(`Update-check coverage is partial: some sources have no completed check. Run ${lifecycleFlagCommand(options,"manage")} ${scopeFlag} to request update checks.`)}if(updateAvailableTotal>0){remediation.push(`Update available managed extensions via ${lifecycleFlagCommand(options,"install")} ${scopeFlag} <source>.`)}if(remediation.length===0){remediation.push(`No immediate action required. Re-run ${lifecycleFlagCommand(options,"manage")} ${scopeFlag} after extension changes.`)}return remediation}function buildExtensionTriageSummary(scope,warnings,extensions,options={}){const normalizedWarnings=[...new Set(warnings)].sort((left,right)=>left.localeCompare(right));const managedTotal=extensions.filter(entry=>entry.managed).length;const enabledTotal=extensions.filter(entry=>entry.enabled).length;const activeTotal=extensions.filter(entry=>entry.active).length;const updateAvailableTotal=extensions.filter(entry=>entry.update_check_status==="checked"&&entry.update_available===true).length;const unmanagedExtensions=extensions.filter(entry=>entry.managed===false);const unmanagedExpectedExtensions=unmanagedExtensions.filter(entry=>isExpectedUnmanagedExtension(entry)).map(entry=>entry.name).sort((left,right)=>left.localeCompare(right));const unmanagedActionRequiredExtensions=unmanagedExtensions.filter(entry=>!isExpectedUnmanagedExtension(entry)).map(entry=>entry.name).sort((left,right)=>left.localeCompare(right));const updateCheckStatusTotals={checked:0,skipped_unmanaged:0,skipped_non_github:0,failed:0,not_checked:0};for(const entry of extensions){updateCheckStatusTotals[entry.update_check_status]+=1}const updateCheckFailedTotal=updateCheckStatusTotals.failed;const skippedNonGithubTotal=extensions.filter(entry=>entry.update_check_status==="skipped_non_github"&&entry.source?.kind!=="builtin").length;const partialCoverageWarnings=Object.entries({skipped_unmanaged:unmanagedActionRequiredExtensions.length,skipped_non_github:skippedNonGithubTotal,failed:updateCheckFailedTotal,not_checked:updateCheckStatusTotals.not_checked}).filter(([,count])=>count>0).map(([status,count])=>`extension_update_health_partial_coverage:${status}:${count}`);const updateHealthPartial=partialCoverageWarnings.length>0;const updateHealthCoverage=updateHealthPartial?"partial":"full";const effectiveWarnings=[...new Set([...normalizedWarnings,...partialCoverageWarnings])].sort((left,right)=>left.localeCompare(right));const warningCodes=[...new Set(effectiveWarnings.map(value=>warningCode(value)))].sort((left,right)=>left.localeCompare(right));const policyWarnings=summarizePolicyWarnings(effectiveWarnings);const scopeFlag=scope==="global"?"--global":"--project";const collisionPlan=buildRegistrationCollisionPlan(scope,normalizedWarnings,extensions,options);const remediation=buildExtensionTriageRemediation({normalizedWarnings:effectiveWarnings,options,scope,scopeFlag,updateCheckFailedTotal,policyWarningCount:policyWarnings.warning_count,unmanagedActionRequiredTotal:unmanagedActionRequiredExtensions.length,notCheckedTotal:updateCheckStatusTotals.not_checked,skippedNonGithubTotal,updateAvailableTotal});return{status:effectiveWarnings.length===0?"ok":"warn",warning_count:effectiveWarnings.length,warning_codes:warningCodes,warnings:effectiveWarnings,policy_warning_count:policyWarnings.warning_count,policy_violation_count:policyWarnings.violation_count,policy_blocked_count:policyWarnings.blocked_count,total_extensions:extensions.length,managed_total:managedTotal,enabled_total:enabledTotal,active_total:activeTotal,update_available_total:updateAvailableTotal,update_health_coverage:updateHealthCoverage,update_health_partial:updateHealthPartial,unmanaged_loaded_extension_count:unmanagedExtensions.length,unmanaged_loaded_extensions:unmanagedExtensions.map(entry=>entry.name).sort((left,right)=>left.localeCompare(right)),unmanaged_expected_extension_count:unmanagedExpectedExtensions.length,unmanaged_expected_extensions:unmanagedExpectedExtensions,unmanaged_action_required_extension_count:unmanagedActionRequiredExtensions.length,unmanaged_action_required_extensions:unmanagedActionRequiredExtensions,update_check_status_totals:updateCheckStatusTotals,update_check_failed_total:updateCheckFailedTotal,top_warnings:effectiveWarnings.slice(0,8),remediation,...collisionPlan?{collision_plan:collisionPlan}:{}}}function parseDoctorDetailMode(raw){if(!raw||raw.trim().length===0){return"summary"}const normalized=raw.trim().toLowerCase();if(normalized==="summary"||normalized==="deep"){return normalized}throw new PmCliError(`Invalid --detail value "${raw}". Expected summary or deep.`,EXIT_CODE.USAGE)}function warningCode(value){const normalized=value.trim();const separator=normalized.indexOf(":");if(separator===-1){return normalized}return normalized.slice(0,separator)}function collectUnknownCapabilityGuidance(warnings){const seen=new Set;const guidance=[];for(const warning of warnings){const parsedDetails=(()=>{const unknownWarning=parseUnknownExtensionCapabilityWarning(warning);if(unknownWarning){return[unknownWarning]}return parseLegacyExtensionCapabilityAliasWarning(warning)})();for(const parsed of parsedDetails){const key=`${parsed.layer}:${parsed.name}:${parsed.capability}`;if(seen.has(key)){continue}seen.add(key);guidance.push(parsed)}}return guidance}function buildCapabilityContractMetadata(){return{version:EXTENSION_CAPABILITY_CONTRACT.version,capabilities:[...EXTENSION_CAPABILITY_CONTRACT.capabilities],legacy_aliases:{...EXTENSION_CAPABILITY_CONTRACT.legacy_aliases}}}function isExpectedUnmanagedExtension(entry){const normalizedName=normalizeExtensionNameForMatch(entry.name);const normalizedDirectory=normalizeExtensionNameForMatch(entry.directory);if(normalizedName.startsWith("builtin-")){return true}return normalizedDirectory==="beads"||normalizedDirectory==="todos"}function buildDoctorConsistencySummary(scope,installedExtensions,loadedExtensions,failedLoads,disabledByFlag){if(scope!=="project"||disabledByFlag){return{warnings:[],summary:{active_project_count:0,loaded_project_count:0,active_project_names:[],loaded_project_names:[],missing_active_project_names:[]}}}const activeProjectNames=[...new Set(installedExtensions.filter(entry=>entry.active).map(entry=>normalizeExtensionNameForMatch(entry.name)))].sort((left,right)=>left.localeCompare(right));const loadedProjectNames=[...new Set(loadedExtensions.filter(entry=>entry.layer==="project").map(entry=>normalizeExtensionNameForMatch(entry.name)))].sort((left,right)=>left.localeCompare(right));const failedLoadNames=new Set(failedLoads.map(entry=>normalizeExtensionNameForMatch(entry.name)));const missingActiveProjectNames=activeProjectNames.filter(name=>!loadedProjectNames.includes(name)&&!failedLoadNames.has(name)).sort((left,right)=>left.localeCompare(right));const warnings=missingActiveProjectNames.length>0?[`extension_doctor_consistency_active_not_loaded:${missingActiveProjectNames.join(",")}`]:[];return{warnings,summary:{active_project_count:activeProjectNames.length,loaded_project_count:loadedProjectNames.length,active_project_names:activeProjectNames,loaded_project_names:loadedProjectNames,missing_active_project_names:missingActiveProjectNames}}}export{applyDoctorRuntimeActivationState,buildCapabilityContractMetadata,buildDoctorConsistencySummary,buildExtensionTriageSummary,buildRegistrationCollisionRemediation,classifyDoctorActivationFailureWarnings,classifyDoctorLoadFailureWarnings,classifyUnusedCapabilityWarnings,collectUnknownCapabilityGuidance,parseDoctorDetailMode,summarizeExtensionFailures};
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1e6087f2-01b5-59c3-a471-433c722316b0")}catch{}})();import{reconcileExtensionCapabilityUsage}from"../../core/extensions/index.js";import{EXTENSION_CAPABILITY_CONTRACT,KNOWN_EXTENSION_CAPABILITIES,parseLegacyExtensionCapabilityAliasWarning,parseUnknownExtensionCapabilityWarning}from"../../core/extensions/loader.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{normalizeExtensionNameForMatch}from"./shared.js";function summarizeExtensionFailures(failures){return failures.map(({layer,name,error})=>({layer,name,error}))}function addRuntimePath(pathsByExtension,extensionName,pathValue){const normalizedName=normalizeExtensionNameForMatch(extensionName),normalizedPath=pathValue.trim();if(normalizedName.length===0||normalizedPath.length===0)return;const existing=pathsByExtension.get(normalizedName)??new Set;existing.add(normalizedPath),pathsByExtension.set(normalizedName,existing)}function collectRuntimeActivationPaths(activationResult){const commandPathsByExtension=new Map,actionPathsByExtension=new Map;for(const registration of activationResult.registrations.commands)addRuntimePath(commandPathsByExtension,registration.name,registration.command),addRuntimePath(actionPathsByExtension,registration.name,registration.action);for(const handler of activationResult.commands.handlers)addRuntimePath(commandPathsByExtension,handler.name,handler.command);for(const override of activationResult.commands.overrides)addRuntimePath(commandPathsByExtension,override.name,override.command);return{commandPathsByExtension,actionPathsByExtension}}function sortedRuntimePaths(values){if(!(!values||values.size===0))return[...values].sort((left,right)=>left.localeCompare(right))}function resolveDoctorActivationStatus(params){const{enabled,normalizedName,loadedNames,loadFailedNames,activationFailedNames}=params;return enabled?loadFailedNames.has(normalizedName)||activationFailedNames.has(normalizedName)?{runtime_active:!1,activation_status:"failed"}:loadedNames.has(normalizedName)?{runtime_active:!0,activation_status:"ok"}:{runtime_active:!1,activation_status:"not_loaded"}:{runtime_active:!1,activation_status:"not_loaded"}}function applyDoctorRuntimeActivationState(extensions,loadResult,activationResult){const loadedNames=new Set(loadResult.loaded.map(entry=>normalizeExtensionNameForMatch(entry.name))),loadFailedNames=new Set(loadResult.failed.map(entry=>normalizeExtensionNameForMatch(entry.name))),activationFailedNames=new Set(activationResult.failed.map(entry=>normalizeExtensionNameForMatch(entry.name))),{commandPathsByExtension,actionPathsByExtension}=collectRuntimeActivationPaths(activationResult);return extensions.map(entry=>{const normalizedName=normalizeExtensionNameForMatch(entry.name),commandPaths=sortedRuntimePaths(commandPathsByExtension.get(normalizedName)),actionPaths=sortedRuntimePaths(actionPathsByExtension.get(normalizedName)),runtimeMetadata={...commandPaths?{command_paths:commandPaths}:{},...actionPaths?{action_paths:actionPaths}:{}},activationStatus=resolveDoctorActivationStatus({enabled:entry.enabled,normalizedName,loadedNames,loadFailedNames,activationFailedNames});return{...entry,...activationStatus,...runtimeMetadata}})}function summarizePolicyWarnings(warnings){let warningCount=0,violationCount=0,blockedCount=0;for(const warning of warnings)if(warning.startsWith("extension_policy_")){if(warningCount+=1,warning.startsWith("extension_policy_violation_")){violationCount+=1;continue}warning.startsWith("extension_policy_blocked_")&&(blockedCount+=1)}return{warning_count:warningCount,violation_count:violationCount,blocked_count:blockedCount}}function lifecycleFlagCommand(options,action){return options.vocabulary==="package"?`pm package --${action}`:`pm extension --${action}`}const REGISTRATION_COLLISION_WARNING_CODES=new Set(["extension_command_handler_collision","extension_command_override_collision","extension_command_override_handler_overlap","extension_parser_override_collision","extension_preflight_override_collision","extension_renderer_collision","extension_service_override_collision"]);function isRegistrationCollisionWarning(warning){return REGISTRATION_COLLISION_WARNING_CODES.has(warningCode(warning))}function isExtensionLayer(value){return value==="project"||value==="global"}function parseRegistrationCollisionWarning(warning){const parts=warning.split(":"),code=parts[0];if(!code||!REGISTRATION_COLLISION_WARNING_CODES.has(code))return null;const winnerLayer=parts.at(-4),winnerName=parts.at(-3)?.trim(),displacedLayer=parts.at(-2),displacedName=parts.at(-1)?.trim();return!isExtensionLayer(winnerLayer)||!isExtensionLayer(displacedLayer)||!winnerName||!displacedName?null:{code,surface:parts.slice(1,-4).join(":")||"global",winner:{layer:winnerLayer,name:winnerName},displaced:{layer:displacedLayer,name:displacedName}}}function collectRegistrationCollisionExtensionNames(warnings){const names=new Set;for(const warning of warnings){const parsed=parseRegistrationCollisionWarning(warning);parsed&&(names.add(parsed.winner.name),names.add(parsed.displaced.name))}return[...names].sort((left,right)=>left.localeCompare(right))}function buildRegistrationCollisionRemediation(warnings,commands){const registrationCollisionWarnings=warnings.filter(isRegistrationCollisionWarning);if(registrationCollisionWarnings.length===0)return null;const collisionNames=collectRegistrationCollisionExtensionNames(registrationCollisionWarnings);return`Extension registration collisions or handler/override overlaps detected.${collisionNames.length>0?` Conflicting extensions: ${collisionNames.join(", ")}.`:""} Single-winner surfaces can hide earlier package behavior. Deactivate one conflicting package with ${commands.deactivate}, or scope registration surfaces in extensions.policy.extension_overrides, then rerun ${commands.doctor}.`}function buildRegistrationCollisionPlan(scope,warnings,extensions,options){const collisions=warnings.map(warning=>parseRegistrationCollisionWarning(warning)).filter(entry=>entry!==null).sort((left,right)=>`${left.code}:${left.surface}:${left.winner.name}:${left.displaced.name}`.localeCompare(`${right.code}:${right.surface}:${right.winner.name}:${right.displaced.name}`));if(collisions.length===0)return;const scopeFlag=scope==="global"?"--global":"--project",deactivatePrefix=lifecycleFlagCommand(options,"deactivate"),doctorCommand=`${lifecycleFlagCommand(options,"doctor")} ${scopeFlag} --detail deep --trace`,extensionByName=new Map(extensions.map(entry=>[normalizeExtensionNameForMatch(entry.name),entry])),affectedByName=new Map;for(const collision of collisions)for(const name of[collision.winner.name,collision.displaced.name]){const normalizedName=normalizeExtensionNameForMatch(name);affectedByName.set(normalizedName,(affectedByName.get(normalizedName)??0)+1)}const remediationCandidates=[...affectedByName.entries()].map(([normalizedName,affectedCollisions])=>{const extension=extensionByName.get(normalizedName),extensionName=extension?.name??normalizedName,commandPaths=extension?.command_paths??[],actionPaths=extension?.action_paths??[];return{action:"deactivate",extension:extensionName,command:`${deactivatePrefix} ${extensionName} ${scopeFlag}`,affected_collisions:affectedCollisions,feature_loss:{command_paths:[...commandPaths].sort((left,right)=>left.localeCompare(right)),action_paths:[...actionPaths].sort((left,right)=>left.localeCompare(right))}}}).sort((left,right)=>{const affectedDelta=right.affected_collisions-left.affected_collisions;if(affectedDelta!==0)return affectedDelta;const leftSurfaceCount=left.feature_loss.command_paths.length+left.feature_loss.action_paths.length,rightSurfaceCount=right.feature_loss.command_paths.length+right.feature_loss.action_paths.length;return leftSurfaceCount!==rightSurfaceCount?leftSurfaceCount-rightSurfaceCount:left.extension.localeCompare(right.extension)});return{status:"conflicts_detected",collision_count:collisions.length,extension_count:affectedByName.size,next_best_command:doctorCommand,collisions,remediation_candidates:remediationCandidates}}function classifyDoctorLoadFailureWarnings(loadFailures){const warnings=[];for(const failure of loadFailures){const normalizedError=failure.error.toLowerCase();(normalizedError.includes("cannot find package '@unbrained/pm-cli'")||normalizedError.includes('cannot find module "@unbrained/pm-cli"')||normalizedError.includes("cannot find module '@unbrained/pm-cli'"))&&warnings.push(`extension_load_failed_sdk_dependency_missing:${failure.name}`),(normalizedError.includes("cannot use import statement outside a module")||normalizedError.includes("to load an es module")||normalizedError.includes("must use import to load es module"))&&warnings.push(`extension_load_failed_module_mode_mismatch:${failure.name}`)}return[...new Set(warnings)].sort((left,right)=>left.localeCompare(right))}function classifyDoctorActivationFailureWarnings(activationFailures=[]){const failures=Array.isArray(activationFailures)?activationFailures:[],warnings=[];for(const failure of failures){if(!failure||typeof failure.name!="string")continue;const missingCapability=failure.trace?.missing_capability??failure.trace?.capability;typeof missingCapability=="string"&&missingCapability.trim().length>0&&warnings.push(`extension_capability_missing:${failure.name}:${missingCapability.trim().toLowerCase()}`)}return[...new Set(warnings)].sort((left,right)=>left.localeCompare(right))}function classifyUnusedCapabilityWarnings(loadResult,activationResult){const warnings=[];for(const entry of reconcileExtensionCapabilityUsage(loadResult.loaded,activationResult))for(const capability of entry.unused)warnings.push(`extension_capability_unused:${entry.layer}:${entry.name}:${capability}`);return[...new Set(warnings)].sort((left,right)=>left.localeCompare(right))}const TRIAGE_REMEDIATION_RULES=[{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_manifest_")),build:ctx=>`Run ${lifecycleFlagCommand(ctx.options,"explore")} ${ctx.scopeFlag} to inspect discovered manifests and directories.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_unknown:")),build:()=>`Unknown extension capabilities detected. Allowed capabilities: ${KNOWN_EXTENSION_CAPABILITIES.join(", ")}. Review extension_capability_unknown warning details for suggested replacements.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_legacy_alias:")),build:()=>"Legacy extension capability aliases were auto-remapped to canonical capabilities. Update manifests to canonical names (migration/validation -> schema)."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_missing:")),build:ctx=>`Extension activation failed because code registered a surface missing from manifest capabilities. Run ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag} --detail deep --trace and add the reported missing_capability to manifest.json before publishing.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_capability_unused:")),build:ctx=>`Extension manifests declare capabilities that are never registered against. Remove each reported unused capability from manifest.json to keep least privilege, or add the matching registration. Run ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag} --detail deep --trace for per-extension registration counts.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_command_definition_legacy_handler_alias:")),build:()=>"Extension command definitions using legacy handler were auto-remapped. Update command definitions to use run: (context) => ... for forward compatibility."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_output_service_override_global:")||warning.startsWith("extension_output_renderer_override_global:")),build:()=>"Global output service/renderer overrides are active. For output_format, return context.payload/null/undefined unless the extension owns the command. For renderers, return null for unrelated payloads so pm falls back to native rendering."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_schema_narrow_activation:")),build:()=>"A package registers custom item types/fields (a GLOBAL schema contribution) but also declares narrow activation.commands, so it never activates for built-in commands like pm create <type> and the custom type silently fails to register. Remove activation.commands from manifest.json so pm activates the package for every command, or \u2014 if the schema is intentionally command-scoped \u2014 knowingly ignore this advisory."},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_load_failed_sdk_dependency_missing:")),build:ctx=>`Detected extension load failures caused by missing SDK dependency resolution. Ensure extension package dependencies include "@unbrained/pm-cli" and reinstall dependencies before running ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag}.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_load_failed_module_mode_mismatch:")),build:ctx=>`Detected extension module-mode mismatches. For ESM-based extension entries/imports, set package.json "type": "module" or use an explicit .mjs entry and rerun ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag}.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_pm_min_version_")||warning.startsWith("extension_pm_max_version_")),build:ctx=>`Extension pm version-bound warnings detected. Align each package manifest's pm_min_version/pm_max_version with the installed pm CLI version (see the warning's required/allowed=...:current=... details), or upgrade/downgrade the pm CLI to satisfy the declared bounds, then rerun ${lifecycleFlagCommand(ctx.options,"doctor")} ${ctx.scopeFlag}.`},{matches:(_warnings,ctx)=>ctx.updateCheckFailedTotal>0,build:ctx=>`Run ${lifecycleFlagCommand(ctx.options,"manage")} ${ctx.scopeFlag} after validating network and repository access.`},{matches:warnings=>warnings.some(warning=>warning.startsWith("extension_manager_state_")),build:ctx=>`Review and repair ${ctx.scope} managed extension state file if schema/read warnings persist.`},{matches:(_warnings,ctx)=>ctx.policyWarningCount>0,build:()=>"Extension governance policy warnings detected. Review settings.extensions.policy mode and allow/block lists to confirm intended capabilities and registration surfaces."}];function buildExtensionTriageRemediation(params){const{normalizedWarnings,options,scope,scopeFlag,updateCheckFailedTotal,policyWarningCount,unmanagedActionRequiredTotal,notCheckedTotal,skippedNonGithubTotal,updateAvailableTotal}=params,remediation=[],ctx={options,scope,scopeFlag,updateCheckFailedTotal,policyWarningCount};if(normalizedWarnings.length>0){const registrationCollisionRemediation=buildRegistrationCollisionRemediation(normalizedWarnings,{deactivate:`${lifecycleFlagCommand(options,"deactivate")} <name> ${scopeFlag}`,doctor:`${lifecycleFlagCommand(options,"doctor")} ${scopeFlag} --detail deep --trace`});registrationCollisionRemediation&&remediation.push(registrationCollisionRemediation);for(const rule of TRIAGE_REMEDIATION_RULES)rule.matches(normalizedWarnings,ctx)&&remediation.push(rule.build(ctx))}return unmanagedActionRequiredTotal>0&&remediation.push(`Update-check coverage is partial because unmanaged extensions need adoption. Adopt existing installs via ${lifecycleFlagCommand(options,"manage")} ${scopeFlag} --fix-managed-state (or ${lifecycleFlagCommand(options,"adopt-all")} ${scopeFlag}, ${lifecycleFlagCommand(options,"adopt")} <name> ${scopeFlag}, or reinstall via ${lifecycleFlagCommand(options,"install")} ${scopeFlag} <source>).`),skippedNonGithubTotal>0&&remediation.push("Update-check coverage is partial: non-GitHub managed sources were not checked. Inspect their registry or source directly; zero detected updates does not mean these packages are current. Runtime activation health is independent."),notCheckedTotal>0&&remediation.push(`Update-check coverage is partial: some sources have no completed check. Run ${lifecycleFlagCommand(options,"manage")} ${scopeFlag} to request update checks.`),updateAvailableTotal>0&&remediation.push(`Update available managed extensions via ${lifecycleFlagCommand(options,"install")} ${scopeFlag} <source>.`),remediation.length===0&&remediation.push(`No immediate action required. Re-run ${lifecycleFlagCommand(options,"manage")} ${scopeFlag} after extension changes.`),remediation}function buildExtensionTriageSummary(scope,warnings,extensions,options={}){const normalizedWarnings=[...new Set(warnings)].sort((left,right)=>left.localeCompare(right)),managedTotal=extensions.filter(entry=>entry.managed).length,enabledTotal=extensions.filter(entry=>entry.enabled).length,activeTotal=extensions.filter(entry=>entry.active).length,updateAvailableTotal=extensions.filter(entry=>entry.update_check_status==="checked"&&entry.update_available===!0).length,unmanagedExtensions=extensions.filter(entry=>entry.managed===!1),unmanagedExpectedExtensions=unmanagedExtensions.filter(entry=>isExpectedUnmanagedExtension(entry)).map(entry=>entry.name).sort((left,right)=>left.localeCompare(right)),unmanagedActionRequiredExtensions=unmanagedExtensions.filter(entry=>!isExpectedUnmanagedExtension(entry)).map(entry=>entry.name).sort((left,right)=>left.localeCompare(right)),updateCheckStatusTotals={checked:0,skipped_unmanaged:0,skipped_non_github:0,failed:0,not_checked:0};for(const entry of extensions)updateCheckStatusTotals[entry.update_check_status]+=1;const updateCheckFailedTotal=updateCheckStatusTotals.failed,skippedNonGithubTotal=extensions.filter(entry=>entry.update_check_status==="skipped_non_github"&&entry.source?.kind!=="builtin").length,partialCoverageWarnings=Object.entries({skipped_unmanaged:unmanagedActionRequiredExtensions.length,skipped_non_github:skippedNonGithubTotal,failed:updateCheckFailedTotal,not_checked:updateCheckStatusTotals.not_checked}).filter(([,count])=>count>0).map(([status,count])=>`extension_update_health_partial_coverage:${status}:${count}`),updateHealthPartial=partialCoverageWarnings.length>0,updateHealthCoverage=updateHealthPartial?"partial":"full",effectiveWarnings=[...new Set([...normalizedWarnings,...partialCoverageWarnings])].sort((left,right)=>left.localeCompare(right)),warningCodes=[...new Set(effectiveWarnings.map(value=>warningCode(value)))].sort((left,right)=>left.localeCompare(right)),policyWarnings=summarizePolicyWarnings(effectiveWarnings),scopeFlag=scope==="global"?"--global":"--project",collisionPlan=buildRegistrationCollisionPlan(scope,normalizedWarnings,extensions,options),remediation=buildExtensionTriageRemediation({normalizedWarnings:effectiveWarnings,options,scope,scopeFlag,updateCheckFailedTotal,policyWarningCount:policyWarnings.warning_count,unmanagedActionRequiredTotal:unmanagedActionRequiredExtensions.length,notCheckedTotal:updateCheckStatusTotals.not_checked,skippedNonGithubTotal,updateAvailableTotal});return{status:effectiveWarnings.length===0?"ok":"warn",warning_count:effectiveWarnings.length,warning_codes:warningCodes,warnings:effectiveWarnings,policy_warning_count:policyWarnings.warning_count,policy_violation_count:policyWarnings.violation_count,policy_blocked_count:policyWarnings.blocked_count,total_extensions:extensions.length,managed_total:managedTotal,enabled_total:enabledTotal,active_total:activeTotal,update_available_total:updateAvailableTotal,update_health_coverage:updateHealthCoverage,update_health_partial:updateHealthPartial,unmanaged_loaded_extension_count:unmanagedExtensions.length,unmanaged_loaded_extensions:unmanagedExtensions.map(entry=>entry.name).sort((left,right)=>left.localeCompare(right)),unmanaged_expected_extension_count:unmanagedExpectedExtensions.length,unmanaged_expected_extensions:unmanagedExpectedExtensions,unmanaged_action_required_extension_count:unmanagedActionRequiredExtensions.length,unmanaged_action_required_extensions:unmanagedActionRequiredExtensions,update_check_status_totals:updateCheckStatusTotals,update_check_failed_total:updateCheckFailedTotal,top_warnings:effectiveWarnings.slice(0,8),remediation,...collisionPlan?{collision_plan:collisionPlan}:{}}}function parseDoctorDetailMode(raw){if(!raw||raw.trim().length===0)return"summary";const normalized=raw.trim().toLowerCase();if(normalized==="summary"||normalized==="deep")return normalized;throw new PmCliError(`Invalid --detail value "${raw}". Expected summary or deep.`,EXIT_CODE.USAGE)}function warningCode(value){const normalized=value.trim(),separator=normalized.indexOf(":");return separator===-1?normalized:normalized.slice(0,separator)}function collectUnknownCapabilityGuidance(warnings){const seen=new Set,guidance=[];for(const warning of warnings){const parsedDetails=(()=>{const unknownWarning=parseUnknownExtensionCapabilityWarning(warning);return unknownWarning?[unknownWarning]:parseLegacyExtensionCapabilityAliasWarning(warning)})();for(const parsed of parsedDetails){const key=`${parsed.layer}:${parsed.name}:${parsed.capability}`;seen.has(key)||(seen.add(key),guidance.push(parsed))}}return guidance}function buildCapabilityContractMetadata(){return{version:EXTENSION_CAPABILITY_CONTRACT.version,capabilities:[...EXTENSION_CAPABILITY_CONTRACT.capabilities],legacy_aliases:{...EXTENSION_CAPABILITY_CONTRACT.legacy_aliases}}}function isExpectedUnmanagedExtension(entry){const normalizedName=normalizeExtensionNameForMatch(entry.name),normalizedDirectory=normalizeExtensionNameForMatch(entry.directory);return normalizedName.startsWith("builtin-")?!0:normalizedDirectory==="beads"||normalizedDirectory==="todos"}function buildDoctorConsistencySummary(scope,installedExtensions,loadedExtensions,failedLoads,disabledByFlag){if(scope!=="project"||disabledByFlag)return{warnings:[],summary:{active_project_count:0,loaded_project_count:0,active_project_names:[],loaded_project_names:[],missing_active_project_names:[]}};const activeProjectNames=[...new Set(installedExtensions.filter(entry=>entry.active).map(entry=>normalizeExtensionNameForMatch(entry.name)))].sort((left,right)=>left.localeCompare(right)),loadedProjectNames=[...new Set(loadedExtensions.filter(entry=>entry.layer==="project").map(entry=>normalizeExtensionNameForMatch(entry.name)))].sort((left,right)=>left.localeCompare(right)),failedLoadNames=new Set(failedLoads.map(entry=>normalizeExtensionNameForMatch(entry.name))),missingActiveProjectNames=activeProjectNames.filter(name=>!loadedProjectNames.includes(name)&&!failedLoadNames.has(name)).sort((left,right)=>left.localeCompare(right));return{warnings:missingActiveProjectNames.length>0?[`extension_doctor_consistency_active_not_loaded:${missingActiveProjectNames.join(",")}`]:[],summary:{active_project_count:activeProjectNames.length,loaded_project_count:loadedProjectNames.length,active_project_names:activeProjectNames,loaded_project_names:loadedProjectNames,missing_active_project_names:missingActiveProjectNames}}}export{applyDoctorRuntimeActivationState,buildCapabilityContractMetadata,buildDoctorConsistencySummary,buildExtensionTriageSummary,buildRegistrationCollisionRemediation,classifyDoctorActivationFailureWarnings,classifyDoctorLoadFailureWarnings,classifyUnusedCapabilityWarnings,collectUnknownCapabilityGuidance,parseDoctorDetailMode,summarizeExtensionFailures};
|
|
2
2
|
//# sourceMappingURL=doctor.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="18bf1015-c2c8-5530-a3ce-1531a8a1d0e2")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import{isPathWithinDirectory}from"../../core/fs/path-utils.js";import{PmCliError}from"../../core/shared/errors.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{includesExtensionCopyPath}from"./copy-scope.js";import{resolveCanonicalExtensionInstallDestination}from"./install-runtime.js";import{pathExists}from"../../core/fs/fs-utils.js";import{areDirectoriesEquivalent}from"./install-sources.js";const DEVELOPMENT_DIRECTORIES=new Set(["node_modules",".git","dist","build","coverage"]);async function buildExtensionInstallPlan(resolved,destination,scope,options){const localStat=resolved.source.kind==="local"?await fs.stat(resolved.source.absolute_path):void 0,sourceMode=resolved.source.kind==="local"?localStat.isDirectory()?"directory":"archive":resolved.source.kind,copy=await planExtensionDirectoryCopy(resolved.directory,destination,options),plan={source_mode:sourceMode,...sourceMode==="archive"?{archive_bytes:localStat.size}:{},copy},packageRoot=resolved.source_root??resolved.directory;if(sourceMode==="directory"&&(!copy.complete||copy.development_entries>0||copy.bytes>=16*1024*1024)&&await pathExists(path.join(packageRoot,"package.json"))&&(plan.packed_alternative={cwd:packageRoot,pack:{command:"npm",args:["pack","--ignore-scripts","--json"]},install:{command:"pm",args:["package","install","<archive-filename>",`--${scope}`]},archive_argument:"pack_result[0].filename"}),sourceMode==="directory"&&!copy.complete){const limit=copy.stop_reason==="entry_limit"?`${copy.max_entries} entries`:`${copy.max_depth} directory levels`;throw new PmCliError(`Local extension source scan stopped at ${limit}; the directory snapshot is incomplete and installation was refused. ${plan.packed_alternative?"Pack the package with npm pack --ignore-scripts --json, then install its archive.":"Install a smaller source directory or a packed archive."}`,EXIT_CODE.USAGE,{code:"extension_install_incomplete_source_scan",reason:copy.stop_reason,nextSteps:plan.packed_alternative?[`Run npm pack --ignore-scripts --json from the package root, then pm package install <archive-filename> --${scope}.`]:["Choose a smaller source directory or install a packed archive."]})}return plan}async function planExtensionDirectoryCopy(sourceDirectory,destinationDirectory,options={}){const{maxEntries=1e4,maxDepth=64,signal}=options;if(![maxEntries,maxDepth].every(value=>Number.isSafeInteger(value)&&value>0))throw new PmCliError("maxEntries and maxDepth must be positive safe integers.",EXIT_CODE.USAGE);signal?.throwIfAborted();const source=await fs.realpath(sourceDirectory),destination=await resolveCanonicalExtensionInstallDestination(destinationDirectory),installInPlace=await areDirectoriesEquivalent(source,destination);signal?.throwIfAborted();const scope=installInPlace?"in_place":isPathWithinDirectory(source,destination)?"nested_filtered_snapshot":"directory_snapshot",plan={copy_scope:scope,source_directory:source,destination_directory:destination,files:0,bytes:0,directories:0,symlinks:0,other_entries:0,scanned_entries:0,excluded_entries:0,development_entries:0,complete:!0,stop_reason:"complete",max_entries:maxEntries,max_depth:maxDepth};return scope==="in_place"||await scanExtensionCopyDirectory(source,0,plan,signal),plan}async function scanExtensionCopyDirectory(directory,depth,plan,signal){signal?.throwIfAborted();const handle=await fs.opendir(directory);for await(const entry of handle){if(signal?.throwIfAborted(),plan.scanned_entries>=plan.max_entries){plan.complete=!1,plan.stop_reason="entry_limit";return}plan.scanned_entries+=1;const candidate=path.join(directory,entry.name);if(!includesExtensionCopyPath(plan.source_directory,plan.destination_directory,candidate,plan.copy_scope==="nested_filtered_snapshot")){plan.excluded_entries+=1;continue}if(path.relative(plan.source_directory,candidate).split(path.sep).some(segment=>DEVELOPMENT_DIRECTORIES.has(segment))&&(plan.development_entries+=1),await countExtensionCopyEntry(candidate,depth,plan,signal),!plan.complete)return}}async function countExtensionCopyEntry(candidate,depth,plan,signal){const stat=await fs.lstat(candidate);if(signal?.throwIfAborted(),stat.isDirectory()){if(plan.directories+=1,depth+1>=plan.max_depth){plan.complete=!1,plan.stop_reason="depth_limit";return}await scanExtensionCopyDirectory(candidate,depth+1,plan,signal)}else stat.isFile()?(plan.files+=1,plan.bytes+=stat.size):stat.isSymbolicLink()?plan.symlinks+=1:plan.other_entries+=1}export{buildExtensionInstallPlan,planExtensionDirectoryCopy};
|
|
2
2
|
//# sourceMappingURL=install-plan.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="fcf7df06-e3b8-5476-a76a-cd391839c13d")}catch{}})();function buildBundledInstallReceipt(packages,dryRun){const succeeded=packages.filter(entry=>entry.result.ok).length;return{installed_all:!dryRun&&succeeded===packages.length,installed_count:dryRun?0:succeeded,...dryRun?{dry_run:!0,planned_count:succeeded}:{},failed_count:packages.length-succeeded,packages:packages.map(({alias,result})=>{const details=result.details;return{alias,ok:result.ok,extension:details.extension,source:details.source,source_resolution:details.source_resolution,install_plan:details.install_plan,dry_run:details.dry_run,destination_path:details.destination_path,activated:details.activated,settings_changed:details.settings_changed,command_paths:details.command_paths,action_paths:details.action_paths,command_discovery:details.command_discovery,verification:details.verification,runtime_activation_status:details.runtime_activation_status,activation_diagnostics:details.activation_diagnostics,warnings:result.warnings}})}}export{buildBundledInstallReceipt};
|
|
2
2
|
//# sourceMappingURL=install-receipts.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
`,"utf8")}
|
|
3
|
-
`,"utf8")}catch(error){await fs.rm(lockPath,{recursive
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="cefb224d-a18f-599a-9cf9-3d3a22616440")}catch{}})();import{withHostEnvironmentBoundary}from"../../core/fs/host-environment-errors.js";import{includesExtensionCopyPath}from"./copy-scope.js";import{randomUUID}from"node:crypto";import fs from"node:fs/promises";import os from"node:os";import path from"node:path";import{isFileAbsentError,pathExists}from"../../core/fs/fs-utils.js";import{isPathWithinDirectory}from"../../core/fs/path-utils.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolvePmPackageRootFromModule}from"../../core/packages/root.js";import{nowIso}from"../../core/shared/time.js";const EXTENSION_INSTALL_COPY_ATTEMPTS=3,EXTENSION_INSTALL_LOCK_ATTEMPTS=120,EXTENSION_INSTALL_LOCK_DELAY_MS=250,EXTENSION_INSTALL_LOCK_STALE_MS=12e4,RETRIABLE_EXTENSION_INSTALL_COPY_CODES=new Set(["EEXIST","ENOTEMPTY","ENOENT"]),errnoCode=error=>typeof error=="object"&&error!==null&&"code"in error?error.code:void 0,isRetriableExtensionInstallCopyError=error=>RETRIABLE_EXTENSION_INSTALL_COPY_CODES.has(String(errnoCode(error))),isErrnoCode=(error,code)=>errnoCode(error)===code,sleep=ms=>new Promise(resolve=>{setTimeout(resolve,ms)}),ensureExtensionModuleTypeMarker=async destinationDirectory=>{const markerPath=path.join(destinationDirectory,"package.json");await pathExists(markerPath)||await fs.writeFile(markerPath,`${JSON.stringify({type:"module"},null,2)}
|
|
2
|
+
`,"utf8")},ensureInstalledExtensionSdkLink=async destinationDirectory=>{const hostPackageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]),scopedDirectory=path.join(destinationDirectory,"node_modules","@unbrained"),linkPath=path.join(scopedDirectory,"pm-cli");await fs.mkdir(scopedDirectory,{recursive:!0}),await fs.rm(linkPath,{recursive:!0,force:!0}),await fs.symlink(hostPackageRoot,linkPath,process.platform==="win32"?"junction":"dir")},resolveCanonicalExtensionInstallDestination=async destinationDirectory=>{const resolvedDestination=path.resolve(destinationDirectory),destinationParent=path.dirname(resolvedDestination),destinationRoot=path.parse(destinationParent).root;let canonicalDestinationParent=await fs.realpath(destinationRoot).catch(()=>destinationRoot);const relativeDestinationParent=path.relative(destinationRoot,destinationParent),destinationSegments=relativeDestinationParent===""?[]:relativeDestinationParent.split(path.sep);for(const[index,segment]of destinationSegments.entries()){const candidate=path.join(canonicalDestinationParent,segment);try{canonicalDestinationParent=await fs.realpath(candidate)}catch{canonicalDestinationParent=path.join(canonicalDestinationParent,...destinationSegments.slice(index));break}}return path.join(canonicalDestinationParent,path.basename(resolvedDestination))},copyExtensionDirectoryWithoutSelfNesting=async(sourceDirectory,destinationDirectory,copyDirectory,temporaryDirectory=os.tmpdir())=>withHostEnvironmentBoundary("extension_install_copy",async()=>{const resolvedSource=path.resolve(sourceDirectory),canonicalSource=await fs.realpath(resolvedSource).catch(()=>resolvedSource),canonicalDestination=await resolveCanonicalExtensionInstallDestination(destinationDirectory);if(canonicalSource===canonicalDestination)return;if(!isPathWithinDirectory(canonicalSource,canonicalDestination)){await copyDirectory(canonicalSource,destinationDirectory,{recursive:!0,force:!0,filter:sourcePath=>includesExtensionCopyPath(canonicalSource,canonicalDestination,path.resolve(sourcePath),!1)});return}const systemTempDirectory=await fs.realpath(path.resolve(temporaryDirectory)).catch(()=>resolveCanonicalExtensionInstallDestination(temporaryDirectory)),stagingBase=isPathWithinDirectory(canonicalSource,systemTempDirectory)?path.dirname(canonicalSource):systemTempDirectory;if(isPathWithinDirectory(canonicalSource,stagingBase))throw new PmCliError(`Extension source "${sourceDirectory}" contains its install destination and no external staging directory is available. Install a narrower package directory instead.`,EXIT_CODE.USAGE,{code:"extension_install_source_contains_destination"});const stagingRoot=await fs.mkdtemp(path.join(stagingBase,"pm-extension-copy-")),stagedDirectory=path.join(stagingRoot,"extension");try{await copyDirectory(canonicalSource,stagedDirectory,{recursive:!0,force:!0,filter:sourcePath=>includesExtensionCopyPath(canonicalSource,canonicalDestination,path.resolve(sourcePath),!0)}),await copyDirectory(stagedDirectory,destinationDirectory,{recursive:!0,force:!0})}finally{await fs.rm(stagingRoot,{recursive:!0,force:!0})}}),copyExtensionDirectoryForInstall=async(sourceDirectory,destinationDirectory,copyDirectory=fs.cp)=>{for(let attempt=1;attempt<=EXTENSION_INSTALL_COPY_ATTEMPTS;attempt+=1)try{await withHostEnvironmentBoundary("extension_install_copy",async()=>{await fs.rm(destinationDirectory,{recursive:!0,force:!0}),await copyExtensionDirectoryWithoutSelfNesting(sourceDirectory,destinationDirectory,copyDirectory)});return}catch(error){if(!isRetriableExtensionInstallCopyError(error)||attempt===EXTENSION_INSTALL_COPY_ATTEMPTS)throw error;await sleep(EXTENSION_INSTALL_LOCK_DELAY_MS)}},readExtensionInstallLockOwnerToken=async lockPath=>{let ownerContents;try{ownerContents=await fs.readFile(path.join(lockPath,"owner.json"),"utf8")}catch(error){if(!isFileAbsentError(error))throw error;return null}let parsed;try{parsed=JSON.parse(ownerContents)}catch{return null}if(typeof parsed!="object"||parsed===null||!("token"in parsed))return null;const token=parsed.token;return typeof token=="string"&&token.length>0?token:null},removeExtensionInstallLockIfOwned=async(lockPath,ownerToken)=>await readExtensionInstallLockOwnerToken(lockPath)!==ownerToken?!1:(await fs.rm(lockPath,{recursive:!0,force:!0}),!0),reclaimStaleExtensionInstallLock=async(lockPath,staleMs)=>{let stat;try{stat=await fs.stat(lockPath)}catch{return!1}if(Date.now()-stat.mtimeMs<=staleMs)return!1;const staleOwnerToken=await readExtensionInstallLockOwnerToken(lockPath);return staleOwnerToken===null?(await fs.rm(lockPath,{recursive:!0,force:!0}),!0):removeExtensionInstallLockIfOwned(lockPath,staleOwnerToken)},startExtensionInstallLockHeartbeat=(lockPath,ownerToken,intervalMs)=>{let heartbeat=Promise.resolve();const timer=setInterval(()=>{heartbeat=heartbeat.then(async()=>{if(await readExtensionInstallLockOwnerToken(lockPath)!==ownerToken)return;const heartbeatAt=new Date;await fs.utimes(lockPath,heartbeatAt,heartbeatAt)}).catch(()=>{})},intervalMs);return timer.unref(),async()=>{clearInterval(timer),await heartbeat}},createExtensionInstallLock=async(lockPath,owner)=>{await fs.mkdir(lockPath);try{await fs.writeFile(path.join(lockPath,"owner.json"),`${JSON.stringify(owner,null,2)}
|
|
3
|
+
`,"utf8")}catch(error){throw await fs.rm(lockPath,{recursive:!0,force:!0}).catch(()=>{}),error}},acquireExtensionInstallLock=async(lockPath,owner,attempts,delayMs,staleMs)=>{for(let attempt=1;attempt<=attempts;attempt+=1)try{return await createExtensionInstallLock(lockPath,owner),!0}catch(error){if(!isErrnoCode(error,"EEXIST"))throw error;await reclaimStaleExtensionInstallLock(lockPath,staleMs)?attempt-=1:await sleep(delayMs)}return!1},withExtensionInstallLock=async(settingsRoot,destinationDirectoryName,run,options)=>withHostEnvironmentBoundary("extension_install",async()=>{const lockRoot=path.join(settingsRoot,"runtime","extension-install-locks"),lockPath=path.join(lockRoot,"scope.lock");await fs.mkdir(lockRoot,{recursive:!0});const{attempts:rawAttempts=EXTENSION_INSTALL_LOCK_ATTEMPTS,delay_ms:rawDelayMs=EXTENSION_INSTALL_LOCK_DELAY_MS,stale_ms:rawStaleMs=EXTENSION_INSTALL_LOCK_STALE_MS,heartbeat_ms:rawHeartbeatMs}=options??{};if(![rawAttempts,rawDelayMs,rawStaleMs,rawHeartbeatMs].filter(value=>value!==void 0).every(Number.isFinite))throw new PmCliError("Extension install lock timings must be finite numbers.",EXIT_CODE.USAGE);const attempts=Math.max(1,Math.floor(rawAttempts)),delayMs=Math.max(0,Math.floor(rawDelayMs)),staleMs=Math.floor(rawStaleMs),heartbeatMs=Math.floor(rawHeartbeatMs??staleMs/3);if(staleMs<=0||heartbeatMs<=0||heartbeatMs>=staleMs)throw new PmCliError("Extension install lock timings require stale_ms > 0 and 0 < heartbeat_ms < stale_ms.",EXIT_CODE.USAGE);const owner={pid:process.pid,token:randomUUID(),created_at:nowIso(),destination:destinationDirectoryName};if(!await acquireExtensionInstallLock(lockPath,owner,attempts,delayMs,staleMs))throw new PmCliError(`Timed out waiting for extension install lock for "${destinationDirectoryName}".`,EXIT_CODE.CONFLICT);const stopHeartbeat=startExtensionInstallLockHeartbeat(lockPath,owner.token,heartbeatMs);let operationSucceeded=!1;try{const result=await run();return operationSucceeded=!0,result}finally{await stopHeartbeat(),await removeExtensionInstallLockIfOwned(lockPath,owner.token).catch(error=>{if(operationSucceeded)throw error})}});export{copyExtensionDirectoryForInstall,copyExtensionDirectoryWithoutSelfNesting,ensureExtensionModuleTypeMarker,ensureInstalledExtensionSdkLink,isErrnoCode,isRetriableExtensionInstallCopyError,resolveCanonicalExtensionInstallDestination,withExtensionInstallLock};
|
|
4
4
|
//# sourceMappingURL=install-runtime.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="776854e4-6df4-507e-b21b-a4d320946642")}catch{}})();import{withHostEnvironmentBoundary}from"../../core/fs/host-environment-errors.js";import fs from"node:fs/promises";import path from"node:path";import{getSettingsPath}from"../../core/store/paths.js";import{isErrnoCode}from"./install-runtime.js";import{resolveManagedExtensionStatePath}from"./managed-state.js";const readOptionalMetadataFile=async filePath=>fs.readFile(filePath).catch(error=>{if(isErrnoCode(error,"ENOENT"))return null;throw error}),captureExtensionInstallSnapshot=async(selectedRoot,settingsRoot,destinationDirectory,destinationExists,backupDirectory)=>withHostEnvironmentBoundary("extension_install_backup",async()=>{const managedStatePath=resolveManagedExtensionStatePath(selectedRoot),settingsPath=getSettingsPath(settingsRoot),[managedStateContents,settingsContents]=await Promise.all([readOptionalMetadataFile(managedStatePath),readOptionalMetadataFile(settingsPath)]);return destinationExists&&await fs.cp(destinationDirectory,backupDirectory,{recursive:!0,force:!0}),{backupDirectory,destinationDirectory,destinationExists,managedStatePath,managedStateContents,settingsPath,settingsContents}}),restoreExtensionInstallSnapshot=async snapshot=>withHostEnvironmentBoundary("extension_install_rollback",async()=>{await fs.rm(snapshot.destinationDirectory,{recursive:!0,force:!0}),snapshot.destinationExists&&await fs.cp(snapshot.backupDirectory,snapshot.destinationDirectory,{recursive:!0,force:!0});for(const[filePath,contents]of[[snapshot.managedStatePath,snapshot.managedStateContents],[snapshot.settingsPath,snapshot.settingsContents]])contents===null?await fs.rm(filePath,{force:!0}):(await fs.mkdir(path.dirname(filePath),{recursive:!0}),await fs.writeFile(filePath,contents))});export{captureExtensionInstallSnapshot,readOptionalMetadataFile,restoreExtensionInstallSnapshot};
|
|
2
2
|
//# sourceMappingURL=install-snapshot.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
${message}`,EXIT_CODE.GENERIC_FAILURE)}}function resolveNpmCommandName(platform=process.platform){return platform==="win32"?"npm.cmd":"npm"}function shouldRunNpmCommandInShell(platform=process.platform){return platform==="win32"}async function runNpmCommand(args,cwd,execRunner=execFileAsync,platform=process.platform,environment=process.env){const npmCommand=resolveNpmCommandName(platform)
|
|
3
|
-
${message}`,EXIT_CODE.GENERIC_FAILURE)}}function npmPackageNameFromSpec(spec){const trimmed=spec.trim();const withoutAlias=trimmed.includes("@file:")?trimmed.slice(0,trimmed.lastIndexOf("@file:")):trimmed;if(withoutAlias.startsWith("@")){const scoped=withoutAlias.match(/^(@[^/@\s]+\/[^/@\s]+)/);return scoped?.[1]??withoutAlias}const unscoped=withoutAlias.match(/^([^/@\s]+)/);return unscoped?.[1]??withoutAlias}function isNpmLocalFileAliasSpec(spec){const marker="@file:";const markerIndex=spec.lastIndexOf(marker);return markerIndex>0&&spec.slice(0,markerIndex).trim().length>0&&spec.slice(markerIndex+marker.length).trim().length>0}function isNpmNotFoundError(error){const message=error instanceof Error?error.message:String(error);const normalized=message.toLowerCase();return normalized.includes("npm err! code e404")||normalized.includes("404 not found")||normalized.includes("is not in this registry")}function isNpmPackNotFoundError(error){const message=error instanceof Error?error.message:String(error);const normalized=message.toLowerCase();return isNpmNotFoundError(error)||normalized.includes("not found")}function isFirstPartyPmPackageName(packageName){const normalized=packageName.trim().toLowerCase();return normalized.startsWith("@unbrained/pm-")||normalized.startsWith("pm-")}function buildNpmNotFoundRecovery(spec){const packageName=npmPackageNameFromSpec(spec);const isFirstPartyPackage=isFirstPartyPmPackageName(packageName);const repoName=packageName.replace(/^.*\//,"");const githubSource=isFirstPartyPackage?`github.com/unbraind/${repoName}`:void 0;const nextBestCommand=githubSource?`pm install --project ${githubSource}`:void 0;return{message:isFirstPartyPackage?`npm package "${spec}" was not found in the registry. If this is an unpublished first-party pm package, install its GitHub repository instead.`:`npm package "${spec}" was not found in the registry.`,context:{code:"npm_package_not_found",required:"Use an install source that exists, or publish the npm package before installing it with npm:<name>.",why:"Classifying npm 404s avoids repeated registry retries and gives agents a deterministic fallback path.",examples:nextBestCommand?[nextBestCommand,`pm package catalog --project --json`]:[`npm view ${packageName}`,`pm package catalog --project --json`],nextSteps:nextBestCommand?[`Try ${nextBestCommand} if the repository exists.`,"Use pm package catalog --project --json to inspect bundled package aliases before installing."]:[`Verify ${packageName} exists in the npm registry and that you have access to it.`,"Use pm package catalog --project --json to inspect bundled package aliases before installing."],recovery:{attempted_command:`pm install --project npm:${spec}`,normalized_args:["install","--project",`npm:${spec}`],...githubSource&&nextBestCommand?{fallback_candidates:[{source:githubSource,command:nextBestCommand,reason:"canonical first-party GitHub repository fallback for unpublished pm packages"}],next_best_command:nextBestCommand}:{}}}}}function wrapNpmPackResolutionError(spec,error){if(!isNpmPackNotFoundError(error)){return null}const recovery=buildNpmNotFoundRecovery(spec);return new PmCliError(recovery.message,EXIT_CODE.NOT_FOUND,recovery.context)}async function resolveLocalNpmPackagePath(spec){if(path.isAbsolute(spec)||spec.startsWith(".")||spec.startsWith("..")){const absolutePath=path.resolve(process.cwd(),spec);return await pathExists(absolutePath)?absolutePath:null}try{const parsed=new URL(spec);if(parsed.protocol==="file:"){const absolutePath=fileURLToPath(parsed);return await pathExists(absolutePath)?absolutePath:null}}catch{}if(!/^[a-z][a-z0-9+.-]*:/i.test(spec)){const absolutePath=path.resolve(process.cwd(),spec);if(await pathExists(absolutePath)){return absolutePath}}return null}async function resolveNpmPackSpec(spec){const localPath=await resolveLocalNpmPackagePath(spec);if(localPath){return localPath}const localFileAlias=normalizeNpmLocalFileAliasSpec(spec);if(localFileAlias!==spec){return localFileAlias}if(/^[a-z][a-z0-9+.-]*:/i.test(spec)){return spec}return spec}function normalizeNpmLocalFileAliasSpec(spec,cwd=process.cwd()){const marker="@file:";const markerIndex=spec.lastIndexOf(marker);if(!isNpmLocalFileAliasSpec(spec)){return spec}const packageName=spec.slice(0,markerIndex);const target=spec.slice(markerIndex+marker.length);if(target.startsWith("//")&&!target.startsWith("///")){return spec}if(!target.startsWith("/")){return`${packageName}@${path.resolve(cwd,target)}`}let decodedPath;try{decodedPath=decodeURIComponent(new URL(`file:${target}`).pathname)}catch{return spec}const nativePath=/^\/[A-Za-z]:/.test(decodedPath)?decodedPath.slice(1):decodedPath;return`${packageName}@${nativePath}`}function resolvePackedTarball(packDirectory,filename){const tarball=path.resolve(packDirectory,filename);const relativeTarball=path.relative(packDirectory,tarball);if(relativeTarball.length===0||relativeTarball===".."||relativeTarball.startsWith(`..${path.sep}`)||path.isAbsolute(relativeTarball)){throw new PmCliError("npm pack reported a package archive outside its isolated destination.",EXIT_CODE.GENERIC_FAILURE,{code:"npm_package_archive_unsafe",required:"Retry with a trusted npm client that writes its archive inside the requested pack destination.",why:"pm will not read a package-manager artifact outside the isolated directory created for this install."})}return tarball}function decodePackedNpmCandidate(value,key){if(typeof value!=="object"||value===null||Array.isArray(value)){return void 0}const record=value;if(typeof record.filename!=="string"||record.filename.trim().length===0){return void 0}return{...key===void 0?{}:{key},filename:record.filename,...typeof record.name==="string"?{name:record.name}:{},...typeof record.version==="string"?{version:record.version}:{}}}function collectPackedNpmCandidates(parsed){const entries=Array.isArray(parsed)?parsed.map(value=>({value})):typeof parsed==="object"&&parsed!==null?Object.entries(parsed).map(([key,value])=>({key,value})):[];return entries.flatMap(({key,value})=>{const candidate=decodePackedNpmCandidate(value,key);return candidate?[candidate]:[]})}function selectPackedNpmCandidate(candidates,expectedPackage){const normalizedExpected=expectedPackage?.trim().toLowerCase();const matchingCandidates=normalizedExpected?candidates.filter(candidate=>{const normalizedName=candidate.name?.trim().toLowerCase();return normalizedName!==void 0?normalizedName===normalizedExpected:candidate.key?.trim().toLowerCase()===normalizedExpected}):[];if(matchingCandidates.length===1)return matchingCandidates[0];if(candidates.length!==1)return void 0;const soleCandidate=candidates[0];const soleIdentity=soleCandidate.name??soleCandidate.key;return normalizedExpected&&soleIdentity!==void 0&&soleIdentity.trim().toLowerCase()!==normalizedExpected?void 0:soleCandidate}function parsePackedNpmPackage(stdout,packDirectory,expectedPackage){let parsed;try{parsed=JSON.parse(stdout)}catch{const filename=stdout.split(/\r?\n/).map(line=>line.trim()).filter(line=>line.length>0).at(-1);if(!filename){throw new PmCliError("npm pack did not report a tarball filename.",EXIT_CODE.GENERIC_FAILURE)}return{tarball:resolvePackedTarball(packDirectory,filename)}}const candidates=collectPackedNpmCandidates(parsed);const selected=selectPackedNpmCandidate(candidates,expectedPackage);if(!selected){throw new PmCliError("npm pack --json returned an unsupported or ambiguous package receipt.",EXIT_CODE.GENERIC_FAILURE,{code:"npm_pack_json_shape_unsupported",required:"Use an npm client that returns an array of package receipts or an object keyed by package name, with exactly one requested package entry containing filename.",why:`Well-formed JSON contained ${candidates.length} usable package receipt(s), but pm could not select ${expectedPackage??"one package"} deterministically.`})}return{tarball:resolvePackedTarball(packDirectory,selected.filename),package:selected.name??selected.key,version:selected.version}}async function resolveNpmSourceDirectory(source){return resolveNpmSourceDirectoryWithRunner(source,runNpmCommand)}async function resolveNpmSourceDirectoryWithRunner(source,npmRunner){const localPackageRoot=await resolveLocalNpmPackagePath(source.spec);if(localPackageRoot){const localStats=await fs.stat(localPackageRoot);if(localStats.isFile()&&isLocalPackageArchive(localPackageRoot)){return extractLocalPackageArchive(localPackageRoot)}const packageJsonPath=path.join(localPackageRoot,"package.json");const packageJson=await pathExists(packageJsonPath)?JSON.parse(await fs.readFile(packageJsonPath,"utf8")):{};return{directory:await resolvePackageExtensionDirectory(localPackageRoot,source.input),package:typeof packageJson.name==="string"?packageJson.name:void 0,version:typeof packageJson.version==="string"?packageJson.version:void 0,cleanup:async()=>{}}}const tempRoot=await fs.mkdtemp(path.join(os.tmpdir(),"pm-npm-package-source-"));const packDirectory=path.join(tempRoot,"pack");await fs.mkdir(packDirectory,{recursive:true});try{const packSpec=await resolveNpmPackSpec(source.spec);const packStdout=await npmRunner(["pack",packSpec,"--json","--pack-destination",packDirectory]);const packed=parsePackedNpmPackage(packStdout,packDirectory,isNpmLocalFileAliasSpec(source.spec)?void 0:npmPackageNameFromSpec(source.spec));if(!await pathExists(packed.tarball)){throw new PmCliError("npm pack did not create its reported package archive.",EXIT_CODE.GENERIC_FAILURE,{code:"npm_package_archive_missing",required:"Retry the npm package install with a healthy registry and writable temporary directory.",why:"The package manager reported a tarball filename that was absent before validation, so pm cannot safely extract or install it."})}const extracted=await extractLocalPackageArchive(packed.tarball);return{directory:extracted.directory,package:packed.package??extracted.package,version:packed.version??extracted.version,cleanup:async()=>{try{await extracted.cleanup()}finally{await fs.rm(tempRoot,{recursive:true,force:true})}}}}catch(error){await fs.rm(tempRoot,{recursive:true,force:true});const wrappedError=wrapNpmPackResolutionError(source.spec,error);if(wrappedError){throw wrappedError}throw error}}function isLocalPackageArchive(candidate){const normalized=candidate.toLowerCase();return normalized.endsWith(".tgz")||normalized.endsWith(".tar.gz")}function failLocalPackageArchive(message){throw new PmCliError(message,EXIT_CODE.USAGE,{code:"local_package_archive_unsafe",required:"Use a bounded npm .tgz or .tar.gz archive with one package/ root and no links or escaping paths.",why:"Package archives are untrusted input and must be validated before any entry reaches the filesystem."})}function validateLocalPackageArchiveEntry(entry,limits,state){if(entry.meta)return;state.entries+=1;if(state.entries>limits.maxEntries){failLocalPackageArchive(`Local package archive exceeds the ${limits.maxEntries} entry limit.`)}const archivePath=entry.path;const segments=archivePath.split("/");if(archivePath.includes("\\")||archivePath.startsWith("/")||/^[A-Za-z]:/u.test(archivePath)||segments.some(segment=>segment==="..")){failLocalPackageArchive(`Local package archive contains an escaping path: "${archivePath}".`)}if(segments[0]!=="package"){failLocalPackageArchive(`Local package archive entry "${archivePath}" is outside the required package/ root.`)}if(entry.type==="SymbolicLink"||entry.type==="Link"){failLocalPackageArchive(`Local package archive link "${archivePath}" is not supported.`)}if(entry.type!=="File"&&entry.type!=="OldFile"&&entry.type!=="Directory"){failLocalPackageArchive(`Local package archive entry "${archivePath}" uses unsupported type "${entry.type}".`)}if(entry.size>limits.maxEntryBytes){failLocalPackageArchive(`Local package archive entry "${archivePath}" exceeds the ${limits.maxEntryBytes} byte entry limit.`)}state.expandedBytes+=entry.size;if(state.expandedBytes>limits.maxExpandedBytes){failLocalPackageArchive(`Local package archive exceeds the ${limits.maxExpandedBytes} expanded byte limit.`)}if(archivePath==="package/package.json"){state.packageJsonEntries+=1}}async function extractLocalPackageArchive(archivePath,limits=LOCAL_PACKAGE_ARCHIVE_LIMITS){const archiveStats=await fs.stat(archivePath);if(archiveStats.size>limits.maxArchiveBytes){failLocalPackageArchive(`Local package archive exceeds the ${limits.maxArchiveBytes} archive byte limit.`)}const tempRoot=await fs.mkdtemp(path.join(os.tmpdir(),"pm-local-package-archive-"));const extractDirectory=path.join(tempRoot,"extract");await fs.mkdir(extractDirectory,{recursive:true});const state={entries:0,expandedBytes:0,packageJsonEntries:0};let validationError;try{await listTar({file:archivePath,strict:true,maxDecompressionRatio:100,onReadEntry:entry=>{if(validationError!==void 0)return;try{validateLocalPackageArchiveEntry(entry,limits,state)}catch(error){validationError=error}}});if(validationError!==void 0)throw validationError;if(state.packageJsonEntries!==1){failLocalPackageArchive(`Local package archive must contain exactly one package/package.json entry; found ${state.packageJsonEntries}.`)}await extractTar({file:archivePath,cwd:extractDirectory,strict:true,preservePaths:false,preserveOwner:false,noMtime:true,unlink:true,maxDepth:64,maxDecompressionRatio:100});const packageRoot=path.join(extractDirectory,"package");const packageJsonPath=path.join(packageRoot,"package.json");const packageJson=JSON.parse(await fs.readFile(packageJsonPath,"utf8"));await installNpmPackageRuntimeDependencies(packageRoot);return{directory:await resolvePackageExtensionDirectory(packageRoot,archivePath),package:typeof packageJson.name==="string"?packageJson.name:void 0,version:typeof packageJson.version==="string"?packageJson.version:void 0,cleanup:async()=>{await fs.rm(tempRoot,{recursive:true,force:true})}}}catch(error){await fs.rm(tempRoot,{recursive:true,force:true});throw error}}async function installNpmPackageRuntimeDependencies(packageRoot,npmRunner=runNpmCommand){const packageJsonPath=path.join(packageRoot,"package.json");if(!await pathExists(packageJsonPath)){return}let parsed;try{parsed=JSON.parse(await fs.readFile(packageJsonPath,"utf8"))}catch{return}if(typeof parsed!=="object"||parsed===null){return}const manifest=parsed;const dependencySpecs=runtimeDependencyInstallSpecs(manifest);const shouldLinkHostedPmCli=hasHostedPmCliDependency(manifest);if(dependencySpecs.length===0&&!shouldLinkHostedPmCli){return}const runtimeOnlyManifest={...parsed};delete runtimeOnlyManifest.devDependencies;const installManifest={...runtimeOnlyManifest};removeHostedPmCliDependency(installManifest);await fs.writeFile(packageJsonPath,`${JSON.stringify(installManifest,null,2)}
|
|
4
|
-
`,"utf8");try{await Promise.all([fs.rm(path.join(packageRoot,"package-lock.json"),{force
|
|
5
|
-
`,"utf8")}}function hasHostedPmCliDependency(manifest){for(const dependencyMap of[manifest.dependencies,manifest.optionalDependencies,manifest.peerDependencies]){if(typeof dependencyMap==="object"&&dependencyMap!==null&&PM_CLI_PACKAGE_NAME in dependencyMap){return true}}return false}function removeHostedPmCliDependency(manifest){for(const field of["dependencies","optionalDependencies","peerDependencies"]){const dependencyMap=manifest[field];if(typeof dependencyMap!=="object"||dependencyMap===null){continue}const nextMap={...dependencyMap};delete nextMap[PM_CLI_PACKAGE_NAME];if(Object.keys(nextMap).length===0){delete manifest[field]}else{manifest[field]=nextMap}}}async function linkHostedPmCliDependency(packageRoot){const hostPackageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);const[scope,packageName]=PM_CLI_PACKAGE_NAME.split("/");const scopedDirectory=path.join(packageRoot,"node_modules",scope);const linkPath=path.join(scopedDirectory,packageName);await fs.mkdir(scopedDirectory,{recursive:true});await fs.rm(linkPath,{recursive:true,force:true});await fs.symlink(hostPackageRoot,linkPath,resolveDirectorySymlinkType(process.platform))}function resolveDirectorySymlinkType(platform){return platform==="win32"?"junction":"dir"}function validateRuntimeDependencySpec(name,version){if(name.startsWith("-")){throw new PmCliError(`Extension runtime dependency name "${name}" is unsafe because npm could interpret it as a command-line option.`,EXIT_CODE.USAGE,{code:"extension_dependency_name_unsafe",required:"Use a valid npm package name that does not begin with a dash.",why:"Extension manifests are untrusted input and dependency names must never become npm options."})}const hasUnsafeControlOrShellCharacter=[...version].some(character=>{const codePoint=character.charCodeAt(0);return codePoint<=31||codePoint===127||"&|;()`\"'".includes(character)});if(hasUnsafeControlOrShellCharacter){throw new PmCliError(`Extension runtime dependency "${name}" has an unsafe version specifier.`,EXIT_CODE.USAGE,{code:"extension_dependency_version_unsafe",required:"Use an npm version, range, dist-tag, URL, or file specifier without shell metacharacters.",why:"npm.cmd requires a command shell on Windows, so untrusted shell metacharacters cannot be forwarded."})}try{npa.resolve(name,version)}catch{throw new PmCliError(`Extension runtime dependency "${name}@${version}" is not a valid npm dependency specifier.`,EXIT_CODE.USAGE,{code:"extension_dependency_spec_invalid",required:"Use a valid npm package name and npm-supported version, range, dist-tag, URL, or file specifier.",why:"Only grammar-validated dependency specs may be written to the isolated runtime install manifest."})}return`${name}@${version}`}function runtimeDependencyInstallSpecs(manifest){const specs=new Map;for(const dependencyMap of[manifest.dependencies,manifest.optionalDependencies,manifest.peerDependencies]){if(typeof dependencyMap!=="object"||dependencyMap===null){continue}for(const[name,version]of Object.entries(dependencyMap)){if(name===PM_CLI_PACKAGE_NAME||typeof version!=="string"||version.trim().length===0||specs.has(name)){continue}const normalizedVersion=version.trim();specs.set(name,validateRuntimeDependencySpec(name,normalizedVersion))}}return[...specs.values()]}async function resolvePackageExtensionDirectory(packageRoot,sourceLabel){const discovered=await collectPackageExtensionDirectories(packageRoot);if(discovered.length===1){return discovered[0]}if(discovered.length>1){const choices=discovered.map(entry=>path.relative(packageRoot,entry).replaceAll(path.sep,"/")).sort((left,right)=>left.localeCompare(right));throw new PmCliError(`Package source "${sourceLabel}" contains multiple extension manifests. Provide an explicit extension path. Candidates: ${choices.join(", ")}`,EXIT_CODE.USAGE)}throw new PmCliError(`Unable to locate a pm extension manifest in package source "${sourceLabel}". Package installs currently activate only extension resources, so add package.json pm.extensions or an extensions/ directory. Metadata-only resources like pm.docs/pm.examples are catalog metadata and do not activate commands.`,EXIT_CODE.USAGE)}async function resolveGithubSourceDirectory(cloneDirectory,source){const candidatePaths=[];if(source.subpath){candidatePaths.push(source.subpath);candidatePaths.push(path.posix.join(".agents/pm/extensions",source.subpath));candidatePaths.push(path.posix.join(".custom/pm-extensions",source.subpath));candidatePaths.push(path.posix.join(".custom/pm-extension",source.subpath))}for(const candidate of candidatePaths){const absolute=path.resolve(cloneDirectory,candidate);if(!isPathWithinDirectory(cloneDirectory,absolute)){continue}if(await pathExists(path.join(absolute,"manifest.json"))){return{directory:absolute,resolved_subpath:candidate}}}if(await pathExists(path.join(cloneDirectory,"manifest.json"))){return{directory:cloneDirectory,resolved_subpath:"."}}const discoveredDirectory=await resolvePackageExtensionDirectory(cloneDirectory,source.input);return{directory:discoveredDirectory,resolved_subpath:path.relative(cloneDirectory,discoveredDirectory).replaceAll(path.sep,"/")}}function looksLikeBarePackageName(input){const trimmed=input.trim();if(trimmed.length===0||trimmed.startsWith(".")||trimmed.startsWith("~")){return false}if(trimmed.startsWith("@")){return trimmed.split("/").length===2}return!trimmed.includes("/")&&!trimmed.includes("\\")}async function buildLocalSourceNotFoundError(source){const baseMessage=`Local extension source does not exist: "${source.absolute_path}".`;const input=source.input.trim();if(!looksLikeBarePackageName(input)){return new PmCliError(baseMessage,EXIT_CODE.NOT_FOUND)}let bundledAliases=[];try{const envPackageRoot=process.env.PM_CLI_PACKAGE_ROOT;const cacheKey=typeof envPackageRoot==="string"&&envPackageRoot.trim().length>0?path.resolve(envPackageRoot.trim()):"";if(bundledPackageAliasesCache?.key!==cacheKey){bundledPackageAliasesCache={key:cacheKey,aliases:await listBundledPackageAliases()}}bundledAliases=bundledPackageAliasesCache.aliases}catch{}const nextSteps=[`Retry with pm install npm:${input} if the package is published to npm.`,`Or inspect bundled packages with pm package catalog --project --json before installing by alias. Known aliases (blank means none found): ${bundledAliases.join(", ")}`];return new PmCliError(`${baseMessage} "${input}" did not match a local directory, bundled package alias, or bundled package name; if you meant an npm package, install it as "npm:${input}".`,EXIT_CODE.NOT_FOUND,{code:"local_source_not_found_bare_name",required:`Use "npm:${input}" for npm registry packages, a bundled catalog alias, or an existing local directory path.`,why:"Bare names resolve as local paths only after bundled aliases, so unmatched names need an explicit npm: source.",examples:[`pm install npm:${input}`,"pm package catalog --project --json"],nextSteps,recovery:{attempted_command:`pm install ${input}`,normalized_args:["install",input],next_best_command:`pm install npm:${input}`}})}async function resolveInstallSource(source){if(source.kind==="local"){let localStats;try{localStats=await fs.stat(source.absolute_path)}catch{throw await buildLocalSourceNotFoundError(source)}if(localStats.isFile()&&isLocalPackageArchive(source.absolute_path)){const resolved=await extractLocalPackageArchive(source.absolute_path);return{source,directory:resolved.directory,source_root:path.dirname(resolved.directory),resolved_subpath:path.relative(path.dirname(resolved.directory),resolved.directory).replaceAll(path.sep,"/"),npm_package:resolved.package,npm_version:resolved.version,cleanup:resolved.cleanup}}if(!localStats.isDirectory()){throw new PmCliError(`Local extension source must be a directory or npm .tgz/.tar.gz archive: "${source.absolute_path}".`,EXIT_CODE.USAGE)}const directory=await resolvePackageExtensionDirectory(source.absolute_path,source.input);return{source,directory,source_root:source.absolute_path}}if(source.kind==="npm"){const resolved=await resolveNpmSourceDirectory(source);return{source,directory:resolved.directory,source_root:path.dirname(resolved.directory),cleanup:resolved.cleanup,resolved_subpath:path.relative(path.dirname(resolved.directory),resolved.directory).replaceAll(path.sep,"/"),npm_package:resolved.package,npm_version:resolved.version}}const cloneDirectory=await fs.mkdtemp(path.join(os.tmpdir(),"pm-extension-source-"));const cloneArgs=["clone","--depth","1"];if(source.ref){cloneArgs.push("--branch",source.ref)}cloneArgs.push(source.repository,cloneDirectory);try{await runGitCommand(cloneArgs);const commit=await runGitCommand(["-C",cloneDirectory,"rev-parse","HEAD"]);const resolved=await resolveGithubSourceDirectory(cloneDirectory,source);return{source,directory:resolved.directory,source_root:cloneDirectory,resolved_subpath:resolved.resolved_subpath,commit,cleanup:async()=>{await fs.rm(cloneDirectory,{recursive:true,force:true})}}}catch(error){await fs.rm(cloneDirectory,{recursive:true,force:true});throw error}}async function areDirectoriesEquivalent(left,right){if(!await pathExists(left)||!await pathExists(right)){return false}const[leftRealPath,rightRealPath]=await Promise.all([fs.realpath(left),fs.realpath(right)]);return leftRealPath===rightRealPath}const _testOnlyInstallSources={extractLocalPackageArchive,validateLocalPackageArchiveEntry,installNpmPackageRuntimeDependencies,npmPackageNameFromSpec,parsePackedNpmPackage,resolveNpmSourceDirectoryWithRunner,resolveNpmSourceDirectory,resolveNpmPackSpec,findInstalledNpmPackageCandidate,resolvePackageExtensionDirectory,runtimeDependencyInstallSpecs,hasHostedPmCliDependency,removeHostedPmCliDependency,linkHostedPmCliDependency,resolveDirectorySymlinkType,runNpmCommand};export{_testOnlyInstallSources,areDirectoriesEquivalent,buildNpmNotFoundRecovery,findInstalledNpmPackageCandidate,isNpmNotFoundError,isNpmPackNotFoundError,normalizeNpmLocalFileAliasSpec,parseExtensionInstallSource,resolveInstallSource,resolveNpmCommandName,runGitCommand,shouldRunNpmCommandInShell,wrapNpmPackResolutionError};
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="db10bb85-f21c-58b1-8b78-8ce1024b3e08")}catch{}})();import{execFile}from"node:child_process";import fs from"node:fs/promises";import os from"node:os";import path from"node:path";import{fileURLToPath}from"node:url";import{promisify}from"node:util";import npa from"npm-package-arg";import{extract as extractTar,list as listTar}from"tar";import{collectPackageExtensionDirectories}from"../../core/packages/manifest.js";import{resolvePmPackageRootFromModule}from"../../core/packages/root.js";import{pathExists}from"../../core/fs/fs-utils.js";import{isPathWithinDirectory}from"../../core/fs/path-utils.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{listBundledPackageAliases}from"./bundled-catalog.js";const execFileAsync=promisify(execFile),PM_CLI_PACKAGE_NAME="@unbrained/pm-cli",LOCAL_PACKAGE_ARCHIVE_LIMITS={maxArchiveBytes:64*1024*1024,maxEntries:4096,maxExpandedBytes:256*1024*1024,maxEntryBytes:64*1024*1024};let bundledPackageAliasesCache;async function findInstalledNpmPackageCandidate(packageName,cwd=process.cwd()){const normalized=packageName.trim();if(!/^(@[^/\\\s]+\/[^/\\\s]+|[^@/\\\s][^/\\\s]*)$/u.test(normalized))return null;let current=path.resolve(cwd);for(;;){const directory=path.join(current,"node_modules",...normalized.split("/")),manifestPath=path.join(directory,"package.json");if(await pathExists(manifestPath))try{const manifest=JSON.parse(await fs.readFile(manifestPath,"utf8"));if(manifest.name===normalized)return{package:normalized,...typeof manifest.version=="string"?{version:manifest.version}:{},directory}}catch{return null}const parent=path.dirname(current);if(parent===current)return null;current=parent}}function parseGithubPathSpec(pathSpec,input,refOverride){const segments=pathSpec.split("/").map(segment=>segment.trim()).filter(segment=>segment.length>0);if(segments.length<2)return null;const owner=segments[0],repo=segments[1].replace(/\.git$/i,"");if(owner.length===0||repo.length===0)return null;const tail=segments.slice(2);let ref,subpath;return tail[0]==="tree"&&tail.length>=2?(ref=tail[1],subpath=tail.slice(2).join("/")):tail.length>0&&(subpath=tail.join("/")),typeof refOverride=="string"&&refOverride.trim().length>0&&(ref=refOverride.trim()),{kind:"github",input,owner,repo,repository:`https://github.com/${owner}/${repo}.git`,ref,subpath:subpath&&subpath.length>0?subpath:void 0}}function parseNpmInstallSource(normalizedInput,forceGithub,refOverride){const spec=normalizedInput.slice(4).trim();if(spec.length===0)throw new PmCliError('npm package source must include a package spec after "npm:".',EXIT_CODE.USAGE);if(forceGithub)throw new PmCliError('Options "--gh/--github" cannot be combined with npm: package sources.',EXIT_CODE.USAGE);if(refOverride)throw new PmCliError('Option "--ref" cannot be combined with npm: package sources.',EXIT_CODE.USAGE);return{kind:"npm",input:normalizedInput,spec}}function parseExtensionInstallSource(input,options={}){const normalizedInput=input.trim();if(normalizedInput.length===0)throw new PmCliError("Extension source is required for --install.",EXIT_CODE.USAGE);const refOverride=typeof options.ref=="string"&&options.ref.trim().length>0?options.ref.trim():void 0;if(normalizedInput.startsWith("npm:"))return parseNpmInstallSource(normalizedInput,options.forceGithub===!0,refOverride);const maybeGithubByUrl=(()=>{try{const parsed=new URL(normalizedInput);if(parsed.hostname!=="github.com")return null;const pathSpec=parsed.pathname.replace(/^\/+/,"");return parseGithubPathSpec(pathSpec,normalizedInput,refOverride)}catch{return null}})();if(maybeGithubByUrl)return maybeGithubByUrl;const strippedDomainInput=normalizedInput.startsWith("github.com/")?normalizedInput.slice(11):null;if(strippedDomainInput){const parsed=parseGithubPathSpec(strippedDomainInput,normalizedInput,refOverride);if(!parsed)throw new PmCliError(`Invalid GitHub source "${normalizedInput}".`,EXIT_CODE.USAGE);return parsed}if(options.forceGithub){const parsed=parseGithubPathSpec(normalizedInput,normalizedInput,refOverride);if(!parsed)throw new PmCliError(`Invalid GitHub shorthand "${normalizedInput}".`,EXIT_CODE.USAGE);return parsed}if(/^https?:\/\//i.test(normalizedInput))throw new PmCliError(`Unsupported extension source URL "${normalizedInput}". Supported remote source host: github.com.`,EXIT_CODE.USAGE);return{kind:"local",input:normalizedInput,absolute_path:path.resolve(process.cwd(),normalizedInput)}}async function runGitCommand(args,execRunner=execFileAsync,timeoutMs){try{return((await execRunner("git",args,{encoding:"utf8",timeout:timeoutMs})).stdout??"").trim()}catch(error){const stderr=typeof error=="object"&&error!==null&&"stderr"in error?String(error.stderr):"",message=stderr.trim().length>0?stderr.trim():error instanceof Error?error.message:String(error);throw new PmCliError(`Git command failed: git ${args.join(" ")}
|
|
2
|
+
${message}`,EXIT_CODE.GENERIC_FAILURE)}}function resolveNpmCommandName(platform=process.platform){return platform==="win32"?"npm.cmd":"npm"}function shouldRunNpmCommandInShell(platform=process.platform){return platform==="win32"}async function runNpmCommand(args,cwd,execRunner=execFileAsync,platform=process.platform,environment=process.env){const npmCommand=resolveNpmCommandName(platform),env=Object.fromEntries(Object.entries(environment).filter(([key])=>key.toLowerCase()!=="npm_config_allow_scripts"));env.NPM_CONFIG_ALLOW_SCRIPTS="";try{return((await execRunner(npmCommand,args,{cwd,encoding:"utf8",env,shell:shouldRunNpmCommandInShell(platform)})).stdout??"").trim()}catch(error){const stderr=typeof error=="object"&&error!==null&&"stderr"in error?String(error.stderr):"",message=stderr.trim().length>0?stderr.trim():error instanceof Error?error.message:String(error);throw new PmCliError(`npm command failed: ${npmCommand} ${args.join(" ")}
|
|
3
|
+
${message}`,EXIT_CODE.GENERIC_FAILURE)}}function npmPackageNameFromSpec(spec){const trimmed=spec.trim(),withoutAlias=trimmed.includes("@file:")?trimmed.slice(0,trimmed.lastIndexOf("@file:")):trimmed;return withoutAlias.startsWith("@")?withoutAlias.match(/^(@[^/@\s]+\/[^/@\s]+)/)?.[1]??withoutAlias:withoutAlias.match(/^([^/@\s]+)/)?.[1]??withoutAlias}function isNpmLocalFileAliasSpec(spec){const marker="@file:",markerIndex=spec.lastIndexOf(marker);return markerIndex>0&&spec.slice(0,markerIndex).trim().length>0&&spec.slice(markerIndex+marker.length).trim().length>0}function isNpmNotFoundError(error){const normalized=(error instanceof Error?error.message:String(error)).toLowerCase();return normalized.includes("npm err! code e404")||normalized.includes("404 not found")||normalized.includes("is not in this registry")}function isNpmPackNotFoundError(error){const normalized=(error instanceof Error?error.message:String(error)).toLowerCase();return isNpmNotFoundError(error)||normalized.includes("not found")}function isFirstPartyPmPackageName(packageName){const normalized=packageName.trim().toLowerCase();return normalized.startsWith("@unbrained/pm-")||normalized.startsWith("pm-")}function buildNpmNotFoundRecovery(spec){const packageName=npmPackageNameFromSpec(spec),isFirstPartyPackage=isFirstPartyPmPackageName(packageName),repoName=packageName.replace(/^.*\//,""),githubSource=isFirstPartyPackage?`github.com/unbraind/${repoName}`:void 0,nextBestCommand=githubSource?`pm install --project ${githubSource}`:void 0;return{message:isFirstPartyPackage?`npm package "${spec}" was not found in the registry. If this is an unpublished first-party pm package, install its GitHub repository instead.`:`npm package "${spec}" was not found in the registry.`,context:{code:"npm_package_not_found",required:"Use an install source that exists, or publish the npm package before installing it with npm:<name>.",why:"Classifying npm 404s avoids repeated registry retries and gives agents a deterministic fallback path.",examples:nextBestCommand?[nextBestCommand,"pm package catalog --project --json"]:[`npm view ${packageName}`,"pm package catalog --project --json"],nextSteps:nextBestCommand?[`Try ${nextBestCommand} if the repository exists.`,"Use pm package catalog --project --json to inspect bundled package aliases before installing."]:[`Verify ${packageName} exists in the npm registry and that you have access to it.`,"Use pm package catalog --project --json to inspect bundled package aliases before installing."],recovery:{attempted_command:`pm install --project npm:${spec}`,normalized_args:["install","--project",`npm:${spec}`],...githubSource&&nextBestCommand?{fallback_candidates:[{source:githubSource,command:nextBestCommand,reason:"canonical first-party GitHub repository fallback for unpublished pm packages"}],next_best_command:nextBestCommand}:{}}}}}function wrapNpmPackResolutionError(spec,error){if(!isNpmPackNotFoundError(error))return null;const recovery=buildNpmNotFoundRecovery(spec);return new PmCliError(recovery.message,EXIT_CODE.NOT_FOUND,recovery.context)}async function resolveLocalNpmPackagePath(spec){if(path.isAbsolute(spec)||spec.startsWith(".")||spec.startsWith("..")){const absolutePath=path.resolve(process.cwd(),spec);return await pathExists(absolutePath)?absolutePath:null}try{const parsed=new URL(spec);if(parsed.protocol==="file:"){const absolutePath=fileURLToPath(parsed);return await pathExists(absolutePath)?absolutePath:null}}catch{}if(!/^[a-z][a-z0-9+.-]*:/i.test(spec)){const absolutePath=path.resolve(process.cwd(),spec);if(await pathExists(absolutePath))return absolutePath}return null}async function resolveNpmPackSpec(spec){const localPath=await resolveLocalNpmPackagePath(spec);if(localPath)return localPath;const localFileAlias=normalizeNpmLocalFileAliasSpec(spec);return localFileAlias!==spec?localFileAlias:(/^[a-z][a-z0-9+.-]*:/i.test(spec),spec)}function normalizeNpmLocalFileAliasSpec(spec,cwd=process.cwd()){const marker="@file:",markerIndex=spec.lastIndexOf(marker);if(!isNpmLocalFileAliasSpec(spec))return spec;const packageName=spec.slice(0,markerIndex),target=spec.slice(markerIndex+marker.length);if(target.startsWith("//")&&!target.startsWith("///"))return spec;if(!target.startsWith("/"))return`${packageName}@${path.resolve(cwd,target)}`;let decodedPath;try{decodedPath=decodeURIComponent(new URL(`file:${target}`).pathname)}catch{return spec}const nativePath=/^\/[A-Za-z]:/.test(decodedPath)?decodedPath.slice(1):decodedPath;return`${packageName}@${nativePath}`}function resolvePackedTarball(packDirectory,filename){const tarball=path.resolve(packDirectory,filename),relativeTarball=path.relative(packDirectory,tarball);if(relativeTarball.length===0||relativeTarball===".."||relativeTarball.startsWith(`..${path.sep}`)||path.isAbsolute(relativeTarball))throw new PmCliError("npm pack reported a package archive outside its isolated destination.",EXIT_CODE.GENERIC_FAILURE,{code:"npm_package_archive_unsafe",required:"Retry with a trusted npm client that writes its archive inside the requested pack destination.",why:"pm will not read a package-manager artifact outside the isolated directory created for this install."});return tarball}function decodePackedNpmCandidate(value,key){if(typeof value!="object"||value===null||Array.isArray(value))return;const record=value;if(!(typeof record.filename!="string"||record.filename.trim().length===0))return{...key===void 0?{}:{key},filename:record.filename,...typeof record.name=="string"?{name:record.name}:{},...typeof record.version=="string"?{version:record.version}:{}}}function collectPackedNpmCandidates(parsed){return(Array.isArray(parsed)?parsed.map(value=>({value})):typeof parsed=="object"&&parsed!==null?Object.entries(parsed).map(([key,value])=>({key,value})):[]).flatMap(({key,value})=>{const candidate=decodePackedNpmCandidate(value,key);return candidate?[candidate]:[]})}function selectPackedNpmCandidate(candidates,expectedPackage){const normalizedExpected=expectedPackage?.trim().toLowerCase(),matchingCandidates=normalizedExpected?candidates.filter(candidate=>{const normalizedName=candidate.name?.trim().toLowerCase();return normalizedName!==void 0?normalizedName===normalizedExpected:candidate.key?.trim().toLowerCase()===normalizedExpected}):[];if(matchingCandidates.length===1)return matchingCandidates[0];if(candidates.length!==1)return;const soleCandidate=candidates[0],soleIdentity=soleCandidate.name??soleCandidate.key;return normalizedExpected&&soleIdentity!==void 0&&soleIdentity.trim().toLowerCase()!==normalizedExpected?void 0:soleCandidate}function parsePackedNpmPackage(stdout,packDirectory,expectedPackage){let parsed;try{parsed=JSON.parse(stdout)}catch{const filename=stdout.split(/\r?\n/).map(line=>line.trim()).filter(line=>line.length>0).at(-1);if(!filename)throw new PmCliError("npm pack did not report a tarball filename.",EXIT_CODE.GENERIC_FAILURE);return{tarball:resolvePackedTarball(packDirectory,filename)}}const candidates=collectPackedNpmCandidates(parsed),selected=selectPackedNpmCandidate(candidates,expectedPackage);if(!selected)throw new PmCliError("npm pack --json returned an unsupported or ambiguous package receipt.",EXIT_CODE.GENERIC_FAILURE,{code:"npm_pack_json_shape_unsupported",required:"Use an npm client that returns an array of package receipts or an object keyed by package name, with exactly one requested package entry containing filename.",why:`Well-formed JSON contained ${candidates.length} usable package receipt(s), but pm could not select ${expectedPackage??"one package"} deterministically.`});return{tarball:resolvePackedTarball(packDirectory,selected.filename),package:selected.name??selected.key,version:selected.version}}async function resolveNpmSourceDirectory(source){return resolveNpmSourceDirectoryWithRunner(source,runNpmCommand)}async function resolveNpmSourceDirectoryWithRunner(source,npmRunner){const localPackageRoot=await resolveLocalNpmPackagePath(source.spec);if(localPackageRoot){if((await fs.stat(localPackageRoot)).isFile()&&isLocalPackageArchive(localPackageRoot))return extractLocalPackageArchive(localPackageRoot);const packageJsonPath=path.join(localPackageRoot,"package.json"),packageJson=await pathExists(packageJsonPath)?JSON.parse(await fs.readFile(packageJsonPath,"utf8")):{};return{directory:await resolvePackageExtensionDirectory(localPackageRoot,source.input),package:typeof packageJson.name=="string"?packageJson.name:void 0,version:typeof packageJson.version=="string"?packageJson.version:void 0,cleanup:async()=>{}}}const tempRoot=await fs.mkdtemp(path.join(os.tmpdir(),"pm-npm-package-source-")),packDirectory=path.join(tempRoot,"pack");await fs.mkdir(packDirectory,{recursive:!0});try{const packSpec=await resolveNpmPackSpec(source.spec),packStdout=await npmRunner(["pack",packSpec,"--json","--pack-destination",packDirectory]),packed=parsePackedNpmPackage(packStdout,packDirectory,isNpmLocalFileAliasSpec(source.spec)?void 0:npmPackageNameFromSpec(source.spec));if(!await pathExists(packed.tarball))throw new PmCliError("npm pack did not create its reported package archive.",EXIT_CODE.GENERIC_FAILURE,{code:"npm_package_archive_missing",required:"Retry the npm package install with a healthy registry and writable temporary directory.",why:"The package manager reported a tarball filename that was absent before validation, so pm cannot safely extract or install it."});const extracted=await extractLocalPackageArchive(packed.tarball);return{directory:extracted.directory,package:packed.package??extracted.package,version:packed.version??extracted.version,cleanup:async()=>{try{await extracted.cleanup()}finally{await fs.rm(tempRoot,{recursive:!0,force:!0})}}}}catch(error){throw await fs.rm(tempRoot,{recursive:!0,force:!0}),wrapNpmPackResolutionError(source.spec,error)||error}}function isLocalPackageArchive(candidate){const normalized=candidate.toLowerCase();return normalized.endsWith(".tgz")||normalized.endsWith(".tar.gz")}function failLocalPackageArchive(message){throw new PmCliError(message,EXIT_CODE.USAGE,{code:"local_package_archive_unsafe",required:"Use a bounded npm .tgz or .tar.gz archive with one package/ root and no links or escaping paths.",why:"Package archives are untrusted input and must be validated before any entry reaches the filesystem."})}function validateLocalPackageArchiveEntry(entry,limits,state){if(entry.meta)return;state.entries+=1,state.entries>limits.maxEntries&&failLocalPackageArchive(`Local package archive exceeds the ${limits.maxEntries} entry limit.`);const archivePath=entry.path,segments=archivePath.split("/");(archivePath.includes("\\")||archivePath.startsWith("/")||/^[A-Za-z]:/u.test(archivePath)||segments.some(segment=>segment===".."))&&failLocalPackageArchive(`Local package archive contains an escaping path: "${archivePath}".`),segments[0]!=="package"&&failLocalPackageArchive(`Local package archive entry "${archivePath}" is outside the required package/ root.`),(entry.type==="SymbolicLink"||entry.type==="Link")&&failLocalPackageArchive(`Local package archive link "${archivePath}" is not supported.`),entry.type!=="File"&&entry.type!=="OldFile"&&entry.type!=="Directory"&&failLocalPackageArchive(`Local package archive entry "${archivePath}" uses unsupported type "${entry.type}".`),entry.size>limits.maxEntryBytes&&failLocalPackageArchive(`Local package archive entry "${archivePath}" exceeds the ${limits.maxEntryBytes} byte entry limit.`),state.expandedBytes+=entry.size,state.expandedBytes>limits.maxExpandedBytes&&failLocalPackageArchive(`Local package archive exceeds the ${limits.maxExpandedBytes} expanded byte limit.`),archivePath==="package/package.json"&&(state.packageJsonEntries+=1)}async function extractLocalPackageArchive(archivePath,limits=LOCAL_PACKAGE_ARCHIVE_LIMITS){(await fs.stat(archivePath)).size>limits.maxArchiveBytes&&failLocalPackageArchive(`Local package archive exceeds the ${limits.maxArchiveBytes} archive byte limit.`);const tempRoot=await fs.mkdtemp(path.join(os.tmpdir(),"pm-local-package-archive-")),extractDirectory=path.join(tempRoot,"extract");await fs.mkdir(extractDirectory,{recursive:!0});const state={entries:0,expandedBytes:0,packageJsonEntries:0};let validationError;try{if(await listTar({file:archivePath,strict:!0,maxDecompressionRatio:100,onReadEntry:entry=>{if(validationError===void 0)try{validateLocalPackageArchiveEntry(entry,limits,state)}catch(error){validationError=error}}}),validationError!==void 0)throw validationError;state.packageJsonEntries!==1&&failLocalPackageArchive(`Local package archive must contain exactly one package/package.json entry; found ${state.packageJsonEntries}.`),await extractTar({file:archivePath,cwd:extractDirectory,strict:!0,preservePaths:!1,preserveOwner:!1,noMtime:!0,unlink:!0,maxDepth:64,maxDecompressionRatio:100});const packageRoot=path.join(extractDirectory,"package"),packageJsonPath=path.join(packageRoot,"package.json"),packageJson=JSON.parse(await fs.readFile(packageJsonPath,"utf8"));return await installNpmPackageRuntimeDependencies(packageRoot),{directory:await resolvePackageExtensionDirectory(packageRoot,archivePath),package:typeof packageJson.name=="string"?packageJson.name:void 0,version:typeof packageJson.version=="string"?packageJson.version:void 0,cleanup:async()=>{await fs.rm(tempRoot,{recursive:!0,force:!0})}}}catch(error){throw await fs.rm(tempRoot,{recursive:!0,force:!0}),error}}async function installNpmPackageRuntimeDependencies(packageRoot,npmRunner=runNpmCommand){const packageJsonPath=path.join(packageRoot,"package.json");if(!await pathExists(packageJsonPath))return;let parsed;try{parsed=JSON.parse(await fs.readFile(packageJsonPath,"utf8"))}catch{return}if(typeof parsed!="object"||parsed===null)return;const manifest=parsed,dependencySpecs=runtimeDependencyInstallSpecs(manifest),shouldLinkHostedPmCli=hasHostedPmCliDependency(manifest);if(dependencySpecs.length===0&&!shouldLinkHostedPmCli)return;const runtimeOnlyManifest={...parsed};delete runtimeOnlyManifest.devDependencies;const installManifest={...runtimeOnlyManifest};removeHostedPmCliDependency(installManifest),await fs.writeFile(packageJsonPath,`${JSON.stringify(installManifest,null,2)}
|
|
4
|
+
`,"utf8");try{await Promise.all([fs.rm(path.join(packageRoot,"package-lock.json"),{force:!0}),fs.rm(path.join(packageRoot,"npm-shrinkwrap.json"),{force:!0})]),dependencySpecs.length>0&&await npmRunner(["install","--ignore-scripts","--no-audit","--fund=false","--package-lock=false","--no-save","--omit=peer","--"],packageRoot),shouldLinkHostedPmCli&&await linkHostedPmCliDependency(packageRoot)}finally{await fs.writeFile(packageJsonPath,`${JSON.stringify(runtimeOnlyManifest,null,2)}
|
|
5
|
+
`,"utf8")}}function hasHostedPmCliDependency(manifest){for(const dependencyMap of[manifest.dependencies,manifest.optionalDependencies,manifest.peerDependencies])if(typeof dependencyMap=="object"&&dependencyMap!==null&&PM_CLI_PACKAGE_NAME in dependencyMap)return!0;return!1}function removeHostedPmCliDependency(manifest){for(const field of["dependencies","optionalDependencies","peerDependencies"]){const dependencyMap=manifest[field];if(typeof dependencyMap!="object"||dependencyMap===null)continue;const nextMap={...dependencyMap};delete nextMap[PM_CLI_PACKAGE_NAME],Object.keys(nextMap).length===0?delete manifest[field]:manifest[field]=nextMap}}async function linkHostedPmCliDependency(packageRoot){const hostPackageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]),[scope,packageName]=PM_CLI_PACKAGE_NAME.split("/"),scopedDirectory=path.join(packageRoot,"node_modules",scope),linkPath=path.join(scopedDirectory,packageName);await fs.mkdir(scopedDirectory,{recursive:!0}),await fs.rm(linkPath,{recursive:!0,force:!0}),await fs.symlink(hostPackageRoot,linkPath,resolveDirectorySymlinkType(process.platform))}function resolveDirectorySymlinkType(platform){return platform==="win32"?"junction":"dir"}function validateRuntimeDependencySpec(name,version){if(name.startsWith("-"))throw new PmCliError(`Extension runtime dependency name "${name}" is unsafe because npm could interpret it as a command-line option.`,EXIT_CODE.USAGE,{code:"extension_dependency_name_unsafe",required:"Use a valid npm package name that does not begin with a dash.",why:"Extension manifests are untrusted input and dependency names must never become npm options."});if([...version].some(character=>{const codePoint=character.charCodeAt(0);return codePoint<=31||codePoint===127||"&|;()`\"'".includes(character)}))throw new PmCliError(`Extension runtime dependency "${name}" has an unsafe version specifier.`,EXIT_CODE.USAGE,{code:"extension_dependency_version_unsafe",required:"Use an npm version, range, dist-tag, URL, or file specifier without shell metacharacters.",why:"npm.cmd requires a command shell on Windows, so untrusted shell metacharacters cannot be forwarded."});try{npa.resolve(name,version)}catch{throw new PmCliError(`Extension runtime dependency "${name}@${version}" is not a valid npm dependency specifier.`,EXIT_CODE.USAGE,{code:"extension_dependency_spec_invalid",required:"Use a valid npm package name and npm-supported version, range, dist-tag, URL, or file specifier.",why:"Only grammar-validated dependency specs may be written to the isolated runtime install manifest."})}return`${name}@${version}`}function runtimeDependencyInstallSpecs(manifest){const specs=new Map;for(const dependencyMap of[manifest.dependencies,manifest.optionalDependencies,manifest.peerDependencies])if(!(typeof dependencyMap!="object"||dependencyMap===null))for(const[name,version]of Object.entries(dependencyMap)){if(name===PM_CLI_PACKAGE_NAME||typeof version!="string"||version.trim().length===0||specs.has(name))continue;const normalizedVersion=version.trim();specs.set(name,validateRuntimeDependencySpec(name,normalizedVersion))}return[...specs.values()]}async function resolvePackageExtensionDirectory(packageRoot,sourceLabel){const discovered=await collectPackageExtensionDirectories(packageRoot);if(discovered.length===1)return discovered[0];if(discovered.length>1){const choices=discovered.map(entry=>path.relative(packageRoot,entry).replaceAll(path.sep,"/")).sort((left,right)=>left.localeCompare(right));throw new PmCliError(`Package source "${sourceLabel}" contains multiple extension manifests. Provide an explicit extension path. Candidates: ${choices.join(", ")}`,EXIT_CODE.USAGE)}throw new PmCliError(`Unable to locate a pm extension manifest in package source "${sourceLabel}". Package installs currently activate only extension resources, so add package.json pm.extensions or an extensions/ directory. Metadata-only resources like pm.docs/pm.examples are catalog metadata and do not activate commands.`,EXIT_CODE.USAGE)}async function resolveGithubSourceDirectory(cloneDirectory,source){const candidatePaths=[];source.subpath&&(candidatePaths.push(source.subpath),candidatePaths.push(path.posix.join(".agents/pm/extensions",source.subpath)),candidatePaths.push(path.posix.join(".custom/pm-extensions",source.subpath)),candidatePaths.push(path.posix.join(".custom/pm-extension",source.subpath)));for(const candidate of candidatePaths){const absolute=path.resolve(cloneDirectory,candidate);if(isPathWithinDirectory(cloneDirectory,absolute)&&await pathExists(path.join(absolute,"manifest.json")))return{directory:absolute,resolved_subpath:candidate}}if(await pathExists(path.join(cloneDirectory,"manifest.json")))return{directory:cloneDirectory,resolved_subpath:"."};const discoveredDirectory=await resolvePackageExtensionDirectory(cloneDirectory,source.input);return{directory:discoveredDirectory,resolved_subpath:path.relative(cloneDirectory,discoveredDirectory).replaceAll(path.sep,"/")}}function looksLikeBarePackageName(input){const trimmed=input.trim();return trimmed.length===0||trimmed.startsWith(".")||trimmed.startsWith("~")?!1:trimmed.startsWith("@")?trimmed.split("/").length===2:!trimmed.includes("/")&&!trimmed.includes("\\")}async function buildLocalSourceNotFoundError(source){const baseMessage=`Local extension source does not exist: "${source.absolute_path}".`,input=source.input.trim();if(!looksLikeBarePackageName(input))return new PmCliError(baseMessage,EXIT_CODE.NOT_FOUND);let bundledAliases=[];try{const envPackageRoot=process.env.PM_CLI_PACKAGE_ROOT,cacheKey=typeof envPackageRoot=="string"&&envPackageRoot.trim().length>0?path.resolve(envPackageRoot.trim()):"";bundledPackageAliasesCache?.key!==cacheKey&&(bundledPackageAliasesCache={key:cacheKey,aliases:await listBundledPackageAliases()}),bundledAliases=bundledPackageAliasesCache.aliases}catch{}const nextSteps=[`Retry with pm install npm:${input} if the package is published to npm.`,`Or inspect bundled packages with pm package catalog --project --json before installing by alias. Known aliases (blank means none found): ${bundledAliases.join(", ")}`];return new PmCliError(`${baseMessage} "${input}" did not match a local directory, bundled package alias, or bundled package name; if you meant an npm package, install it as "npm:${input}".`,EXIT_CODE.NOT_FOUND,{code:"local_source_not_found_bare_name",required:`Use "npm:${input}" for npm registry packages, a bundled catalog alias, or an existing local directory path.`,why:"Bare names resolve as local paths only after bundled aliases, so unmatched names need an explicit npm: source.",examples:[`pm install npm:${input}`,"pm package catalog --project --json"],nextSteps,recovery:{attempted_command:`pm install ${input}`,normalized_args:["install",input],next_best_command:`pm install npm:${input}`}})}async function resolveInstallSource(source){if(source.kind==="local"){let localStats;try{localStats=await fs.stat(source.absolute_path)}catch{throw await buildLocalSourceNotFoundError(source)}if(localStats.isFile()&&isLocalPackageArchive(source.absolute_path)){const resolved=await extractLocalPackageArchive(source.absolute_path);return{source,directory:resolved.directory,source_root:path.dirname(resolved.directory),resolved_subpath:path.relative(path.dirname(resolved.directory),resolved.directory).replaceAll(path.sep,"/"),npm_package:resolved.package,npm_version:resolved.version,cleanup:resolved.cleanup}}if(!localStats.isDirectory())throw new PmCliError(`Local extension source must be a directory or npm .tgz/.tar.gz archive: "${source.absolute_path}".`,EXIT_CODE.USAGE);const directory=await resolvePackageExtensionDirectory(source.absolute_path,source.input);return{source,directory,source_root:source.absolute_path}}if(source.kind==="npm"){const resolved=await resolveNpmSourceDirectory(source);return{source,directory:resolved.directory,source_root:path.dirname(resolved.directory),cleanup:resolved.cleanup,resolved_subpath:path.relative(path.dirname(resolved.directory),resolved.directory).replaceAll(path.sep,"/"),npm_package:resolved.package,npm_version:resolved.version}}const cloneDirectory=await fs.mkdtemp(path.join(os.tmpdir(),"pm-extension-source-")),cloneArgs=["clone","--depth","1"];source.ref&&cloneArgs.push("--branch",source.ref),cloneArgs.push(source.repository,cloneDirectory);try{await runGitCommand(cloneArgs);const commit=await runGitCommand(["-C",cloneDirectory,"rev-parse","HEAD"]),resolved=await resolveGithubSourceDirectory(cloneDirectory,source);return{source,directory:resolved.directory,source_root:cloneDirectory,resolved_subpath:resolved.resolved_subpath,commit,cleanup:async()=>{await fs.rm(cloneDirectory,{recursive:!0,force:!0})}}}catch(error){throw await fs.rm(cloneDirectory,{recursive:!0,force:!0}),error}}async function areDirectoriesEquivalent(left,right){if(!await pathExists(left)||!await pathExists(right))return!1;const[leftRealPath,rightRealPath]=await Promise.all([fs.realpath(left),fs.realpath(right)]);return leftRealPath===rightRealPath}const _testOnlyInstallSources={extractLocalPackageArchive,validateLocalPackageArchiveEntry,installNpmPackageRuntimeDependencies,npmPackageNameFromSpec,parsePackedNpmPackage,resolveNpmSourceDirectoryWithRunner,resolveNpmSourceDirectory,resolveNpmPackSpec,findInstalledNpmPackageCandidate,resolvePackageExtensionDirectory,runtimeDependencyInstallSpecs,hasHostedPmCliDependency,removeHostedPmCliDependency,linkHostedPmCliDependency,resolveDirectorySymlinkType,runNpmCommand};export{_testOnlyInstallSources,areDirectoriesEquivalent,buildNpmNotFoundRecovery,findInstalledNpmPackageCandidate,isNpmNotFoundError,isNpmPackNotFoundError,normalizeNpmLocalFileAliasSpec,parseExtensionInstallSource,resolveInstallSource,resolveNpmCommandName,runGitCommand,shouldRunNpmCommandInShell,wrapNpmPackResolutionError};
|
|
6
6
|
//# sourceMappingURL=install-sources.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
`,"utf8")}function upsertManagedEntry(state,entry){const updatedEntries=state.entries.filter(candidate=>normalizeExtensionNameForMatch(candidate.name)!==normalizeExtensionNameForMatch(entry.name)&&normalizeExtensionNameForMatch(candidate.directory)!==normalizeExtensionNameForMatch(entry.directory));updatedEntries.push(entry)
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="57d830e7-a4e2-56f5-a89b-ae4403e256ce")}catch{}})();import{isFileMissingError}from"../../core/fs/fs-utils.js";import fs from"node:fs/promises";import path from"node:path";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{nowIso}from"../../core/shared/time.js";import{normalizeExtensionContributionInventory}from"../../core/extensions/contribution-inventory.js";import{normalizeExtensionNameForMatch,normalizeStringList}from"./shared.js";const MANAGED_EXTENSION_STATE_FILENAME=".managed-extensions.json",MANAGED_EXTENSION_STATE_VERSION=1;function resolveManagedExtensionStatePath(extensionsRoot){return path.join(extensionsRoot,MANAGED_EXTENSION_STATE_FILENAME)}function createEmptyManagedExtensionState(){return{version:MANAGED_EXTENSION_STATE_VERSION,updated_at:nowIso(),entries:[]}}function sortManagedEntries(entries){return[...entries].sort((left,right)=>{const byScope=left.scope.localeCompare(right.scope);if(byScope!==0)return byScope;const byName=left.name.localeCompare(right.name);return byName!==0?byName:left.directory.localeCompare(right.directory)})}function managedExtensionSourcesEquivalent(left,right){return left.kind!==right.kind||left.input!==right.input||left.location!==right.location?!1:left.kind==="npm"&&right.kind==="npm"?left.package===right.package&&left.version===right.version:left.kind==="github"&&right.kind==="github"?left.repository===right.repository&&left.ref===right.ref&&left.subpath===right.subpath&&left.commit===right.commit:left.kind==="builtin"&&right.kind==="builtin"?left.name===right.name:!0}function optionalString(value){return typeof value=="string"?value:void 0}function hasRequiredManagedRecordFields(entry){return typeof entry.name=="string"&&entry.name.trim().length>0&&typeof entry.directory=="string"&&entry.directory.trim().length>0&&(entry.scope==="project"||entry.scope==="global")&&typeof entry.manifest_version=="string"&&typeof entry.manifest_entry=="string"&&Array.isArray(entry.capabilities)&&entry.capabilities.every(value=>typeof value=="string")&&typeof entry.installed_at=="string"&&typeof entry.updated_at=="string"}function normalizeManagedSource(raw){if(typeof raw!="object"||raw===null)return null;const source=raw;return source.kind!=="local"&&source.kind!=="github"&&source.kind!=="npm"&&source.kind!=="builtin"||typeof source.input!="string"||typeof source.location!="string"?null:{kind:source.kind,input:source.input,location:source.location,name:optionalString(source.name),package:optionalString(source.package),version:optionalString(source.version),repository:optionalString(source.repository),owner:optionalString(source.owner),repo:optionalString(source.repo),ref:optionalString(source.ref),subpath:optionalString(source.subpath),commit:optionalString(source.commit)}}function normalizeManagedRecord(raw){if(typeof raw!="object"||raw===null)return null;const entry=raw;if(!hasRequiredManagedRecordFields(entry))return null;const source=normalizeManagedSource(entry.source);if(!source)return null;const contributions=normalizeExtensionContributionInventory(entry.contributions);return contributions===null?null:{name:entry.name.trim(),directory:entry.directory.trim(),scope:entry.scope,manifest_version:entry.manifest_version,manifest_entry:entry.manifest_entry,capabilities:normalizeStringList(entry.capabilities),contributions,installed_at:entry.installed_at,updated_at:entry.updated_at,source,last_update_check_at:optionalString(entry.last_update_check_at),last_update_remote_commit:optionalString(entry.last_update_remote_commit),update_available:typeof entry.update_available=="boolean"||entry.update_available===null?entry.update_available:void 0,update_error:optionalString(entry.update_error)}}function normalizeManagedState(raw){if(typeof raw!="object"||raw===null)return null;const candidate=raw;if(candidate.version!==MANAGED_EXTENSION_STATE_VERSION||!Array.isArray(candidate.entries))return null;const entries=[];for(const rawEntry of candidate.entries){const record=normalizeManagedRecord(rawEntry);record&&entries.push(record)}return{version:MANAGED_EXTENSION_STATE_VERSION,updated_at:optionalString(candidate.updated_at)??nowIso(),entries:sortManagedEntries(entries)}}async function readManagedExtensionState(extensionsRoot){const statePath=resolveManagedExtensionStatePath(extensionsRoot),fallback=createEmptyManagedExtensionState();try{const raw=await fs.readFile(statePath,"utf8"),parsed=JSON.parse(raw),normalized=normalizeManagedState(parsed);if(!normalized)throw new PmCliError(`Managed extension state file "${statePath}" has an invalid schema. Repair or remove it before mutating extension state.`,EXIT_CODE.GENERIC_FAILURE);return{path:statePath,state:normalized,warnings:[]}}catch(error){if(error instanceof PmCliError)throw error;if(typeof error=="object"&&error!==null&&"code"in error&&isFileMissingError(error))return{path:statePath,state:fallback,warnings:[]};throw new PmCliError(`Managed extension state file "${statePath}" could not be read. Repair or remove it before mutating extension state.`,EXIT_CODE.GENERIC_FAILURE)}}async function writeManagedExtensionState(extensionsRoot,state){const statePath=resolveManagedExtensionStatePath(extensionsRoot),normalized={version:MANAGED_EXTENSION_STATE_VERSION,updated_at:nowIso(),entries:sortManagedEntries(state.entries)};await fs.mkdir(extensionsRoot,{recursive:!0}),await fs.writeFile(statePath,`${JSON.stringify(normalized,null,2)}
|
|
2
|
+
`,"utf8")}function upsertManagedEntry(state,entry){const updatedEntries=state.entries.filter(candidate=>normalizeExtensionNameForMatch(candidate.name)!==normalizeExtensionNameForMatch(entry.name)&&normalizeExtensionNameForMatch(candidate.directory)!==normalizeExtensionNameForMatch(entry.directory));return updatedEntries.push(entry),{...state,updated_at:nowIso(),entries:sortManagedEntries(updatedEntries)}}async function persistManagedContributionInventory(extensionsRoot,state,extensionName,contributions){const entry=state.entries.find(candidate=>normalizeExtensionNameForMatch(candidate.name)===normalizeExtensionNameForMatch(extensionName));if(!entry)return state;const updated=upsertManagedEntry(state,{...entry,contributions});return await writeManagedExtensionState(extensionsRoot,updated),updated}export{createEmptyManagedExtensionState,managedExtensionSourcesEquivalent,normalizeManagedState,persistManagedContributionInventory,readManagedExtensionState,resolveManagedExtensionStatePath,sortManagedEntries,upsertManagedEntry,writeManagedExtensionState};
|
|
3
3
|
//# sourceMappingURL=managed-state.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
`,op:"extension_migrations_apply",author:options.author,lockTtlSeconds:settings.locks.ttl_seconds,lockWaitMs:settings.locks.wait_ms})}const pendingCount=receipts.filter(receipt=>receipt.outcome==="pending").length
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7be00b26-4a56-5399-94f6-f2f67cc5c1e6")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import{pathExists}from"../../core/fs/fs-utils.js";import{activateExtensions,loadExtensions}from"../../core/extensions/index.js";import{writeWorkspaceJsonWithHistory}from"../../core/history/workspace-history.js";import{readSettings}from"../../core/store/settings.js";function resolveExtensionMigrationStatePath(pmRoot){return path.join(pmRoot,"extension-migrations.json")}function migrationId(migration,index){const id=migration.definition.id;return typeof id=="string"&&id.trim().length>0?id.trim():`migration-${String(index+1).padStart(3,"0")}`}function migrationKey(migration,id){return`${migration.layer}:${migration.name}:${id}`}async function readExtensionMigrationState(pmRoot){const statePath=resolveExtensionMigrationStatePath(pmRoot);if(!await pathExists(statePath))return{version:1,updated_at:"",entries:[]};const parsed=JSON.parse(await fs.readFile(statePath,"utf8"));return{version:1,updated_at:typeof parsed.updated_at=="string"?parsed.updated_at:"",entries:Array.isArray(parsed.entries)?parsed.entries.filter(entry=>typeof entry?.key=="string"&&(entry.status==="applied"||entry.status==="failed")):[]}}async function applyStoredExtensionMigrationState(pmRoot,migrations){const state=await readExtensionMigrationState(pmRoot),byKey=new Map(state.entries.map(entry=>[entry.key,entry]));return migrations.forEach((migration,index)=>{const id=migrationId(migration,index),entry=byKey.get(migrationKey(migration,id));entry&&(migration.definition.status=entry.status,entry.status==="failed"?migration.definition.reason=entry.error:(delete migration.definition.reason,delete migration.definition.error,delete migration.definition.message))}),state}async function runExtensionMigrations(options){const state=await applyStoredExtensionMigrationState(options.pmRoot,options.migrations),stateByKey=new Map(state.entries.map(entry=>[entry.key,entry])),receipts=[];let changed=!1;const scopedMigrations=options.migrations.map((migration,index)=>({migration,index})).filter(({migration})=>options.scope===void 0||migration.layer===options.scope);for(const{migration,index}of scopedMigrations){const id=migrationId(migration,index),key=migrationKey(migration,id),stored=stateByKey.get(key),declaredStatus=String(migration.definition.status??"pending").toLowerCase(),before=stored?.status??(declaredStatus==="applied"||declaredStatus==="failed"?declaredStatus:"pending");if(before==="applied"){receipts.push({key,layer:migration.layer,extension:migration.name,id,before,outcome:"skipped"});continue}if(options.dryRun===!0){receipts.push({key,layer:migration.layer,extension:migration.name,id,before,outcome:"pending"});continue}const run=migration.runtime_definition?.run??migration.definition.run;if(typeof run!="function"){receipts.push({key,layer:migration.layer,extension:migration.name,id,before,outcome:"pending"});continue}const attemptedAt=new Date().toISOString();try{await Promise.resolve(run({id,command:"migration",layer:migration.layer,extension:migration.name,pm_root:options.pmRoot,status:before}));const entry={key,layer:migration.layer,extension:migration.name,id,status:"applied",attempted_at:attemptedAt};stateByKey.set(key,entry),migration.definition.status="applied",delete migration.definition.reason,delete migration.definition.error,delete migration.definition.message,receipts.push({key,layer:migration.layer,extension:migration.name,id,before,outcome:"applied"}),changed=!0}catch(error){const message=error instanceof Error?error.message:String(error),entry={key,layer:migration.layer,extension:migration.name,id,status:"failed",attempted_at:attemptedAt,error:message};stateByKey.set(key,entry),migration.definition.status="failed",migration.definition.reason=message,receipts.push({key,layer:migration.layer,extension:migration.name,id,before,outcome:"failed",error:message}),changed=!0}}if(changed){const settings=await readSettings(options.pmRoot),nextState={version:1,updated_at:new Date().toISOString(),entries:[...stateByKey.values()].sort((left,right)=>left.key.localeCompare(right.key))};await writeWorkspaceJsonWithHistory({pmRoot:options.pmRoot,filePath:resolveExtensionMigrationStatePath(options.pmRoot),raw:`${JSON.stringify(nextState,null,2)}
|
|
2
|
+
`,op:"extension_migrations_apply",author:options.author,lockTtlSeconds:settings.locks.ttl_seconds,lockWaitMs:settings.locks.wait_ms})}const pendingCount=receipts.filter(receipt=>receipt.outcome==="pending").length,appliedCount=receipts.filter(receipt=>receipt.outcome==="applied").length,skippedCount=receipts.filter(receipt=>receipt.outcome==="skipped").length,failedCount=receipts.filter(receipt=>receipt.outcome==="failed").length;return{ok:failedCount===0,dry_run:options.dryRun===!0,state_path:resolveExtensionMigrationStatePath(options.pmRoot),total:receipts.length,pending_count:pendingCount,applied_count:appliedCount,skipped_count:skippedCount,failed_count:failedCount,migrations:receipts}}async function runExtensionMigrateAction(context){const settings=await readSettings(context.resolvedRoots.settings_root),loaded=await loadExtensions({pmRoot:context.resolvedRoots.pm_root,settings,cwd:process.cwd(),noExtensions:context.global.noExtensions===!0}),activated=await activateExtensions(loaded);context.warnings.push(...loaded.warnings,...activated.warnings);const migration=await runExtensionMigrations({pmRoot:context.resolvedRoots.pm_root,migrations:activated.registrations.migrations,author:typeof context.global.author=="string"&&context.global.author.trim().length>0?context.global.author.trim():"pm-extension-migration",dryRun:context.options.dryRun===!0,...context.scope==="global"?{scope:"global"}:{}});return context.withResult({migration,load_failure_count:loaded.failed.length,activation_failure_count:activated.failed.length},migration.ok)}export{applyStoredExtensionMigrationState,readExtensionMigrationState,resolveExtensionMigrationStatePath,runExtensionMigrateAction,runExtensionMigrations};
|
|
3
3
|
//# sourceMappingURL=migrations.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f2cac210-bba0-5c7f-867b-8b59f8d36e11")}catch{}})();import{normalizeExtensionNameForMatch}from"./shared.js";function collectGlobalOutputOverrideDoctorWarnings(activationResult,loadResult){const commandScopedOwners=new Set((loadResult?.loaded??[]).flatMap(entry=>(entry.activation?.commands?.length??0)>0?[`${entry.layer}:${normalizeExtensionNameForMatch(entry.name)}`]:[])),serviceWarnings=activationResult.services.overrides.filter(entry=>entry.service==="output_format").filter(entry=>entry.passThrough!==!0).filter(entry=>!commandScopedOwners.has(`${entry.layer}:${normalizeExtensionNameForMatch(entry.name)}`)).map(entry=>`extension_output_service_override_global:${entry.service}:${entry.layer}:${entry.name}`),rendererWarnings=activationResult.renderers.overrides.filter(entry=>(entry.commands?.length??0)===0&&entry.resultDiscriminator===void 0).map(entry=>`extension_output_renderer_override_global:${entry.format}:${entry.layer}:${entry.name}`);return[...new Set([...serviceWarnings,...rendererWarnings])].sort((left,right)=>left.localeCompare(right))}export{collectGlobalOutputOverrideDoctorWarnings};
|
|
2
2
|
//# sourceMappingURL=output-ownership.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="accde468-de04-51b6-81ad-5c5ea218a87b")}catch{}})();import{normalizeExtensionNameForMatch}from"./shared.js";function summarizeRuntimeCommandPathsForExtension(extensionName,installed){const normalizedName=normalizeExtensionNameForMatch(extensionName),entry=installed.find(candidate=>normalizeExtensionNameForMatch(candidate.name)===normalizedName);return{command_paths:[...entry?.command_paths??[]].sort((left,right)=>left.localeCompare(right)),action_paths:[...entry?.action_paths??[]].sort((left,right)=>left.localeCompare(right))}}export{summarizeRuntimeCommandPathsForExtension};
|
|
2
2
|
//# sourceMappingURL=runtime-summary.js.map
|