@unbrained/pm-cli 2026.5.14 → 2026.5.24
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 +4 -4
- package/AGENTS.md +78 -457
- package/CHANGELOG.md +71 -0
- package/CONTRIBUTING.md +1 -0
- package/README.md +8 -6
- package/dist/cli/argv-utils.js +4 -1
- package/dist/cli/argv-utils.js.map +1 -1
- package/dist/cli/bootstrap-args.js +4 -1
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commander-usage.js +19 -1
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/activity.js +4 -1
- package/dist/cli/commands/activity.js.map +1 -1
- package/dist/cli/commands/aggregate.js +5 -2
- package/dist/cli/commands/aggregate.js.map +1 -1
- package/dist/cli/commands/annotation-command.d.ts +49 -0
- package/dist/cli/commands/annotation-command.js +135 -0
- package/dist/cli/commands/annotation-command.js.map +1 -0
- package/dist/cli/commands/append.js +5 -6
- package/dist/cli/commands/append.js.map +1 -1
- package/dist/cli/commands/calendar.js +5 -5
- package/dist/cli/commands/calendar.js.map +1 -1
- package/dist/cli/commands/claim.d.ts +3 -0
- package/dist/cli/commands/claim.js +29 -23
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.js +63 -8
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/comments-audit.js +4 -1
- package/dist/cli/commands/comments-audit.js.map +1 -1
- package/dist/cli/commands/comments.d.ts +5 -0
- package/dist/cli/commands/comments.js +29 -116
- package/dist/cli/commands/comments.js.map +1 -1
- package/dist/cli/commands/completion.js +198 -15
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/config.js +4 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/context.js +21 -13
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/contracts.d.ts +9 -0
- package/dist/cli/commands/contracts.js +314 -64
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.js +77 -48
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/dedupe-audit.js +9 -3
- package/dist/cli/commands/dedupe-audit.js.map +1 -1
- package/dist/cli/commands/delete.d.ts +3 -0
- package/dist/cli/commands/delete.js +11 -7
- package/dist/cli/commands/delete.js.map +1 -1
- package/dist/cli/commands/deps.js +4 -1
- package/dist/cli/commands/deps.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +1 -0
- package/dist/cli/commands/docs.js +6 -7
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/event-validation-messages.d.ts +3 -0
- package/dist/cli/commands/event-validation-messages.js +44 -0
- package/dist/cli/commands/event-validation-messages.js.map +1 -0
- package/dist/cli/commands/extension.d.ts +3 -1
- package/dist/cli/commands/extension.js +259 -52
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.js +8 -12
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/gc.js +19 -3
- package/dist/cli/commands/gc.js.map +1 -1
- package/dist/cli/commands/get.d.ts +10 -5
- package/dist/cli/commands/get.js +135 -20
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/guide.js +6 -8
- package/dist/cli/commands/guide.js.map +1 -1
- package/dist/cli/commands/health.d.ts +14 -0
- package/dist/cli/commands/health.js +269 -67
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-redact.d.ts +50 -0
- package/dist/cli/commands/history-redact.js +476 -0
- package/dist/cli/commands/history-redact.js.map +1 -0
- package/dist/cli/commands/history-repair.d.ts +33 -0
- package/dist/cli/commands/history-repair.js +166 -0
- package/dist/cli/commands/history-repair.js.map +1 -0
- package/dist/cli/commands/history.d.ts +4 -0
- package/dist/cli/commands/history.js +12 -79
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/index.d.ts +5 -1
- package/dist/cli/commands/index.js +9 -2
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init-agent-guidance.d.ts +31 -0
- package/dist/cli/commands/init-agent-guidance.js +336 -0
- package/dist/cli/commands/init-agent-guidance.js.map +1 -0
- package/dist/cli/commands/init.d.ts +42 -0
- package/dist/cli/commands/init.js +96 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/learnings.js +22 -118
- package/dist/cli/commands/learnings.js.map +1 -1
- package/dist/cli/commands/linked-test-entry.d.ts +3 -0
- package/dist/cli/commands/linked-test-entry.js +62 -0
- package/dist/cli/commands/linked-test-entry.js.map +1 -0
- package/dist/cli/commands/list.d.ts +1 -0
- package/dist/cli/commands/list.js +72 -38
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/metadata-normalizers.js +4 -1
- package/dist/cli/commands/metadata-normalizers.js.map +1 -1
- package/dist/cli/commands/normalize.js +4 -1
- package/dist/cli/commands/normalize.js.map +1 -1
- package/dist/cli/commands/notes.js +22 -118
- package/dist/cli/commands/notes.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +121 -0
- package/dist/cli/commands/plan.js +1137 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/reindex.js +4 -1
- package/dist/cli/commands/reindex.js.map +1 -1
- package/dist/cli/commands/restore.js +9 -49
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/schema.d.ts +31 -0
- package/dist/cli/commands/schema.js +98 -0
- package/dist/cli/commands/schema.js.map +1 -0
- package/dist/cli/commands/search.js +156 -40
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/stats.js +4 -1
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/templates.d.ts +4 -0
- package/dist/cli/commands/templates.js +91 -16
- package/dist/cli/commands/templates.js.map +1 -1
- package/dist/cli/commands/test-all.js +6 -7
- package/dist/cli/commands/test-all.js.map +1 -1
- package/dist/cli/commands/test-runs.js +4 -1
- package/dist/cli/commands/test-runs.js.map +1 -1
- package/dist/cli/commands/test.d.ts +1 -0
- package/dist/cli/commands/test.js +9 -9
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.js +6 -7
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.js +204 -103
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/upgrade.js +6 -3
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +3 -1
- package/dist/cli/commands/validate.js +44 -64
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/error-guidance.js +99 -6
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/extension-command-help.d.ts +0 -1
- package/dist/cli/extension-command-help.js +4 -12
- package/dist/cli/extension-command-help.js.map +1 -1
- package/dist/cli/extension-command-options.d.ts +1 -0
- package/dist/cli/extension-command-options.js +108 -6
- package/dist/cli/extension-command-options.js.map +1 -1
- package/dist/cli/guide-topics.js +4 -1
- package/dist/cli/guide-topics.js.map +1 -1
- package/dist/cli/help-content.d.ts +0 -1
- package/dist/cli/help-content.js +46 -22
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/help-json-payload.d.ts +1 -0
- package/dist/cli/help-json-payload.js +35 -2
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.js +214 -30
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/migration-gates.js +4 -1
- package/dist/cli/migration-gates.js.map +1 -1
- package/dist/cli/register-list-query.d.ts +1 -1
- package/dist/cli/register-list-query.js +75 -29
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.d.ts +1 -1
- package/dist/cli/register-mutation.js +430 -38
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +47 -10
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +47 -25
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.d.ts +0 -2
- package/dist/cli/registration-helpers.js +21 -40
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli/shared-parsers.js +4 -1
- package/dist/cli/shared-parsers.js.map +1 -1
- package/dist/cli/telemetry-flush.js +4 -1
- package/dist/cli/telemetry-flush.js.map +1 -1
- package/dist/cli.js +65 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/extensions/extension-types.js +4 -1
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +0 -1
- package/dist/core/extensions/index.js +4 -13
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/item-fields.js +4 -1
- package/dist/core/extensions/item-fields.js.map +1 -1
- package/dist/core/extensions/loader.js +78 -60
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runtime-registrations.js +4 -1
- package/dist/core/extensions/runtime-registrations.js.map +1 -1
- package/dist/core/fs/fs-utils.js +4 -1
- package/dist/core/fs/fs-utils.js.map +1 -1
- package/dist/core/fs/index.js +4 -1
- package/dist/core/fs/index.js.map +1 -1
- package/dist/core/fs/path-utils.d.ts +1 -0
- package/dist/core/fs/path-utils.js +12 -0
- package/dist/core/fs/path-utils.js.map +1 -0
- package/dist/core/history/drift-scan.d.ts +11 -0
- package/dist/core/history/drift-scan.js +67 -0
- package/dist/core/history/drift-scan.js.map +1 -0
- package/dist/core/history/history-stream-policy.js +4 -1
- package/dist/core/history/history-stream-policy.js.map +1 -1
- package/dist/core/history/history.js +4 -1
- package/dist/core/history/history.js.map +1 -1
- package/dist/core/history/index.js +4 -1
- package/dist/core/history/index.js.map +1 -1
- package/dist/core/history/replay.d.ts +82 -0
- package/dist/core/history/replay.js +249 -0
- package/dist/core/history/replay.js.map +1 -0
- package/dist/core/item/id.js +4 -1
- package/dist/core/item/id.js.map +1 -1
- package/dist/core/item/index.js +4 -1
- package/dist/core/item/index.js.map +1 -1
- package/dist/core/item/item-format.js +250 -8
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/core/item/item-type-definition.d.ts +52 -0
- package/dist/core/item/item-type-definition.js +123 -0
- package/dist/core/item/item-type-definition.js.map +1 -0
- package/dist/core/item/parent-reference-policy.js +4 -1
- package/dist/core/item/parent-reference-policy.js.map +1 -1
- package/dist/core/item/parse.js +34 -3
- package/dist/core/item/parse.js.map +1 -1
- package/dist/core/item/priority.d.ts +23 -0
- package/dist/core/item/priority.js +55 -0
- package/dist/core/item/priority.js.map +1 -0
- package/dist/core/item/sprint-release-format.js +4 -1
- package/dist/core/item/sprint-release-format.js.map +1 -1
- package/dist/core/item/status.d.ts +14 -1
- package/dist/core/item/status.js +24 -1
- package/dist/core/item/status.js.map +1 -1
- package/dist/core/item/toon-decode.d.ts +19 -0
- package/dist/core/item/toon-decode.js +69 -0
- package/dist/core/item/toon-decode.js.map +1 -0
- package/dist/core/item/type-registry.js +15 -83
- package/dist/core/item/type-registry.js.map +1 -1
- package/dist/core/lock/index.js +4 -1
- package/dist/core/lock/index.js.map +1 -1
- package/dist/core/lock/lock.js +4 -1
- package/dist/core/lock/lock.js.map +1 -1
- package/dist/core/output/output.d.ts +4 -0
- package/dist/core/output/output.js +47 -6
- package/dist/core/output/output.js.map +1 -1
- package/dist/core/packages/manifest.d.ts +1 -0
- package/dist/core/packages/manifest.js +6 -8
- package/dist/core/packages/manifest.js.map +1 -1
- package/dist/core/packages/root.d.ts +3 -0
- package/dist/core/packages/root.js +51 -0
- package/dist/core/packages/root.js.map +1 -0
- package/dist/core/schema/item-types-file.d.ts +85 -0
- package/dist/core/schema/item-types-file.js +243 -0
- package/dist/core/schema/item-types-file.js.map +1 -0
- package/dist/core/schema/runtime-field-filters.js +4 -1
- package/dist/core/schema/runtime-field-filters.js.map +1 -1
- package/dist/core/schema/runtime-field-values.js +4 -1
- package/dist/core/schema/runtime-field-values.js.map +1 -1
- package/dist/core/schema/runtime-schema.d.ts +2 -1
- package/dist/core/schema/runtime-schema.js +13 -8
- package/dist/core/schema/runtime-schema.js.map +1 -1
- package/dist/core/search/cache.js +7 -2
- package/dist/core/search/cache.js.map +1 -1
- package/dist/core/search/corpus.d.ts +2 -0
- package/dist/core/search/corpus.js +77 -2
- package/dist/core/search/corpus.js.map +1 -1
- package/dist/core/search/embedding-batches.js +21 -7
- package/dist/core/search/embedding-batches.js.map +1 -1
- package/dist/core/search/http-client.js +4 -1
- package/dist/core/search/http-client.js.map +1 -1
- package/dist/core/search/providers.js +4 -1
- package/dist/core/search/providers.js.map +1 -1
- package/dist/core/search/semantic-defaults.js +12 -3
- package/dist/core/search/semantic-defaults.js.map +1 -1
- package/dist/core/search/vector-stores.js +4 -1
- package/dist/core/search/vector-stores.js.map +1 -1
- package/dist/core/sentry/helpers.js +4 -1
- package/dist/core/sentry/helpers.js.map +1 -1
- package/dist/core/sentry/instrument.js +10 -13
- package/dist/core/sentry/instrument.js.map +1 -1
- package/dist/core/shared/author.d.ts +1 -0
- package/dist/core/shared/author.js +9 -0
- package/dist/core/shared/author.js.map +1 -0
- package/dist/core/shared/command-types.js +4 -1
- package/dist/core/shared/command-types.js.map +1 -1
- package/dist/core/shared/conflict-markers.js +4 -1
- package/dist/core/shared/conflict-markers.js.map +1 -1
- package/dist/core/shared/constants.d.ts +2 -2
- package/dist/core/shared/constants.js +24 -1
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/shared/errors.js +4 -1
- package/dist/core/shared/errors.js.map +1 -1
- package/dist/core/shared/index.js +4 -1
- package/dist/core/shared/index.js.map +1 -1
- package/dist/core/shared/lazy-module.d.ts +1 -0
- package/dist/core/shared/lazy-module.js +11 -0
- package/dist/core/shared/lazy-module.js.map +1 -0
- package/dist/core/shared/levenshtein.js +4 -1
- package/dist/core/shared/levenshtein.js.map +1 -1
- package/dist/core/shared/option-alias-visibility.d.ts +44 -0
- package/dist/core/shared/option-alias-visibility.js +76 -0
- package/dist/core/shared/option-alias-visibility.js.map +1 -0
- package/dist/core/shared/primitives.js +4 -1
- package/dist/core/shared/primitives.js.map +1 -1
- package/dist/core/shared/serialization.js +4 -1
- package/dist/core/shared/serialization.js.map +1 -1
- package/dist/core/shared/text-normalization.d.ts +0 -1
- package/dist/core/shared/text-normalization.js +4 -4
- package/dist/core/shared/text-normalization.js.map +1 -1
- package/dist/core/shared/time.js +4 -1
- package/dist/core/shared/time.js.map +1 -1
- package/dist/core/store/front-matter-cache.js +8 -3
- package/dist/core/store/front-matter-cache.js.map +1 -1
- package/dist/core/store/index.js +4 -1
- package/dist/core/store/index.js.map +1 -1
- package/dist/core/store/item-format-migration.js +4 -1
- package/dist/core/store/item-format-migration.js.map +1 -1
- package/dist/core/store/item-store.d.ts +4 -0
- package/dist/core/store/item-store.js +133 -39
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/paths.js +4 -1
- package/dist/core/store/paths.js.map +1 -1
- package/dist/core/store/settings-validator.d.ts +106 -0
- package/dist/core/store/settings-validator.js +279 -0
- package/dist/core/store/settings-validator.js.map +1 -0
- package/dist/core/store/settings.js +32 -331
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/consent.js +4 -1
- package/dist/core/telemetry/consent.js.map +1 -1
- package/dist/core/telemetry/observability.d.ts +1 -1
- package/dist/core/telemetry/observability.js +11 -2
- package/dist/core/telemetry/observability.js.map +1 -1
- package/dist/core/telemetry/runtime.js +34 -6
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/core/test/background-runs.js +4 -1
- package/dist/core/test/background-runs.js.map +1 -1
- package/dist/core/test/item-test-run-tracking.js +4 -1
- package/dist/core/test/item-test-run-tracking.js.map +1 -1
- package/dist/mcp/server.js +182 -22
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts/commander-mutation-options.js +10 -3
- package/dist/sdk/cli-contracts/commander-mutation-options.js.map +1 -1
- package/dist/sdk/cli-contracts/commander-types.js +4 -1
- package/dist/sdk/cli-contracts/commander-types.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +13 -2
- package/dist/sdk/cli-contracts.js +410 -26
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/index.js +4 -1
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/runtime.d.ts +25 -1
- package/dist/sdk/runtime.js +48 -2
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/types/index.js +4 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types.d.ts +92 -2
- package/dist/types.js +42 -1
- package/dist/types.js.map +1 -1
- package/docs/AGENT_GUIDE.md +23 -7
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/CLAUDE_CODE_PLUGIN.md +10 -10
- package/docs/CODEX_PLUGIN.md +2 -2
- package/docs/COMMANDS.md +117 -12
- package/docs/CONFIGURATION.md +5 -2
- package/docs/EXTENSIONS.md +158 -814
- package/docs/QUICKSTART.md +11 -5
- package/docs/README.md +7 -6
- package/docs/RELEASING.md +13 -9
- package/docs/SDK.md +11 -2
- package/docs/TESTING.md +2 -2
- package/marketplace.json +3 -3
- package/package.json +15 -12
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/README.md +4 -2
- package/packages/pm-calendar/extensions/calendar/index.js +22 -3
- package/packages/pm-calendar/extensions/calendar/index.ts +22 -3
- package/packages/pm-calendar/extensions/calendar/runtime.js +26 -7
- package/packages/pm-calendar/extensions/calendar/runtime.ts +26 -7
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/extensions/guide-shell/index.js +1 -1
- package/packages/pm-guide-shell/extensions/guide-shell/index.ts +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/README.md +8 -0
- package/packages/pm-search-advanced/extensions/search-advanced/index.js +74 -0
- package/packages/pm-search-advanced/extensions/search-advanced/index.ts +75 -1
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +67 -9
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +67 -9
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/README.md +1 -1
- package/packages/pm-templates/extensions/templates/runtime.js +11 -202
- package/packages/pm-templates/extensions/templates/runtime.ts +38 -230
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/plugins/{pm-cli-claude → pm-claude}/.claude-plugin/plugin.json +2 -2
- package/plugins/{pm-cli-claude → pm-claude}/.mcp.json +1 -1
- package/plugins/{pm-cli-claude → pm-claude}/README.md +4 -4
- package/plugins/{pm-cli-claude → pm-claude}/agents/pm-coordinator.md +1 -1
- package/plugins/{pm-cli-claude → pm-claude}/commands/pm-init.md +10 -1
- package/plugins/{pm-cli-claude → pm-claude}/commands/pm-planner.md +18 -0
- package/plugins/{pm-cli-claude → pm-claude}/skills/pm-planner/SKILL.md +46 -1
- package/plugins/{pm-cli-codex → pm-codex}/.codex-plugin/plugin.json +3 -3
- package/plugins/{pm-cli-codex → pm-codex}/.mcp.json +1 -1
- package/plugins/{pm-cli-codex → pm-codex}/README.md +7 -4
- package/plugins/pm-codex/skills/pm-native/SKILL.md +81 -0
- package/scripts/finalize-build.mjs +28 -0
- package/scripts/prepare-build-cache.mjs +37 -0
- package/dist/core/output/command-aware.d.ts +0 -1
- package/dist/core/output/command-aware.js +0 -394
- package/dist/core/output/command-aware.js.map +0 -1
- package/plugins/pm-cli-codex/skills/pm-native/SKILL.md +0 -57
- /package/plugins/{pm-cli-claude → pm-claude}/agents/pm-delivery-chain.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/agents/pm-triage-agent.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/agents/pm-verification-agent.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-audit.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-calendar.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-close-task.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-developer.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-list.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-new.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-release.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-search.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-start-task.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-status.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-triage.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/commands/pm-workflow.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/hooks/hooks.json +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/hooks/session-start.mjs +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/scripts/pm-mcp-server.mjs +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/skills/pm-audit/SKILL.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/skills/pm-developer/SKILL.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/skills/pm-release/SKILL.md +0 -0
- /package/plugins/{pm-cli-claude → pm-claude}/skills/pm-workflow/SKILL.md +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/assets/pm-cli-small.svg +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/commands/pm-audit.md +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/commands/pm-close-task.md +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/commands/pm-start-task.md +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/scripts/pm-mcp-server.mjs +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/skills/pm-auditor/SKILL.md +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/skills/pm-auditor/agents/openai.yaml +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/skills/pm-native/agents/openai.yaml +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/skills/pm-release/SKILL.md +0 -0
- /package/plugins/{pm-cli-codex → pm-codex}/skills/pm-release/agents/openai.yaml +0 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9f6d7165-e26e-5815-9ac5-aad4ce4d3877")}catch(e){}}();
|
|
3
|
+
import jsonPatch from "fast-json-patch";
|
|
4
|
+
import { FRONT_MATTER_KEY_ORDER } from "../shared/constants.js";
|
|
5
|
+
import { canonicalDocument } from "../item/item-format.js";
|
|
6
|
+
import { orderObject, sha256Hex, stableStringify } from "../shared/serialization.js";
|
|
7
|
+
import { hashDocument } from "./history.js";
|
|
8
|
+
export const EMPTY_REPLAY_DOCUMENT = {
|
|
9
|
+
metadata: {},
|
|
10
|
+
body: "",
|
|
11
|
+
};
|
|
12
|
+
export function cloneEmptyReplayDocument() {
|
|
13
|
+
return structuredClone(EMPTY_REPLAY_DOCUMENT);
|
|
14
|
+
}
|
|
15
|
+
export function replayHash(document) {
|
|
16
|
+
try {
|
|
17
|
+
return hashDocument({
|
|
18
|
+
metadata: document.metadata,
|
|
19
|
+
body: document.body,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Legacy/malformed replay states (for example a stream whose first entry never
|
|
24
|
+
// established a full `create` document, so the canonicalizer cannot normalize it)
|
|
25
|
+
// cannot be canonically hashed. Fall back to a deterministic structural hash so
|
|
26
|
+
// re-anchor and verification stay internally consistent for these streams. Fully
|
|
27
|
+
// formed documents always take the canonical path above, so valid streams are
|
|
28
|
+
// unaffected.
|
|
29
|
+
return sha256Hex(stableStringify({ replay_fallback: true, metadata: document.metadata, body: document.body }));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function replayToItemDocument(document) {
|
|
33
|
+
return {
|
|
34
|
+
metadata: document.metadata,
|
|
35
|
+
body: document.body,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Canonicalize an item document into the ordered replay form used when comparing
|
|
40
|
+
* a replayed chain against the on-disk item (restore + history-repair reconciliation).
|
|
41
|
+
*/
|
|
42
|
+
export function toReplayDocument(document) {
|
|
43
|
+
if (!document.metadata || Object.keys(document.metadata).length === 0) {
|
|
44
|
+
return {
|
|
45
|
+
metadata: {},
|
|
46
|
+
body: document.body ?? "",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const canonical = canonicalDocument(document);
|
|
50
|
+
return {
|
|
51
|
+
metadata: orderObject(canonical.metadata, FRONT_MATTER_KEY_ORDER),
|
|
52
|
+
body: canonical.body,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function normalizeReplayPatchPath(path) {
|
|
56
|
+
if (path === "/front_matter") {
|
|
57
|
+
return "/metadata";
|
|
58
|
+
}
|
|
59
|
+
if (path.startsWith("/front_matter/")) {
|
|
60
|
+
return `/metadata/${path.slice("/front_matter/".length)}`;
|
|
61
|
+
}
|
|
62
|
+
return path;
|
|
63
|
+
}
|
|
64
|
+
export function normalizeReplayPatchOps(patch) {
|
|
65
|
+
return patch.map((operation) => ({
|
|
66
|
+
...operation,
|
|
67
|
+
path: normalizeReplayPatchPath(operation.path),
|
|
68
|
+
from: operation.from ? normalizeReplayPatchPath(operation.from) : undefined,
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
function isReplayDocumentShape(value) {
|
|
72
|
+
return (typeof value === "object" &&
|
|
73
|
+
value !== null &&
|
|
74
|
+
"metadata" in value &&
|
|
75
|
+
"body" in value &&
|
|
76
|
+
typeof value.body === "string" &&
|
|
77
|
+
typeof value.metadata === "object" &&
|
|
78
|
+
value.metadata !== null);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Strictly apply a history patch (front_matter->metadata normalized) to a replay
|
|
82
|
+
* document. Returns a result envelope rather than throwing so each caller can
|
|
83
|
+
* format its own error contract.
|
|
84
|
+
*/
|
|
85
|
+
export function tryApplyReplayPatch(current, patch) {
|
|
86
|
+
try {
|
|
87
|
+
const normalizedPatch = normalizeReplayPatchOps(patch);
|
|
88
|
+
const applied = jsonPatch.applyPatch(structuredClone(current), normalizedPatch, true, false).newDocument;
|
|
89
|
+
if (!isReplayDocumentShape(applied)) {
|
|
90
|
+
return { ok: false, error: new Error("history_replay_invalid_document_shape") };
|
|
91
|
+
}
|
|
92
|
+
return { ok: true, document: { metadata: applied.metadata, body: applied.body } };
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
return { ok: false, error };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Deterministically verify a history chain: each entry's before_hash must equal
|
|
100
|
+
* the prior replayed after_hash, the patch must strictly apply, and the recorded
|
|
101
|
+
* after_hash must equal the replayed result.
|
|
102
|
+
*/
|
|
103
|
+
export function verifyHistoryChain(entries) {
|
|
104
|
+
let replay = cloneEmptyReplayDocument();
|
|
105
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
106
|
+
const entry = entries[index];
|
|
107
|
+
if (replayHash(replay) !== entry.before_hash) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
errors: [`verify_failed:before_hash_mismatch:entry_${index + 1}`],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const applied = tryApplyReplayPatch(replay, entry.patch);
|
|
114
|
+
if (!applied.ok) {
|
|
115
|
+
return {
|
|
116
|
+
ok: false,
|
|
117
|
+
errors: [`verify_failed:patch_apply_failed:entry_${index + 1}`],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
replay = applied.document;
|
|
121
|
+
if (replayHash(replay) !== entry.after_hash) {
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
errors: [`verify_failed:after_hash_mismatch:entry_${index + 1}`],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { ok: true, errors: [] };
|
|
129
|
+
}
|
|
130
|
+
function tryApplySingleOp(document, op) {
|
|
131
|
+
try {
|
|
132
|
+
const applied = jsonPatch.applyPatch(structuredClone(document), [op], true, false).newDocument;
|
|
133
|
+
return { ok: true, document: applied };
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return { ok: false };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Apply a legacy patch op-by-op, recovering from drift that strict replay rejects:
|
|
141
|
+
* a `replace` whose path no longer exists is retried as `add`, and any op that
|
|
142
|
+
* still cannot apply against the current replay state is skipped. The resulting
|
|
143
|
+
* document is what the repaired entry's recomputed patch should target.
|
|
144
|
+
*/
|
|
145
|
+
export function lenientApplyReplayPatch(current, patch) {
|
|
146
|
+
let working = structuredClone(current);
|
|
147
|
+
let convertedReplaceToAdd = 0;
|
|
148
|
+
let skippedOps = 0;
|
|
149
|
+
for (const op of normalizeReplayPatchOps(patch)) {
|
|
150
|
+
const direct = tryApplySingleOp(working, op);
|
|
151
|
+
if (direct.ok) {
|
|
152
|
+
working = direct.document;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (op.op === "replace") {
|
|
156
|
+
const asAdd = tryApplySingleOp(working, { ...op, op: "add" });
|
|
157
|
+
if (asAdd.ok) {
|
|
158
|
+
working = asAdd.document;
|
|
159
|
+
convertedReplaceToAdd += 1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
skippedOps += 1;
|
|
164
|
+
}
|
|
165
|
+
const candidate = working;
|
|
166
|
+
const document = {
|
|
167
|
+
metadata: typeof candidate.metadata === "object" && candidate.metadata !== null
|
|
168
|
+
? candidate.metadata
|
|
169
|
+
: {},
|
|
170
|
+
body: typeof candidate.body === "string" ? candidate.body : current.body,
|
|
171
|
+
};
|
|
172
|
+
return { document, convertedReplaceToAdd, skippedOps };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Re-anchor a drifted history chain: replay every entry from empty, recompute the
|
|
176
|
+
* before/after hashes, and only rewrite a patch when the original op set no longer
|
|
177
|
+
* strictly applies (legacy drift). Clean entries keep their patch verbatim so the
|
|
178
|
+
* on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain.
|
|
179
|
+
*/
|
|
180
|
+
export function reanchorHistoryEntries(entries) {
|
|
181
|
+
let replay = cloneEmptyReplayDocument();
|
|
182
|
+
const rewritten = [];
|
|
183
|
+
const details = [];
|
|
184
|
+
let entriesRehashed = 0;
|
|
185
|
+
let entriesPatchRepaired = 0;
|
|
186
|
+
let convertedReplaceToAdd = 0;
|
|
187
|
+
let skippedOps = 0;
|
|
188
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
189
|
+
const entry = entries[index];
|
|
190
|
+
const beforeHash = replayHash(replay);
|
|
191
|
+
const strict = tryApplyReplayPatch(replay, entry.patch);
|
|
192
|
+
let next;
|
|
193
|
+
let outPatch;
|
|
194
|
+
let patchRepaired = false;
|
|
195
|
+
let entryConverted = 0;
|
|
196
|
+
let entrySkipped = 0;
|
|
197
|
+
if (strict.ok) {
|
|
198
|
+
next = strict.document;
|
|
199
|
+
outPatch = entry.patch;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const lenient = lenientApplyReplayPatch(replay, entry.patch);
|
|
203
|
+
next = lenient.document;
|
|
204
|
+
outPatch = jsonPatch.compare(replay, next);
|
|
205
|
+
patchRepaired = true;
|
|
206
|
+
entryConverted = lenient.convertedReplaceToAdd;
|
|
207
|
+
entrySkipped = lenient.skippedOps;
|
|
208
|
+
convertedReplaceToAdd += entryConverted;
|
|
209
|
+
skippedOps += entrySkipped;
|
|
210
|
+
entriesPatchRepaired += 1;
|
|
211
|
+
}
|
|
212
|
+
const afterHash = replayHash(next);
|
|
213
|
+
const rehashed = beforeHash !== entry.before_hash || afterHash !== entry.after_hash;
|
|
214
|
+
if (rehashed) {
|
|
215
|
+
entriesRehashed += 1;
|
|
216
|
+
}
|
|
217
|
+
rewritten.push({
|
|
218
|
+
...entry,
|
|
219
|
+
patch: outPatch,
|
|
220
|
+
before_hash: beforeHash,
|
|
221
|
+
after_hash: afterHash,
|
|
222
|
+
});
|
|
223
|
+
details.push({
|
|
224
|
+
index: index + 1,
|
|
225
|
+
rehashed,
|
|
226
|
+
patch_repaired: patchRepaired,
|
|
227
|
+
converted_replace_to_add: entryConverted,
|
|
228
|
+
skipped_ops: entrySkipped,
|
|
229
|
+
});
|
|
230
|
+
replay = next;
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
entries: rewritten,
|
|
234
|
+
finalDocument: replay,
|
|
235
|
+
entriesRehashed,
|
|
236
|
+
entriesPatchRepaired,
|
|
237
|
+
convertedReplaceToAdd,
|
|
238
|
+
skippedOps,
|
|
239
|
+
details,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
export function historyEntriesToRaw(entries) {
|
|
243
|
+
if (entries.length === 0) {
|
|
244
|
+
return "";
|
|
245
|
+
}
|
|
246
|
+
return `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`;
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=replay.js.map
|
|
249
|
+
//# debugId=9f6d7165-e26e-5815-9ac5-aad4ce4d3877
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sources":["core/history/replay.ts"],"sourceRoot":"/","sourcesContent":["import jsonPatch from \"fast-json-patch\";\nimport { FRONT_MATTER_KEY_ORDER } from \"../shared/constants.js\";\nimport { canonicalDocument } from \"../item/item-format.js\";\nimport { orderObject, sha256Hex, stableStringify } from \"../shared/serialization.js\";\nimport { hashDocument } from \"./history.js\";\nimport type { HistoryEntry, HistoryPatchOp, ItemDocument, ItemMetadata } from \"../../types/index.js\";\n\n/**\n * Shared history replay/patch mechanics single-sourced for the history, restore,\n * history-redact, and history-repair commands plus the health/validate drift checks.\n *\n * Each command keeps its own thin error-formatting wrapper so the exact CLI error\n * contracts (restore's rich patch-failure context, redact's op tag, history's\n * generic message) are preserved; only the underlying replay/patch logic is shared.\n */\n\nexport interface ReplayDocument {\n metadata: Record<string, unknown>;\n body: string;\n}\n\nexport const EMPTY_REPLAY_DOCUMENT: ReplayDocument = {\n metadata: {},\n body: \"\",\n};\n\nexport function cloneEmptyReplayDocument(): ReplayDocument {\n return structuredClone(EMPTY_REPLAY_DOCUMENT);\n}\n\nexport function replayHash(document: ReplayDocument): string {\n try {\n return hashDocument({\n metadata: document.metadata as unknown as ItemMetadata,\n body: document.body,\n });\n } catch {\n // Legacy/malformed replay states (for example a stream whose first entry never\n // established a full `create` document, so the canonicalizer cannot normalize it)\n // cannot be canonically hashed. Fall back to a deterministic structural hash so\n // re-anchor and verification stay internally consistent for these streams. Fully\n // formed documents always take the canonical path above, so valid streams are\n // unaffected.\n return sha256Hex(stableStringify({ replay_fallback: true, metadata: document.metadata, body: document.body }));\n }\n}\n\nexport function replayToItemDocument(document: ReplayDocument): ItemDocument {\n return {\n metadata: document.metadata as unknown as ItemMetadata,\n body: document.body,\n };\n}\n\n/**\n * Canonicalize an item document into the ordered replay form used when comparing\n * a replayed chain against the on-disk item (restore + history-repair reconciliation).\n */\nexport function toReplayDocument(document: ItemDocument): ReplayDocument {\n if (!document.metadata || Object.keys(document.metadata).length === 0) {\n return {\n metadata: {},\n body: document.body ?? \"\",\n };\n }\n const canonical = canonicalDocument(document);\n return {\n metadata: orderObject(canonical.metadata as unknown as Record<string, unknown>, FRONT_MATTER_KEY_ORDER),\n body: canonical.body,\n };\n}\n\nexport function normalizeReplayPatchPath(path: string): string {\n if (path === \"/front_matter\") {\n return \"/metadata\";\n }\n if (path.startsWith(\"/front_matter/\")) {\n return `/metadata/${path.slice(\"/front_matter/\".length)}`;\n }\n return path;\n}\n\nexport function normalizeReplayPatchOps(patch: HistoryPatchOp[]): HistoryPatchOp[] {\n return patch.map((operation) => ({\n ...operation,\n path: normalizeReplayPatchPath(operation.path),\n from: operation.from ? normalizeReplayPatchPath(operation.from) : undefined,\n }));\n}\n\nfunction isReplayDocumentShape(value: unknown): value is { metadata: Record<string, unknown>; body: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"metadata\" in value &&\n \"body\" in value &&\n typeof (value as { body: unknown }).body === \"string\" &&\n typeof (value as { metadata: unknown }).metadata === \"object\" &&\n (value as { metadata: unknown }).metadata !== null\n );\n}\n\nexport type ReplayApplyResult =\n | { ok: true; document: ReplayDocument }\n | { ok: false; error: unknown };\n\n/**\n * Strictly apply a history patch (front_matter->metadata normalized) to a replay\n * document. Returns a result envelope rather than throwing so each caller can\n * format its own error contract.\n */\nexport function tryApplyReplayPatch(current: ReplayDocument, patch: HistoryPatchOp[]): ReplayApplyResult {\n try {\n const normalizedPatch = normalizeReplayPatchOps(patch);\n const applied = jsonPatch.applyPatch(\n structuredClone(current),\n normalizedPatch as jsonPatch.Operation[],\n true,\n false,\n ).newDocument as unknown;\n if (!isReplayDocumentShape(applied)) {\n return { ok: false, error: new Error(\"history_replay_invalid_document_shape\") };\n }\n return { ok: true, document: { metadata: applied.metadata, body: applied.body } };\n } catch (error) {\n return { ok: false, error };\n }\n}\n\n/**\n * Deterministically verify a history chain: each entry's before_hash must equal\n * the prior replayed after_hash, the patch must strictly apply, and the recorded\n * after_hash must equal the replayed result.\n */\nexport function verifyHistoryChain(entries: HistoryEntry[]): { ok: boolean; errors: string[] } {\n let replay = cloneEmptyReplayDocument();\n for (let index = 0; index < entries.length; index += 1) {\n const entry = entries[index];\n if (replayHash(replay) !== entry.before_hash) {\n return {\n ok: false,\n errors: [`verify_failed:before_hash_mismatch:entry_${index + 1}`],\n };\n }\n const applied = tryApplyReplayPatch(replay, entry.patch);\n if (!applied.ok) {\n return {\n ok: false,\n errors: [`verify_failed:patch_apply_failed:entry_${index + 1}`],\n };\n }\n replay = applied.document;\n if (replayHash(replay) !== entry.after_hash) {\n return {\n ok: false,\n errors: [`verify_failed:after_hash_mismatch:entry_${index + 1}`],\n };\n }\n }\n return { ok: true, errors: [] };\n}\n\nexport interface LenientApplyResult {\n document: ReplayDocument;\n convertedReplaceToAdd: number;\n skippedOps: number;\n}\n\nfunction tryApplySingleOp(document: unknown, op: HistoryPatchOp): { ok: true; document: unknown } | { ok: false } {\n try {\n const applied = jsonPatch.applyPatch(\n structuredClone(document),\n [op as jsonPatch.Operation],\n true,\n false,\n ).newDocument as unknown;\n return { ok: true, document: applied };\n } catch {\n return { ok: false };\n }\n}\n\n/**\n * Apply a legacy patch op-by-op, recovering from drift that strict replay rejects:\n * a `replace` whose path no longer exists is retried as `add`, and any op that\n * still cannot apply against the current replay state is skipped. The resulting\n * document is what the repaired entry's recomputed patch should target.\n */\nexport function lenientApplyReplayPatch(current: ReplayDocument, patch: HistoryPatchOp[]): LenientApplyResult {\n let working: unknown = structuredClone(current);\n let convertedReplaceToAdd = 0;\n let skippedOps = 0;\n\n for (const op of normalizeReplayPatchOps(patch)) {\n const direct = tryApplySingleOp(working, op);\n if (direct.ok) {\n working = direct.document;\n continue;\n }\n if (op.op === \"replace\") {\n const asAdd = tryApplySingleOp(working, { ...op, op: \"add\" });\n if (asAdd.ok) {\n working = asAdd.document;\n convertedReplaceToAdd += 1;\n continue;\n }\n }\n skippedOps += 1;\n }\n\n const candidate = working as { metadata?: unknown; body?: unknown };\n const document: ReplayDocument = {\n metadata:\n typeof candidate.metadata === \"object\" && candidate.metadata !== null\n ? (candidate.metadata as Record<string, unknown>)\n : {},\n body: typeof candidate.body === \"string\" ? candidate.body : current.body,\n };\n return { document, convertedReplaceToAdd, skippedOps };\n}\n\nexport interface ReanchorEntryDetail {\n index: number;\n rehashed: boolean;\n patch_repaired: boolean;\n converted_replace_to_add: number;\n skipped_ops: number;\n}\n\nexport interface ReanchorResult {\n entries: HistoryEntry[];\n finalDocument: ReplayDocument;\n entriesRehashed: number;\n entriesPatchRepaired: number;\n convertedReplaceToAdd: number;\n skippedOps: number;\n details: ReanchorEntryDetail[];\n}\n\n/**\n * Re-anchor a drifted history chain: replay every entry from empty, recompute the\n * before/after hashes, and only rewrite a patch when the original op set no longer\n * strictly applies (legacy drift). Clean entries keep their patch verbatim so the\n * on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain.\n */\nexport function reanchorHistoryEntries(entries: HistoryEntry[]): ReanchorResult {\n let replay = cloneEmptyReplayDocument();\n const rewritten: HistoryEntry[] = [];\n const details: ReanchorEntryDetail[] = [];\n let entriesRehashed = 0;\n let entriesPatchRepaired = 0;\n let convertedReplaceToAdd = 0;\n let skippedOps = 0;\n\n for (let index = 0; index < entries.length; index += 1) {\n const entry = entries[index];\n const beforeHash = replayHash(replay);\n const strict = tryApplyReplayPatch(replay, entry.patch);\n\n let next: ReplayDocument;\n let outPatch: HistoryPatchOp[];\n let patchRepaired = false;\n let entryConverted = 0;\n let entrySkipped = 0;\n\n if (strict.ok) {\n next = strict.document;\n outPatch = entry.patch;\n } else {\n const lenient = lenientApplyReplayPatch(replay, entry.patch);\n next = lenient.document;\n outPatch = jsonPatch.compare(replay, next) as HistoryPatchOp[];\n patchRepaired = true;\n entryConverted = lenient.convertedReplaceToAdd;\n entrySkipped = lenient.skippedOps;\n convertedReplaceToAdd += entryConverted;\n skippedOps += entrySkipped;\n entriesPatchRepaired += 1;\n }\n\n const afterHash = replayHash(next);\n const rehashed = beforeHash !== entry.before_hash || afterHash !== entry.after_hash;\n if (rehashed) {\n entriesRehashed += 1;\n }\n\n rewritten.push({\n ...entry,\n patch: outPatch,\n before_hash: beforeHash,\n after_hash: afterHash,\n });\n details.push({\n index: index + 1,\n rehashed,\n patch_repaired: patchRepaired,\n converted_replace_to_add: entryConverted,\n skipped_ops: entrySkipped,\n });\n replay = next;\n }\n\n return {\n entries: rewritten,\n finalDocument: replay,\n entriesRehashed,\n entriesPatchRepaired,\n convertedReplaceToAdd,\n skippedOps,\n details,\n };\n}\n\nexport function historyEntriesToRaw(entries: HistoryEntry[]): string {\n if (entries.length === 0) {\n return \"\";\n }\n return `${entries.map((entry) => JSON.stringify(entry)).join(\"\\n\")}\\n`;\n}\n"],"names":[],"mappings":"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","debugId":"9f6d7165-e26e-5815-9ac5-aad4ce4d3877"}
|
package/dist/core/item/id.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f427a735-ffab-5a1c-b4cf-7069624a58cd")}catch(e){}}();
|
|
1
3
|
import crypto from "node:crypto";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
import { TYPE_TO_FOLDER } from "../shared/constants.js";
|
|
@@ -58,4 +60,5 @@ export async function generateItemId(pmRoot, prefix) {
|
|
|
58
60
|
}
|
|
59
61
|
throw new Error(`Unable to generate unique id after ${attempts} attempts`);
|
|
60
62
|
}
|
|
61
|
-
//# sourceMappingURL=id.js.map
|
|
63
|
+
//# sourceMappingURL=id.js.map
|
|
64
|
+
//# debugId=f427a735-ffab-5a1c-b4cf-7069624a58cd
|
package/dist/core/item/id.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id.js","sourceRoot":"/","
|
|
1
|
+
{"version":3,"file":"id.js","sources":["core/item/id.ts"],"sourceRoot":"/","sourcesContent":["import crypto from \"node:crypto\";\nimport path from \"node:path\";\nimport { TYPE_TO_FOLDER } from \"../shared/constants.js\";\nimport { pathExists } from \"../fs/fs-utils.js\";\n\nexport function normalizePrefix(input: string | undefined): string {\n const normalized = (input ?? \"\").trim().toLowerCase();\n if (!normalized) return \"pm-\";\n return normalized.endsWith(\"-\") ? normalized : `${normalized}-`;\n}\n\nexport function normalizeRawItemId(input: string): string {\n let normalized = input.trim().toLowerCase();\n if (normalized.startsWith(\"#\")) {\n normalized = normalized.slice(1);\n }\n return normalized;\n}\n\nexport function normalizeItemId(input: string, prefix: string): string {\n const canonicalPrefix = normalizePrefix(prefix);\n const normalized = normalizeRawItemId(input);\n if (normalized.startsWith(canonicalPrefix)) {\n return normalized;\n }\n return `${canonicalPrefix}${normalized}`;\n}\n\nfunction randomToken(length: number): string {\n const bytes = crypto.randomBytes(length);\n let token = \"\";\n for (const byte of bytes) {\n token += (byte % 36).toString(36);\n }\n return token;\n}\n\nasync function idExists(pmRoot: string, id: string): Promise<boolean> {\n const checks = Object.values(TYPE_TO_FOLDER).flatMap((folder) => [\n path.join(pmRoot, folder, `${id}.md`),\n path.join(pmRoot, folder, `${id}.toon`),\n ]);\n for (const target of checks) {\n if (await pathExists(target)) {\n return true;\n }\n }\n return false;\n}\n\nexport async function generateItemId(pmRoot: string, prefix: string): Promise<string> {\n let tokenLength = 4;\n let attempts = 0;\n\n while (tokenLength <= 10) {\n for (let i = 0; i < 32; i += 1) {\n const id = `${normalizePrefix(prefix)}${randomToken(tokenLength)}`;\n if (!(await idExists(pmRoot, id))) {\n return id;\n }\n attempts += 1;\n }\n tokenLength += 1;\n }\n\n throw new Error(`Unable to generate unique id after ${attempts} attempts`);\n}\n"],"names":[],"mappings":"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","debugId":"f427a735-ffab-5a1c-b4cf-7069624a58cd"}
|
package/dist/core/item/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5bf96e1c-d6d4-5402-b212-19cd1ea27587")}catch(e){}}();
|
|
1
3
|
export * from "./id.js";
|
|
2
4
|
export * from "./item-format.js";
|
|
3
5
|
export * from "./parse.js";
|
|
4
6
|
export * from "./type-registry.js";
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
8
|
+
//# debugId=5bf96e1c-d6d4-5402-b212-19cd1ea27587
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","sources":["core/item/index.ts"],"sourceRoot":"/","sourcesContent":["export * from \"./id.js\";\nexport * from \"./item-format.js\";\nexport * from \"./parse.js\";\nexport * from \"./type-registry.js\";\n"],"names":[],"mappings":";;AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC","debugId":"5bf96e1c-d6d4-5402-b212-19cd1ea27587"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7ce34b61-0ca0-51e3-8969-50ee0dbe020b")}catch(e){}}();
|
|
3
|
+
import { encode as encodeToon } from "@toon-format/toon";
|
|
4
|
+
import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RECURRENCE_FREQUENCY_VALUES, RECURRENCE_WEEKDAY_VALUES, STATUS_VALUES, weekdayOrderIndex, } from "../../types/index.js";
|
|
3
5
|
import { coerceRuntimeFieldValue } from "../schema/runtime-field-values.js";
|
|
4
6
|
import { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, } from "../schema/runtime-schema.js";
|
|
5
7
|
import { normalizeStatusInput } from "./status.js";
|
|
8
|
+
import { decodeToonItemContent } from "./toon-decode.js";
|
|
6
9
|
import { EXIT_CODE, FRONT_MATTER_KEY_ORDER } from "../shared/constants.js";
|
|
7
10
|
import { findFirstMergeConflictMarker } from "../shared/conflict-markers.js";
|
|
8
11
|
import { PmCliError } from "../shared/errors.js";
|
|
@@ -40,9 +43,6 @@ function runtimeFieldRequiredForType(definition, typeName) {
|
|
|
40
43
|
}
|
|
41
44
|
return definition.required_types.map((value) => value.toLowerCase()).includes(typeName.trim().toLowerCase());
|
|
42
45
|
}
|
|
43
|
-
function weekdayOrderIndex(value) {
|
|
44
|
-
return RECURRENCE_WEEKDAY_VALUES.indexOf(value);
|
|
45
|
-
}
|
|
46
46
|
function validationError(message) {
|
|
47
47
|
throw new PmCliError(`Invalid item front matter: ${message}`, EXIT_CODE.GENERIC_FAILURE);
|
|
48
48
|
}
|
|
@@ -456,7 +456,9 @@ function sortTests(values) {
|
|
|
456
456
|
command: value.command?.trim() || undefined,
|
|
457
457
|
path: value.path ? normalizePathValue(value.path) : undefined,
|
|
458
458
|
scope: value.scope,
|
|
459
|
-
timeout_seconds: value.timeout_seconds
|
|
459
|
+
timeout_seconds: typeof value.timeout_seconds === "number" && Number.isFinite(value.timeout_seconds) && value.timeout_seconds > 0
|
|
460
|
+
? value.timeout_seconds
|
|
461
|
+
: undefined,
|
|
460
462
|
pm_context_mode: (() => {
|
|
461
463
|
const normalized = value.pm_context_mode?.trim().toLowerCase();
|
|
462
464
|
if (!normalized || !LINKED_TEST_PM_CONTEXT_MODE_VALUES.has(normalized)) {
|
|
@@ -573,6 +575,232 @@ function sortDocs(values) {
|
|
|
573
575
|
return (a.note ?? "").localeCompare(b.note ?? "");
|
|
574
576
|
});
|
|
575
577
|
}
|
|
578
|
+
function trimStringOrUndefined(value) {
|
|
579
|
+
if (typeof value !== "string")
|
|
580
|
+
return undefined;
|
|
581
|
+
const trimmed = value.trim();
|
|
582
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
583
|
+
}
|
|
584
|
+
function normalizePlanStepLinks(value) {
|
|
585
|
+
if (!Array.isArray(value))
|
|
586
|
+
return undefined;
|
|
587
|
+
const out = [];
|
|
588
|
+
for (const entry of value) {
|
|
589
|
+
if (entry === null || typeof entry !== "object")
|
|
590
|
+
continue;
|
|
591
|
+
const record = entry;
|
|
592
|
+
const id = trimStringOrUndefined(record.id);
|
|
593
|
+
const kind = trimStringOrUndefined(record.kind);
|
|
594
|
+
if (!id || !kind)
|
|
595
|
+
continue;
|
|
596
|
+
const link = { id, kind: kind };
|
|
597
|
+
const note = trimStringOrUndefined(record.note);
|
|
598
|
+
if (note)
|
|
599
|
+
link.note = note;
|
|
600
|
+
if (record.required_before_step === true)
|
|
601
|
+
link.required_before_step = true;
|
|
602
|
+
out.push(link);
|
|
603
|
+
}
|
|
604
|
+
return out.length > 0 ? out : undefined;
|
|
605
|
+
}
|
|
606
|
+
function normalizePlanStepFiles(value) {
|
|
607
|
+
if (!Array.isArray(value))
|
|
608
|
+
return undefined;
|
|
609
|
+
const out = [];
|
|
610
|
+
for (const entry of value) {
|
|
611
|
+
if (entry === null || typeof entry !== "object")
|
|
612
|
+
continue;
|
|
613
|
+
const record = entry;
|
|
614
|
+
const path = trimStringOrUndefined(record.path);
|
|
615
|
+
if (!path)
|
|
616
|
+
continue;
|
|
617
|
+
const file = { path: normalizePathValue(path) };
|
|
618
|
+
if (record.scope === "project" || record.scope === "global")
|
|
619
|
+
file.scope = record.scope;
|
|
620
|
+
const note = trimStringOrUndefined(record.note);
|
|
621
|
+
if (note)
|
|
622
|
+
file.note = note;
|
|
623
|
+
out.push(file);
|
|
624
|
+
}
|
|
625
|
+
return out.length > 0 ? out : undefined;
|
|
626
|
+
}
|
|
627
|
+
function normalizePlanStepTests(value) {
|
|
628
|
+
if (!Array.isArray(value))
|
|
629
|
+
return undefined;
|
|
630
|
+
const out = [];
|
|
631
|
+
for (const entry of value) {
|
|
632
|
+
if (entry === null || typeof entry !== "object")
|
|
633
|
+
continue;
|
|
634
|
+
const record = entry;
|
|
635
|
+
const command = trimStringOrUndefined(record.command);
|
|
636
|
+
const path = trimStringOrUndefined(record.path);
|
|
637
|
+
if (!command && !path)
|
|
638
|
+
continue;
|
|
639
|
+
const test = {};
|
|
640
|
+
if (command)
|
|
641
|
+
test.command = command;
|
|
642
|
+
if (path)
|
|
643
|
+
test.path = normalizePathValue(path);
|
|
644
|
+
const note = trimStringOrUndefined(record.note);
|
|
645
|
+
if (note)
|
|
646
|
+
test.note = note;
|
|
647
|
+
out.push(test);
|
|
648
|
+
}
|
|
649
|
+
return out.length > 0 ? out : undefined;
|
|
650
|
+
}
|
|
651
|
+
function normalizePlanStepDocs(value) {
|
|
652
|
+
if (!Array.isArray(value))
|
|
653
|
+
return undefined;
|
|
654
|
+
const out = [];
|
|
655
|
+
for (const entry of value) {
|
|
656
|
+
if (entry === null || typeof entry !== "object")
|
|
657
|
+
continue;
|
|
658
|
+
const record = entry;
|
|
659
|
+
const path = trimStringOrUndefined(record.path);
|
|
660
|
+
if (!path)
|
|
661
|
+
continue;
|
|
662
|
+
const doc = { path: normalizePathValue(path) };
|
|
663
|
+
if (record.scope === "project" || record.scope === "global")
|
|
664
|
+
doc.scope = record.scope;
|
|
665
|
+
const note = trimStringOrUndefined(record.note);
|
|
666
|
+
if (note)
|
|
667
|
+
doc.note = note;
|
|
668
|
+
out.push(doc);
|
|
669
|
+
}
|
|
670
|
+
return out.length > 0 ? out : undefined;
|
|
671
|
+
}
|
|
672
|
+
function normalizePlanSteps(value) {
|
|
673
|
+
if (!Array.isArray(value))
|
|
674
|
+
return undefined;
|
|
675
|
+
const out = [];
|
|
676
|
+
for (const entry of value) {
|
|
677
|
+
if (entry === null || typeof entry !== "object")
|
|
678
|
+
continue;
|
|
679
|
+
const record = entry;
|
|
680
|
+
const id = trimStringOrUndefined(record.id);
|
|
681
|
+
const title = trimStringOrUndefined(record.title);
|
|
682
|
+
const status = trimStringOrUndefined(record.status);
|
|
683
|
+
const orderRaw = record.order;
|
|
684
|
+
const order = typeof orderRaw === "number" && Number.isFinite(orderRaw) ? orderRaw : Number(orderRaw);
|
|
685
|
+
if (!id || !title || !status || !Number.isFinite(order))
|
|
686
|
+
continue;
|
|
687
|
+
const created_at = typeof record.created_at === "string" ? record.created_at : "";
|
|
688
|
+
const updated_at = typeof record.updated_at === "string" ? record.updated_at : "";
|
|
689
|
+
if (!created_at || !updated_at)
|
|
690
|
+
continue;
|
|
691
|
+
const step = {
|
|
692
|
+
id,
|
|
693
|
+
order,
|
|
694
|
+
title,
|
|
695
|
+
status: status,
|
|
696
|
+
created_at,
|
|
697
|
+
updated_at,
|
|
698
|
+
};
|
|
699
|
+
const body = trimStringOrUndefined(record.body);
|
|
700
|
+
if (body)
|
|
701
|
+
step.body = body;
|
|
702
|
+
const owner = trimStringOrUndefined(record.owner);
|
|
703
|
+
if (owner)
|
|
704
|
+
step.owner = owner;
|
|
705
|
+
const evidence = trimStringOrUndefined(record.evidence);
|
|
706
|
+
if (evidence)
|
|
707
|
+
step.evidence = evidence;
|
|
708
|
+
const blockedReason = trimStringOrUndefined(record.blocked_reason);
|
|
709
|
+
if (blockedReason)
|
|
710
|
+
step.blocked_reason = blockedReason;
|
|
711
|
+
const supersededBy = trimStringOrUndefined(record.superseded_by);
|
|
712
|
+
if (supersededBy)
|
|
713
|
+
step.superseded_by = supersededBy;
|
|
714
|
+
const completedAt = typeof record.completed_at === "string" ? record.completed_at : undefined;
|
|
715
|
+
if (completedAt && completedAt.length > 0)
|
|
716
|
+
step.completed_at = completedAt;
|
|
717
|
+
const links = normalizePlanStepLinks(record.linked_items);
|
|
718
|
+
if (links)
|
|
719
|
+
step.linked_items = links;
|
|
720
|
+
const files = normalizePlanStepFiles(record.files);
|
|
721
|
+
if (files)
|
|
722
|
+
step.files = files;
|
|
723
|
+
const tests = normalizePlanStepTests(record.tests);
|
|
724
|
+
if (tests)
|
|
725
|
+
step.tests = tests;
|
|
726
|
+
const docs = normalizePlanStepDocs(record.docs);
|
|
727
|
+
if (docs)
|
|
728
|
+
step.docs = docs;
|
|
729
|
+
out.push(step);
|
|
730
|
+
}
|
|
731
|
+
out.sort((left, right) => left.order - right.order);
|
|
732
|
+
return out.length > 0 ? out : undefined;
|
|
733
|
+
}
|
|
734
|
+
function normalizePlanDecisions(value) {
|
|
735
|
+
if (!Array.isArray(value))
|
|
736
|
+
return undefined;
|
|
737
|
+
const out = [];
|
|
738
|
+
for (const entry of value) {
|
|
739
|
+
if (entry === null || typeof entry !== "object")
|
|
740
|
+
continue;
|
|
741
|
+
const record = entry;
|
|
742
|
+
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
743
|
+
const author = typeof record.author === "string" ? record.author : "";
|
|
744
|
+
const decision = trimStringOrUndefined(record.decision);
|
|
745
|
+
if (!ts || !author || !decision)
|
|
746
|
+
continue;
|
|
747
|
+
const item = { ts, author, decision };
|
|
748
|
+
const rationale = trimStringOrUndefined(record.rationale);
|
|
749
|
+
if (rationale)
|
|
750
|
+
item.rationale = rationale;
|
|
751
|
+
const evidence = trimStringOrUndefined(record.evidence);
|
|
752
|
+
if (evidence)
|
|
753
|
+
item.evidence = evidence;
|
|
754
|
+
const stepId = trimStringOrUndefined(record.step_id);
|
|
755
|
+
if (stepId)
|
|
756
|
+
item.step_id = stepId;
|
|
757
|
+
out.push(item);
|
|
758
|
+
}
|
|
759
|
+
return out.length > 0 ? out : undefined;
|
|
760
|
+
}
|
|
761
|
+
function normalizePlanDiscoveries(value) {
|
|
762
|
+
if (!Array.isArray(value))
|
|
763
|
+
return undefined;
|
|
764
|
+
const out = [];
|
|
765
|
+
for (const entry of value) {
|
|
766
|
+
if (entry === null || typeof entry !== "object")
|
|
767
|
+
continue;
|
|
768
|
+
const record = entry;
|
|
769
|
+
const ts = typeof record.ts === "string" ? record.ts : "";
|
|
770
|
+
const author = typeof record.author === "string" ? record.author : "";
|
|
771
|
+
const text = trimStringOrUndefined(record.text);
|
|
772
|
+
if (!ts || !author || !text)
|
|
773
|
+
continue;
|
|
774
|
+
const item = { ts, author, text };
|
|
775
|
+
const stepId = trimStringOrUndefined(record.step_id);
|
|
776
|
+
if (stepId)
|
|
777
|
+
item.step_id = stepId;
|
|
778
|
+
out.push(item);
|
|
779
|
+
}
|
|
780
|
+
return out.length > 0 ? out : undefined;
|
|
781
|
+
}
|
|
782
|
+
function normalizePlanValidation(value) {
|
|
783
|
+
if (!Array.isArray(value))
|
|
784
|
+
return undefined;
|
|
785
|
+
const out = [];
|
|
786
|
+
for (const entry of value) {
|
|
787
|
+
if (entry === null || typeof entry !== "object")
|
|
788
|
+
continue;
|
|
789
|
+
const record = entry;
|
|
790
|
+
const text = trimStringOrUndefined(record.text);
|
|
791
|
+
if (!text)
|
|
792
|
+
continue;
|
|
793
|
+
const item = { text };
|
|
794
|
+
const command = trimStringOrUndefined(record.command);
|
|
795
|
+
if (command)
|
|
796
|
+
item.command = command;
|
|
797
|
+
const expected = trimStringOrUndefined(record.expected);
|
|
798
|
+
if (expected)
|
|
799
|
+
item.expected = expected;
|
|
800
|
+
out.push(item);
|
|
801
|
+
}
|
|
802
|
+
return out.length > 0 ? out : undefined;
|
|
803
|
+
}
|
|
576
804
|
function normalizeTypeOptions(values) {
|
|
577
805
|
if (!values) {
|
|
578
806
|
return undefined;
|
|
@@ -683,6 +911,14 @@ export function normalizeFrontMatter(frontMatter, options = {}) {
|
|
|
683
911
|
regression: frontMatter.regression,
|
|
684
912
|
customer_impact: frontMatter.customer_impact?.trim() || undefined,
|
|
685
913
|
close_reason: frontMatter.close_reason || undefined,
|
|
914
|
+
plan_mode: trimStringOrUndefined(frontMatter.plan_mode),
|
|
915
|
+
plan_scope: trimStringOrUndefined(frontMatter.plan_scope),
|
|
916
|
+
plan_harness: trimStringOrUndefined(frontMatter.plan_harness),
|
|
917
|
+
plan_resume_context: trimStringOrUndefined(frontMatter.plan_resume_context),
|
|
918
|
+
plan_steps: normalizePlanSteps(frontMatter.plan_steps),
|
|
919
|
+
plan_decisions: normalizePlanDecisions(frontMatter.plan_decisions),
|
|
920
|
+
plan_discoveries: normalizePlanDiscoveries(frontMatter.plan_discoveries),
|
|
921
|
+
plan_validation: normalizePlanValidation(frontMatter.plan_validation),
|
|
686
922
|
};
|
|
687
923
|
const sourceRecord = frontMatter;
|
|
688
924
|
for (const [key, value] of Object.entries(sourceRecord)) {
|
|
@@ -821,7 +1057,12 @@ function parseJsonMarkdownItemDocument(content, runtimeContext, options = {}) {
|
|
|
821
1057
|
function parseToonItemDocument(content, runtimeContext, options = {}) {
|
|
822
1058
|
let parsed;
|
|
823
1059
|
try {
|
|
824
|
-
|
|
1060
|
+
// decodeToonItemContent transparently recovers documents that the upstream
|
|
1061
|
+
// strict decoder rejects (bracketed-token-then-colon inside a quoted value;
|
|
1062
|
+
// see toon-decode.ts). The recovery is lossless, so it stays silent rather
|
|
1063
|
+
// than emitting a per-read warning that would perpetually flip pm health
|
|
1064
|
+
// red for legacy files. The behavior is pinned by toon-decode.spec.ts.
|
|
1065
|
+
parsed = decodeToonItemContent(content).value;
|
|
825
1066
|
}
|
|
826
1067
|
catch {
|
|
827
1068
|
validationError("TOON item document is not valid TOON");
|
|
@@ -887,4 +1128,5 @@ export function canonicalDocument(document, options = {}) {
|
|
|
887
1128
|
body: normalizeBody(document.body ?? ""),
|
|
888
1129
|
};
|
|
889
1130
|
}
|
|
890
|
-
//# sourceMappingURL=item-format.js.map
|
|
1131
|
+
//# sourceMappingURL=item-format.js.map
|
|
1132
|
+
//# debugId=7ce34b61-0ca0-51e3-8969-50ee0dbe020b
|