@unbrained/pm-cli 2026.5.18 → 2026.5.27
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/CHANGELOG.md +953 -472
- package/README.md +4 -11
- package/dist/cli/bootstrap-args.d.ts +18 -1
- package/dist/cli/bootstrap-args.js +143 -3
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commander-usage.js +147 -10
- package/dist/cli/commander-usage.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 -8
- package/dist/cli/commands/append.js.map +1 -1
- package/dist/cli/commands/calendar.js +3 -6
- package/dist/cli/commands/calendar.js.map +1 -1
- package/dist/cli/commands/claim.js +15 -24
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.js +63 -10
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/comments.d.ts +5 -0
- package/dist/cli/commands/comments.js +27 -117
- package/dist/cli/commands/comments.js.map +1 -1
- package/dist/cli/commands/completion.d.ts +2 -2
- package/dist/cli/commands/completion.js +203 -63
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/config.d.ts +1 -1
- package/dist/cli/commands/config.js +82 -4
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/context.js +4 -10
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/contracts.js +168 -36
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.js +53 -313
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/dedupe-audit.js +7 -4
- 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 -9
- package/dist/cli/commands/delete.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +2 -12
- package/dist/cli/commands/docs.js +8 -316
- 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/bundled-catalog.d.ts +14 -0
- package/dist/cli/commands/extension/bundled-catalog.js +268 -0
- package/dist/cli/commands/extension/bundled-catalog.js.map +1 -0
- package/dist/cli/commands/extension/doctor.d.ts +31 -0
- package/dist/cli/commands/extension/doctor.js +345 -0
- package/dist/cli/commands/extension/doctor.js.map +1 -0
- package/dist/cli/commands/extension/install-sources.d.ts +37 -0
- package/dist/cli/commands/extension/install-sources.js +384 -0
- package/dist/cli/commands/extension/install-sources.js.map +1 -0
- package/dist/cli/commands/extension/managed-state.d.ts +48 -0
- package/dist/cli/commands/extension/managed-state.js +172 -0
- package/dist/cli/commands/extension/managed-state.js.map +1 -0
- package/dist/cli/commands/extension/scaffold.d.ts +14 -0
- package/dist/cli/commands/extension/scaffold.js +169 -0
- package/dist/cli/commands/extension/scaffold.js.map +1 -0
- package/dist/cli/commands/extension/shared.d.ts +14 -0
- package/dist/cli/commands/extension/shared.js +106 -0
- package/dist/cli/commands/extension/shared.js.map +1 -0
- package/dist/cli/commands/extension.d.ts +37 -68
- package/dist/cli/commands/extension.js +157 -1319
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.d.ts +1 -12
- package/dist/cli/commands/files.js +14 -318
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/gc.js +17 -4
- package/dist/cli/commands/gc.js.map +1 -1
- package/dist/cli/commands/get.d.ts +3 -2
- package/dist/cli/commands/get.js +52 -9
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/health.d.ts +10 -0
- package/dist/cli/commands/health.js +269 -76
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-redact.d.ts +8 -0
- package/dist/cli/commands/history-redact.js +35 -113
- package/dist/cli/commands/history-redact.js.map +1 -1
- package/dist/cli/commands/history-repair.d.ts +33 -0
- package/dist/cli/commands/history-repair.js +172 -0
- package/dist/cli/commands/history-repair.js.map +1 -0
- package/dist/cli/commands/history.d.ts +4 -4
- package/dist/cli/commands/history.js +10 -88
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/index.d.ts +3 -1
- package/dist/cli/commands/index.js +5 -3
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +28 -0
- package/dist/cli/commands/init.js +23 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/learnings.js +20 -119
- package/dist/cli/commands/learnings.js.map +1 -1
- package/dist/cli/commands/legacy-none-tokens.d.ts +3 -0
- package/dist/cli/commands/legacy-none-tokens.js +39 -0
- package/dist/cli/commands/legacy-none-tokens.js.map +1 -0
- package/dist/cli/commands/linked-artifacts.d.ts +96 -0
- package/dist/cli/commands/linked-artifacts.js +335 -0
- package/dist/cli/commands/linked-artifacts.js.map +1 -0
- 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/linked-test-parsers.d.ts +28 -0
- package/dist/cli/commands/linked-test-parsers.js +192 -0
- package/dist/cli/commands/linked-test-parsers.js.map +1 -0
- package/dist/cli/commands/list.js +49 -24
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/normalize.js +4 -3
- package/dist/cli/commands/normalize.js.map +1 -1
- package/dist/cli/commands/notes.js +20 -119
- package/dist/cli/commands/notes.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +3 -0
- package/dist/cli/commands/plan.js +184 -22
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/recurrence-parsers.d.ts +26 -0
- package/dist/cli/commands/recurrence-parsers.js +98 -0
- package/dist/cli/commands/recurrence-parsers.js.map +1 -0
- package/dist/cli/commands/restore.js +24 -56
- 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 +154 -42
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/templates.d.ts +4 -0
- package/dist/cli/commands/templates.js +89 -17
- package/dist/cli/commands/templates.js.map +1 -1
- package/dist/cli/commands/test/linked-command-detection.d.ts +37 -0
- package/dist/cli/commands/test/linked-command-detection.js +200 -0
- package/dist/cli/commands/test/linked-command-detection.js.map +1 -0
- package/dist/cli/commands/test-all.js +4 -8
- package/dist/cli/commands/test-all.js.map +1 -1
- package/dist/cli/commands/test.d.ts +2 -2
- package/dist/cli/commands/test.js +12 -357
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.js +6 -9
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.js +167 -401
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +3 -1
- package/dist/cli/commands/validate.js +23 -71
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/error-guidance.d.ts +1 -0
- package/dist/cli/error-guidance.js +100 -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 +2 -13
- 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 +106 -7
- package/dist/cli/extension-command-options.js.map +1 -1
- package/dist/cli/help-content.d.ts +0 -1
- package/dist/cli/help-content.js +13 -9
- 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 +33 -3
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.d.ts +11 -0
- package/dist/cli/main.js +109 -55
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.d.ts +5 -2
- package/dist/cli/register-list-query.js +254 -192
- 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 +247 -64
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +17 -12
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +33 -16
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.d.ts +0 -2
- package/dist/cli/registration-helpers.js +14 -40
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli.js +25 -4
- package/dist/cli.js.map +1 -1
- package/dist/core/config/positional-value.d.ts +44 -0
- package/dist/core/config/positional-value.js +109 -0
- package/dist/core/config/positional-value.js.map +1 -0
- package/dist/core/extensions/extension-capability-aliases.d.ts +14 -0
- package/dist/core/extensions/extension-capability-aliases.js +159 -0
- package/dist/core/extensions/extension-capability-aliases.js.map +1 -0
- package/dist/core/extensions/extension-hook-runtime.d.ts +13 -0
- package/dist/core/extensions/extension-hook-runtime.js +414 -0
- package/dist/core/extensions/extension-hook-runtime.js.map +1 -0
- package/dist/core/extensions/extension-policy.d.ts +69 -0
- package/dist/core/extensions/extension-policy.js +481 -0
- package/dist/core/extensions/extension-policy.js.map +1 -0
- package/dist/core/extensions/extension-registries.d.ts +8 -0
- package/dist/core/extensions/extension-registries.js +52 -0
- package/dist/core/extensions/extension-registries.js.map +1 -0
- package/dist/core/extensions/extension-runtime-helpers.d.ts +6 -0
- package/dist/core/extensions/extension-runtime-helpers.js +29 -0
- package/dist/core/extensions/extension-runtime-helpers.js.map +1 -0
- package/dist/core/extensions/extension-types.d.ts +13 -39
- package/dist/core/extensions/extension-types.js +34 -2
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +7 -1
- package/dist/core/extensions/index.js +11 -14
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +4 -22
- package/dist/core/extensions/loader.js +23 -1146
- package/dist/core/extensions/loader.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 +22 -0
- package/dist/core/history/drift-scan.js +149 -0
- package/dist/core/history/drift-scan.js.map +1 -0
- package/dist/core/history/history-rewrite.d.ts +43 -0
- package/dist/core/history/history-rewrite.js +48 -0
- package/dist/core/history/history-rewrite.js.map +1 -0
- package/dist/core/history/history.js +5 -4
- package/dist/core/history/history.js.map +1 -1
- package/dist/core/history/replay.d.ts +82 -0
- package/dist/core/history/replay.js +250 -0
- package/dist/core/history/replay.js.map +1 -0
- package/dist/core/item/item-format.js +11 -8
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/core/item/item-record.d.ts +19 -0
- package/dist/core/item/item-record.js +24 -0
- package/dist/core/item/item-record.js.map +1 -0
- 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/parse.js +3 -2
- 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/status.d.ts +14 -1
- package/dist/core/item/status.js +22 -2
- 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 +13 -84
- package/dist/core/item/type-registry.js.map +1 -1
- package/dist/core/output/mutation-projection.d.ts +31 -0
- package/dist/core/output/mutation-projection.js +103 -0
- package/dist/core/output/mutation-projection.js.map +1 -0
- package/dist/core/output/output.d.ts +2 -0
- package/dist/core/output/output.js +5 -3
- package/dist/core/output/output.js.map +1 -1
- package/dist/core/packages/manifest.js +3 -9
- package/dist/core/packages/manifest.js.map +1 -1
- 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-schema.d.ts +2 -1
- package/dist/core/schema/runtime-schema.js +17 -45
- package/dist/core/schema/runtime-schema.js.map +1 -1
- package/dist/core/search/semantic-defaults.js +3 -3
- package/dist/core/search/semantic-defaults.js.map +1 -1
- package/dist/core/search/vector-stores.js +46 -9
- package/dist/core/search/vector-stores.js.map +1 -1
- package/dist/core/sentry/helpers.d.ts +1 -1
- package/dist/core/sentry/helpers.js +20 -3
- package/dist/core/sentry/helpers.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.d.ts +1 -0
- package/dist/core/shared/command-types.js +2 -2
- package/dist/core/shared/command-types.js.map +1 -1
- package/dist/core/shared/constants.d.ts +10 -1
- package/dist/core/shared/constants.js +56 -58
- package/dist/core/shared/constants.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/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.d.ts +23 -0
- package/dist/core/shared/primitives.js +39 -2
- package/dist/core/shared/primitives.js.map +1 -1
- package/dist/core/shared/text-normalization.d.ts +0 -1
- package/dist/core/shared/text-normalization.js +2 -5
- package/dist/core/shared/text-normalization.js.map +1 -1
- package/dist/core/store/front-matter-cache.d.ts +16 -2
- package/dist/core/store/front-matter-cache.js +99 -33
- package/dist/core/store/front-matter-cache.js.map +1 -1
- package/dist/core/store/item-store.d.ts +2 -0
- package/dist/core/store/item-store.js +76 -110
- package/dist/core/store/item-store.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 +6 -343
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/runtime.js +5 -3
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/mcp/server.js +138 -39
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +20 -0
- package/dist/sdk/cli-contracts/enum-contracts.js +156 -0
- package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +14 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.js +243 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -0
- package/dist/sdk/cli-contracts/tool-parameter-tables.d.ts +11 -0
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +901 -0
- package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -0
- package/dist/sdk/cli-contracts.d.ts +18 -33
- package/dist/sdk/cli-contracts.js +96 -1238
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/package-import-adapters.d.ts +74 -0
- package/dist/sdk/package-import-adapters.js +186 -0
- package/dist/sdk/package-import-adapters.js.map +1 -0
- package/dist/sdk/package-runtime-options.d.ts +26 -0
- package/dist/sdk/package-runtime-options.js +71 -0
- package/dist/sdk/package-runtime-options.js.map +1 -0
- package/dist/sdk/runtime.d.ts +27 -1
- package/dist/sdk/runtime.js +48 -3
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.js +10 -2
- package/dist/types.js.map +1 -1
- package/docs/AGENT_GUIDE.md +13 -11
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/CLAUDE_CODE_PLUGIN.md +5 -28
- package/docs/CODEX_PLUGIN.md +5 -5
- package/docs/COMMANDS.md +58 -9
- package/docs/CONFIGURATION.md +16 -1
- package/docs/EXTENSIONS.md +4 -63
- package/docs/RELEASING.md +12 -8
- package/docs/SDK.md +11 -2
- package/marketplace.json +7 -3
- package/package.json +18 -14
- package/packages/pm-beads/extensions/beads/index.js +2 -49
- package/packages/pm-beads/extensions/beads/index.ts +2 -54
- package/packages/pm-beads/extensions/beads/runtime-loader.js +86 -0
- package/packages/pm-beads/extensions/beads/runtime-loader.ts +88 -0
- package/packages/pm-beads/extensions/beads/runtime.js +26 -115
- package/packages/pm-beads/extensions/beads/runtime.ts +33 -132
- package/packages/pm-calendar/README.md +3 -1
- package/packages/pm-calendar/extensions/calendar/index.js +66 -2
- package/packages/pm-calendar/extensions/calendar/index.ts +71 -2
- package/packages/pm-calendar/extensions/calendar/runtime.js +1 -0
- package/packages/pm-calendar/extensions/calendar/runtime.ts +1 -0
- package/packages/pm-governance-audit/extensions/governance-audit/runtime.js +14 -41
- package/packages/pm-governance-audit/extensions/governance-audit/runtime.ts +25 -41
- package/packages/pm-guide-shell/extensions/guide-shell/runtime.js +10 -50
- package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +17 -50
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.js +8 -40
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.ts +10 -40
- package/packages/pm-search-advanced/README.md +8 -0
- package/packages/pm-search-advanced/extensions/search-advanced/index.js +75 -1
- package/packages/pm-search-advanced/extensions/search-advanced/index.ts +74 -0
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +58 -33
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +60 -33
- package/packages/pm-templates/extensions/templates/runtime.js +11 -202
- package/packages/pm-templates/extensions/templates/runtime.ts +38 -230
- package/packages/pm-todos/extensions/todos/index.js +3 -50
- package/packages/pm-todos/extensions/todos/index.ts +3 -55
- package/packages/pm-todos/extensions/todos/runtime-loader.js +86 -0
- package/packages/pm-todos/extensions/todos/runtime-loader.ts +88 -0
- package/packages/pm-todos/extensions/todos/runtime.js +24 -117
- package/packages/pm-todos/extensions/todos/runtime.ts +32 -129
- package/plugins/pm-claude/README.md +2 -2
- package/plugins/pm-claude/commands/pm-planner.md +1 -15
- package/plugins/pm-claude/scripts/pm-mcp-server.mjs +5 -2
- package/plugins/pm-claude/skills/pm-planner/SKILL.md +3 -21
- package/plugins/pm-codex/scripts/pm-mcp-server.mjs +15 -6
- package/plugins/pm-codex/skills/pm-native/SKILL.md +1 -13
- package/PRD.md +0 -1734
- package/dist/core/output/command-aware.d.ts +0 -1
- package/dist/core/output/command-aware.js +0 -397
- package/dist/core/output/command-aware.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
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]="
|
|
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]="10f962f6-810b-5b40-a073-b763d0b0d8b0")}catch(e){}}();
|
|
3
3
|
import { pathExists, removeFileIfExists, writeFileAtomic } from "../../core/fs/fs-utils.js";
|
|
4
4
|
import { appendHistoryEntry, createHistoryEntry } from "../../core/history/history.js";
|
|
5
5
|
import { generateItemId, normalizeItemId } from "../../core/item/id.js";
|
|
@@ -7,9 +7,11 @@ import { canonicalDocument, normalizeFrontMatter, serializeItemDocument } from "
|
|
|
7
7
|
import { normalizeParentReferenceValue, validateMissingParentReference, } from "../../core/item/parent-reference-policy.js";
|
|
8
8
|
import { validateSprintOrReleaseValue } from "../../core/item/sprint-release-format.js";
|
|
9
9
|
import { createStdinTokenResolver, parseCsvKv, parseOptionalNumber, parseTags } from "../../core/item/parse.js";
|
|
10
|
+
import { resolvePriority } from "../../core/item/priority.js";
|
|
10
11
|
import { normalizeStatusInput } from "../../core/item/status.js";
|
|
11
12
|
import { canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, } from "../../core/item/type-registry.js";
|
|
12
13
|
import { acquireLock } from "../../core/lock/lock.js";
|
|
14
|
+
import { buildInvalidTypeError } from "../../core/schema/item-types-file.js";
|
|
13
15
|
import { collectRuntimeCreateFieldValues } from "../../core/schema/runtime-field-values.js";
|
|
14
16
|
import { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, } from "../../core/schema/runtime-schema.js";
|
|
15
17
|
import { EXIT_CODE, FRONT_MATTER_KEY_ORDER } from "../../core/shared/constants.js";
|
|
@@ -21,12 +23,16 @@ import { locateItem } from "../../core/store/item-store.js";
|
|
|
21
23
|
import { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from "../../core/store/paths.js";
|
|
22
24
|
import { readSettings } from "../../core/store/settings.js";
|
|
23
25
|
import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
|
|
24
|
-
import {
|
|
26
|
+
import { resolveEventEndAt } from "./event-validation-messages.js";
|
|
27
|
+
import { assertNoLegacyNoneToken, assertNoLegacyNoneTokens, isLegacyNoneToken } from "./legacy-none-tokens.js";
|
|
28
|
+
import { parseLinkedTestAssertionEqualsMap, parseLinkedTestAssertionGteMap, parseLinkedTestBoolean, parseLinkedTestContextMode, parseLinkedTestEnvClear, parseLinkedTestEnvSet, parseLinkedTestMinLines, parseLinkedTestRegexList, parseLinkedTestStringList, } from "./linked-test-parsers.js";
|
|
29
|
+
import { looksLikeStructuredLinkedTestEntry, normalizeStructuredLinkedTestEntry } from "./linked-test-entry.js";
|
|
30
|
+
import { ensureEnumValue, parseEventBoolean, parseRecurrenceRule } from "./recurrence-parsers.js";
|
|
31
|
+
import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES, SCOPE_VALUES, } from "../../types/index.js";
|
|
25
32
|
const CREATE_MODE_VALUES = ["strict", "progressive"];
|
|
26
33
|
const SCHEDULE_CREATE_PRESET_VALUES = ["lightweight"];
|
|
27
34
|
const SCHEDULE_CREATE_PRESET_TYPES = new Set(["Reminder", "Meeting", "Event"]);
|
|
28
35
|
const LOG_SEED_ALLOWED_KEYS = new Set(["author", "created_at", "text"]);
|
|
29
|
-
const LEGACY_NONE_TOKENS = new Set(["none", "null"]);
|
|
30
36
|
const CREATE_UNSET_FIELD_DEFINITIONS = [
|
|
31
37
|
{ canonical: "tags", aliases: ["tags"], optionKey: "tags", frontMatterKey: "tags" },
|
|
32
38
|
{ canonical: "deadline", aliases: ["deadline"], optionKey: "deadline", frontMatterKey: "deadline" },
|
|
@@ -159,12 +165,6 @@ function buildInvalidLogSeedKeysMessage(optionName, unsupportedKeys) {
|
|
|
159
165
|
'(for example text="first,scope:project"), use markdown-style key/value input, ' +
|
|
160
166
|
`or pass ${optionName} - with piped stdin.`);
|
|
161
167
|
}
|
|
162
|
-
function ensureEnumValue(value, allowed, label) {
|
|
163
|
-
if (!allowed.includes(value)) {
|
|
164
|
-
throw new PmCliError(`Invalid ${label} value "${value}". Allowed: ${allowed.join(", ")}`, EXIT_CODE.USAGE);
|
|
165
|
-
}
|
|
166
|
-
return value;
|
|
167
|
-
}
|
|
168
168
|
function parseStatusValue(value, statusRegistry) {
|
|
169
169
|
const normalized = normalizeStatusInput(value, statusRegistry);
|
|
170
170
|
if (!normalized) {
|
|
@@ -183,30 +183,6 @@ function parseCreatedAt(value, currentIso) {
|
|
|
183
183
|
}
|
|
184
184
|
return new Date(parsed).toISOString();
|
|
185
185
|
}
|
|
186
|
-
function isLegacyNoneToken(value) {
|
|
187
|
-
if (value === undefined) {
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
return LEGACY_NONE_TOKENS.has(value.trim().toLowerCase());
|
|
191
|
-
}
|
|
192
|
-
function assertNoLegacyNoneToken(value, flag, replacementHint) {
|
|
193
|
-
if (!isLegacyNoneToken(value)) {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
const suffix = replacementHint ? ` ${replacementHint}` : "";
|
|
197
|
-
throw new PmCliError(`${flag} no longer accepts "none" or "null".${suffix}`.trim(), EXIT_CODE.USAGE);
|
|
198
|
-
}
|
|
199
|
-
function assertNoLegacyNoneTokens(values, flag, replacementHint) {
|
|
200
|
-
if (!values || values.length === 0) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
const hasLegacyToken = values.some((value) => isLegacyNoneToken(value));
|
|
204
|
-
if (!hasLegacyToken) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const suffix = replacementHint ? ` ${replacementHint}` : "";
|
|
208
|
-
throw new PmCliError(`${flag} no longer accepts "none" or "null".${suffix}`.trim(), EXIT_CODE.USAGE);
|
|
209
|
-
}
|
|
210
186
|
const CREATE_LEGACY_NONE_COLLECTION_NORMALIZERS = [
|
|
211
187
|
{ optionKey: "dep", clearFlagKey: "clearDeps", valueFlag: "--dep", clearFlag: "--clear-deps" },
|
|
212
188
|
{ optionKey: "comment", clearFlagKey: "clearComments", valueFlag: "--comment", clearFlag: "--clear-comments" },
|
|
@@ -316,9 +292,6 @@ function parseCreateUnsetTargets(raw, runtimeFieldRegistry) {
|
|
|
316
292
|
}
|
|
317
293
|
return { frontMatterKeys, optionKeys };
|
|
318
294
|
}
|
|
319
|
-
function weekdayOrderIndex(value) {
|
|
320
|
-
return RECURRENCE_WEEKDAY_VALUES.indexOf(value);
|
|
321
|
-
}
|
|
322
295
|
function parseDependencies(raw, nowValue, prefix) {
|
|
323
296
|
if (!raw || raw.length === 0)
|
|
324
297
|
return { values: undefined, explicitEmpty: false };
|
|
@@ -423,202 +396,14 @@ export function parseFiles(raw) {
|
|
|
423
396
|
});
|
|
424
397
|
return { values, explicitEmpty: false };
|
|
425
398
|
}
|
|
426
|
-
const LINKED_TEST_PROTECTED_ENV_KEYS = new Set(["PM_PATH", "PM_GLOBAL_PATH", "FORCE_COLOR"]);
|
|
427
|
-
const LINKED_TEST_ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
428
|
-
const LINKED_TEST_PM_CONTEXT_MODE_VALUES = ["schema", "tracker", "auto"];
|
|
429
|
-
function parseLinkedTestEnvSet(raw, optionName) {
|
|
430
|
-
const normalized = parseOptionalString(raw);
|
|
431
|
-
if (!normalized) {
|
|
432
|
-
return undefined;
|
|
433
|
-
}
|
|
434
|
-
const assignments = normalized
|
|
435
|
-
.split(/[;\n]/)
|
|
436
|
-
.map((entry) => entry.trim())
|
|
437
|
-
.filter((entry) => entry.length > 0);
|
|
438
|
-
if (assignments.length === 0) {
|
|
439
|
-
throw new PmCliError(`${optionName} env_set must include at least one KEY=VALUE assignment`, EXIT_CODE.USAGE);
|
|
440
|
-
}
|
|
441
|
-
const envSet = {};
|
|
442
|
-
for (const assignment of assignments) {
|
|
443
|
-
const separatorIndex = assignment.indexOf("=");
|
|
444
|
-
if (separatorIndex <= 0) {
|
|
445
|
-
throw new PmCliError(`${optionName} env_set entries must use KEY=VALUE and be separated by semicolons. Example: env_set=PORT=0;PLAYWRIGHT_BASE_URL=http://127.0.0.1:4173`, EXIT_CODE.USAGE);
|
|
446
|
-
}
|
|
447
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
448
|
-
const value = assignment.slice(separatorIndex + 1);
|
|
449
|
-
if (!LINKED_TEST_ENV_NAME_PATTERN.test(key)) {
|
|
450
|
-
throw new PmCliError(`${optionName} env_set key "${key}" is invalid`, EXIT_CODE.USAGE);
|
|
451
|
-
}
|
|
452
|
-
if (LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())) {
|
|
453
|
-
throw new PmCliError(`${optionName} env_set key "${key}" is reserved for sandbox safety`, EXIT_CODE.USAGE);
|
|
454
|
-
}
|
|
455
|
-
envSet[key] = value;
|
|
456
|
-
}
|
|
457
|
-
return Object.keys(envSet).length > 0 ? envSet : undefined;
|
|
458
|
-
}
|
|
459
|
-
function parseLinkedTestEnvClear(raw, optionName) {
|
|
460
|
-
const normalized = parseOptionalString(raw);
|
|
461
|
-
if (!normalized) {
|
|
462
|
-
return undefined;
|
|
463
|
-
}
|
|
464
|
-
const keys = [...new Set(normalized.split(/[;,\n]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0))];
|
|
465
|
-
if (keys.length === 0) {
|
|
466
|
-
throw new PmCliError(`${optionName} env_clear must include at least one environment variable name`, EXIT_CODE.USAGE);
|
|
467
|
-
}
|
|
468
|
-
for (const key of keys) {
|
|
469
|
-
if (!LINKED_TEST_ENV_NAME_PATTERN.test(key)) {
|
|
470
|
-
throw new PmCliError(`${optionName} env_clear key "${key}" is invalid`, EXIT_CODE.USAGE);
|
|
471
|
-
}
|
|
472
|
-
if (LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())) {
|
|
473
|
-
throw new PmCliError(`${optionName} env_clear key "${key}" is reserved for sandbox safety`, EXIT_CODE.USAGE);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
return keys;
|
|
477
|
-
}
|
|
478
|
-
function parseLinkedTestBoolean(raw, optionName, fieldLabel) {
|
|
479
|
-
const normalized = parseOptionalString(raw);
|
|
480
|
-
if (!normalized) {
|
|
481
|
-
return undefined;
|
|
482
|
-
}
|
|
483
|
-
const value = normalized.trim().toLowerCase();
|
|
484
|
-
if (value === "true" || value === "1" || value === "yes") {
|
|
485
|
-
return true;
|
|
486
|
-
}
|
|
487
|
-
if (value === "false" || value === "0" || value === "no") {
|
|
488
|
-
return false;
|
|
489
|
-
}
|
|
490
|
-
throw new PmCliError(`${optionName} ${fieldLabel} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
|
|
491
|
-
}
|
|
492
|
-
function parseLinkedTestContextMode(raw, optionName) {
|
|
493
|
-
const normalized = parseOptionalString(raw);
|
|
494
|
-
if (!normalized) {
|
|
495
|
-
return undefined;
|
|
496
|
-
}
|
|
497
|
-
const value = normalized.trim().toLowerCase();
|
|
498
|
-
if (LINKED_TEST_PM_CONTEXT_MODE_VALUES.includes(value)) {
|
|
499
|
-
return value;
|
|
500
|
-
}
|
|
501
|
-
throw new PmCliError(`${optionName} pm_context_mode must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`, EXIT_CODE.USAGE);
|
|
502
|
-
}
|
|
503
|
-
function parseLinkedTestStringList(raw) {
|
|
504
|
-
const normalized = parseOptionalString(raw);
|
|
505
|
-
if (!normalized) {
|
|
506
|
-
return undefined;
|
|
507
|
-
}
|
|
508
|
-
const values = [...new Set(normalized.split(/[;\n]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0))];
|
|
509
|
-
return values.length > 0 ? values : undefined;
|
|
510
|
-
}
|
|
511
|
-
function parseLinkedTestRegexList(raw, optionName, fieldLabel) {
|
|
512
|
-
const values = parseLinkedTestStringList(raw);
|
|
513
|
-
if (!values || values.length === 0) {
|
|
514
|
-
return undefined;
|
|
515
|
-
}
|
|
516
|
-
for (const pattern of values) {
|
|
517
|
-
try {
|
|
518
|
-
// Validate syntax early so malformed assertions fail at mutation time.
|
|
519
|
-
new RegExp(pattern, "m");
|
|
520
|
-
}
|
|
521
|
-
catch (error) {
|
|
522
|
-
throw new PmCliError(`${optionName} ${fieldLabel} includes invalid regex "${pattern}": ${error instanceof Error ? error.message : String(error)}`, EXIT_CODE.USAGE);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
return values;
|
|
526
|
-
}
|
|
527
|
-
function parseLinkedTestMinLines(raw, optionName) {
|
|
528
|
-
const normalized = parseOptionalString(raw);
|
|
529
|
-
if (!normalized) {
|
|
530
|
-
return undefined;
|
|
531
|
-
}
|
|
532
|
-
const parsed = parseOptionalNumber(normalized, "assert_stdout_min_lines");
|
|
533
|
-
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
534
|
-
throw new PmCliError(`${optionName} assert_stdout_min_lines must be an integer >= 0`, EXIT_CODE.USAGE);
|
|
535
|
-
}
|
|
536
|
-
return parsed;
|
|
537
|
-
}
|
|
538
|
-
function parseLinkedTestAssertionEqualsMap(raw, optionName) {
|
|
539
|
-
const normalized = parseOptionalString(raw);
|
|
540
|
-
if (!normalized) {
|
|
541
|
-
return undefined;
|
|
542
|
-
}
|
|
543
|
-
const assignments = normalized
|
|
544
|
-
.split(/[;\n]/)
|
|
545
|
-
.map((entry) => entry.trim())
|
|
546
|
-
.filter((entry) => entry.length > 0);
|
|
547
|
-
if (assignments.length === 0) {
|
|
548
|
-
throw new PmCliError(`${optionName} assert_json_field_equals must include at least one path=value assignment`, EXIT_CODE.USAGE);
|
|
549
|
-
}
|
|
550
|
-
const values = {};
|
|
551
|
-
for (const assignment of assignments) {
|
|
552
|
-
const separatorIndex = assignment.indexOf("=");
|
|
553
|
-
if (separatorIndex <= 0) {
|
|
554
|
-
throw new PmCliError(`${optionName} assert_json_field_equals entries must use path=value and be separated by semicolons`, EXIT_CODE.USAGE);
|
|
555
|
-
}
|
|
556
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
557
|
-
const value = assignment.slice(separatorIndex + 1).trim();
|
|
558
|
-
if (key.length === 0 || value.length === 0) {
|
|
559
|
-
throw new PmCliError(`${optionName} assert_json_field_equals entries must include non-empty path and value`, EXIT_CODE.USAGE);
|
|
560
|
-
}
|
|
561
|
-
values[key] = value;
|
|
562
|
-
}
|
|
563
|
-
return Object.keys(values).length > 0 ? values : undefined;
|
|
564
|
-
}
|
|
565
|
-
function parseLinkedTestAssertionGteMap(raw, optionName) {
|
|
566
|
-
const normalized = parseOptionalString(raw);
|
|
567
|
-
if (!normalized) {
|
|
568
|
-
return undefined;
|
|
569
|
-
}
|
|
570
|
-
const assignments = normalized
|
|
571
|
-
.split(/[;\n]/)
|
|
572
|
-
.map((entry) => entry.trim())
|
|
573
|
-
.filter((entry) => entry.length > 0);
|
|
574
|
-
if (assignments.length === 0) {
|
|
575
|
-
throw new PmCliError(`${optionName} assert_json_field_gte must include at least one path=value assignment`, EXIT_CODE.USAGE);
|
|
576
|
-
}
|
|
577
|
-
const values = {};
|
|
578
|
-
for (const assignment of assignments) {
|
|
579
|
-
const separatorIndex = assignment.indexOf("=");
|
|
580
|
-
if (separatorIndex <= 0) {
|
|
581
|
-
throw new PmCliError(`${optionName} assert_json_field_gte entries must use path=value and be separated by semicolons`, EXIT_CODE.USAGE);
|
|
582
|
-
}
|
|
583
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
584
|
-
const valueRaw = assignment.slice(separatorIndex + 1).trim();
|
|
585
|
-
if (key.length === 0 || valueRaw.length === 0) {
|
|
586
|
-
throw new PmCliError(`${optionName} assert_json_field_gte entries must include non-empty path and value`, EXIT_CODE.USAGE);
|
|
587
|
-
}
|
|
588
|
-
const value = Number.parseFloat(valueRaw);
|
|
589
|
-
if (!Number.isFinite(value)) {
|
|
590
|
-
throw new PmCliError(`${optionName} assert_json_field_gte value for "${key}" must be numeric`, EXIT_CODE.USAGE);
|
|
591
|
-
}
|
|
592
|
-
values[key] = value;
|
|
593
|
-
}
|
|
594
|
-
return Object.keys(values).length > 0 ? values : undefined;
|
|
595
|
-
}
|
|
596
399
|
export function parseTests(raw) {
|
|
597
400
|
if (!raw || raw.length === 0)
|
|
598
401
|
return { values: undefined, explicitEmpty: false };
|
|
599
402
|
assertNoLegacyNoneTokens(raw, "--test", "Use --clear-tests to clear linked tests.");
|
|
600
403
|
const values = raw.map((entry) => {
|
|
601
404
|
const trimmedEntry = entry.trim();
|
|
602
|
-
const kv =
|
|
603
|
-
"
|
|
604
|
-
"path",
|
|
605
|
-
"scope",
|
|
606
|
-
"timeout",
|
|
607
|
-
"timeout_seconds",
|
|
608
|
-
"pm_context_mode",
|
|
609
|
-
"env_set",
|
|
610
|
-
"env_clear",
|
|
611
|
-
"shared_host_safe",
|
|
612
|
-
"assert_stdout_contains",
|
|
613
|
-
"assert_stdout_regex",
|
|
614
|
-
"assert_stderr_contains",
|
|
615
|
-
"assert_stderr_regex",
|
|
616
|
-
"assert_stdout_min_lines",
|
|
617
|
-
"assert_json_field_equals",
|
|
618
|
-
"assert_json_field_gte",
|
|
619
|
-
"note",
|
|
620
|
-
])
|
|
621
|
-
? parseCsvKv(entry, "--test")
|
|
405
|
+
const kv = looksLikeStructuredLinkedTestEntry(trimmedEntry)
|
|
406
|
+
? normalizeStructuredLinkedTestEntry(parseCsvKv(entry, "--test"), "--test")
|
|
622
407
|
: { command: trimmedEntry };
|
|
623
408
|
const command = parseOptionalString(kv.command);
|
|
624
409
|
const filePath = parseOptionalString(kv.path);
|
|
@@ -678,10 +463,10 @@ function parseReminders(raw, nowValue) {
|
|
|
678
463
|
assertNoLegacyNoneTokens(raw, "--reminder", "Use --clear-reminders to clear reminders.");
|
|
679
464
|
const values = raw.map((entry) => {
|
|
680
465
|
const kv = parseCsvKv(entry, "--reminder");
|
|
681
|
-
const atRaw = parseOptionalString(kv.at);
|
|
682
|
-
const textRaw = parseOptionalString(kv.text);
|
|
466
|
+
const atRaw = parseOptionalString(kv.at ?? kv.date);
|
|
467
|
+
const textRaw = parseOptionalString(kv.text ?? kv.title);
|
|
683
468
|
if (!atRaw || !textRaw) {
|
|
684
|
-
throw new PmCliError("--reminder requires at=<iso|relative>
|
|
469
|
+
throw new PmCliError("--reminder requires at=<iso|relative> or date=<iso|relative>, plus text=<value> or title=<value>", EXIT_CODE.USAGE);
|
|
685
470
|
}
|
|
686
471
|
const text = textRaw.trim();
|
|
687
472
|
if (!text) {
|
|
@@ -694,73 +479,6 @@ function parseReminders(raw, nowValue) {
|
|
|
694
479
|
});
|
|
695
480
|
return { values, explicitEmpty: false };
|
|
696
481
|
}
|
|
697
|
-
function parseEventBoolean(value, flag) {
|
|
698
|
-
const normalized = value.trim().toLowerCase();
|
|
699
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
700
|
-
return true;
|
|
701
|
-
}
|
|
702
|
-
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
703
|
-
return false;
|
|
704
|
-
}
|
|
705
|
-
throw new PmCliError(`${flag} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
|
|
706
|
-
}
|
|
707
|
-
function parseDelimitedList(raw) {
|
|
708
|
-
if (!raw) {
|
|
709
|
-
return [];
|
|
710
|
-
}
|
|
711
|
-
return raw
|
|
712
|
-
.split("|")
|
|
713
|
-
.map((value) => value.trim())
|
|
714
|
-
.filter((value) => value.length > 0);
|
|
715
|
-
}
|
|
716
|
-
function parseRecurrenceRule(kv, startAt, nowValue) {
|
|
717
|
-
const freqRaw = parseOptionalString(kv.recur_freq)?.trim();
|
|
718
|
-
const intervalRaw = parseOptionalString(kv.recur_interval)?.trim();
|
|
719
|
-
const countRaw = parseOptionalString(kv.recur_count)?.trim();
|
|
720
|
-
const untilRaw = parseOptionalString(kv.recur_until)?.trim();
|
|
721
|
-
const byWeekdayRaw = parseOptionalString(kv.recur_by_weekday)?.trim();
|
|
722
|
-
const byMonthDayRaw = parseOptionalString(kv.recur_by_month_day)?.trim();
|
|
723
|
-
const exdatesRaw = parseOptionalString(kv.recur_exdates)?.trim();
|
|
724
|
-
const recurrenceInputsProvided = [freqRaw, intervalRaw, countRaw, untilRaw, byWeekdayRaw, byMonthDayRaw, exdatesRaw].some((value) => value !== undefined);
|
|
725
|
-
if (!recurrenceInputsProvided) {
|
|
726
|
-
return undefined;
|
|
727
|
-
}
|
|
728
|
-
if (!freqRaw) {
|
|
729
|
-
throw new PmCliError("--event recurrence fields require recur_freq=<daily|weekly|monthly|yearly>", EXIT_CODE.USAGE);
|
|
730
|
-
}
|
|
731
|
-
const freq = ensureEnumValue(freqRaw.toLowerCase(), RECURRENCE_FREQUENCY_VALUES, "event recurrence frequency");
|
|
732
|
-
const interval = intervalRaw !== undefined ? parseOptionalNumber(intervalRaw, "event recur_interval") : undefined;
|
|
733
|
-
if (interval !== undefined && (!Number.isInteger(interval) || interval < 1)) {
|
|
734
|
-
throw new PmCliError("--event recur_interval must be an integer >= 1", EXIT_CODE.USAGE);
|
|
735
|
-
}
|
|
736
|
-
const count = countRaw !== undefined ? parseOptionalNumber(countRaw, "event recur_count") : undefined;
|
|
737
|
-
if (count !== undefined && (!Number.isInteger(count) || count < 1)) {
|
|
738
|
-
throw new PmCliError("--event recur_count must be an integer >= 1", EXIT_CODE.USAGE);
|
|
739
|
-
}
|
|
740
|
-
const until = untilRaw ? resolveIsoOrRelative(untilRaw, nowValue, "event.recur_until") : undefined;
|
|
741
|
-
if (until && until < startAt) {
|
|
742
|
-
throw new PmCliError("--event recur_until must be at or after start", EXIT_CODE.USAGE);
|
|
743
|
-
}
|
|
744
|
-
const byWeekday = Array.from(new Set(parseDelimitedList(byWeekdayRaw).map((value) => ensureEnumValue(value.toLowerCase(), RECURRENCE_WEEKDAY_VALUES, "event weekday")))).sort((left, right) => weekdayOrderIndex(left) -
|
|
745
|
-
weekdayOrderIndex(right));
|
|
746
|
-
const byMonthDay = Array.from(new Set(parseDelimitedList(byMonthDayRaw).map((value) => {
|
|
747
|
-
const day = parseOptionalNumber(value, "event recur_by_month_day");
|
|
748
|
-
if (!Number.isInteger(day) || day < 1 || day > 31) {
|
|
749
|
-
throw new PmCliError("--event recur_by_month_day values must be integers 1..31", EXIT_CODE.USAGE);
|
|
750
|
-
}
|
|
751
|
-
return day;
|
|
752
|
-
}))).sort((left, right) => left - right);
|
|
753
|
-
const exdates = Array.from(new Set(parseDelimitedList(exdatesRaw).map((value) => resolveIsoOrRelative(value, nowValue, "event.recur_exdates")))).sort((left, right) => left.localeCompare(right));
|
|
754
|
-
return {
|
|
755
|
-
freq,
|
|
756
|
-
interval,
|
|
757
|
-
count,
|
|
758
|
-
until,
|
|
759
|
-
by_weekday: byWeekday.length > 0 ? byWeekday : undefined,
|
|
760
|
-
by_month_day: byMonthDay.length > 0 ? byMonthDay : undefined,
|
|
761
|
-
exdates: exdates.length > 0 ? exdates : undefined,
|
|
762
|
-
};
|
|
763
|
-
}
|
|
764
482
|
function parseEvents(raw, nowValue) {
|
|
765
483
|
if (!raw || raw.length === 0)
|
|
766
484
|
return { values: undefined, explicitEmpty: false };
|
|
@@ -774,10 +492,8 @@ function parseEvents(raw, nowValue) {
|
|
|
774
492
|
}
|
|
775
493
|
const startAt = resolveIsoOrRelative(startRaw, referenceDate, "event.start");
|
|
776
494
|
const endRaw = parseOptionalString(kv.end)?.trim();
|
|
777
|
-
const
|
|
778
|
-
|
|
779
|
-
throw new PmCliError("--event end must be after start", EXIT_CODE.USAGE);
|
|
780
|
-
}
|
|
495
|
+
const durationRaw = parseOptionalString(kv.duration)?.trim();
|
|
496
|
+
const endAt = resolveEventEndAt(startAt, endRaw, durationRaw, referenceDate);
|
|
781
497
|
const titleRaw = parseOptionalString(kv.title);
|
|
782
498
|
const descriptionRaw = parseOptionalString(kv.description);
|
|
783
499
|
const locationRaw = parseOptionalString(kv.location);
|
|
@@ -799,7 +515,7 @@ function parseEvents(raw, nowValue) {
|
|
|
799
515
|
throw new PmCliError("--event timezone must not be empty", EXIT_CODE.USAGE);
|
|
800
516
|
}
|
|
801
517
|
const allDayRaw = parseOptionalString(kv.all_day)?.trim();
|
|
802
|
-
const recurrence = parseRecurrenceRule(kv, startAt, referenceDate);
|
|
518
|
+
const recurrence = parseRecurrenceRule(kv, startAt, referenceDate, "defined");
|
|
803
519
|
return {
|
|
804
520
|
start_at: startAt,
|
|
805
521
|
end_at: endAt,
|
|
@@ -813,10 +529,10 @@ function parseEvents(raw, nowValue) {
|
|
|
813
529
|
});
|
|
814
530
|
return { values, explicitEmpty: false };
|
|
815
531
|
}
|
|
816
|
-
function buildChangedFields(frontMatter, explicitUnsets) {
|
|
532
|
+
function buildChangedFields(frontMatter, body, explicitUnsets) {
|
|
817
533
|
const changed = [
|
|
818
534
|
...FRONT_MATTER_KEY_ORDER.filter((key) => frontMatter[key] !== undefined),
|
|
819
|
-
"body",
|
|
535
|
+
...(body.length > 0 ? ["body"] : []),
|
|
820
536
|
...explicitUnsets.map((key) => `unset:${key}`),
|
|
821
537
|
];
|
|
822
538
|
return Array.from(new Set(changed));
|
|
@@ -1127,11 +843,7 @@ function selectAuthor(explicitAuthor, settingsAuthor) {
|
|
|
1127
843
|
return trimmed || "unknown";
|
|
1128
844
|
}
|
|
1129
845
|
function ensurePriority(rawPriority) {
|
|
1130
|
-
|
|
1131
|
-
if (![0, 1, 2, 3, 4].includes(parsed)) {
|
|
1132
|
-
throw new PmCliError("Priority must be 0..4 (0=critical, 1=high, 2=medium, 3=low, 4=minimal)", EXIT_CODE.USAGE);
|
|
1133
|
-
}
|
|
1134
|
-
return parsed;
|
|
846
|
+
return resolvePriority(rawPriority);
|
|
1135
847
|
}
|
|
1136
848
|
function mergeCreateOptionsWithTemplate(templateOptions, explicitOptions) {
|
|
1137
849
|
const merged = {};
|
|
@@ -1244,7 +956,7 @@ export async function runCreate(options, global) {
|
|
|
1244
956
|
}
|
|
1245
957
|
const resolvedTypeName = resolveTypeName(resolvedOptions.type, typeRegistry);
|
|
1246
958
|
if (!resolvedTypeName) {
|
|
1247
|
-
throw new PmCliError(
|
|
959
|
+
throw new PmCliError(buildInvalidTypeError(resolvedOptions.type, typeRegistry.types), EXIT_CODE.USAGE);
|
|
1248
960
|
}
|
|
1249
961
|
const typeDefinition = resolveTypeDefinition(resolvedTypeName, typeRegistry);
|
|
1250
962
|
if (!typeDefinition) {
|
|
@@ -1498,7 +1210,7 @@ export async function runCreate(options, global) {
|
|
|
1498
1210
|
});
|
|
1499
1211
|
}
|
|
1500
1212
|
const id = await generateItemId(pmRoot, settings.id_prefix);
|
|
1501
|
-
|
|
1213
|
+
let status = resolvedOptions.status !== undefined ? parseStatusValue(resolvedOptions.status, statusRegistry) : statusRegistry.open_status;
|
|
1502
1214
|
const priority = resolvedOptions.priority !== undefined ? ensurePriority(resolvedOptions.priority) : 2;
|
|
1503
1215
|
const tags = unsetTargets.frontMatterKeys.has("tags")
|
|
1504
1216
|
? []
|
|
@@ -1572,6 +1284,10 @@ export async function runCreate(options, global) {
|
|
|
1572
1284
|
const parentReferencePolicy = settings.validation.parent_reference;
|
|
1573
1285
|
const sprintReleasePolicy = settings.validation.sprint_release_format;
|
|
1574
1286
|
const validationWarnings = [];
|
|
1287
|
+
// Event-type items with no attached schedule never surface on the calendar; warn (never block).
|
|
1288
|
+
if (type.toLowerCase() === "event" && (events.values === undefined || events.values.length === 0)) {
|
|
1289
|
+
validationWarnings.push(`event_without_schedule:${id}:no_time_set`);
|
|
1290
|
+
}
|
|
1575
1291
|
if (parent !== undefined) {
|
|
1576
1292
|
parent = normalizeParentReferenceValue(parent);
|
|
1577
1293
|
const parentLocated = await locateItem(pmRoot, parent, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
|
|
@@ -1599,6 +1315,30 @@ export async function runCreate(options, global) {
|
|
|
1599
1315
|
const blockedBy = unsetTargets.frontMatterKeys.has("blocked_by") || resolvedOptions.blockedBy === undefined
|
|
1600
1316
|
? undefined
|
|
1601
1317
|
: parseOptionalString(resolvedOptions.blockedBy);
|
|
1318
|
+
let dependencyValues = dependencies.values;
|
|
1319
|
+
if (blockedBy !== undefined) {
|
|
1320
|
+
const normalizedBlockedBy = normalizeItemId(blockedBy, settings.id_prefix);
|
|
1321
|
+
const blockedByLocated = await locateItem(pmRoot, normalizedBlockedBy, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
|
|
1322
|
+
if (blockedByLocated) {
|
|
1323
|
+
const hasBlockedByDependency = (dependencyValues ?? []).some((dependency) => dependency.id === blockedByLocated.id && dependency.kind === "blocked_by");
|
|
1324
|
+
if (!hasBlockedByDependency) {
|
|
1325
|
+
dependencyValues = [
|
|
1326
|
+
...(dependencyValues ?? []),
|
|
1327
|
+
{
|
|
1328
|
+
id: blockedByLocated.id,
|
|
1329
|
+
kind: "blocked_by",
|
|
1330
|
+
created_at: nowValue,
|
|
1331
|
+
author,
|
|
1332
|
+
},
|
|
1333
|
+
];
|
|
1334
|
+
}
|
|
1335
|
+
if (resolvedOptions.status === undefined) {
|
|
1336
|
+
status = statusRegistry.blocked_statuses.has("blocked")
|
|
1337
|
+
? "blocked"
|
|
1338
|
+
: [...statusRegistry.blocked_statuses].sort((left, right) => left.localeCompare(right))[0] ?? statusRegistry.open_status;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1602
1342
|
const blockedReason = unsetTargets.frontMatterKeys.has("blocked_reason") || resolvedOptions.blockedReason === undefined
|
|
1603
1343
|
? undefined
|
|
1604
1344
|
: parseOptionalString(resolvedOptions.blockedReason);
|
|
@@ -1691,7 +1431,7 @@ export async function runCreate(options, global) {
|
|
|
1691
1431
|
component,
|
|
1692
1432
|
regression,
|
|
1693
1433
|
customer_impact: customerImpact,
|
|
1694
|
-
dependencies:
|
|
1434
|
+
dependencies: dependencyValues,
|
|
1695
1435
|
comments: comments.values,
|
|
1696
1436
|
notes: notes.values,
|
|
1697
1437
|
learnings: learnings.values,
|
|
@@ -1755,7 +1495,7 @@ export async function runCreate(options, global) {
|
|
|
1755
1495
|
finally {
|
|
1756
1496
|
await lockRelease();
|
|
1757
1497
|
}
|
|
1758
|
-
const changedFields = buildChangedFields(frontMatter, explicitUnsetKeys);
|
|
1498
|
+
const changedFields = buildChangedFields(frontMatter, body, explicitUnsetKeys);
|
|
1759
1499
|
const outputItem = structuredClone(frontMatter);
|
|
1760
1500
|
return {
|
|
1761
1501
|
item: outputItem,
|
|
@@ -1764,4 +1504,4 @@ export async function runCreate(options, global) {
|
|
|
1764
1504
|
};
|
|
1765
1505
|
}
|
|
1766
1506
|
//# sourceMappingURL=create.js.map
|
|
1767
|
-
//# debugId=
|
|
1507
|
+
//# debugId=10f962f6-810b-5b40-a073-b763d0b0d8b0
|