@unbrained/pm-cli 2026.5.24 → 2026.5.28
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 -522
- package/README.md +2 -10
- 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 +134 -11
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/append.js +4 -3
- package/dist/cli/commands/append.js.map +1 -1
- package/dist/cli/commands/claim.js +5 -4
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.d.ts +3 -0
- package/dist/cli/commands/close.js +26 -3
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/completion.d.ts +2 -2
- package/dist/cli/commands/completion.js +109 -56
- 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/create.js +7 -272
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/delete.js +4 -3
- package/dist/cli/commands/delete.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +1 -12
- package/dist/cli/commands/docs.js +8 -312
- package/dist/cli/commands/docs.js.map +1 -1
- 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 +202 -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 +36 -68
- package/dist/cli/commands/extension.js +143 -1422
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.d.ts +1 -12
- package/dist/cli/commands/files.js +11 -308
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/get.js +4 -3
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/health.js +17 -3
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-redact.js +23 -18
- package/dist/cli/commands/history-redact.js.map +1 -1
- package/dist/cli/commands/history-repair.js +24 -18
- package/dist/cli/commands/history-repair.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-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 +19 -5
- 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/plan.d.ts +5 -0
- package/dist/cli/commands/plan.js +56 -8
- 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 +19 -8
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/search.js +5 -8
- package/dist/cli/commands/search.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.d.ts +1 -2
- package/dist/cli/commands/test.js +8 -350
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.js +4 -3
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.js +83 -356
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.js +32 -12
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/error-guidance.d.ts +1 -0
- package/dist/cli/error-guidance.js +6 -2
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/main.d.ts +11 -0
- package/dist/cli/main.js +76 -28
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.d.ts +4 -1
- package/dist/cli/register-list-query.js +242 -203
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.js +73 -11
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +3 -3
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +12 -7
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.js +3 -2
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli.js +4 -3
- 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 -0
- package/dist/core/extensions/index.js +11 -2
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +4 -22
- package/dist/core/extensions/loader.js +22 -1139
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/history/drift-scan.d.ts +11 -0
- package/dist/core/history/drift-scan.js +114 -32
- package/dist/core/history/drift-scan.js.map +1 -1
- 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.js +4 -3
- package/dist/core/history/replay.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/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/schema/runtime-schema.js +8 -38
- package/dist/core/schema/runtime-schema.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/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/levenshtein.js +23 -7
- package/dist/core/shared/levenshtein.js.map +1 -1
- 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/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.js +8 -73
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/mcp/server.js +76 -28
- 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 +11 -33
- package/dist/sdk/cli-contracts.js +30 -1356
- 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 +2 -0
- package/dist/sdk/runtime.js +4 -2
- package/dist/sdk/runtime.js.map +1 -1
- package/docs/AGENT_GUIDE.md +6 -10
- package/docs/CLAUDE_CODE_PLUGIN.md +5 -28
- package/docs/CODEX_PLUGIN.md +5 -5
- package/docs/COMMANDS.md +19 -3
- package/docs/CONFIGURATION.md +15 -0
- package/docs/EXTENSIONS.md +4 -63
- package/docs/RELEASING.md +4 -4
- package/marketplace.json +7 -3
- package/package.json +9 -6
- 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/extensions/calendar/index.js +47 -2
- package/packages/pm-calendar/extensions/calendar/index.ts +52 -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/extensions/search-advanced/index.js +1 -1
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +4 -37
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +6 -37
- 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
|
@@ -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";
|
|
@@ -24,13 +24,15 @@ import { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from "../
|
|
|
24
24
|
import { readSettings } from "../../core/store/settings.js";
|
|
25
25
|
import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
|
|
26
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";
|
|
27
29
|
import { looksLikeStructuredLinkedTestEntry, normalizeStructuredLinkedTestEntry } from "./linked-test-entry.js";
|
|
28
|
-
import {
|
|
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";
|
|
29
32
|
const CREATE_MODE_VALUES = ["strict", "progressive"];
|
|
30
33
|
const SCHEDULE_CREATE_PRESET_VALUES = ["lightweight"];
|
|
31
34
|
const SCHEDULE_CREATE_PRESET_TYPES = new Set(["Reminder", "Meeting", "Event"]);
|
|
32
35
|
const LOG_SEED_ALLOWED_KEYS = new Set(["author", "created_at", "text"]);
|
|
33
|
-
const LEGACY_NONE_TOKENS = new Set(["none", "null"]);
|
|
34
36
|
const CREATE_UNSET_FIELD_DEFINITIONS = [
|
|
35
37
|
{ canonical: "tags", aliases: ["tags"], optionKey: "tags", frontMatterKey: "tags" },
|
|
36
38
|
{ canonical: "deadline", aliases: ["deadline"], optionKey: "deadline", frontMatterKey: "deadline" },
|
|
@@ -163,12 +165,6 @@ function buildInvalidLogSeedKeysMessage(optionName, unsupportedKeys) {
|
|
|
163
165
|
'(for example text="first,scope:project"), use markdown-style key/value input, ' +
|
|
164
166
|
`or pass ${optionName} - with piped stdin.`);
|
|
165
167
|
}
|
|
166
|
-
function ensureEnumValue(value, allowed, label) {
|
|
167
|
-
if (!allowed.includes(value)) {
|
|
168
|
-
throw new PmCliError(`Invalid ${label} value "${value}". Allowed: ${allowed.join(", ")}`, EXIT_CODE.USAGE);
|
|
169
|
-
}
|
|
170
|
-
return value;
|
|
171
|
-
}
|
|
172
168
|
function parseStatusValue(value, statusRegistry) {
|
|
173
169
|
const normalized = normalizeStatusInput(value, statusRegistry);
|
|
174
170
|
if (!normalized) {
|
|
@@ -187,30 +183,6 @@ function parseCreatedAt(value, currentIso) {
|
|
|
187
183
|
}
|
|
188
184
|
return new Date(parsed).toISOString();
|
|
189
185
|
}
|
|
190
|
-
function isLegacyNoneToken(value) {
|
|
191
|
-
if (value === undefined) {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
return LEGACY_NONE_TOKENS.has(value.trim().toLowerCase());
|
|
195
|
-
}
|
|
196
|
-
function assertNoLegacyNoneToken(value, flag, replacementHint) {
|
|
197
|
-
if (!isLegacyNoneToken(value)) {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const suffix = replacementHint ? ` ${replacementHint}` : "";
|
|
201
|
-
throw new PmCliError(`${flag} no longer accepts "none" or "null".${suffix}`.trim(), EXIT_CODE.USAGE);
|
|
202
|
-
}
|
|
203
|
-
function assertNoLegacyNoneTokens(values, flag, replacementHint) {
|
|
204
|
-
if (!values || values.length === 0) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const hasLegacyToken = values.some((value) => isLegacyNoneToken(value));
|
|
208
|
-
if (!hasLegacyToken) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
const suffix = replacementHint ? ` ${replacementHint}` : "";
|
|
212
|
-
throw new PmCliError(`${flag} no longer accepts "none" or "null".${suffix}`.trim(), EXIT_CODE.USAGE);
|
|
213
|
-
}
|
|
214
186
|
const CREATE_LEGACY_NONE_COLLECTION_NORMALIZERS = [
|
|
215
187
|
{ optionKey: "dep", clearFlagKey: "clearDeps", valueFlag: "--dep", clearFlag: "--clear-deps" },
|
|
216
188
|
{ optionKey: "comment", clearFlagKey: "clearComments", valueFlag: "--comment", clearFlag: "--clear-comments" },
|
|
@@ -424,176 +396,6 @@ export function parseFiles(raw) {
|
|
|
424
396
|
});
|
|
425
397
|
return { values, explicitEmpty: false };
|
|
426
398
|
}
|
|
427
|
-
const LINKED_TEST_PROTECTED_ENV_KEYS = new Set(["PM_PATH", "PM_GLOBAL_PATH", "FORCE_COLOR"]);
|
|
428
|
-
const LINKED_TEST_ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
429
|
-
const LINKED_TEST_PM_CONTEXT_MODE_VALUES = ["schema", "tracker", "auto"];
|
|
430
|
-
function parseLinkedTestEnvSet(raw, optionName) {
|
|
431
|
-
const normalized = parseOptionalString(raw);
|
|
432
|
-
if (!normalized) {
|
|
433
|
-
return undefined;
|
|
434
|
-
}
|
|
435
|
-
const assignments = normalized
|
|
436
|
-
.split(/[;\n]/)
|
|
437
|
-
.map((entry) => entry.trim())
|
|
438
|
-
.filter((entry) => entry.length > 0);
|
|
439
|
-
if (assignments.length === 0) {
|
|
440
|
-
throw new PmCliError(`${optionName} env_set must include at least one KEY=VALUE assignment`, EXIT_CODE.USAGE);
|
|
441
|
-
}
|
|
442
|
-
const envSet = {};
|
|
443
|
-
for (const assignment of assignments) {
|
|
444
|
-
const separatorIndex = assignment.indexOf("=");
|
|
445
|
-
if (separatorIndex <= 0) {
|
|
446
|
-
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);
|
|
447
|
-
}
|
|
448
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
449
|
-
const value = assignment.slice(separatorIndex + 1);
|
|
450
|
-
if (!LINKED_TEST_ENV_NAME_PATTERN.test(key)) {
|
|
451
|
-
throw new PmCliError(`${optionName} env_set key "${key}" is invalid`, EXIT_CODE.USAGE);
|
|
452
|
-
}
|
|
453
|
-
if (LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())) {
|
|
454
|
-
throw new PmCliError(`${optionName} env_set key "${key}" is reserved for sandbox safety`, EXIT_CODE.USAGE);
|
|
455
|
-
}
|
|
456
|
-
envSet[key] = value;
|
|
457
|
-
}
|
|
458
|
-
return Object.keys(envSet).length > 0 ? envSet : undefined;
|
|
459
|
-
}
|
|
460
|
-
function parseLinkedTestEnvClear(raw, optionName) {
|
|
461
|
-
const normalized = parseOptionalString(raw);
|
|
462
|
-
if (!normalized) {
|
|
463
|
-
return undefined;
|
|
464
|
-
}
|
|
465
|
-
const keys = [...new Set(normalized.split(/[;,\n]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0))];
|
|
466
|
-
if (keys.length === 0) {
|
|
467
|
-
throw new PmCliError(`${optionName} env_clear must include at least one environment variable name`, EXIT_CODE.USAGE);
|
|
468
|
-
}
|
|
469
|
-
for (const key of keys) {
|
|
470
|
-
if (!LINKED_TEST_ENV_NAME_PATTERN.test(key)) {
|
|
471
|
-
throw new PmCliError(`${optionName} env_clear key "${key}" is invalid`, EXIT_CODE.USAGE);
|
|
472
|
-
}
|
|
473
|
-
if (LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())) {
|
|
474
|
-
throw new PmCliError(`${optionName} env_clear key "${key}" is reserved for sandbox safety`, EXIT_CODE.USAGE);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
return keys;
|
|
478
|
-
}
|
|
479
|
-
function parseLinkedTestBoolean(raw, optionName, fieldLabel) {
|
|
480
|
-
const normalized = parseOptionalString(raw);
|
|
481
|
-
if (!normalized) {
|
|
482
|
-
return undefined;
|
|
483
|
-
}
|
|
484
|
-
const value = normalized.trim().toLowerCase();
|
|
485
|
-
if (value === "true" || value === "1" || value === "yes") {
|
|
486
|
-
return true;
|
|
487
|
-
}
|
|
488
|
-
if (value === "false" || value === "0" || value === "no") {
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
throw new PmCliError(`${optionName} ${fieldLabel} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
|
|
492
|
-
}
|
|
493
|
-
function parseLinkedTestContextMode(raw, optionName) {
|
|
494
|
-
const normalized = parseOptionalString(raw);
|
|
495
|
-
if (!normalized) {
|
|
496
|
-
return undefined;
|
|
497
|
-
}
|
|
498
|
-
const value = normalized.trim().toLowerCase();
|
|
499
|
-
if (LINKED_TEST_PM_CONTEXT_MODE_VALUES.includes(value)) {
|
|
500
|
-
return value;
|
|
501
|
-
}
|
|
502
|
-
throw new PmCliError(`${optionName} pm_context_mode must be one of: ${LINKED_TEST_PM_CONTEXT_MODE_VALUES.join(", ")}`, EXIT_CODE.USAGE);
|
|
503
|
-
}
|
|
504
|
-
function parseLinkedTestStringList(raw) {
|
|
505
|
-
const normalized = parseOptionalString(raw);
|
|
506
|
-
if (!normalized) {
|
|
507
|
-
return undefined;
|
|
508
|
-
}
|
|
509
|
-
const values = [...new Set(normalized.split(/[;\n]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0))];
|
|
510
|
-
return values.length > 0 ? values : undefined;
|
|
511
|
-
}
|
|
512
|
-
function parseLinkedTestRegexList(raw, optionName, fieldLabel) {
|
|
513
|
-
const values = parseLinkedTestStringList(raw);
|
|
514
|
-
if (!values || values.length === 0) {
|
|
515
|
-
return undefined;
|
|
516
|
-
}
|
|
517
|
-
for (const pattern of values) {
|
|
518
|
-
try {
|
|
519
|
-
// Validate syntax early so malformed assertions fail at mutation time.
|
|
520
|
-
new RegExp(pattern, "m");
|
|
521
|
-
}
|
|
522
|
-
catch (error) {
|
|
523
|
-
throw new PmCliError(`${optionName} ${fieldLabel} includes invalid regex "${pattern}": ${error instanceof Error ? error.message : String(error)}`, EXIT_CODE.USAGE);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
return values;
|
|
527
|
-
}
|
|
528
|
-
function parseLinkedTestMinLines(raw, optionName) {
|
|
529
|
-
const normalized = parseOptionalString(raw);
|
|
530
|
-
if (!normalized) {
|
|
531
|
-
return undefined;
|
|
532
|
-
}
|
|
533
|
-
const parsed = parseOptionalNumber(normalized, "assert_stdout_min_lines");
|
|
534
|
-
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
535
|
-
throw new PmCliError(`${optionName} assert_stdout_min_lines must be an integer >= 0`, EXIT_CODE.USAGE);
|
|
536
|
-
}
|
|
537
|
-
return parsed;
|
|
538
|
-
}
|
|
539
|
-
function parseLinkedTestAssertionEqualsMap(raw, optionName) {
|
|
540
|
-
const normalized = parseOptionalString(raw);
|
|
541
|
-
if (!normalized) {
|
|
542
|
-
return undefined;
|
|
543
|
-
}
|
|
544
|
-
const assignments = normalized
|
|
545
|
-
.split(/[;\n]/)
|
|
546
|
-
.map((entry) => entry.trim())
|
|
547
|
-
.filter((entry) => entry.length > 0);
|
|
548
|
-
if (assignments.length === 0) {
|
|
549
|
-
throw new PmCliError(`${optionName} assert_json_field_equals must include at least one path=value assignment`, EXIT_CODE.USAGE);
|
|
550
|
-
}
|
|
551
|
-
const values = {};
|
|
552
|
-
for (const assignment of assignments) {
|
|
553
|
-
const separatorIndex = assignment.indexOf("=");
|
|
554
|
-
if (separatorIndex <= 0) {
|
|
555
|
-
throw new PmCliError(`${optionName} assert_json_field_equals entries must use path=value and be separated by semicolons`, EXIT_CODE.USAGE);
|
|
556
|
-
}
|
|
557
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
558
|
-
const value = assignment.slice(separatorIndex + 1).trim();
|
|
559
|
-
if (key.length === 0 || value.length === 0) {
|
|
560
|
-
throw new PmCliError(`${optionName} assert_json_field_equals entries must include non-empty path and value`, EXIT_CODE.USAGE);
|
|
561
|
-
}
|
|
562
|
-
values[key] = value;
|
|
563
|
-
}
|
|
564
|
-
return Object.keys(values).length > 0 ? values : undefined;
|
|
565
|
-
}
|
|
566
|
-
function parseLinkedTestAssertionGteMap(raw, optionName) {
|
|
567
|
-
const normalized = parseOptionalString(raw);
|
|
568
|
-
if (!normalized) {
|
|
569
|
-
return undefined;
|
|
570
|
-
}
|
|
571
|
-
const assignments = normalized
|
|
572
|
-
.split(/[;\n]/)
|
|
573
|
-
.map((entry) => entry.trim())
|
|
574
|
-
.filter((entry) => entry.length > 0);
|
|
575
|
-
if (assignments.length === 0) {
|
|
576
|
-
throw new PmCliError(`${optionName} assert_json_field_gte must include at least one path=value assignment`, EXIT_CODE.USAGE);
|
|
577
|
-
}
|
|
578
|
-
const values = {};
|
|
579
|
-
for (const assignment of assignments) {
|
|
580
|
-
const separatorIndex = assignment.indexOf("=");
|
|
581
|
-
if (separatorIndex <= 0) {
|
|
582
|
-
throw new PmCliError(`${optionName} assert_json_field_gte entries must use path=value and be separated by semicolons`, EXIT_CODE.USAGE);
|
|
583
|
-
}
|
|
584
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
585
|
-
const valueRaw = assignment.slice(separatorIndex + 1).trim();
|
|
586
|
-
if (key.length === 0 || valueRaw.length === 0) {
|
|
587
|
-
throw new PmCliError(`${optionName} assert_json_field_gte entries must include non-empty path and value`, EXIT_CODE.USAGE);
|
|
588
|
-
}
|
|
589
|
-
const value = Number.parseFloat(valueRaw);
|
|
590
|
-
if (!Number.isFinite(value)) {
|
|
591
|
-
throw new PmCliError(`${optionName} assert_json_field_gte value for "${key}" must be numeric`, EXIT_CODE.USAGE);
|
|
592
|
-
}
|
|
593
|
-
values[key] = value;
|
|
594
|
-
}
|
|
595
|
-
return Object.keys(values).length > 0 ? values : undefined;
|
|
596
|
-
}
|
|
597
399
|
export function parseTests(raw) {
|
|
598
400
|
if (!raw || raw.length === 0)
|
|
599
401
|
return { values: undefined, explicitEmpty: false };
|
|
@@ -677,73 +479,6 @@ function parseReminders(raw, nowValue) {
|
|
|
677
479
|
});
|
|
678
480
|
return { values, explicitEmpty: false };
|
|
679
481
|
}
|
|
680
|
-
function parseEventBoolean(value, flag) {
|
|
681
|
-
const normalized = value.trim().toLowerCase();
|
|
682
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
683
|
-
return true;
|
|
684
|
-
}
|
|
685
|
-
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
686
|
-
return false;
|
|
687
|
-
}
|
|
688
|
-
throw new PmCliError(`${flag} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
|
|
689
|
-
}
|
|
690
|
-
function parseDelimitedList(raw) {
|
|
691
|
-
if (!raw) {
|
|
692
|
-
return [];
|
|
693
|
-
}
|
|
694
|
-
return raw
|
|
695
|
-
.split("|")
|
|
696
|
-
.map((value) => value.trim())
|
|
697
|
-
.filter((value) => value.length > 0);
|
|
698
|
-
}
|
|
699
|
-
function parseRecurrenceRule(kv, startAt, nowValue) {
|
|
700
|
-
const freqRaw = parseOptionalString(kv.recur_freq)?.trim();
|
|
701
|
-
const intervalRaw = parseOptionalString(kv.recur_interval)?.trim();
|
|
702
|
-
const countRaw = parseOptionalString(kv.recur_count)?.trim();
|
|
703
|
-
const untilRaw = parseOptionalString(kv.recur_until)?.trim();
|
|
704
|
-
const byWeekdayRaw = parseOptionalString(kv.recur_by_weekday)?.trim();
|
|
705
|
-
const byMonthDayRaw = parseOptionalString(kv.recur_by_month_day)?.trim();
|
|
706
|
-
const exdatesRaw = parseOptionalString(kv.recur_exdates)?.trim();
|
|
707
|
-
const recurrenceInputsProvided = [freqRaw, intervalRaw, countRaw, untilRaw, byWeekdayRaw, byMonthDayRaw, exdatesRaw].some((value) => value !== undefined);
|
|
708
|
-
if (!recurrenceInputsProvided) {
|
|
709
|
-
return undefined;
|
|
710
|
-
}
|
|
711
|
-
if (!freqRaw) {
|
|
712
|
-
throw new PmCliError("--event recurrence fields require recur_freq=<daily|weekly|monthly|yearly>", EXIT_CODE.USAGE);
|
|
713
|
-
}
|
|
714
|
-
const freq = ensureEnumValue(freqRaw.toLowerCase(), RECURRENCE_FREQUENCY_VALUES, "event recurrence frequency");
|
|
715
|
-
const interval = intervalRaw !== undefined ? parseOptionalNumber(intervalRaw, "event recur_interval") : undefined;
|
|
716
|
-
if (interval !== undefined && (!Number.isInteger(interval) || interval < 1)) {
|
|
717
|
-
throw new PmCliError("--event recur_interval must be an integer >= 1", EXIT_CODE.USAGE);
|
|
718
|
-
}
|
|
719
|
-
const count = countRaw !== undefined ? parseOptionalNumber(countRaw, "event recur_count") : undefined;
|
|
720
|
-
if (count !== undefined && (!Number.isInteger(count) || count < 1)) {
|
|
721
|
-
throw new PmCliError("--event recur_count must be an integer >= 1", EXIT_CODE.USAGE);
|
|
722
|
-
}
|
|
723
|
-
const until = untilRaw ? resolveIsoOrRelative(untilRaw, nowValue, "event.recur_until") : undefined;
|
|
724
|
-
if (until && until < startAt) {
|
|
725
|
-
throw new PmCliError("--event recur_until must be at or after start", EXIT_CODE.USAGE);
|
|
726
|
-
}
|
|
727
|
-
const byWeekday = Array.from(new Set(parseDelimitedList(byWeekdayRaw).map((value) => ensureEnumValue(value.toLowerCase(), RECURRENCE_WEEKDAY_VALUES, "event weekday")))).sort((left, right) => weekdayOrderIndex(left) -
|
|
728
|
-
weekdayOrderIndex(right));
|
|
729
|
-
const byMonthDay = Array.from(new Set(parseDelimitedList(byMonthDayRaw).map((value) => {
|
|
730
|
-
const day = parseOptionalNumber(value, "event recur_by_month_day");
|
|
731
|
-
if (!Number.isInteger(day) || day < 1 || day > 31) {
|
|
732
|
-
throw new PmCliError("--event recur_by_month_day values must be integers 1..31", EXIT_CODE.USAGE);
|
|
733
|
-
}
|
|
734
|
-
return day;
|
|
735
|
-
}))).sort((left, right) => left - right);
|
|
736
|
-
const exdates = Array.from(new Set(parseDelimitedList(exdatesRaw).map((value) => resolveIsoOrRelative(value, nowValue, "event.recur_exdates")))).sort((left, right) => left.localeCompare(right));
|
|
737
|
-
return {
|
|
738
|
-
freq,
|
|
739
|
-
interval,
|
|
740
|
-
count,
|
|
741
|
-
until,
|
|
742
|
-
by_weekday: byWeekday.length > 0 ? byWeekday : undefined,
|
|
743
|
-
by_month_day: byMonthDay.length > 0 ? byMonthDay : undefined,
|
|
744
|
-
exdates: exdates.length > 0 ? exdates : undefined,
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
482
|
function parseEvents(raw, nowValue) {
|
|
748
483
|
if (!raw || raw.length === 0)
|
|
749
484
|
return { values: undefined, explicitEmpty: false };
|
|
@@ -780,7 +515,7 @@ function parseEvents(raw, nowValue) {
|
|
|
780
515
|
throw new PmCliError("--event timezone must not be empty", EXIT_CODE.USAGE);
|
|
781
516
|
}
|
|
782
517
|
const allDayRaw = parseOptionalString(kv.all_day)?.trim();
|
|
783
|
-
const recurrence = parseRecurrenceRule(kv, startAt, referenceDate);
|
|
518
|
+
const recurrence = parseRecurrenceRule(kv, startAt, referenceDate, "defined");
|
|
784
519
|
return {
|
|
785
520
|
start_at: startAt,
|
|
786
521
|
end_at: endAt,
|
|
@@ -1769,4 +1504,4 @@ export async function runCreate(options, global) {
|
|
|
1769
1504
|
};
|
|
1770
1505
|
}
|
|
1771
1506
|
//# sourceMappingURL=create.js.map
|
|
1772
|
-
//# debugId=
|
|
1507
|
+
//# debugId=10f962f6-810b-5b40-a073-b763d0b0d8b0
|