@happyvertical/smrt-playbooks 0.44.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/__smrt-register__.ts","../src/cache.ts","../src/utils.ts","../src/playbook-registry.ts","../src/models/PlaybookOverride.ts","../src/collections/PlaybookOverrideCollection.ts","../src/playbook-resolver.ts","../src/index.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt()\n * decorator in the package fires. Fixes issue #1132: in consumer runtimes\n * (tsx, SvelteKit SSR, plain `vite dev`) the decorator's synchronous manifest\n * lookup previously missed because no step populated the global manifest cache\n * — classes got registered with zero fields and `save()` / `toJSON()`\n * silently dropped every declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates\n * manifests via a different path. Only needs to succeed in the published dist\n * output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// During library builds, smrtPlugin replaces this entire module with generated\n// code that embeds the scanned manifest inline (#1506/#1507) — published dists\n// never resolve this URL, so downstream bundlers cannot break registration by\n// relocating the compiled module away from dist/manifest.json. The runtime\n// lookup below is the fallback for source-mode runs without that transform.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","import type { DatabaseInterface } from '@happyvertical/sql';\nimport type { PlaybookCacheValue } from './types.js';\n\nconst PLAYBOOK_CACHE_TTL_MS = 30_000;\n\ntype CacheEntry = {\n expiresAt: number;\n value: PlaybookCacheValue;\n};\n\nconst playbookCache = new Map<string, CacheEntry>();\n/** Monotonic per-`(db, key)` invalidation counter; see getPlaybookCacheGeneration. */\nconst cacheGenerations = new Map<string, number>();\nconst dbInstanceIds = new WeakMap<object, string>();\nlet nextDbId = 1;\n\nfunction getDbNamespace(db: unknown): string {\n if (!db) {\n return 'no-db';\n }\n\n if (typeof db === 'string') {\n return `db:${db}`;\n }\n\n if (typeof db === 'object') {\n const dbObject = db as Record<string, unknown>;\n if (typeof dbObject.query === 'function') {\n if (!dbInstanceIds.has(dbObject)) {\n dbInstanceIds.set(dbObject, `db-instance:${nextDbId++}`);\n }\n const namespace = dbInstanceIds.get(dbObject);\n if (namespace) {\n return namespace;\n }\n\n return 'db-instance:unknown';\n }\n\n try {\n return `db-config:${JSON.stringify(dbObject)}`;\n } catch {\n return 'db-config:opaque';\n }\n }\n\n return 'db:unknown';\n}\n\nfunction buildCacheKey(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): string {\n return `${getDbNamespace(db)}::${key}::${tenantId ?? 'app'}`;\n}\n\nfunction buildGenerationKey(\n key: string,\n db: DatabaseInterface | unknown,\n): string {\n return `${getDbNamespace(db)}::${key}`;\n}\n\nfunction bumpGeneration(key: string, db: DatabaseInterface | unknown): void {\n const generationKey = buildGenerationKey(key, db);\n cacheGenerations.set(\n generationKey,\n (cacheGenerations.get(generationKey) ?? 0) + 1,\n );\n}\n\nexport function getPlaybookCacheTtlMs(): number {\n return PLAYBOOK_CACHE_TTL_MS;\n}\n\nexport function getCachedPlaybookBase(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): PlaybookCacheValue | null {\n const cacheKey = buildCacheKey(key, tenantId, db);\n const cached = playbookCache.get(cacheKey);\n\n if (!cached) {\n return null;\n }\n\n if (cached.expiresAt <= Date.now()) {\n playbookCache.delete(cacheKey);\n return null;\n }\n\n return cached.value;\n}\n\n/**\n * Reads the current invalidation generation for a key.\n *\n * A resolution captures this *before* its asynchronous layer loads and hands\n * it back to {@link setCachedPlaybookBase}. Any write that lands while those\n * loads are in flight bumps the generation, so the in-flight resolution — which\n * read the pre-write layers — is refused the cache write instead of\n * repopulating the key it just invalidated. Without this, the acceptance rule\n * \"a stale entry is never served after a write\" held only until a read raced a\n * write, and then failed for the full TTL.\n *\n * Tracked per `(db, key)` rather than per `(db, key, tenantId)`: an app-level\n * row is inherited by every tenant, so a write to any scope of a key must\n * invalidate every scope of it.\n */\nexport function getPlaybookCacheGeneration(\n key: string,\n db: DatabaseInterface | unknown,\n): number {\n return cacheGenerations.get(buildGenerationKey(key, db)) ?? 0;\n}\n\nexport function setCachedPlaybookBase(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n value: PlaybookCacheValue,\n loadedAtGeneration: number,\n): void {\n if (getPlaybookCacheGeneration(key, db) !== loadedAtGeneration) {\n // A write landed while this resolution was loading. Its value is already\n // stale, so drop it rather than poison the key for the whole TTL.\n return;\n }\n\n playbookCache.set(buildCacheKey(key, tenantId, db), {\n expiresAt: Date.now() + PLAYBOOK_CACHE_TTL_MS,\n value,\n });\n}\n\n/**\n * Invalidates a cached resolution. An app-level write (tenantId null) clears\n * every tenant's entry for that key, because each tenant inherits from it.\n */\nexport function invalidatePlaybookCache(\n key: string,\n tenantId: string | null | undefined,\n db: DatabaseInterface | unknown,\n): void {\n const dbNamespace = getDbNamespace(db);\n bumpGeneration(key, db);\n\n if (tenantId !== null && tenantId !== undefined) {\n playbookCache.delete(buildCacheKey(key, tenantId, db));\n return;\n }\n\n const keyPrefix = `${dbNamespace}::${key}::`;\n for (const cacheKey of playbookCache.keys()) {\n if (cacheKey.startsWith(keyPrefix)) {\n playbookCache.delete(cacheKey);\n }\n }\n}\n\nexport function clearPlaybookCache(): void {\n playbookCache.clear();\n // Generations deliberately survive: resetting them to zero would let a\n // resolution that started before the clear write its stale value back.\n for (const generationKey of cacheGenerations.keys()) {\n cacheGenerations.set(\n generationKey,\n (cacheGenerations.get(generationKey) ?? 0) + 1,\n );\n }\n}\n","import type {\n CapabilityClassification,\n CapabilityDeclaration,\n} from '@happyvertical/smrt-types';\nimport {\n PLAYBOOK_PLANES,\n type PlaybookConfigOverrideInput,\n type PlaybookDefinition,\n type PlaybookDefinitionInput,\n type PlaybookEditableConfig,\n type PlaybookFailurePolicy,\n type PlaybookLayer,\n type PlaybookMetadata,\n type PlaybookPlane,\n type PlaybookStep,\n} from './types.js';\n\n/**\n * Every field defaults to non-editable, matching `normalizeEditableConfig` in\n * `@happyvertical/smrt-prompts`. `steps` is not in this table at all — it is\n * structurally non-editable rather than defaulted false.\n */\nconst DEFAULT_EDITABLE: PlaybookEditableConfig = {\n title: false,\n description: false,\n planes: false,\n onStepFailure: false,\n enabled: false,\n metadata: false,\n};\n\n/**\n * Fail-closed capability classification, per epic #2585 invariant 3. Applied\n * whenever the host cannot tell us how a referenced operation is classified.\n */\nexport const FAIL_CLOSED_CLASSIFICATION: CapabilityClassification = {\n effect: 'destructive',\n idempotent: false,\n openWorld: true,\n};\n\nconst FAILURE_POLICIES = new Set<PlaybookFailurePolicy>(['abort', 'continue']);\n\n/**\n * `<package>:<Class>` — the same qualified form STI discriminators and\n * `@crossPackageRef` use. Both halves are required and neither may be padded.\n */\nconst QUALIFIED_MODEL_PATTERN = /^\\S+:\\S+$/;\n\n/** Frozen so a definition's default plane list can never be mutated in place. */\nconst BROWSER_ONLY_PLANES: readonly PlaybookPlane[] = Object.freeze([\n 'browser',\n]);\n\nexport function isPlainObject(\n value: unknown,\n): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function normalizeEditableConfig(\n editable?: Partial<PlaybookEditableConfig>,\n): PlaybookEditableConfig {\n const flag = (name: keyof PlaybookEditableConfig): boolean => {\n const supplied = editable?.[name];\n if (supplied === undefined) {\n return DEFAULT_EDITABLE[name];\n }\n\n // Only a real `true` unlocks a field. A truthy non-boolean such as\n // `'false'` would otherwise read as an explicit opt-in and open a stored\n // override the definition never meant to allow.\n if (typeof supplied !== 'boolean') {\n throw new Error(\n `Playbook editable.${name} must be a boolean, received ${typeof supplied} \"${String(supplied)}\"`,\n );\n }\n\n return supplied;\n };\n\n return {\n title: flag('title'),\n description: flag('description'),\n planes: flag('planes'),\n onStepFailure: flag('onStepFailure'),\n enabled: flag('enabled'),\n metadata: flag('metadata'),\n };\n}\n\n/**\n * Applies a partial capability declaration over the fail-closed default.\n *\n * A playbook step never classifies itself: this only fills the gaps left by a\n * declaration that the host inherited from the referenced operation.\n */\nexport function applyCapabilityDeclaration(\n declaration?: CapabilityDeclaration | null,\n): CapabilityClassification {\n if (!isPlainObject(declaration)) {\n return { ...FAIL_CLOSED_CLASSIFICATION };\n }\n\n return {\n effect: declaration.effect ?? FAIL_CLOSED_CLASSIFICATION.effect,\n idempotent: declaration.idempotent ?? FAIL_CLOSED_CLASSIFICATION.idempotent,\n openWorld: declaration.openWorld ?? FAIL_CLOSED_CLASSIFICATION.openWorld,\n };\n}\n\nexport function isCapabilityDeclarationComplete(\n declaration?: CapabilityDeclaration | null,\n): boolean {\n return (\n isPlainObject(declaration) &&\n declaration.effect !== undefined &&\n declaration.idempotent !== undefined &&\n declaration.openWorld !== undefined\n );\n}\n\nexport function normalizePlanes(\n planes: readonly PlaybookPlane[] | null | undefined,\n context: string,\n): readonly PlaybookPlane[] | undefined {\n if (planes === undefined) {\n return undefined;\n }\n\n if (planes === null) {\n return undefined;\n }\n\n if (!Array.isArray(planes)) {\n throw new Error(`${context} planes must be an array`);\n }\n\n const normalized: PlaybookPlane[] = [];\n for (const plane of planes) {\n if (!PLAYBOOK_PLANES.includes(plane)) {\n throw new Error(\n `${context} declares unknown plane \"${String(plane)}\"; expected one of ${PLAYBOOK_PLANES.join(', ')}`,\n );\n }\n if (!normalized.includes(plane)) {\n normalized.push(plane);\n }\n }\n\n if (normalized.length === 0) {\n throw new Error(`${context} must declare at least one plane`);\n }\n\n // Stable order keeps stored/serialized planes comparable.\n return PLAYBOOK_PLANES.filter((plane) => normalized.includes(plane));\n}\n\nfunction normalizeFailurePolicy(\n value: unknown,\n context: string,\n): PlaybookFailurePolicy {\n if (!FAILURE_POLICIES.has(value as PlaybookFailurePolicy)) {\n throw new Error(\n `${context} onStepFailure must be \"abort\" or \"continue\", received \"${String(value)}\"`,\n );\n }\n\n return value as PlaybookFailurePolicy;\n}\n\n/**\n * Enablement is a gate, so it is validated rather than coerced. Truthiness\n * would silently read a config or runtime `\"false\"` as enabled — the one\n * coercion failure here that fails open.\n */\nfunction normalizeEnabled(value: unknown, context: string): boolean {\n if (typeof value !== 'boolean') {\n throw new Error(\n `${context} enabled must be a boolean, received ${typeof value} \"${String(value)}\"`,\n );\n }\n\n return value;\n}\n\n/**\n * Validated, not coerced, for the same reason as {@link normalizeEnabled}: a\n * stringly-typed `\"false\"` would turn a required step into a skippable one.\n */\nfunction normalizeStepOptional(value: unknown, context: string): boolean {\n if (typeof value !== 'boolean') {\n throw new Error(\n `${context} optional must be a boolean, received ${typeof value} \"${String(value)}\"`,\n );\n }\n\n return value;\n}\n\nfunction normalizeOptionalText(\n value: unknown,\n context: string,\n field: string,\n): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value !== 'string') {\n throw new Error(`${context} ${field} must be a string`);\n }\n\n return value;\n}\n\n/**\n * Validates and freezes the declared step list.\n *\n * Rejects nested playbooks at definition time (epic #2585): a package playbook\n * referencing a tenant-overridden playbook is the description-behavior\n * mismatch one level removed.\n */\nexport function normalizeSteps(\n steps: readonly PlaybookStep[] | undefined,\n context: string,\n): readonly PlaybookStep[] {\n if (!Array.isArray(steps) || steps.length === 0) {\n throw new Error(`${context} requires at least one step`);\n }\n\n return Object.freeze(\n steps.map((rawStep, index) => {\n const stepContext = `${context} step ${index}`;\n\n if (!isPlainObject(rawStep)) {\n throw new Error(`${stepContext} must be an object`);\n }\n\n const kind = rawStep.kind;\n\n if (kind === 'playbook' || 'playbook' in rawStep) {\n throw new Error(\n `${stepContext} references another playbook; nested playbooks are not supported`,\n );\n }\n\n if (kind === 'operation') {\n const model = rawStep.model;\n const action = rawStep.action;\n\n if (typeof model !== 'string' || model.trim() === '') {\n throw new Error(`${stepContext} requires a qualified model name`);\n }\n\n // Both halves must be present and unpadded: ':', '@pkg:', and ':Order'\n // all contain a separator but identify no model, and would resolve\n // into a plan that no classifier or executor lookup can ever match.\n if (!QUALIFIED_MODEL_PATTERN.test(model)) {\n throw new Error(\n `${stepContext} model \"${model}\" must be a qualified pair such as \"@happyvertical/smrt-commerce:Order\"`,\n );\n }\n\n if (typeof action !== 'string' || action.trim() === '') {\n throw new Error(`${stepContext} requires an action name`);\n }\n\n return Object.freeze({\n kind: 'operation' as const,\n model,\n action,\n ...(normalizeOptionalText(rawStep.label, stepContext, 'label') !==\n undefined\n ? { label: rawStep.label as string }\n : {}),\n ...(normalizeOptionalText(\n rawStep.description,\n stepContext,\n 'description',\n ) !== undefined\n ? { description: rawStep.description as string }\n : {}),\n ...(rawStep.optional === undefined\n ? {}\n : {\n optional: normalizeStepOptional(rawStep.optional, stepContext),\n }),\n }) satisfies PlaybookStep;\n }\n\n if (kind === 'intent') {\n const id = rawStep.id;\n\n if (typeof id !== 'string' || id.trim() === '') {\n throw new Error(`${stepContext} requires an intent id`);\n }\n\n return Object.freeze({\n kind: 'intent' as const,\n id,\n ...(normalizeOptionalText(rawStep.label, stepContext, 'label') !==\n undefined\n ? { label: rawStep.label as string }\n : {}),\n ...(normalizeOptionalText(\n rawStep.description,\n stepContext,\n 'description',\n ) !== undefined\n ? { description: rawStep.description as string }\n : {}),\n ...(rawStep.optional === undefined\n ? {}\n : {\n optional: normalizeStepOptional(rawStep.optional, stepContext),\n }),\n }) satisfies PlaybookStep;\n }\n\n throw new Error(\n `${stepContext} has unknown kind \"${String(kind)}\"; expected \"operation\" or \"intent\"`,\n );\n }),\n );\n}\n\nexport function hasIntentStep(steps: readonly PlaybookStep[]): boolean {\n return steps.some((step) => step.kind === 'intent');\n}\n\n/**\n * Default plane validity. Operation-only playbooks are valid on both planes;\n * anything containing a view intent is browser-valid only until the author\n * explicitly declares server validity through the #2446 command/ack bridge.\n */\nexport function defaultPlanesForSteps(\n steps: readonly PlaybookStep[],\n): readonly PlaybookPlane[] {\n return hasIntentStep(steps) ? BROWSER_ONLY_PLANES : PLAYBOOK_PLANES;\n}\n\nexport function normalizePlaybookDefinitionInput(\n input: PlaybookDefinitionInput,\n): PlaybookDefinition {\n if (!input || typeof input.key !== 'string' || input.key.trim() === '') {\n throw new Error('Playbook definitions require a non-empty key');\n }\n\n const context = `Playbook \"${input.key}\"`;\n\n if (typeof input.title !== 'string' || input.title.trim() === '') {\n throw new Error(`${context} requires a title`);\n }\n\n if (\n typeof input.description !== 'string' ||\n input.description.trim() === ''\n ) {\n throw new Error(`${context} requires a description`);\n }\n\n if ('steps' in ((input.editable ?? {}) as Record<string, unknown>)) {\n throw new Error(\n `${context} cannot mark steps editable; playbook step lists are never editable`,\n );\n }\n\n const steps = normalizeSteps(input.steps, context);\n const declaredPlanes = normalizePlanes(input.planes, context);\n\n // Freeze the nested values too, not just the outer object: `planes` and\n // `editable` are the declared fail-closed policy, and a shallow freeze would\n // still let a caller push 'server' onto a browser-only definition or flip an\n // `editable` flag on the object the registry hands back.\n return Object.freeze({\n key: input.key,\n title: input.title,\n description: input.description,\n steps,\n planes: Object.freeze(declaredPlanes ?? defaultPlanesForSteps(steps)),\n onStepFailure:\n input.onStepFailure === undefined\n ? 'abort'\n : normalizeFailurePolicy(input.onStepFailure, context),\n enabled:\n input.enabled === undefined\n ? true\n : normalizeEnabled(input.enabled, context),\n metadata: Object.freeze(\n input.metadata ? sanitizeMetadata(input.metadata) : {},\n ),\n editable: Object.freeze(normalizeEditableConfig(input.editable)),\n });\n}\n\nexport function sanitizeMetadata(\n metadata: PlaybookMetadata | null | undefined,\n): PlaybookMetadata {\n if (!isPlainObject(metadata)) {\n return {};\n }\n\n // Copy and deep-freeze rather than aliasing the caller's object: metadata\n // ends up in the registered definition and the shared cache entry, and a\n // shallow freeze would leave nested values mutable through the caller's\n // original reference.\n return deepFreezeJsonObject(metadata);\n}\n\nfunction deepFreezeJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return Object.freeze(value.map(deepFreezeJsonValue));\n }\n\n if (isPlainObject(value)) {\n return deepFreezeJsonObject(value);\n }\n\n return value;\n}\n\nfunction deepFreezeJsonObject(\n source: Record<string, unknown>,\n): PlaybookMetadata {\n const copied: PlaybookMetadata = {};\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined) {\n continue;\n }\n copied[key] = deepFreezeJsonValue(value);\n }\n\n return Object.freeze(copied);\n}\n\nexport function parseMetadata(\n raw: string | null | undefined,\n): PlaybookMetadata {\n if (!raw) {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return isPlainObject(parsed) ? sanitizeMetadata(parsed) : {};\n } catch {\n return {};\n }\n}\n\nexport function serializeMetadata(\n metadata: PlaybookMetadata | null | undefined,\n): string | null {\n if (metadata === null || metadata === undefined) {\n return null;\n }\n\n return JSON.stringify(sanitizeMetadata(metadata));\n}\n\nexport function parsePlanes(\n raw: string | null | undefined,\n): readonly PlaybookPlane[] | null {\n if (!raw) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) {\n return null;\n }\n return (\n normalizePlanes(parsed as PlaybookPlane[], 'Stored override') ?? null\n );\n } catch {\n return null;\n }\n}\n\nexport function serializePlanes(\n planes: readonly PlaybookPlane[] | null | undefined,\n): string | null {\n if (planes === null || planes === undefined) {\n return null;\n }\n\n return JSON.stringify(normalizePlanes(planes, 'Stored override') ?? []);\n}\n\n/**\n * Normalizes an override layer from config, storage, or a runtime call.\n *\n * A `steps` key is rejected rather than dropped: \"a tenant override cannot\n * alter steps through any path\" is enforced loudly at every entry point.\n */\nexport function normalizePlaybookLayer(\n input?: PlaybookConfigOverrideInput | null,\n context = 'Playbook override',\n): PlaybookLayer {\n if (!isPlainObject(input)) {\n return {};\n }\n\n if ('steps' in input) {\n throw new Error(\n `${context} cannot set steps; playbook step lists are never editable`,\n );\n }\n\n const layer: PlaybookLayer = {};\n\n if (input.title !== undefined) {\n layer.title =\n input.title === null\n ? null\n : (normalizeOptionalText(input.title, context, 'title') ?? null);\n }\n\n if (input.description !== undefined) {\n layer.description =\n input.description === null\n ? null\n : (normalizeOptionalText(input.description, context, 'description') ??\n null);\n }\n\n if (input.planes !== undefined) {\n layer.planes =\n input.planes === null\n ? null\n : (normalizePlanes(input.planes, context) ?? null);\n }\n\n if (input.onStepFailure !== undefined) {\n layer.onStepFailure =\n input.onStepFailure === null\n ? null\n : normalizeFailurePolicy(input.onStepFailure, context);\n }\n\n if (input.enabled !== undefined) {\n layer.enabled =\n input.enabled === null ? null : normalizeEnabled(input.enabled, context);\n }\n\n if (input.metadata !== undefined) {\n layer.metadata =\n input.metadata === null ? null : sanitizeMetadata(input.metadata);\n }\n\n return layer;\n}\n\nexport interface MergedPlaybookLayers {\n title: string;\n description: string;\n planes: readonly PlaybookPlane[];\n onStepFailure: PlaybookFailurePolicy;\n enabled: boolean;\n metadata: PlaybookMetadata;\n}\n\n/**\n * Merges layers low → high, field by field.\n *\n * Enablement is one-directional: once any layer disables a playbook, no\n * higher layer can enable it again. A tenant may narrow, never widen.\n */\nexport function mergePlaybookLayers(\n base: PlaybookDefinition,\n ...layers: Array<PlaybookLayer | null | undefined>\n): MergedPlaybookLayers {\n let title = base.title;\n let description = base.description;\n let planes = base.planes;\n let onStepFailure = base.onStepFailure;\n let enabled = base.enabled;\n let metadata: PlaybookMetadata = { ...base.metadata };\n\n for (const layer of layers) {\n if (!layer) {\n continue;\n }\n\n if (layer.title !== undefined && layer.title !== null) {\n title = layer.title;\n }\n\n if (layer.description !== undefined && layer.description !== null) {\n description = layer.description;\n }\n\n if (layer.planes !== undefined && layer.planes !== null) {\n // Plane validity only ever narrows: an override cannot claim a plane the\n // lower layers never declared.\n planes = layer.planes.filter((plane) => planes.includes(plane));\n }\n\n if (layer.onStepFailure !== undefined && layer.onStepFailure !== null) {\n onStepFailure = layer.onStepFailure;\n }\n\n if (layer.enabled !== undefined && layer.enabled !== null) {\n enabled = enabled && layer.enabled;\n }\n\n if (layer.metadata !== undefined && layer.metadata !== null) {\n metadata = { ...metadata, ...layer.metadata };\n }\n }\n\n // The merged result is both cached and handed to callers as part of the\n // plan, so the policy values must be immutable: a caller pushing onto a\n // narrowed `planes` array would otherwise corrupt the cached entry and widen\n // the declared-plane gate for every resolution until the TTL expires.\n return Object.freeze({\n title,\n description,\n planes: Object.freeze(planes),\n onStepFailure,\n enabled,\n metadata: Object.freeze(metadata),\n });\n}\n","import type { PlaybookDefinition, PlaybookDefinitionInput } from './types.js';\nimport { normalizePlaybookDefinitionInput } from './utils.js';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtPlaybookRegistry: Map<string, PlaybookDefinition> | undefined;\n}\n\nfunction getRegistry(): Map<string, PlaybookDefinition> {\n if (!globalThis.__smrtPlaybookRegistry) {\n globalThis.__smrtPlaybookRegistry = new Map<string, PlaybookDefinition>();\n }\n\n return globalThis.__smrtPlaybookRegistry;\n}\n\nfunction stableStringify(value: unknown): string {\n if (Array.isArray(value)) {\n return `[${value.map((item) => stableStringify(item)).join(',')}]`;\n }\n\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>).sort(\n ([left], [right]) => left.localeCompare(right),\n );\n return `{${entries\n .map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)\n .join(',')}}`;\n }\n\n return JSON.stringify(value);\n}\n\n/**\n * Global process registry of code-default playbooks, keyed by namespaced key.\n *\n * Held on `globalThis` so it survives HMR, mirroring `PromptRegistry`.\n */\nexport const PlaybookRegistry = {\n register(input: PlaybookDefinitionInput): PlaybookDefinition {\n const definition = normalizePlaybookDefinitionInput(input);\n const registry = getRegistry();\n const existing = registry.get(definition.key);\n\n if (existing) {\n const existingSignature = stableStringify(existing);\n const incomingSignature = stableStringify(definition);\n\n if (existingSignature !== incomingSignature) {\n throw new Error(\n `Playbook \"${definition.key}\" is already registered with a different definition`,\n );\n }\n\n return existing;\n }\n\n registry.set(definition.key, definition);\n return definition;\n },\n\n get(key: string): PlaybookDefinition | undefined {\n return getRegistry().get(key);\n },\n\n has(key: string): boolean {\n return getRegistry().has(key);\n },\n\n getAll(): PlaybookDefinition[] {\n return Array.from(getRegistry().values());\n },\n\n clear(): void {\n getRegistry().clear();\n },\n};\n\n/**\n * Registers a code-default playbook. Packages call this at import time so a\n * bundled playbook resolves without any application registration.\n */\nexport function definePlaybook(\n input: PlaybookDefinitionInput,\n): PlaybookDefinition {\n return PlaybookRegistry.register(input);\n}\n","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { invalidatePlaybookCache } from '../cache.js';\nimport { PlaybookRegistry } from '../playbook-registry.js';\nimport type {\n PlaybookConfigOverrideInput,\n PlaybookFailurePolicy,\n PlaybookLayer,\n PlaybookMetadata,\n PlaybookOverrideOptions as PlaybookOverrideFieldOptions,\n PlaybookPackageConfig,\n PlaybookPlane,\n} from '../types.js';\nimport {\n mergePlaybookLayers,\n normalizePlaybookLayer,\n parseMetadata,\n parsePlanes,\n serializeMetadata,\n serializePlanes,\n} from '../utils.js';\n\nexport interface PlaybookOverrideOptions\n extends SmrtObjectOptions,\n PlaybookOverrideFieldOptions {}\n\ntype PlaybookOverrideIdentity = {\n key: string;\n tenantId: string | null;\n};\n\ntype PlaybookTransactionHandle = DatabaseInterface & {\n commit: () => Promise<void>;\n rollback: () => Promise<void>;\n};\n\nfunction getPlaybookConfig(): PlaybookPackageConfig {\n return getPackageConfig<PlaybookPackageConfig>('playbooks', {\n playbooks: {},\n });\n}\n\n/**\n * Stored app-level (`tenantId = null`) and tenant-level playbook overrides.\n *\n * There is deliberately **no `steps` column**. `steps` is structurally\n * non-editable: an override layer has nowhere to put a step list, and\n * assigning one is rejected in `save()` rather than silently dropped. That is\n * the description-behavior guarantee from epic #2585 — an agent announcing\n * \"checking out your cart\" must not be following a rewritten script.\n */\n@smrt({\n tableName: '_smrt_playbook_overrides',\n conflictColumns: ['key', 'context'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n exclude: [\n 'getMetadata',\n 'setMetadata',\n 'getPlanes',\n 'setPlanes',\n 'toPlaybookLayer',\n ],\n },\n mcp: { include: [] },\n})\nexport class PlaybookOverride extends SmrtObject {\n @field({ required: true })\n key: string = '';\n\n @field({ type: 'text', nullable: true })\n tenantId: string | null = null;\n\n @field({ type: 'text', nullable: true })\n title: string | null = null;\n\n @field({ type: 'text', nullable: true })\n description: string | null = null;\n\n /** JSON array of plane names; null inherits the lower layer. */\n @field({ type: 'text', nullable: true })\n planes: string | null = null;\n\n @field({ type: 'text', nullable: true })\n onStepFailure: string | null = null;\n\n /** Tri-state: null inherits, false disables. True can never widen. */\n @field({ type: 'boolean', nullable: true })\n enabled: boolean | null = null;\n\n /** JSON object; stored as a string with guarded get/set helpers. */\n @field({ type: 'text', nullable: true })\n metadata: string | null = null;\n\n constructor(options: PlaybookOverrideOptions = {}) {\n super(options);\n\n // `SmrtCollection.create()` spreads its caller's option bag straight into\n // the constructor, so this is the entry point a `steps` key actually\n // reaches. Reject it loudly instead of letting it be silently dropped:\n // step lists are never editable through any path.\n if ((options as Record<string, unknown>).steps !== undefined) {\n throw new Error(\n 'Playbook step lists are never editable; PlaybookOverride cannot carry steps',\n );\n }\n\n if (options.key !== undefined) this.key = options.key;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.onStepFailure !== undefined)\n this.onStepFailure = options.onStepFailure;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.planes !== undefined) {\n this.planes =\n typeof options.planes === 'string' || options.planes === null\n ? options.planes\n : serializePlanes(options.planes);\n }\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string' || options.metadata === null\n ? options.metadata\n : serializeMetadata(options.metadata);\n }\n }\n\n getMetadata(): PlaybookMetadata {\n return parseMetadata(this.metadata);\n }\n\n setMetadata(metadata: PlaybookMetadata | null): void {\n this.metadata = serializeMetadata(metadata);\n }\n\n getPlanes(): readonly PlaybookPlane[] | null {\n return parsePlanes(this.planes);\n }\n\n setPlanes(planes: readonly PlaybookPlane[] | null): void {\n this.planes = serializePlanes(planes);\n }\n\n toPlaybookLayer(): PlaybookLayer {\n return {\n title: this.title,\n description: this.description,\n planes: this.getPlanes(),\n onStepFailure: (this.onStepFailure ??\n null) as PlaybookFailurePolicy | null,\n // The database boundary is where coercion is legitimate: SQLite hydrates\n // a boolean column as 0/1. Everywhere above this, enablement is\n // validated rather than coerced.\n enabled:\n this.enabled === null || this.enabled === undefined\n ? null\n : Boolean(this.enabled),\n metadata: this.metadata === null ? null : this.getMetadata(),\n };\n }\n\n override async save(): Promise<this> {\n const previousIdentity = await this.getPersistedIdentity();\n this.normalizeForPersistence();\n await this.validatePlaybookOverride();\n // `context` is the conflictColumn-friendly scope: '__app__' for a nullable\n // tenant, tenantId otherwise. Mirrors PromptOverride / LanguageOverride so\n // app-level rows stay unique on PostgreSQL, SQLite, and DuckDB alike,\n // where multiple NULLs would otherwise all satisfy a unique index.\n this.context = this.tenantId ?? '__app__';\n\n const identityChanged =\n !!previousIdentity &&\n (previousIdentity.key !== this.key ||\n previousIdentity.tenantId !== this.tenantId);\n\n const result =\n identityChanged && previousIdentity\n ? await this.saveAfterIdentityChange()\n : await super.save();\n\n if (identityChanged && previousIdentity) {\n invalidatePlaybookCache(\n previousIdentity.key,\n previousIdentity.tenantId,\n this.db,\n );\n }\n invalidatePlaybookCache(this.key, this.tenantId, this.db);\n return result;\n }\n\n private async saveAfterIdentityChange(): Promise<this> {\n if (typeof this.db.beginTransaction === 'function') {\n return this.saveAfterIdentityChangeInTransaction();\n }\n\n return this.saveAfterIdentityChangeWithDeferredDelete();\n }\n\n private async saveAfterIdentityChangeInTransaction(): Promise<this> {\n const originalDb = this._db;\n const originalOptionsDb = this.options.db;\n const tx = (await this.db.beginTransaction?.()) as\n | PlaybookTransactionHandle\n | undefined;\n\n if (!tx) {\n return this.saveAfterIdentityChangeWithDeferredDelete();\n }\n\n try {\n this._db = tx;\n this.options.db = tx;\n await super.delete();\n const result = await super.save();\n await tx.commit();\n return result;\n } catch (error) {\n try {\n await tx.rollback();\n } catch {\n // Preserve the original save error; rollback failures are secondary.\n }\n throw error;\n } finally {\n this._db = originalDb;\n this.options.db = originalOptionsDb;\n }\n }\n\n private async saveAfterIdentityChangeWithDeferredDelete(): Promise<this> {\n const previousId = this.id;\n if (!previousId) {\n return super.save();\n }\n\n const replacementId = crypto.randomUUID();\n let replacementSaved = false;\n this.id = replacementId;\n\n try {\n const result = await super.save();\n replacementSaved = true;\n await this.db.delete(this.tableName, { id: previousId });\n return result;\n } catch (error) {\n if (replacementSaved) {\n try {\n await this.db.delete(this.tableName, { id: replacementId });\n } catch {\n // Best effort cleanup keeps the original row as the source of truth.\n }\n }\n\n this.id = previousId;\n throw error;\n }\n }\n\n override async delete(): Promise<void> {\n const key = this.key;\n const tenantId = this.tenantId;\n await super.delete();\n invalidatePlaybookCache(key, tenantId, this.db);\n }\n\n private async validatePlaybookOverride(): Promise<void> {\n if (!this.key || this.key.trim() === '') {\n throw new Error('PlaybookOverride.key is required');\n }\n\n // Structural, not merely defaulted-false: there is no `steps` column, and\n // a caller assigning one through the untyped option bag is rejected here\n // rather than having the value silently dropped by persistence.\n const assignedSteps = (this as unknown as Record<string, unknown>).steps;\n if (assignedSteps !== undefined) {\n throw new Error(\n `Playbook \"${this.key}\" step lists are never editable; PlaybookOverride cannot carry steps`,\n );\n }\n\n const definition = PlaybookRegistry.get(this.key);\n if (!definition) {\n throw new Error(`Unknown playbook key \"${this.key}\"`);\n }\n\n const editable = definition.editable;\n\n if (this.title !== null && !editable.title) {\n throw new Error(`Playbook \"${this.key}\" does not allow title overrides`);\n }\n\n if (this.description !== null && !editable.description) {\n throw new Error(\n `Playbook \"${this.key}\" does not allow description overrides`,\n );\n }\n\n if (this.planes !== null && !editable.planes) {\n throw new Error(`Playbook \"${this.key}\" does not allow planes overrides`);\n }\n\n if (this.onStepFailure !== null && !editable.onStepFailure) {\n throw new Error(\n `Playbook \"${this.key}\" does not allow onStepFailure overrides`,\n );\n }\n\n if (this.enabled !== null && !editable.enabled) {\n throw new Error(\n `Playbook \"${this.key}\" does not allow enablement overrides`,\n );\n }\n\n if (this.metadata !== null && !editable.metadata) {\n throw new Error(\n `Playbook \"${this.key}\" does not allow metadata overrides`,\n );\n }\n\n if (this.metadata !== null) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(this.metadata);\n } catch (error) {\n throw new Error(\n `Playbook \"${this.key}\" has invalid metadata JSON: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(\n `Playbook \"${this.key}\" metadata must be a JSON object`,\n );\n }\n }\n\n if (this.planes !== null) {\n const parsedPlanes = parsePlanes(this.planes);\n if (!parsedPlanes || parsedPlanes.length === 0) {\n throw new Error(\n `Playbook \"${this.key}\" planes must be a non-empty JSON array of plane names`,\n );\n }\n }\n\n if (\n this.onStepFailure !== null &&\n this.onStepFailure !== 'abort' &&\n this.onStepFailure !== 'continue'\n ) {\n throw new Error(\n `Playbook \"${this.key}\" onStepFailure must be \"abort\" or \"continue\"`,\n );\n }\n\n const lowerLayers = await this.getLowerPrecedenceLayers();\n const currentLayer = this.toPlaybookLayer();\n const lowerMerged = mergePlaybookLayers(definition, ...lowerLayers);\n\n // Enablement is one-directional: a layer may disable, never re-enable\n // something a lower layer disabled.\n if (this.enabled === true && !lowerMerged.enabled) {\n throw new Error(\n `Playbook \"${this.key}\" is disabled by a lower layer and cannot be re-enabled by an override`,\n );\n }\n\n // Plane validity narrows only; an override cannot claim a plane the lower\n // layers never declared.\n if (currentLayer.planes) {\n const widened = currentLayer.planes.filter(\n (plane) => !lowerMerged.planes.includes(plane),\n );\n if (widened.length > 0) {\n throw new Error(\n `Playbook \"${this.key}\" cannot add plane(s) ${widened.join(', ')} that no lower layer declares`,\n );\n }\n }\n }\n\n private async getLowerPrecedenceLayers(): Promise<PlaybookLayer[]> {\n const config = getPlaybookConfig();\n const layers: PlaybookLayer[] = [\n normalizePlaybookLayer(\n config.playbooks?.[this.key] as PlaybookConfigOverrideInput | undefined,\n `Playbook \"${this.key}\" config override`,\n ),\n ];\n\n const { PlaybookOverrideCollection } = await import(\n '../collections/PlaybookOverrideCollection.js'\n );\n const collection = await PlaybookOverrideCollection.create({\n db: this.options.db ?? this.options.persistence,\n });\n\n if (this.tenantId) {\n const appOverride = await collection.getAppOverride(this.key, {\n excludeId: this.id ?? undefined,\n });\n if (appOverride) {\n layers.push(appOverride.toPlaybookLayer());\n }\n }\n\n return layers;\n }\n\n private normalizeForPersistence(): void {\n const rawMetadata = this.metadata as unknown;\n if (rawMetadata === undefined) {\n this.metadata = null;\n } else if (\n rawMetadata !== null &&\n typeof rawMetadata === 'object' &&\n !Array.isArray(rawMetadata)\n ) {\n this.metadata = serializeMetadata(rawMetadata as PlaybookMetadata);\n } else if (rawMetadata !== null && typeof rawMetadata !== 'string') {\n throw new Error(\n `Playbook \"${this.key}\" metadata must be a JSON object or JSON string`,\n );\n }\n\n const rawPlanes = this.planes as unknown;\n if (rawPlanes === undefined) {\n this.planes = null;\n } else if (Array.isArray(rawPlanes)) {\n this.planes = serializePlanes(rawPlanes as PlaybookPlane[]);\n } else if (rawPlanes !== null && typeof rawPlanes !== 'string') {\n throw new Error(\n `Playbook \"${this.key}\" planes must be an array or JSON string`,\n );\n }\n\n // Enablement is a gate, so it is validated before it is ever persisted.\n // A stringly-typed `'false'` arriving through the untyped collection API\n // would otherwise hydrate as a truthy string and resolve as enabled.\n if (this.enabled === undefined) {\n this.enabled = null;\n } else if (this.enabled !== null && typeof this.enabled !== 'boolean') {\n throw new Error(\n `Playbook \"${this.key}\" enabled must be a boolean or null, received ${typeof this.enabled} \"${String(this.enabled)}\"`,\n );\n }\n }\n\n private async getPersistedIdentity(): Promise<PlaybookOverrideIdentity | null> {\n if (!this.id) {\n return null;\n }\n\n const existing = await this.db.get(this.tableName, { id: this.id });\n if (!existing) {\n return null;\n }\n\n const row = existing as Record<string, unknown>;\n return {\n key: String(row.key ?? this.key),\n tenantId:\n row.tenantId !== undefined\n ? (row.tenantId as string | null)\n : ((row.tenant_id as string | null | undefined) ?? null),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { PlaybookOverride } from '../models/PlaybookOverride.js';\n\nexport class PlaybookOverrideCollection extends SmrtCollection<PlaybookOverride> {\n static readonly _itemClass = PlaybookOverride;\n\n private excludeOverrideId(\n items: PlaybookOverride[],\n excludeId?: string,\n ): PlaybookOverride[] {\n return items.filter((item) => (excludeId ? item.id !== excludeId : true));\n }\n\n async getAppOverride(\n key: string,\n options: { excludeId?: string } = {},\n ): Promise<PlaybookOverride | null> {\n const items = await this.list({ where: { key, tenantId: null } });\n return this.excludeOverrideId(items, options.excludeId)[0] ?? null;\n }\n\n async getTenantOverride(\n key: string,\n tenantId: string,\n options: { excludeId?: string } = {},\n ): Promise<PlaybookOverride | null> {\n const items = await this.list({ where: { key, tenantId } });\n return this.excludeOverrideId(items, options.excludeId)[0] ?? null;\n }\n\n async getResolutionLayers(\n key: string,\n tenantId?: string | null,\n options: { excludeId?: string } = {},\n ): Promise<{\n app: PlaybookOverride | null;\n tenant: PlaybookOverride | null;\n }> {\n const [app, tenant] = await Promise.all([\n this.getAppOverride(key, options),\n tenantId != null\n ? this.getTenantOverride(key, tenantId, options)\n : Promise.resolve(null),\n ]);\n\n return { app, tenant };\n }\n}\n","import { getPackageConfig } from '@happyvertical/smrt-config';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport {\n getCachedPlaybookBase,\n getPlaybookCacheGeneration,\n setCachedPlaybookBase,\n} from './cache.js';\nimport { PlaybookOverrideCollection } from './collections/PlaybookOverrideCollection.js';\nimport { PlaybookRegistry } from './playbook-registry.js';\nimport type {\n PlaybookCacheValue,\n PlaybookDefinition,\n PlaybookPackageConfig,\n PlaybookPlan,\n PlaybookPlane,\n PlaybookPlanStep,\n PlaybookRejection,\n PlaybookResolution,\n ResolvePlaybookOptions,\n} from './types.js';\nimport {\n applyCapabilityDeclaration,\n isCapabilityDeclarationComplete,\n mergePlaybookLayers,\n normalizePlaybookLayer,\n} from './utils.js';\n\n/** An intent record that declares no planes is browser-only (fail closed). */\nconst DEFAULT_INTENT_PLANES: readonly PlaybookPlane[] = Object.freeze([\n 'browser',\n]);\n\nfunction getPlaybookConfig(): PlaybookPackageConfig {\n return getPackageConfig<PlaybookPackageConfig>('playbooks', {\n playbooks: {},\n });\n}\n\nfunction reject(\n key: string,\n reason: PlaybookRejection['reason'],\n message: string,\n stepIndex?: number,\n): PlaybookRejection {\n return {\n ok: false,\n reason,\n message,\n key,\n ...(stepIndex === undefined ? {} : { stepIndex }),\n };\n}\n\nasync function loadPlaybookBase(\n definition: PlaybookDefinition,\n options: ResolvePlaybookOptions,\n): Promise<PlaybookCacheValue> {\n const key = definition.key;\n const tenantId =\n options.tenantId !== undefined ? options.tenantId : (getTenantId() ?? null);\n\n let collection: PlaybookOverrideCollection | null = null;\n let cacheDb: ResolvePlaybookOptions['db'] | undefined = options.db;\n if (options.db) {\n const initializedCollection = await PlaybookOverrideCollection.create({\n db: options.db,\n });\n collection = initializedCollection;\n cacheDb = initializedCollection.db as ResolvePlaybookOptions['db'];\n }\n\n const cached = getCachedPlaybookBase(key, tenantId, cacheDb);\n if (cached) {\n return cached;\n }\n\n // Capture the invalidation generation before the asynchronous layer loads. A\n // write that lands while they are in flight bumps it, and the cache write\n // below is then refused rather than repopulating the key the write just\n // invalidated with the pre-write value.\n const loadedAtGeneration = getPlaybookCacheGeneration(key, cacheDb);\n\n const config = getPlaybookConfig();\n const layers = [\n normalizePlaybookLayer(\n config.playbooks?.[key],\n `Playbook \"${key}\" config override`,\n ),\n ];\n\n if (collection) {\n const stored = await collection.getResolutionLayers(key, tenantId);\n\n if (stored.app) {\n layers.push(stored.app.toPlaybookLayer());\n }\n\n if (stored.tenant) {\n layers.push(stored.tenant.toPlaybookLayer());\n }\n }\n\n const merged = mergePlaybookLayers(definition, ...layers);\n // Frozen: this object is shared by every resolution that hits the cache.\n const value: PlaybookCacheValue = Object.freeze({\n key,\n title: merged.title,\n description: merged.description,\n planes: merged.planes,\n onStepFailure: merged.onStepFailure,\n enabled: merged.enabled,\n metadata: merged.metadata,\n });\n\n setCachedPlaybookBase(key, tenantId, cacheDb, value, loadedAtGeneration);\n return value;\n}\n\n/**\n * Resolves a playbook to a plan for a caller on a given plane.\n *\n * Returns a discriminated result rather than throwing: resolution fails closed\n * and every rejection names a specific reason. Nothing here executes a step —\n * the plan is followed step by step by the agent, and each step is authorized\n * independently at the REST boundary or by `PrincipalRun.assertToolAllowed()`.\n */\nexport async function resolvePlaybook(\n key: string,\n options: ResolvePlaybookOptions = {},\n): Promise<PlaybookResolution> {\n const definition = PlaybookRegistry.get(key);\n if (!definition) {\n return reject(key, 'unknown-playbook', `Unknown playbook key \"${key}\"`);\n }\n\n const base = await loadPlaybookBase(definition, options);\n const runtimeOverride = normalizePlaybookLayer(\n options.override,\n `Playbook \"${key}\" runtime override`,\n );\n const merged = mergePlaybookLayers(\n {\n ...definition,\n title: base.title,\n description: base.description,\n planes: base.planes,\n onStepFailure: base.onStepFailure,\n enabled: base.enabled,\n metadata: base.metadata,\n },\n runtimeOverride,\n );\n\n if (!merged.enabled) {\n return reject(\n key,\n 'disabled',\n `Playbook \"${key}\" is disabled for this scope`,\n );\n }\n\n const plane = options.plane ?? 'server';\n if (!merged.planes.includes(plane)) {\n return reject(\n key,\n 'plane-not-declared',\n `Playbook \"${key}\" is not valid on the \"${plane}\" plane; it declares ${merged.planes.join(', ')}`,\n );\n }\n\n const steps: PlaybookPlanStep[] = [];\n\n for (const [index, step] of definition.steps.entries()) {\n if (step.kind === 'operation') {\n // The step never classifies itself: the host supplies the classification\n // emitted for the referenced operation, and anything undeclared resolves\n // to the fail-closed default.\n const declaration = options.classifier?.(step) ?? null;\n steps.push({\n index,\n step,\n classification: applyCapabilityDeclaration(declaration),\n classificationDeclared: isCapabilityDeclarationComplete(declaration),\n });\n continue;\n }\n\n // Seam for #2588: without a declared-intent registry there is no identity\n // to resolve against, so an intent step fails closed rather than being\n // assumed valid.\n if (!options.intents) {\n return reject(\n key,\n 'intent-registry-unavailable',\n `Playbook \"${key}\" step ${index} references view intent \"${step.id}\", but no intent registry was supplied (see #2588)`,\n index,\n );\n }\n\n const record = options.intents(step.id);\n if (!record) {\n return reject(\n key,\n 'unknown-intent',\n `Playbook \"${key}\" step ${index} references unknown view intent \"${step.id}\"`,\n index,\n );\n }\n\n // Fail closed: an intent record that does not declare its planes is\n // browser-only, the same default an intent-bearing playbook gets. Server\n // validity rides the #2446 command/ack bridge and must be declared at both\n // the playbook and the intent, never assumed from silence.\n const intentPlanes = record.planes ?? DEFAULT_INTENT_PLANES;\n if (!intentPlanes.includes(plane)) {\n return reject(\n key,\n 'intent-plane-not-declared',\n `Playbook \"${key}\" step ${index} references view intent \"${step.id}\", which is not valid on the \"${plane}\" plane`,\n index,\n );\n }\n\n steps.push({\n index,\n step,\n classification: applyCapabilityDeclaration(record.classification),\n classificationDeclared: isCapabilityDeclarationComplete(\n record.classification,\n ),\n });\n }\n\n // A plan is a read-only description of what the agent is about to do; the\n // policy fields it carries are shared with the cache, so freeze it rather\n // than hand a caller a handle that can widen a gate after the fact.\n const plan: PlaybookPlan = Object.freeze({\n key,\n title: merged.title,\n description: merged.description,\n plane,\n planes: merged.planes,\n onStepFailure: merged.onStepFailure,\n metadata: merged.metadata,\n // Steps come from the code definition alone. No layer can supply them.\n steps: Object.freeze(steps),\n });\n\n return { ok: true, plan };\n}\n","/**\n * @happyvertical/smrt-playbooks\n *\n * Code-first playbooks — named, described, layered step sequences an agent\n * follows — with config, app-level, tenant-level, and runtime overrides.\n *\n * A playbook resolves to a plan the agent executes step by step. Nothing in\n * this package executes a step, so a playbook is never an authority boundary:\n * every step is authorized independently at the REST boundary or, server-side,\n * by `PrincipalRun.assertToolAllowed()`.\n *\n * @packageDocumentation\n */\n\n// Self-register this package's manifest before any @smrt() decorator fires\n// downstream. Must come first so the side effect runs ahead of the class\n// module loads below. See __smrt-register__.ts for issue #1132 context.\nimport './__smrt-register__.js';\n\nexport { clearPlaybookCache, getPlaybookCacheTtlMs } from './cache.js';\nexport { PlaybookOverrideCollection } from './collections/PlaybookOverrideCollection.js';\nexport {\n PlaybookOverride,\n type PlaybookOverrideOptions,\n} from './models/PlaybookOverride.js';\nexport { definePlaybook, PlaybookRegistry } from './playbook-registry.js';\nexport { resolvePlaybook } from './playbook-resolver.js';\nexport type {\n PlaybookAcceptance,\n PlaybookCacheValue,\n PlaybookConfigOverrideInput,\n PlaybookDefinition,\n PlaybookDefinitionInput,\n PlaybookEditableConfig,\n PlaybookFailurePolicy,\n PlaybookIntentRecord,\n PlaybookIntentResolver,\n PlaybookIntentStep,\n PlaybookLayer,\n PlaybookMetadata,\n PlaybookOperationClassifier,\n PlaybookOperationStep,\n PlaybookPackageConfig,\n PlaybookPlan,\n PlaybookPlane,\n PlaybookPlanStep,\n PlaybookRejection,\n PlaybookRejectionReason,\n PlaybookResolution,\n PlaybookStep,\n ResolvePlaybookOptions,\n} from './types.js';\nexport { PLAYBOOK_PLANES } from './types.js';\nexport {\n FAIL_CLOSED_CLASSIFICATION,\n normalizeEditableConfig,\n} from './utils.js';\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"mappings":"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"}
@@ -0,0 +1,424 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "timestamp": 0,
4
+ "packageName": "@happyvertical/smrt-playbooks",
5
+ "packageVersion": "0.44.0",
6
+ "objects": {
7
+ "@happyvertical/smrt-playbooks:PlaybookOverrideCollection": {
8
+ "name": "playbookoverridecollection",
9
+ "className": "PlaybookOverrideCollection",
10
+ "qualifiedName": "@happyvertical/smrt-playbooks:PlaybookOverrideCollection",
11
+ "collection": "playbookoverrides",
12
+ "filePath": "/home/runner/work/smrt/smrt/packages/playbooks/src/collections/PlaybookOverrideCollection.ts",
13
+ "packageName": "@happyvertical/smrt-playbooks",
14
+ "fields": {},
15
+ "methods": {
16
+ "getAppOverride": {
17
+ "name": "getAppOverride",
18
+ "async": true,
19
+ "parameters": [
20
+ {
21
+ "name": "key",
22
+ "type": "string",
23
+ "optional": false
24
+ },
25
+ {
26
+ "name": "options",
27
+ "type": "object",
28
+ "optional": true
29
+ }
30
+ ],
31
+ "returnType": "Promise<PlaybookOverride | null>",
32
+ "isStatic": false,
33
+ "isPublic": true
34
+ },
35
+ "getTenantOverride": {
36
+ "name": "getTenantOverride",
37
+ "async": true,
38
+ "parameters": [
39
+ {
40
+ "name": "key",
41
+ "type": "string",
42
+ "optional": false
43
+ },
44
+ {
45
+ "name": "tenantId",
46
+ "type": "string",
47
+ "optional": false
48
+ },
49
+ {
50
+ "name": "options",
51
+ "type": "object",
52
+ "optional": true
53
+ }
54
+ ],
55
+ "returnType": "Promise<PlaybookOverride | null>",
56
+ "isStatic": false,
57
+ "isPublic": true
58
+ },
59
+ "getResolutionLayers": {
60
+ "name": "getResolutionLayers",
61
+ "async": true,
62
+ "parameters": [
63
+ {
64
+ "name": "key",
65
+ "type": "string",
66
+ "optional": false
67
+ },
68
+ {
69
+ "name": "tenantId",
70
+ "type": "string | null",
71
+ "optional": true
72
+ },
73
+ {
74
+ "name": "options",
75
+ "type": "object",
76
+ "optional": true
77
+ }
78
+ ],
79
+ "returnType": "Promise<object>",
80
+ "isStatic": false,
81
+ "isPublic": true
82
+ }
83
+ },
84
+ "decoratorConfig": {
85
+ "tableName": "_smrt_playbook_overrides"
86
+ },
87
+ "extends": "SmrtCollection",
88
+ "extendsTypeArg": "PlaybookOverride",
89
+ "exportName": "PlaybookOverrideCollection",
90
+ "collectionExportName": "PlaybookOverrideCollectionCollection",
91
+ "schema": {
92
+ "tableName": "_smrt_playbook_overrides",
93
+ "ddl": "CREATE TABLE IF NOT EXISTS \"_smrt_playbook_overrides\" (\n \"id\" UUID PRIMARY KEY NOT NULL,\n \"slug\" TEXT NOT NULL,\n \"context\" TEXT NOT NULL DEFAULT '',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp\n);",
94
+ "columns": {
95
+ "id": {
96
+ "type": "UUID",
97
+ "primaryKey": true,
98
+ "referenceKind": "id",
99
+ "notNull": true
100
+ },
101
+ "slug": {
102
+ "type": "TEXT",
103
+ "notNull": true
104
+ },
105
+ "context": {
106
+ "type": "TEXT",
107
+ "notNull": true,
108
+ "default": ""
109
+ },
110
+ "created_at": {
111
+ "type": "TIMESTAMP",
112
+ "notNull": true,
113
+ "default": "current_timestamp"
114
+ },
115
+ "updated_at": {
116
+ "type": "TIMESTAMP",
117
+ "notNull": true,
118
+ "default": "current_timestamp"
119
+ }
120
+ },
121
+ "indexes": [
122
+ {
123
+ "name": "_smrt_playbook_overrides_slug_context_idx",
124
+ "columns": [
125
+ "slug",
126
+ "context"
127
+ ],
128
+ "unique": true
129
+ },
130
+ {
131
+ "name": "_smrt_playbook_overrides_created_at_idx",
132
+ "columns": [
133
+ "created_at"
134
+ ]
135
+ }
136
+ ],
137
+ "version": "410e08c4"
138
+ }
139
+ },
140
+ "@happyvertical/smrt-playbooks:PlaybookOverride": {
141
+ "name": "playbookoverride",
142
+ "className": "PlaybookOverride",
143
+ "qualifiedName": "@happyvertical/smrt-playbooks:PlaybookOverride",
144
+ "collection": "playbookoverrides",
145
+ "filePath": "/home/runner/work/smrt/smrt/packages/playbooks/src/models/PlaybookOverride.ts",
146
+ "packageName": "@happyvertical/smrt-playbooks",
147
+ "fields": {
148
+ "key": {
149
+ "type": "text",
150
+ "required": true,
151
+ "default": "",
152
+ "_meta": {
153
+ "required": true
154
+ }
155
+ },
156
+ "tenantId": {
157
+ "type": "text",
158
+ "required": false,
159
+ "_meta": {
160
+ "nullable": true
161
+ }
162
+ },
163
+ "title": {
164
+ "type": "text",
165
+ "required": false,
166
+ "_meta": {
167
+ "nullable": true
168
+ }
169
+ },
170
+ "description": {
171
+ "type": "text",
172
+ "required": false,
173
+ "_meta": {
174
+ "nullable": true
175
+ }
176
+ },
177
+ "planes": {
178
+ "type": "text",
179
+ "required": false,
180
+ "_meta": {
181
+ "nullable": true
182
+ }
183
+ },
184
+ "onStepFailure": {
185
+ "type": "text",
186
+ "required": false,
187
+ "_meta": {
188
+ "nullable": true
189
+ }
190
+ },
191
+ "enabled": {
192
+ "type": "boolean",
193
+ "required": false,
194
+ "_meta": {
195
+ "nullable": true
196
+ }
197
+ },
198
+ "metadata": {
199
+ "type": "text",
200
+ "required": false,
201
+ "_meta": {
202
+ "nullable": true
203
+ }
204
+ }
205
+ },
206
+ "methods": {
207
+ "getMetadata": {
208
+ "name": "getMetadata",
209
+ "async": false,
210
+ "parameters": [],
211
+ "returnType": "PlaybookMetadata",
212
+ "isStatic": false,
213
+ "isPublic": true
214
+ },
215
+ "setMetadata": {
216
+ "name": "setMetadata",
217
+ "async": false,
218
+ "parameters": [
219
+ {
220
+ "name": "metadata",
221
+ "type": "PlaybookMetadata | null",
222
+ "optional": false
223
+ }
224
+ ],
225
+ "returnType": "void",
226
+ "isStatic": false,
227
+ "isPublic": true
228
+ },
229
+ "getPlanes": {
230
+ "name": "getPlanes",
231
+ "async": false,
232
+ "parameters": [],
233
+ "returnType": "null",
234
+ "isStatic": false,
235
+ "isPublic": true
236
+ },
237
+ "setPlanes": {
238
+ "name": "setPlanes",
239
+ "async": false,
240
+ "parameters": [
241
+ {
242
+ "name": "planes",
243
+ "type": "null",
244
+ "optional": false
245
+ }
246
+ ],
247
+ "returnType": "void",
248
+ "isStatic": false,
249
+ "isPublic": true
250
+ },
251
+ "toPlaybookLayer": {
252
+ "name": "toPlaybookLayer",
253
+ "async": false,
254
+ "parameters": [],
255
+ "returnType": "PlaybookLayer",
256
+ "isStatic": false,
257
+ "isPublic": true
258
+ },
259
+ "save": {
260
+ "name": "save",
261
+ "async": true,
262
+ "parameters": [],
263
+ "returnType": "Promise",
264
+ "isStatic": false,
265
+ "isPublic": true
266
+ },
267
+ "delete": {
268
+ "name": "delete",
269
+ "async": true,
270
+ "parameters": [],
271
+ "returnType": "Promise<void>",
272
+ "isStatic": false,
273
+ "isPublic": true
274
+ }
275
+ },
276
+ "decoratorConfig": {
277
+ "tableName": "_smrt_playbook_overrides",
278
+ "conflictColumns": [
279
+ "key",
280
+ "context"
281
+ ],
282
+ "api": {
283
+ "include": [
284
+ "list",
285
+ "get",
286
+ "create",
287
+ "update",
288
+ "delete"
289
+ ]
290
+ },
291
+ "cli": {
292
+ "include": [
293
+ "list",
294
+ "get",
295
+ "create",
296
+ "update",
297
+ "delete"
298
+ ],
299
+ "exclude": [
300
+ "getMetadata",
301
+ "setMetadata",
302
+ "getPlanes",
303
+ "setPlanes",
304
+ "toPlaybookLayer"
305
+ ]
306
+ },
307
+ "mcp": {
308
+ "include": []
309
+ }
310
+ },
311
+ "extends": "SmrtObject",
312
+ "exportName": "PlaybookOverride",
313
+ "collectionExportName": "PlaybookOverrideCollection",
314
+ "validationRules": [
315
+ {
316
+ "field": "key",
317
+ "rule": "required",
318
+ "fieldType": "text"
319
+ }
320
+ ],
321
+ "schema": {
322
+ "tableName": "_smrt_playbook_overrides",
323
+ "ddl": "CREATE TABLE IF NOT EXISTS \"_smrt_playbook_overrides\" (\n \"id\" UUID PRIMARY KEY NOT NULL,\n \"slug\" TEXT NOT NULL,\n \"context\" TEXT NOT NULL DEFAULT '',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"key\" TEXT NOT NULL DEFAULT '',\n \"tenant_id\" TEXT,\n \"title\" TEXT,\n \"description\" TEXT,\n \"planes\" TEXT,\n \"on_step_failure\" TEXT,\n \"enabled\" BOOLEAN,\n \"metadata\" TEXT\n);",
324
+ "columns": {
325
+ "id": {
326
+ "type": "UUID",
327
+ "primaryKey": true,
328
+ "referenceKind": "id",
329
+ "notNull": true
330
+ },
331
+ "slug": {
332
+ "type": "TEXT",
333
+ "notNull": true
334
+ },
335
+ "context": {
336
+ "type": "TEXT",
337
+ "notNull": true,
338
+ "default": ""
339
+ },
340
+ "created_at": {
341
+ "type": "TIMESTAMP",
342
+ "notNull": true,
343
+ "default": "current_timestamp"
344
+ },
345
+ "updated_at": {
346
+ "type": "TIMESTAMP",
347
+ "notNull": true,
348
+ "default": "current_timestamp"
349
+ },
350
+ "key": {
351
+ "type": "TEXT",
352
+ "notNull": true,
353
+ "unique": false,
354
+ "default": ""
355
+ },
356
+ "tenant_id": {
357
+ "type": "TEXT",
358
+ "notNull": false,
359
+ "unique": false
360
+ },
361
+ "title": {
362
+ "type": "TEXT",
363
+ "notNull": false,
364
+ "unique": false
365
+ },
366
+ "description": {
367
+ "type": "TEXT",
368
+ "notNull": false,
369
+ "unique": false
370
+ },
371
+ "planes": {
372
+ "type": "TEXT",
373
+ "notNull": false,
374
+ "unique": false
375
+ },
376
+ "on_step_failure": {
377
+ "type": "TEXT",
378
+ "notNull": false,
379
+ "unique": false
380
+ },
381
+ "enabled": {
382
+ "type": "BOOLEAN",
383
+ "notNull": false,
384
+ "unique": false
385
+ },
386
+ "metadata": {
387
+ "type": "TEXT",
388
+ "notNull": false,
389
+ "unique": false
390
+ }
391
+ },
392
+ "indexes": [
393
+ {
394
+ "name": "_smrt_playbook_overrides_key_context_idx",
395
+ "columns": [
396
+ "key",
397
+ "context"
398
+ ],
399
+ "unique": true
400
+ },
401
+ {
402
+ "name": "_smrt_playbook_overrides_slug_context_idx",
403
+ "columns": [
404
+ "slug",
405
+ "context"
406
+ ]
407
+ },
408
+ {
409
+ "name": "_smrt_playbook_overrides_created_at_idx",
410
+ "columns": [
411
+ "created_at"
412
+ ]
413
+ }
414
+ ],
415
+ "version": "8aec8e13"
416
+ }
417
+ }
418
+ },
419
+ "moduleType": "smrt",
420
+ "smrtDependencies": [
421
+ "@happyvertical/smrt-core",
422
+ "@happyvertical/smrt-tenancy"
423
+ ]
424
+ }