@unbrained/pm-cli 2026.8.16 → 2026.8.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +30 -3
- package/README.md +13 -13
- package/dist/cli/public.d.ts +2 -0
- package/dist/cli/public.js +21 -0
- package/dist/cli/register-mutation.js +4 -4
- package/dist/cli-bundle/bundle-manifest.json +151 -151
- package/dist/cli-bundle/chunks/{chunk-I2LUWWR5.js → chunk-2QLOXC3V.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-URW4QRMI.js → chunk-3UEGXBMR.js} +22 -22
- package/dist/cli-bundle/chunks/chunk-4JPYF536.js +35 -0
- package/dist/cli-bundle/chunks/chunk-6VDLG2FC.js +13 -0
- package/dist/cli-bundle/chunks/chunk-7IBRGCHX.js +2 -0
- package/dist/cli-bundle/chunks/chunk-HBJAS566.js +8 -0
- package/dist/cli-bundle/chunks/chunk-ION3E43Q.js +197 -0
- package/dist/cli-bundle/chunks/{chunk-73UGEBRS.js → chunk-JOKATURE.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-RIS565OA.js → chunk-TPXZIBIV.js} +5 -5
- package/dist/cli-bundle/chunks/chunk-YM2YAMF7.js +2 -0
- package/dist/cli-bundle/chunks/{register-list-query-EYCXHZAG.js → register-list-query-Q7KII4G5.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-4WBRPXLV.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-KGDNRMCL.js → register-operations-SSENDH5B.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-NVXBOD5I.js → register-setup-DOSFBGKE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-TZATVC4G.js → chunk-267MUUS6.js} +11 -11
- package/dist/cli-bundle/focused-chunks/chunk-2NNFLLNG.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-HAACPSUW.js → chunk-2QSAKMIH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6ROKKT4X.js → chunk-ATEY76SX.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-BUCG4ZI2.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-SSNDYZTM.js → chunk-CYFK5UPB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-EHXIKD6K.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-J4UFYHOD.js → chunk-KGEXTMPG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-KP2VQQVQ.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-MHPIL773.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-POEEAD2V.js +4 -0
- package/dist/cli-bundle/focused-chunks/{chunk-T46KLOIB.js → chunk-SALH6B6K.js} +47 -47
- package/dist/cli-bundle/focused-chunks/{chunk-CODV5LUT.js → chunk-SYZENPIT.js} +3 -3
- package/dist/cli-bundle/focused-chunks/{chunk-4JPEBFFC.js → chunk-XKAMP5OU.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-NJ5RLEFD.js → chunk-XPIC53VA.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-C7JUBRFP.js → chunk-ZQPGZZWQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-ZT2DJS27.js +155 -0
- package/dist/cli-bundle/main.js +2 -2
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +31 -31
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +32 -32
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +4 -2
- package/dist/core/extensions/loader.js +10 -6
- package/dist/core/extensions/manifest-schema.d.ts +20 -0
- package/dist/core/extensions/manifest-schema.js +52 -0
- package/dist/core/history/replay.js +32 -14
- package/dist/core/schema/fields-file.d.ts +1 -1
- package/dist/core/schema/fields-file.js +2 -2
- package/dist/core/schema/runtime-field-values.js +115 -9
- package/dist/core/schema/runtime-schema.d.ts +3 -1
- package/dist/core/schema/runtime-schema.js +124 -3
- package/dist/core/shared/errors.d.ts +10 -0
- package/dist/core/shared/errors.js +2 -2
- package/dist/core/shared/time.d.ts +2 -0
- package/dist/core/shared/time.js +27 -2
- package/dist/sdk/agent/refusal-reachability.d.ts +46 -6
- package/dist/sdk/agent/refusal-reachability.js +350 -8
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +5 -4
- package/dist/sdk/compose.d.ts +6 -2
- package/dist/sdk/compose.js +33 -3
- package/dist/sdk/context-intent-contracts.d.ts +8 -4
- package/dist/sdk/context-intent-contracts.js +76 -31
- package/dist/sdk/dependency-flag-validation.d.ts +9 -2
- package/dist/sdk/dependency-flag-validation.js +101 -35
- package/dist/sdk/environment/host-environment-errors.js +25 -7
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +26 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
- package/dist/sdk/governance/assurance-action.d.ts +3 -7
- package/dist/sdk/governance/assurance-action.js +97 -2
- package/dist/sdk/governance/boundary-fixtures.d.ts +86 -0
- package/dist/sdk/governance/boundary-fixtures.js +201 -0
- package/dist/sdk/governance/defect-recurrence-signals.d.ts +10 -0
- package/dist/sdk/governance/defect-recurrence-signals.js +25 -0
- package/dist/sdk/governance/defect-recurrence.d.ts +242 -0
- package/dist/sdk/governance/defect-recurrence.js +523 -0
- package/dist/sdk/governance.d.ts +2 -0
- package/dist/sdk/governance.js +4 -2
- package/dist/sdk/graph/governance.js +3 -2
- package/dist/sdk/guide-topics.js +191 -2
- package/dist/sdk/index.d.ts +3 -0
- package/dist/sdk/index.js +4 -2
- package/dist/sdk/lifecycle/create.js +4 -2
- package/dist/sdk/lifecycle/update-many.js +15 -2
- package/dist/sdk/lifecycle/update.js +5 -2
- package/dist/sdk/linked-artifacts.js +63 -14
- package/dist/sdk/query/get.d.ts +2 -0
- package/dist/sdk/query/get.js +32 -7
- package/dist/sdk/relationship-analytics.js +90 -14
- package/dist/sdk/relationship-kinds/contract.d.ts +4 -0
- package/dist/sdk/relationship-kinds/contract.js +3 -2
- package/dist/sdk/relationships.d.ts +1 -1
- package/dist/sdk/relationships.js +11 -2
- package/dist/sdk/schema.d.ts +1 -0
- package/dist/sdk/schema.js +2 -2
- package/dist/sdk/test/execution.d.ts +6 -2
- package/dist/sdk/test/execution.js +39 -13
- package/dist/types.d.ts +29 -2
- package/dist/types.js +4 -2
- package/docs/CONFIGURATION.md +58 -1
- package/docs/CONTEXT_INTEGRITY_CONTRACTS.md +58 -0
- package/docs/DEFECT_RECURRENCE.md +134 -0
- package/docs/DEPENDENCY_KIND_CONTRACT.md +12 -2
- package/docs/README.md +2 -0
- package/docs/RELATIONSHIP_GRAPH.md +16 -2
- package/docs/SDK.md +38 -5
- package/docs/SDK_RUNTIME_BOUNDARIES.md +9 -1
- package/docs/TESTING.md +18 -1
- package/docs/TRUSTWORTHY_CONTEXT_EVIDENCE.md +1 -1
- package/marketplace.json +2 -2
- package/package.json +6 -4
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/skills/pm-audit/SKILL.md +26 -0
- package/plugins/pm-claude/skills/pm-developer/SKILL.md +26 -0
- package/plugins/pm-claude/skills/pm-planner/SKILL.md +26 -0
- package/plugins/pm-claude/skills/pm-release/SKILL.md +26 -0
- package/plugins/pm-claude/skills/pm-workflow/SKILL.md +26 -0
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/skills/pm-auditor/SKILL.md +26 -0
- package/plugins/pm-codex/skills/pm-native/SKILL.md +26 -0
- package/plugins/pm-codex/skills/pm-release/SKILL.md +26 -0
- package/sdk/public-surface.json +588 -20
- package/dist/cli-bundle/chunks/chunk-47OQEOQB.js +0 -2
- package/dist/cli-bundle/chunks/chunk-HCIYWD6M.js +0 -35
- package/dist/cli-bundle/chunks/chunk-IC5W2T34.js +0 -2
- package/dist/cli-bundle/chunks/chunk-PANOOBIS.js +0 -13
- package/dist/cli-bundle/chunks/chunk-TK6N7HGM.js +0 -8
- package/dist/cli-bundle/chunks/chunk-TOFG2URD.js +0 -197
- package/dist/cli-bundle/chunks/register-mutation-7YVIG54J.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-5NMFSX26.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-725JSCMP.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-DQ6SMTBF.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-JX5Z344Q.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-L4RDYBIQ.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-QYZERYR5.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-WY3WRPVN.js +0 -2
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements extension runtime contracts and governance for Loader.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="c88047fc-2bbd-5781-96a8-01685c06fb33")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { pathToFileURL } from "node:url";
|
|
@@ -28,6 +28,7 @@ import { normalizeExtensionPolicy, serializeExtensionPolicy, hydrateExtensionPol
|
|
|
28
28
|
import { createEmptyExtensionHookRegistry, createEmptyExtensionCommandRegistry, createEmptyExtensionParserRegistry, createEmptyExtensionPreflightRegistry, createEmptyExtensionServiceRegistry, createEmptyExtensionRendererRegistry, createEmptyExtensionRegistrationRegistry, } from "./extension-registries.js";
|
|
29
29
|
import { normalizeCommandName, cloneContextSnapshot, } from "./extension-runtime-helpers.js";
|
|
30
30
|
import { normalizeExtensionContributionInventory } from "./contribution-inventory.js";
|
|
31
|
+
import { formatExtensionManifestSchemaWarnings } from "./manifest-schema.js";
|
|
31
32
|
import { attachRuntimeDefinition, assertHookHandler, assertNonEmptyRegistrationString, assertRegistrationFunction, cloneRuntimeRegistrationValue, createRegistrationValidationError, extractRegistrationValidationTrace, isExtensionServiceName, isOutputRendererFormat, normalizeRegistrationRecord, normalizeRegistrationRecordList, normalizeRuntimeRegistrationRecord, normalizeRegistrationName, sanitizeRegistrationValue, toRegistrationCommandPath, validateAssuranceMeasurementProviderDefinition, } from "./registration-values.js";
|
|
32
33
|
import { buildReadyExtensionCandidate, } from "./extension-candidate.js";
|
|
33
34
|
export { parseUnknownExtensionCapabilityWarning, parseLegacyExtensionCapabilityAliasWarning, } from "./extension-capability-aliases.js";
|
|
@@ -513,8 +514,8 @@ function buildUnavailableExtensionScan(layer, directory, manifestPath, warning)
|
|
|
513
514
|
};
|
|
514
515
|
}
|
|
515
516
|
/** Collect the non-fatal load warnings for a parsed extension manifest, in detection order: legacy capability aliases, unknown capabilities, an entry outside or absent from the extension directory, then the pm version floor/ceiling incompatibility warnings. */
|
|
516
|
-
function collectScannedExtensionWarnings(layer, manifest, entryWithinDirectory, entryExists, pmVersionCompatibility, pmMaxVersionCompatibility) {
|
|
517
|
-
const extensionWarnings =
|
|
517
|
+
function collectScannedExtensionWarnings(layer, manifest, rawManifest, entryWithinDirectory, entryExists, pmVersionCompatibility, pmMaxVersionCompatibility) {
|
|
518
|
+
const extensionWarnings = formatExtensionManifestSchemaWarnings(layer, manifest, rawManifest);
|
|
518
519
|
if (Array.isArray(manifest.legacy_capability_aliases) &&
|
|
519
520
|
manifest.legacy_capability_aliases.length > 0) {
|
|
520
521
|
extensionWarnings.push(formatLegacyExtensionCapabilityAliasWarning(layer, manifest.name, manifest.legacy_capability_aliases));
|
|
@@ -543,14 +544,17 @@ async function scanExtensionDirectory(layer, extensionsRoot, directory, enabled,
|
|
|
543
544
|
return buildUnavailableExtensionScan(layer, directory, manifestPath, `extension_manifest_missing:${layer}:${directory}`);
|
|
544
545
|
}
|
|
545
546
|
let manifest;
|
|
547
|
+
let rawManifest;
|
|
546
548
|
try {
|
|
547
549
|
const parsed = JSON.parse(await fs.readFile(manifestPath, "utf8"));
|
|
550
|
+
rawManifest = asRecordLoose(parsed);
|
|
548
551
|
manifest = parseExtensionManifestDocument(parsed);
|
|
549
552
|
}
|
|
550
553
|
catch {
|
|
554
|
+
rawManifest = null;
|
|
551
555
|
manifest = null;
|
|
552
556
|
}
|
|
553
|
-
if (!manifest) {
|
|
557
|
+
if (!manifest || !rawManifest) {
|
|
554
558
|
return buildUnavailableExtensionScan(layer, directory, manifestPath, `extension_manifest_invalid:${layer}:${directory}`);
|
|
555
559
|
}
|
|
556
560
|
const entryPath = path.resolve(extensionDir, manifest.entry);
|
|
@@ -564,7 +568,7 @@ async function scanExtensionDirectory(layer, extensionsRoot, directory, enabled,
|
|
|
564
568
|
const enabledForLoad = shouldEnable(manifest.name, enabled, disabled);
|
|
565
569
|
const pmVersionCompatibility = await evaluatePmMinVersionCompatibility(layer, manifest);
|
|
566
570
|
const pmMaxVersionCompatibility = await evaluatePmMaxVersionCompatibility(layer, manifest, pmMaxVersionExceededMode);
|
|
567
|
-
const extensionWarnings = collectScannedExtensionWarnings(layer, manifest, entryWithinDirectory, entryExists, pmVersionCompatibility, pmMaxVersionCompatibility);
|
|
571
|
+
const extensionWarnings = collectScannedExtensionWarnings(layer, manifest, rawManifest, entryWithinDirectory, entryExists, pmVersionCompatibility, pmMaxVersionCompatibility);
|
|
568
572
|
const extensionReady = entryWithinDirectory &&
|
|
569
573
|
entryExists &&
|
|
570
574
|
pmVersionCompatibility.allowed &&
|
|
@@ -2221,4 +2225,4 @@ export const _testOnlyLoader = {
|
|
|
2221
2225
|
},
|
|
2222
2226
|
};
|
|
2223
2227
|
//# sourceMappingURL=loader.js.map
|
|
2224
|
-
//# debugId=
|
|
2228
|
+
//# debugId=c88047fc-2bbd-5781-96a8-01685c06fb33
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/extensions/manifest-schema
|
|
3
|
+
*
|
|
4
|
+
* Defines the closed extension-manifest key vocabulary and returns pure schema
|
|
5
|
+
* diagnostics shared by SDK authoring checks and runtime discovery.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExtensionLayer, ExtensionManifest } from "./extension-types.js";
|
|
8
|
+
/** Canonical top-level keys accepted by an extension `manifest.json`. */
|
|
9
|
+
export declare const KNOWN_EXTENSION_MANIFEST_KEYS: Set<string>;
|
|
10
|
+
/** Pure closed-schema inspection result for one raw extension manifest. */
|
|
11
|
+
export interface ExtensionManifestSchemaInspection {
|
|
12
|
+
/** Unknown top-level keys in deterministic lexical order. */
|
|
13
|
+
unknownKeys: string[];
|
|
14
|
+
/** Whether neither canonical pm compatibility bound is present. */
|
|
15
|
+
missingVersionBounds: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** Inspect raw manifest keys without parsing, loading, or mutating an extension. */
|
|
18
|
+
export declare function inspectExtensionManifestSchema(manifest: Readonly<Record<string, unknown>>): ExtensionManifestSchemaInspection;
|
|
19
|
+
/** Format runtime discovery warnings for unknown keys and absent canonical compatibility bounds. */
|
|
20
|
+
export declare function formatExtensionManifestSchemaWarnings(layer: ExtensionLayer, manifest: ExtensionManifest, rawManifest: Readonly<Record<string, unknown>>): string[];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/extensions/manifest-schema
|
|
3
|
+
*
|
|
4
|
+
* Defines the closed extension-manifest key vocabulary and returns pure schema
|
|
5
|
+
* diagnostics shared by SDK authoring checks and runtime discovery.
|
|
6
|
+
*/
|
|
7
|
+
/** Canonical top-level keys accepted by an extension `manifest.json`. */
|
|
8
|
+
|
|
9
|
+
!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]="7d9d8924-3186-5aab-ac36-164fb08624a8")}catch(e){}}();
|
|
10
|
+
export const KNOWN_EXTENSION_MANIFEST_KEYS = new Set([
|
|
11
|
+
"name",
|
|
12
|
+
"version",
|
|
13
|
+
"entry",
|
|
14
|
+
"priority",
|
|
15
|
+
"description",
|
|
16
|
+
"author",
|
|
17
|
+
"capabilities",
|
|
18
|
+
"manifest_version",
|
|
19
|
+
"pm_min_version",
|
|
20
|
+
"pm_max_version",
|
|
21
|
+
"engines",
|
|
22
|
+
"trusted",
|
|
23
|
+
"provenance",
|
|
24
|
+
"sandbox_profile",
|
|
25
|
+
"permissions",
|
|
26
|
+
"activation",
|
|
27
|
+
"contributions",
|
|
28
|
+
"legacy_capability_aliases",
|
|
29
|
+
]);
|
|
30
|
+
/** Inspect raw manifest keys without parsing, loading, or mutating an extension. */
|
|
31
|
+
export function inspectExtensionManifestSchema(manifest) {
|
|
32
|
+
return {
|
|
33
|
+
unknownKeys: Object.keys(manifest)
|
|
34
|
+
.filter((key) => !KNOWN_EXTENSION_MANIFEST_KEYS.has(key))
|
|
35
|
+
.sort((left, right) => (left > right ? 1 : -1)),
|
|
36
|
+
missingVersionBounds: manifest.pm_min_version === undefined &&
|
|
37
|
+
manifest.pm_max_version === undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Format runtime discovery warnings for unknown keys and absent canonical compatibility bounds. */
|
|
41
|
+
export function formatExtensionManifestSchemaWarnings(layer, manifest, rawManifest) {
|
|
42
|
+
const inspection = inspectExtensionManifestSchema(rawManifest);
|
|
43
|
+
const warnings = inspection.unknownKeys.map((key) => key === "compatibility"
|
|
44
|
+
? `extension_manifest_unknown_key:${layer}:${manifest.name}:key=compatibility:suggested=pm_min_version`
|
|
45
|
+
: `extension_manifest_unknown_key:${layer}:${manifest.name}:key=${key}`);
|
|
46
|
+
if (inspection.missingVersionBounds) {
|
|
47
|
+
warnings.push(`extension_manifest_no_version_bounds:${layer}:${manifest.name}:suggested=pm_min_version`);
|
|
48
|
+
}
|
|
49
|
+
return warnings;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=manifest-schema.js.map
|
|
52
|
+
//# debugId=7d9d8924-3186-5aab-ac36-164fb08624a8
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements append-only history and replay behavior for Replay.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="bf8797ec-53d3-5d23-8a6e-8296a027ddf2")}catch(e){}}();
|
|
8
8
|
import jsonPatch from "fast-json-patch";
|
|
9
9
|
import { ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
|
|
10
10
|
import { canonicalDocument } from "../item/item-format.js";
|
|
@@ -123,11 +123,30 @@ export function tryApplyReplayPatch(current, patch) {
|
|
|
123
123
|
return { ok: false, error };
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
/** Return the distinct supported hash epochs explicitly declared by a stream. */
|
|
127
|
+
function supportedExplicitHistoryItemHashVersions(entries) {
|
|
128
|
+
return [
|
|
129
|
+
...new Set(entries
|
|
130
|
+
.map((entry) => entry.item_hash_version)
|
|
131
|
+
.filter((version) => version !== undefined &&
|
|
132
|
+
SUPPORTED_HISTORY_ITEM_HASH_VERSIONS.includes(version))),
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
/** Select the hash epochs allowed for one entry under an authoritative stream marker. */
|
|
136
|
+
function historyEntryHashCandidates(explicitVersion, authoritativeVersion) {
|
|
137
|
+
if (explicitVersion !== undefined) {
|
|
138
|
+
return [explicitVersion];
|
|
139
|
+
}
|
|
140
|
+
return authoritativeVersion === undefined
|
|
141
|
+
? [1, CURRENT_HISTORY_ITEM_HASH_VERSION]
|
|
142
|
+
: [authoritativeVersion];
|
|
143
|
+
}
|
|
126
144
|
/** Deterministically verify a history chain: each entry's before_hash must equal the prior replayed after_hash, the patch must strictly apply, and the recorded after_hash must equal the replayed result. */
|
|
127
145
|
/** Verify a chain and report the explicit or auto-detected item hash epoch. */
|
|
128
146
|
export function verifyHistoryChainWithVersion(entries) {
|
|
129
147
|
let replay = cloneEmptyReplayDocument();
|
|
130
148
|
let detectedVersion;
|
|
149
|
+
let authoritativeExplicitVersion;
|
|
131
150
|
for (let index = 0; index < entries.length; index += 1) {
|
|
132
151
|
const entry = entries[index];
|
|
133
152
|
const explicitVersion = entry.item_hash_version;
|
|
@@ -147,9 +166,10 @@ export function verifyHistoryChainWithVersion(entries) {
|
|
|
147
166
|
errors: [`verify_failed:patch_apply_failed:entry_${index + 1}`],
|
|
148
167
|
};
|
|
149
168
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
169
|
+
// Prefer legacy epoch 1 when an unversioned entry is valid under both
|
|
170
|
+
// algorithms, but retain compatibility with transitional epoch-2 writers
|
|
171
|
+
// that shipped before item_hash_version became explicit.
|
|
172
|
+
const candidates = historyEntryHashCandidates(explicitVersion, authoritativeExplicitVersion);
|
|
153
173
|
const beforeMatches = candidates.filter((version) => replayHash(replay, version) === entry.before_hash);
|
|
154
174
|
if (beforeMatches.length === 0) {
|
|
155
175
|
return {
|
|
@@ -166,6 +186,9 @@ export function verifyHistoryChainWithVersion(entries) {
|
|
|
166
186
|
}
|
|
167
187
|
replay = applied.document;
|
|
168
188
|
detectedVersion = version;
|
|
189
|
+
if (explicitVersion !== undefined) {
|
|
190
|
+
authoritativeExplicitVersion = version;
|
|
191
|
+
}
|
|
169
192
|
}
|
|
170
193
|
return {
|
|
171
194
|
ok: true,
|
|
@@ -228,19 +251,14 @@ export function lenientApplyReplayPatch(current, patch) {
|
|
|
228
251
|
* irreconcilably mixed stream falls forward to the current epoch.
|
|
229
252
|
*/
|
|
230
253
|
export function resolveHistoryRepairItemHashVersion(entries) {
|
|
254
|
+
const explicitVersions = supportedExplicitHistoryItemHashVersions(entries);
|
|
255
|
+
if (explicitVersions.length === 1) {
|
|
256
|
+
return explicitVersions[0];
|
|
257
|
+
}
|
|
231
258
|
const verified = verifyHistoryChainWithVersion(entries);
|
|
232
259
|
if (verified.ok && verified.item_hash_version !== undefined) {
|
|
233
260
|
return verified.item_hash_version;
|
|
234
261
|
}
|
|
235
|
-
const explicitVersions = [
|
|
236
|
-
...new Set(entries
|
|
237
|
-
.map((entry) => entry.item_hash_version)
|
|
238
|
-
.filter((version) => version !== undefined &&
|
|
239
|
-
SUPPORTED_HISTORY_ITEM_HASH_VERSIONS.includes(version))),
|
|
240
|
-
];
|
|
241
|
-
if (explicitVersions.length === 1) {
|
|
242
|
-
return explicitVersions[0];
|
|
243
|
-
}
|
|
244
262
|
if (explicitVersions.length === 0) {
|
|
245
263
|
return 1;
|
|
246
264
|
}
|
|
@@ -333,4 +351,4 @@ export function historyEntriesToRaw(entries) {
|
|
|
333
351
|
return `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`;
|
|
334
352
|
}
|
|
335
353
|
//# sourceMappingURL=replay.js.map
|
|
336
|
-
//# debugId=
|
|
354
|
+
//# debugId=bf8797ec-53d3-5d23-8a6e-8296a027ddf2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RuntimeFieldCommand, RuntimeFieldDefinition, RuntimeFieldType } from "../../types/index.js";
|
|
2
2
|
export { normalizeStatusToken as normalizeFieldKey } from "./status-token.js";
|
|
3
|
-
export type { RuntimeFieldCommand, RuntimeFieldDefinition, RuntimeFieldType, } from "../../types/index.js";
|
|
3
|
+
export type { RuntimeFieldCommand, RuntimeFieldDefinition, RuntimeFieldValueSchema, RuntimeFieldType, } from "../../types/index.js";
|
|
4
4
|
/** Built-in item-metadata field names a custom field key must never shadow. A custom key that collides with one of these would let `pm create --<key>` write over reserved metadata, so add-field rejects them up front (symmetric with the built-in-type guard in item-types-file.ts). */
|
|
5
5
|
export declare const BUILTIN_FIELD_KEYS: ReadonlySet<string>;
|
|
6
6
|
/** The shape persisted at `.agents/pm/schema/fields.json`. */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Resolves configurable schema, fields, statuses, and workflows for Fields File.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="2b5a573e-1e36-58b9-b93b-4a4088f71e9a")}catch(e){}}();
|
|
8
8
|
import { RUNTIME_FIELD_COMMAND_VALUES, RUNTIME_FIELD_TYPE_VALUES, } from "../../types/index.js";
|
|
9
9
|
import { ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
|
|
10
10
|
import { normalizeStatusToken as normalizeFieldKey } from "./status-token.js";
|
|
@@ -286,4 +286,4 @@ function applyBooleanFlag(definition, key, value) {
|
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
//# sourceMappingURL=fields-file.js.map
|
|
289
|
-
//# debugId=
|
|
289
|
+
//# debugId=2b5a573e-1e36-58b9-b93b-4a4088f71e9a
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
* Resolves configurable schema, fields, statuses, and workflows for Runtime Field Values.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="91a3969e-59b3-506e-9349-ca08e73a1228")}catch(e){}}();
|
|
8
8
|
import { EXIT_CODE } from "../shared/constants.js";
|
|
9
9
|
import { PmCliError } from "../shared/errors.js";
|
|
10
|
+
import { stableStringify } from "../shared/serialization.js";
|
|
11
|
+
import { isRfc3339DateTime } from "../shared/time.js";
|
|
10
12
|
import { runtimeFieldOptionTarget, } from "./runtime-schema.js";
|
|
13
|
+
const MAX_VALUE_SCHEMA_DEPTH = 16;
|
|
11
14
|
function toCamelToken(value) {
|
|
12
15
|
const segments = value
|
|
13
16
|
.trim()
|
|
@@ -116,6 +119,109 @@ function parseJsonContainerValue(raw, label, expectedType) {
|
|
|
116
119
|
}
|
|
117
120
|
throw new PmCliError(`${label} must be valid JSON ${expectedType}`, EXIT_CODE.USAGE);
|
|
118
121
|
}
|
|
122
|
+
function valueMatchesSchemaType(value, type) {
|
|
123
|
+
if (type === undefined)
|
|
124
|
+
return true;
|
|
125
|
+
if (type === "array")
|
|
126
|
+
return Array.isArray(value);
|
|
127
|
+
if (type === "object") {
|
|
128
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
129
|
+
}
|
|
130
|
+
return typeof value === type;
|
|
131
|
+
}
|
|
132
|
+
function runtimeFieldPrimitiveSchemaError(value, schema, path) {
|
|
133
|
+
if (schema.const !== undefined &&
|
|
134
|
+
stableStringify(value) !== stableStringify(schema.const)) {
|
|
135
|
+
return `${path} must equal ${stableStringify(schema.const)}`;
|
|
136
|
+
}
|
|
137
|
+
if (schema.enum !== undefined &&
|
|
138
|
+
!schema.enum.some((candidate) => stableStringify(candidate) === stableStringify(value))) {
|
|
139
|
+
return `${path} must be one of ${schema.enum.map((entry) => stableStringify(entry)).join("|")}`;
|
|
140
|
+
}
|
|
141
|
+
if (!valueMatchesSchemaType(value, schema.type)) {
|
|
142
|
+
return `${path} must match configured type ${String(schema.type)}`;
|
|
143
|
+
}
|
|
144
|
+
if (typeof value === "string") {
|
|
145
|
+
if (schema.min_length !== undefined && value.length < schema.min_length) {
|
|
146
|
+
return `${path} must contain at least ${schema.min_length} characters`;
|
|
147
|
+
}
|
|
148
|
+
if (schema.format === "date-time" && !isRfc3339DateTime(value)) {
|
|
149
|
+
return `${path} must be an RFC 3339 date-time`;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
function runtimeFieldArraySchemaError(value, schema, path, depth) {
|
|
155
|
+
if (!Array.isArray(value))
|
|
156
|
+
return undefined;
|
|
157
|
+
if (schema.min_items !== undefined && value.length < schema.min_items) {
|
|
158
|
+
return `${path} must contain at least ${schema.min_items} items`;
|
|
159
|
+
}
|
|
160
|
+
if (!schema.items)
|
|
161
|
+
return undefined;
|
|
162
|
+
for (const [index, entry] of value.entries()) {
|
|
163
|
+
const error = runtimeFieldSchemaError(entry, schema.items, `${path}[${index}]`, depth + 1);
|
|
164
|
+
if (error)
|
|
165
|
+
return error;
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
function runtimeFieldObjectSchemaError(value, schema, path, depth) {
|
|
170
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
171
|
+
return undefined;
|
|
172
|
+
const record = value;
|
|
173
|
+
for (const key of schema.required ?? []) {
|
|
174
|
+
if (!Object.hasOwn(record, key))
|
|
175
|
+
return `${path}.${key} is required`;
|
|
176
|
+
}
|
|
177
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
178
|
+
const propertySchema = schema.properties?.[key];
|
|
179
|
+
if (!propertySchema) {
|
|
180
|
+
if (schema.additional_properties === false)
|
|
181
|
+
return `${path}.${key} is not allowed`;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const error = runtimeFieldSchemaError(entry, propertySchema, `${path}.${key}`, depth + 1);
|
|
185
|
+
if (error)
|
|
186
|
+
return error;
|
|
187
|
+
}
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
/** Return the first semantic schema mismatch without mutating the input value. */
|
|
191
|
+
function runtimeFieldSchemaError(value, schema, path, depth = 0) {
|
|
192
|
+
if (depth > MAX_VALUE_SCHEMA_DEPTH)
|
|
193
|
+
return `${path} value schema exceeds maximum depth`;
|
|
194
|
+
const directError = runtimeFieldPrimitiveSchemaError(value, schema, path);
|
|
195
|
+
if (directError)
|
|
196
|
+
return directError;
|
|
197
|
+
const arrayError = runtimeFieldArraySchemaError(value, schema, path, depth);
|
|
198
|
+
if (arrayError)
|
|
199
|
+
return arrayError;
|
|
200
|
+
const objectError = runtimeFieldObjectSchemaError(value, schema, path, depth);
|
|
201
|
+
if (objectError)
|
|
202
|
+
return objectError;
|
|
203
|
+
if (!schema.one_of)
|
|
204
|
+
return undefined;
|
|
205
|
+
let matches = 0;
|
|
206
|
+
for (const candidate of schema.one_of) {
|
|
207
|
+
if (runtimeFieldSchemaError(value, candidate, path, depth + 1) === undefined) {
|
|
208
|
+
matches += 1;
|
|
209
|
+
if (matches > 1)
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return matches === 1
|
|
214
|
+
? undefined
|
|
215
|
+
: `${path} must match exactly one configured schema variant`;
|
|
216
|
+
}
|
|
217
|
+
function validateRuntimeFieldValue(definition, value, label) {
|
|
218
|
+
if (!definition.value_schema || value === undefined)
|
|
219
|
+
return value;
|
|
220
|
+
const error = runtimeFieldSchemaError(value, definition.value_schema, label);
|
|
221
|
+
if (error)
|
|
222
|
+
throw new PmCliError(error, EXIT_CODE.USAGE);
|
|
223
|
+
return value;
|
|
224
|
+
}
|
|
119
225
|
/** Implements coerce runtime field value for the public runtime surface of this module. */
|
|
120
226
|
export function coerceRuntimeFieldValue(definition, rawValue, labelOverride) {
|
|
121
227
|
const label = labelOverride ?? `--${definition.cli_flag}`;
|
|
@@ -126,17 +232,17 @@ export function coerceRuntimeFieldValue(definition, rawValue, labelOverride) {
|
|
|
126
232
|
if (containerRaw === undefined) {
|
|
127
233
|
return undefined;
|
|
128
234
|
}
|
|
129
|
-
return parseJsonContainerValue(containerRaw, label, definition.type);
|
|
235
|
+
return validateRuntimeFieldValue(definition, parseJsonContainerValue(containerRaw, label, definition.type), label);
|
|
130
236
|
}
|
|
131
237
|
if (definition.repeatable || definition.type === "string_array") {
|
|
132
238
|
const values = normalizeStringArrayValue(rawValue);
|
|
133
239
|
if (definition.type === "number") {
|
|
134
|
-
return values.map((value) => parseNumberValue(value, label));
|
|
240
|
+
return validateRuntimeFieldValue(definition, values.map((value) => parseNumberValue(value, label)), label);
|
|
135
241
|
}
|
|
136
242
|
if (definition.type === "boolean") {
|
|
137
|
-
return values.map((value) => parseBooleanValue(value, label));
|
|
243
|
+
return validateRuntimeFieldValue(definition, values.map((value) => parseBooleanValue(value, label)), label);
|
|
138
244
|
}
|
|
139
|
-
return values;
|
|
245
|
+
return validateRuntimeFieldValue(definition, values, label);
|
|
140
246
|
}
|
|
141
247
|
const scalarRaw = Array.isArray(rawValue)
|
|
142
248
|
? rawValue[rawValue.length - 1]
|
|
@@ -145,12 +251,12 @@ export function coerceRuntimeFieldValue(definition, rawValue, labelOverride) {
|
|
|
145
251
|
return undefined;
|
|
146
252
|
}
|
|
147
253
|
if (definition.type === "number") {
|
|
148
|
-
return parseNumberValue(scalarRaw, label);
|
|
254
|
+
return validateRuntimeFieldValue(definition, parseNumberValue(scalarRaw, label), label);
|
|
149
255
|
}
|
|
150
256
|
if (definition.type === "boolean") {
|
|
151
|
-
return parseBooleanValue(scalarRaw, label);
|
|
257
|
+
return validateRuntimeFieldValue(definition, parseBooleanValue(scalarRaw, label), label);
|
|
152
258
|
}
|
|
153
|
-
return typeof scalarRaw === "string" ? scalarRaw : String(scalarRaw);
|
|
259
|
+
return validateRuntimeFieldValue(definition, typeof scalarRaw === "string" ? scalarRaw : String(scalarRaw), label);
|
|
154
260
|
}
|
|
155
261
|
function shouldRequireFieldOnCreate(definition, itemTypeName) {
|
|
156
262
|
if (!definition.required && !definition.required_on_create) {
|
|
@@ -205,4 +311,4 @@ export function collectRuntimeUpdateFieldValues(options, fieldRegistry, commands
|
|
|
205
311
|
return values;
|
|
206
312
|
}
|
|
207
313
|
//# sourceMappingURL=runtime-field-values.js.map
|
|
208
|
-
//# debugId=
|
|
314
|
+
//# debugId=91a3969e-59b3-506e-9349-ca08e73a1228
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ItemTypeDefinition, RuntimeFieldCommand, RuntimeFieldType, RuntimeSchemaSettings, RuntimeStatusDefinition, RuntimeStatusRole, RuntimeWorkflowDefinition } from "../../types/index.js";
|
|
1
|
+
import type { ItemTypeDefinition, RuntimeFieldCommand, RuntimeFieldValueSchema, RuntimeFieldType, RuntimeSchemaSettings, RuntimeStatusDefinition, RuntimeStatusRole, RuntimeWorkflowDefinition } from "../../types/index.js";
|
|
2
2
|
export type { RuntimeFieldCommand } from "../../types/index.js";
|
|
3
3
|
/** Fallback runtime schema file paths used when callers do not provide an override. */
|
|
4
4
|
export declare const DEFAULT_RUNTIME_SCHEMA_FILE_PATHS: Readonly<{
|
|
@@ -50,6 +50,8 @@ export interface RuntimeFieldDefinitionResolved {
|
|
|
50
50
|
required_types: string[];
|
|
51
51
|
/** Value that configures or reports allow unset for this contract. */
|
|
52
52
|
allow_unset: boolean;
|
|
53
|
+
/** Optional semantic JSON-value constraints enforced on create and update. */
|
|
54
|
+
value_schema?: RuntimeFieldValueSchema;
|
|
53
55
|
}
|
|
54
56
|
/** Documents the runtime status registry payload exchanged by command, SDK, and package integrations. */
|
|
55
57
|
export interface RuntimeStatusRegistry {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Resolves configurable schema, fields, statuses, and workflows for Runtime Schema.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="88b9179f-569e-5cd6-b67c-c27431961554")}catch(e){}}();
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { pathExists, readFileIfExists, writeFileAtomic, } from "../fs/fs-utils.js";
|
|
10
10
|
import { DEFAULT_STATUS_DEFINITIONS, DEFAULT_WORKFLOW_DEFINITION, } from "../shared/constants.js";
|
|
@@ -32,6 +32,119 @@ const RUNTIME_STATUS_ROLE_SET = new Set(RUNTIME_STATUS_ROLE_VALUES);
|
|
|
32
32
|
const RUNTIME_FIELD_TYPE_SET = new Set(RUNTIME_FIELD_TYPE_VALUES);
|
|
33
33
|
const RUNTIME_FIELD_COMMAND_SET = new Set(RUNTIME_FIELD_COMMAND_VALUES);
|
|
34
34
|
const RUNTIME_UNKNOWN_FIELD_POLICY_SET = new Set(RUNTIME_UNKNOWN_FIELD_POLICY_VALUES);
|
|
35
|
+
const RUNTIME_FIELD_VALUE_TYPE_SET = new Set([
|
|
36
|
+
"string",
|
|
37
|
+
"number",
|
|
38
|
+
"boolean",
|
|
39
|
+
"array",
|
|
40
|
+
"object",
|
|
41
|
+
]);
|
|
42
|
+
const MAX_RUNTIME_FIELD_VALUE_SCHEMA_DEPTH = 16;
|
|
43
|
+
function isPlainObject(value) {
|
|
44
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45
|
+
}
|
|
46
|
+
const RUNTIME_FIELD_VALUE_SCHEMA_SHAPE_VALIDATORS = [
|
|
47
|
+
(schema) => schema.type === undefined ||
|
|
48
|
+
(typeof schema.type === "string" &&
|
|
49
|
+
RUNTIME_FIELD_VALUE_TYPE_SET.has(schema.type)),
|
|
50
|
+
(schema) => !Object.hasOwn(schema, "const") || isStructuredJsonValue(schema.const),
|
|
51
|
+
(schema) => schema.enum === undefined ||
|
|
52
|
+
(Array.isArray(schema.enum) &&
|
|
53
|
+
schema.enum.every((entry) => isStructuredJsonValue(entry))),
|
|
54
|
+
(schema) => schema.min_length === undefined ||
|
|
55
|
+
(Number.isInteger(schema.min_length) &&
|
|
56
|
+
schema.min_length >= 0),
|
|
57
|
+
(schema) => schema.min_items === undefined ||
|
|
58
|
+
(Number.isInteger(schema.min_items) && schema.min_items >= 0),
|
|
59
|
+
(schema) => schema.format === undefined || schema.format === "date-time",
|
|
60
|
+
(schema) => schema.required === undefined ||
|
|
61
|
+
(Array.isArray(schema.required) &&
|
|
62
|
+
schema.required.every((entry) => typeof entry === "string" && entry.length > 0)),
|
|
63
|
+
(schema) => schema.additional_properties === undefined ||
|
|
64
|
+
typeof schema.additional_properties === "boolean",
|
|
65
|
+
(schema) => schema.properties === undefined ||
|
|
66
|
+
isPlainObject(schema.properties),
|
|
67
|
+
(schema) => schema.one_of === undefined ||
|
|
68
|
+
(Array.isArray(schema.one_of) && schema.one_of.length > 0),
|
|
69
|
+
];
|
|
70
|
+
function isStructuredJsonValue(value, ancestors = new Set()) {
|
|
71
|
+
if (value === null ||
|
|
72
|
+
typeof value === "string" ||
|
|
73
|
+
typeof value === "boolean") {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (typeof value === "number")
|
|
77
|
+
return Number.isFinite(value);
|
|
78
|
+
if (typeof value !== "object" || ancestors.has(value))
|
|
79
|
+
return false;
|
|
80
|
+
ancestors.add(value);
|
|
81
|
+
const valid = Array.isArray(value)
|
|
82
|
+
? value.every((entry) => isStructuredJsonValue(entry, ancestors))
|
|
83
|
+
: Object.values(value).every((entry) => isStructuredJsonValue(entry, ancestors));
|
|
84
|
+
ancestors.delete(value);
|
|
85
|
+
return valid;
|
|
86
|
+
}
|
|
87
|
+
/** Normalize an untrusted recursive custom-field value schema or reject it. */
|
|
88
|
+
function normalizeRuntimeFieldValueSchema(value, depth = 0, ancestors = new Set()) {
|
|
89
|
+
if (!isPlainObject(value) ||
|
|
90
|
+
depth > MAX_RUNTIME_FIELD_VALUE_SCHEMA_DEPTH ||
|
|
91
|
+
ancestors.has(value)) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
ancestors.add(value);
|
|
95
|
+
const schema = value;
|
|
96
|
+
const type = schema.type;
|
|
97
|
+
const enumValues = schema.enum;
|
|
98
|
+
const oneOf = schema.one_of;
|
|
99
|
+
const properties = schema.properties;
|
|
100
|
+
const items = schema.items;
|
|
101
|
+
const required = schema.required;
|
|
102
|
+
const minLength = schema.min_length;
|
|
103
|
+
const minItems = schema.min_items;
|
|
104
|
+
const format = schema.format;
|
|
105
|
+
const additionalProperties = schema.additional_properties;
|
|
106
|
+
if (!RUNTIME_FIELD_VALUE_SCHEMA_SHAPE_VALIDATORS.every((check) => check(schema))) {
|
|
107
|
+
ancestors.delete(value);
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const normalizedProperties = properties === undefined
|
|
111
|
+
? undefined
|
|
112
|
+
: Object.fromEntries(Object.entries(properties).map(([key, entry]) => [
|
|
113
|
+
key,
|
|
114
|
+
normalizeRuntimeFieldValueSchema(entry, depth + 1, ancestors),
|
|
115
|
+
]));
|
|
116
|
+
const normalizedItems = items === undefined
|
|
117
|
+
? undefined
|
|
118
|
+
: normalizeRuntimeFieldValueSchema(items, depth + 1, ancestors);
|
|
119
|
+
const normalizedOneOf = oneOf === undefined
|
|
120
|
+
? undefined
|
|
121
|
+
: oneOf.map((entry) => normalizeRuntimeFieldValueSchema(entry, depth + 1, ancestors));
|
|
122
|
+
const normalizedNestedSchemas = [
|
|
123
|
+
...Object.values(normalizedProperties ?? {}),
|
|
124
|
+
...(items === undefined ? [] : [normalizedItems]),
|
|
125
|
+
...(normalizedOneOf ?? []),
|
|
126
|
+
];
|
|
127
|
+
if (normalizedNestedSchemas.some((entry) => entry === undefined)) {
|
|
128
|
+
ancestors.delete(value);
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
ancestors.delete(value);
|
|
132
|
+
return Object.fromEntries(Object.entries({
|
|
133
|
+
type: type,
|
|
134
|
+
const: Object.hasOwn(schema, "const") ? schema.const : undefined,
|
|
135
|
+
enum: enumValues,
|
|
136
|
+
min_length: minLength,
|
|
137
|
+
min_items: minItems,
|
|
138
|
+
format: format,
|
|
139
|
+
properties: normalizedProperties,
|
|
140
|
+
required: required === undefined
|
|
141
|
+
? undefined
|
|
142
|
+
: [...new Set(required)],
|
|
143
|
+
additional_properties: additionalProperties,
|
|
144
|
+
items: normalizedItems,
|
|
145
|
+
one_of: normalizedOneOf,
|
|
146
|
+
}).filter(([, entry]) => entry !== undefined));
|
|
147
|
+
}
|
|
35
148
|
function normalizeStringList(values) {
|
|
36
149
|
const candidates = Array.isArray(values) ? values : [];
|
|
37
150
|
return [
|
|
@@ -202,6 +315,12 @@ function normalizeRuntimeFieldDefinition(definition) {
|
|
|
202
315
|
})();
|
|
203
316
|
const description = definition.description?.trim();
|
|
204
317
|
const requiredTypes = normalizeStringList(definition.required_types);
|
|
318
|
+
const valueSchema = definition.value_schema === undefined
|
|
319
|
+
? undefined
|
|
320
|
+
: normalizeRuntimeFieldValueSchema(definition.value_schema);
|
|
321
|
+
if (definition.value_schema !== undefined && valueSchema === undefined) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
205
324
|
return {
|
|
206
325
|
key,
|
|
207
326
|
metadata_key: metadataKey,
|
|
@@ -210,11 +329,12 @@ function normalizeRuntimeFieldDefinition(definition) {
|
|
|
210
329
|
description: description && description.length > 0 ? description : undefined,
|
|
211
330
|
type,
|
|
212
331
|
commands,
|
|
213
|
-
repeatable: definition.repeatable === true
|
|
332
|
+
repeatable: [definition.repeatable === true, type === "string_array"].includes(true),
|
|
214
333
|
required: definition.required === true,
|
|
215
334
|
required_on_create: definition.required_on_create === true,
|
|
216
335
|
required_types: requiredTypes,
|
|
217
336
|
allow_unset: definition.allow_unset !== false,
|
|
337
|
+
value_schema: valueSchema,
|
|
218
338
|
};
|
|
219
339
|
}
|
|
220
340
|
function normalizeRuntimeStatusDefinitions(statusesSource) {
|
|
@@ -277,6 +397,7 @@ function serializeRuntimeFieldDefinition(definition) {
|
|
|
277
397
|
? [...definition.required_types]
|
|
278
398
|
: undefined,
|
|
279
399
|
allow_unset: definition.allow_unset === false ? false : undefined,
|
|
400
|
+
value_schema: definition.value_schema,
|
|
280
401
|
};
|
|
281
402
|
}
|
|
282
403
|
function normalizeUnknownFieldPolicy(policy) {
|
|
@@ -691,4 +812,4 @@ export function statusIsTerminal(status, registry) {
|
|
|
691
812
|
return registry.terminal_statuses.has(normalized);
|
|
692
813
|
}
|
|
693
814
|
//# sourceMappingURL=runtime-schema.js.map
|
|
694
|
-
//# debugId=
|
|
815
|
+
//# debugId=88b9179f-569e-5cd6-b67c-c27431961554
|
|
@@ -63,6 +63,16 @@ export interface PmCliErrorContext {
|
|
|
63
63
|
measurement_id?: string;
|
|
64
64
|
/** Assurance measurement source kind involved in a refusal, when known. */
|
|
65
65
|
source_kind?: string;
|
|
66
|
+
/** Source item whose endpoint metadata violated a relationship contract. */
|
|
67
|
+
source_id?: string;
|
|
68
|
+
/** Source item creation time used to evaluate a temporal relationship contract. */
|
|
69
|
+
source_created_at?: string;
|
|
70
|
+
/** Target item whose endpoint metadata violated a relationship contract. */
|
|
71
|
+
target_id?: string;
|
|
72
|
+
/** Target item creation time used to evaluate a temporal relationship contract. */
|
|
73
|
+
target_created_at?: string;
|
|
74
|
+
/** Temporal relationship rule evaluated for the source and target. */
|
|
75
|
+
temporal_order?: string;
|
|
66
76
|
/** Validate or health check selected by an assurance source, when known. */
|
|
67
77
|
check?: string;
|
|
68
78
|
/** Serialization format involved in a parse failure. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Implements the exported pm cli error runtime abstraction for core/shared/errors.ts. */
|
|
2
2
|
|
|
3
|
-
!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]="
|
|
3
|
+
!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]="c863f07f-428b-5b7f-a5f7-23e7f5fa749a")}catch(e){}}();
|
|
4
4
|
export class PmCliError extends Error {
|
|
5
5
|
/** Value that configures or reports exit code for this contract. */
|
|
6
6
|
exitCode;
|
|
@@ -18,4 +18,4 @@ export class PmCliError extends Error {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
//# sourceMappingURL=errors.js.map
|
|
21
|
-
//# debugId=
|
|
21
|
+
//# debugId=c863f07f-428b-5b7f-a5f7-23e7f5fa749a
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export declare function nowIso(): string;
|
|
3
3
|
/** Implements check whether timestamp literal for the public runtime surface of this module. */
|
|
4
4
|
export declare function isTimestampLiteral(input: string): boolean;
|
|
5
|
+
/** Return whether a string is a calendar-valid RFC 3339 date-time. */
|
|
6
|
+
export declare function isRfc3339DateTime(input: string): boolean;
|
|
5
7
|
/** Implements compare timestamp strings for the public runtime surface of this module. */
|
|
6
8
|
export declare function compareTimestampStrings(left: string, right: string): number;
|
|
7
9
|
/** Timestamp-bearing record accepted by shared inclusive bound filtering. */
|