@odla-ai/brand 0.7.2 → 0.8.1

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/dist/index.d.cts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { P as ProposalKind, a as ProposalStatus, A as AssetKind, b as AssetAnalysis, B as BookStatus, c as BrandTokensSnapshot, d as PaletteStatus, S as Swatch, e as PaletteSource, f as SectionKind, g as SectionStatus, h as SwatchRole } from './index-r6SGidYT.cjs';
2
2
  export { i as ASSET_KINDS, j as BOOK_STATUSES, k as BRAND_CHART_TOKENS, l as BRAND_CHAT_TOKENS, m as BRAND_DERIVED_TOKENS, n as BRAND_EMITTED_TOKENS, o as BRAND_NS, p as BRAND_REQUIRED_TOKENS, q as BrandTokens, C as CompileInput, r as CompiledBrandTokens, D as DARK_FLIP_L_MAX, s as DARK_FLIP_L_MIN, t as DEFAULT_ACCENT_SEED, u as DESIGN_ASSET_KIND, I as ImagerySection, L as LogoSection, M as MapResult, v as PALETTE_SOURCES, w as PALETTE_STATUSES, x as PROPOSAL_KINDS, y as PROPOSAL_STATUSES, z as PaletteSection, R as ROLE_TOKEN, E as RenderTokensCssOptions, F as SECTION_KINDS, G as SECTION_STATUSES, H as SWATCH_ROLES, T as TokenWarning, J as TypographySection, V as VoiceSection, K as compileBrandTokens, N as deriveDarkTokens, O as mapPaletteToTokens, Q as renderTokensCss } from './index-r6SGidYT.cjs';
3
3
  import { ToolHandler, Skill, ToolDef, Persona, Inference, AgentRunInput, ImageBlock, OracleContentBlock } from '@odla-ai/ai';
4
+ import { PromotionAdapterResult } from '@odla-ai/promotion';
4
5
 
5
6
  /** One entry of the bundle's base64 asset manifest, without its payload. */
6
7
  interface DesignBundleAsset {
@@ -1901,4 +1902,15 @@ interface CreateBrandIntegrationOptions {
1901
1902
  */
1902
1903
  declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
1903
1904
 
1904
- export { ASSET_CONTENT_TYPES, type AcceptProposalInput, AssetAnalysis, AssetKind, type AttrType, type AudienceChildren, BRAND_AGENT_PROFILE, BRAND_DISCUSSION_REFERENCE_KINDS, BRAND_INSTRUCTIONS, BRAND_RULES, BRAND_SCHEMA, BookStatus, type BrandActor, type BrandAgentBridge, type BrandAgentProfile, type BrandApprovalReceipt, type BrandAsset, type BrandAttrs, type BrandBook, type BrandBotTriggerOpts, type BrandCapabilityAuthority, BrandConflictError, type BrandDb, type BrandDecisionBinding, type BrandDeps, type BrandDiscussionReference, type BrandDiscussionReferenceKind, type BrandDiscussionReferenceTarget, type BrandDiscussionSwatch, type BrandDispatchBody, type BrandDispatchDeps, type BrandEntityRef, type BrandFetchedBytes, type BrandFileRecord, BrandForbiddenError, BrandGoneError, type BrandHumanAuthorityConsumption, BrandInputError, type BrandIntegrationDescriptor, type BrandIntegrationProbe, type BrandLookup, BrandNotFoundError, type BrandOp, type BrandPalette, type BrandPrincipalProjection, type BrandProposal, type BrandProposalProvenance, type BrandProposalReviewSnapshot, type BrandResult, BrandReviewStateChangedError, type BrandRouteCtx, type BrandRouteOpts, type BrandRow, type BrandRule, type BrandRules, type BrandScalar, type BrandSection, type BrandSkillOpts, type BrandSkillSelf, type BrandSourceAssetSnapshot, type BrandStorage, BrandTokensSnapshot, type BrandToolCtx, type BrandTransactGuard, type BrandTransactOptions, type BrandTrigger, type BrandUploadBody, type BrandVisionCapabilities, type BrandVisionSpec, CHART_DELTA_MIN, CHAT_MESSAGE_NS, CSS_NAMED_COLORS, type ContrastKind, type CreateAssetInput, type CreateBookInput, type CreateBrandIntegrationOptions, type CreateBrandPersonaOpts, DEFAULT_BRAND_SYSTEM, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, MAX_VIEW_BYTES, type NamedColor, type NearestNamedColor, type Oklab, type Oklch, PICK_TEXT_DEFAULT_CANDIDATES, PaletteSource, PaletteStatus, ProposalKind, ProposalStatus, type ProposePaletteInput, type ProposeSectionInput, RAMP_L_MAX, RAMP_L_MIN, type RejectProposalInput, type ResolvedBrandDeps, type Rgb, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalAsWritten, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, receiptAsWritten, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, rowAsWritten, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
1905
+ /** Stable adapter identity bound into Brand artifact provenance. */
1906
+ declare const BRAND_PROMOTION_ADAPTER = "@odla-ai/brand/v1";
1907
+ /** Approved Brand rows required to export one bounded promotion selection. */
1908
+ interface BrandPromotionInput {
1909
+ book: BrandBook;
1910
+ sections: readonly BrandSection[];
1911
+ palettes: readonly BrandPalette[];
1912
+ }
1913
+ /** Export only human-approved, provider-independent Brand state. */
1914
+ declare function exportBrandPromotion(input: BrandPromotionInput): PromotionAdapterResult;
1915
+
1916
+ export { ASSET_CONTENT_TYPES, type AcceptProposalInput, AssetAnalysis, AssetKind, type AttrType, type AudienceChildren, BRAND_AGENT_PROFILE, BRAND_DISCUSSION_REFERENCE_KINDS, BRAND_INSTRUCTIONS, BRAND_PROMOTION_ADAPTER, BRAND_RULES, BRAND_SCHEMA, BookStatus, type BrandActor, type BrandAgentBridge, type BrandAgentProfile, type BrandApprovalReceipt, type BrandAsset, type BrandAttrs, type BrandBook, type BrandBotTriggerOpts, type BrandCapabilityAuthority, BrandConflictError, type BrandDb, type BrandDecisionBinding, type BrandDeps, type BrandDiscussionReference, type BrandDiscussionReferenceKind, type BrandDiscussionReferenceTarget, type BrandDiscussionSwatch, type BrandDispatchBody, type BrandDispatchDeps, type BrandEntityRef, type BrandFetchedBytes, type BrandFileRecord, BrandForbiddenError, BrandGoneError, type BrandHumanAuthorityConsumption, BrandInputError, type BrandIntegrationDescriptor, type BrandIntegrationProbe, type BrandLookup, BrandNotFoundError, type BrandOp, type BrandPalette, type BrandPrincipalProjection, type BrandPromotionInput, type BrandProposal, type BrandProposalProvenance, type BrandProposalReviewSnapshot, type BrandResult, BrandReviewStateChangedError, type BrandRouteCtx, type BrandRouteOpts, type BrandRow, type BrandRule, type BrandRules, type BrandScalar, type BrandSection, type BrandSkillOpts, type BrandSkillSelf, type BrandSourceAssetSnapshot, type BrandStorage, BrandTokensSnapshot, type BrandToolCtx, type BrandTransactGuard, type BrandTransactOptions, type BrandTrigger, type BrandUploadBody, type BrandVisionCapabilities, type BrandVisionSpec, CHART_DELTA_MIN, CHAT_MESSAGE_NS, CSS_NAMED_COLORS, type ContrastKind, type CreateAssetInput, type CreateBookInput, type CreateBrandIntegrationOptions, type CreateBrandPersonaOpts, DEFAULT_BRAND_SYSTEM, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, MAX_VIEW_BYTES, type NamedColor, type NearestNamedColor, type Oklab, type Oklch, PICK_TEXT_DEFAULT_CANDIDATES, PaletteSource, PaletteStatus, ProposalKind, ProposalStatus, type ProposePaletteInput, type ProposeSectionInput, RAMP_L_MAX, RAMP_L_MIN, type RejectProposalInput, type ResolvedBrandDeps, type Rgb, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, exportBrandPromotion, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalAsWritten, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, receiptAsWritten, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, rowAsWritten, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { P as ProposalKind, a as ProposalStatus, A as AssetKind, b as AssetAnalysis, B as BookStatus, c as BrandTokensSnapshot, d as PaletteStatus, S as Swatch, e as PaletteSource, f as SectionKind, g as SectionStatus, h as SwatchRole } from './index-r6SGidYT.js';
2
2
  export { i as ASSET_KINDS, j as BOOK_STATUSES, k as BRAND_CHART_TOKENS, l as BRAND_CHAT_TOKENS, m as BRAND_DERIVED_TOKENS, n as BRAND_EMITTED_TOKENS, o as BRAND_NS, p as BRAND_REQUIRED_TOKENS, q as BrandTokens, C as CompileInput, r as CompiledBrandTokens, D as DARK_FLIP_L_MAX, s as DARK_FLIP_L_MIN, t as DEFAULT_ACCENT_SEED, u as DESIGN_ASSET_KIND, I as ImagerySection, L as LogoSection, M as MapResult, v as PALETTE_SOURCES, w as PALETTE_STATUSES, x as PROPOSAL_KINDS, y as PROPOSAL_STATUSES, z as PaletteSection, R as ROLE_TOKEN, E as RenderTokensCssOptions, F as SECTION_KINDS, G as SECTION_STATUSES, H as SWATCH_ROLES, T as TokenWarning, J as TypographySection, V as VoiceSection, K as compileBrandTokens, N as deriveDarkTokens, O as mapPaletteToTokens, Q as renderTokensCss } from './index-r6SGidYT.js';
3
3
  import { ToolHandler, Skill, ToolDef, Persona, Inference, AgentRunInput, ImageBlock, OracleContentBlock } from '@odla-ai/ai';
4
+ import { PromotionAdapterResult } from '@odla-ai/promotion';
4
5
 
5
6
  /** One entry of the bundle's base64 asset manifest, without its payload. */
6
7
  interface DesignBundleAsset {
@@ -1901,4 +1902,15 @@ interface CreateBrandIntegrationOptions {
1901
1902
  */
1902
1903
  declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
1903
1904
 
1904
- export { ASSET_CONTENT_TYPES, type AcceptProposalInput, AssetAnalysis, AssetKind, type AttrType, type AudienceChildren, BRAND_AGENT_PROFILE, BRAND_DISCUSSION_REFERENCE_KINDS, BRAND_INSTRUCTIONS, BRAND_RULES, BRAND_SCHEMA, BookStatus, type BrandActor, type BrandAgentBridge, type BrandAgentProfile, type BrandApprovalReceipt, type BrandAsset, type BrandAttrs, type BrandBook, type BrandBotTriggerOpts, type BrandCapabilityAuthority, BrandConflictError, type BrandDb, type BrandDecisionBinding, type BrandDeps, type BrandDiscussionReference, type BrandDiscussionReferenceKind, type BrandDiscussionReferenceTarget, type BrandDiscussionSwatch, type BrandDispatchBody, type BrandDispatchDeps, type BrandEntityRef, type BrandFetchedBytes, type BrandFileRecord, BrandForbiddenError, BrandGoneError, type BrandHumanAuthorityConsumption, BrandInputError, type BrandIntegrationDescriptor, type BrandIntegrationProbe, type BrandLookup, BrandNotFoundError, type BrandOp, type BrandPalette, type BrandPrincipalProjection, type BrandProposal, type BrandProposalProvenance, type BrandProposalReviewSnapshot, type BrandResult, BrandReviewStateChangedError, type BrandRouteCtx, type BrandRouteOpts, type BrandRow, type BrandRule, type BrandRules, type BrandScalar, type BrandSection, type BrandSkillOpts, type BrandSkillSelf, type BrandSourceAssetSnapshot, type BrandStorage, BrandTokensSnapshot, type BrandToolCtx, type BrandTransactGuard, type BrandTransactOptions, type BrandTrigger, type BrandUploadBody, type BrandVisionCapabilities, type BrandVisionSpec, CHART_DELTA_MIN, CHAT_MESSAGE_NS, CSS_NAMED_COLORS, type ContrastKind, type CreateAssetInput, type CreateBookInput, type CreateBrandIntegrationOptions, type CreateBrandPersonaOpts, DEFAULT_BRAND_SYSTEM, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, MAX_VIEW_BYTES, type NamedColor, type NearestNamedColor, type Oklab, type Oklch, PICK_TEXT_DEFAULT_CANDIDATES, PaletteSource, PaletteStatus, ProposalKind, ProposalStatus, type ProposePaletteInput, type ProposeSectionInput, RAMP_L_MAX, RAMP_L_MIN, type RejectProposalInput, type ResolvedBrandDeps, type Rgb, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalAsWritten, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, receiptAsWritten, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, rowAsWritten, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
1905
+ /** Stable adapter identity bound into Brand artifact provenance. */
1906
+ declare const BRAND_PROMOTION_ADAPTER = "@odla-ai/brand/v1";
1907
+ /** Approved Brand rows required to export one bounded promotion selection. */
1908
+ interface BrandPromotionInput {
1909
+ book: BrandBook;
1910
+ sections: readonly BrandSection[];
1911
+ palettes: readonly BrandPalette[];
1912
+ }
1913
+ /** Export only human-approved, provider-independent Brand state. */
1914
+ declare function exportBrandPromotion(input: BrandPromotionInput): PromotionAdapterResult;
1915
+
1916
+ export { ASSET_CONTENT_TYPES, type AcceptProposalInput, AssetAnalysis, AssetKind, type AttrType, type AudienceChildren, BRAND_AGENT_PROFILE, BRAND_DISCUSSION_REFERENCE_KINDS, BRAND_INSTRUCTIONS, BRAND_PROMOTION_ADAPTER, BRAND_RULES, BRAND_SCHEMA, BookStatus, type BrandActor, type BrandAgentBridge, type BrandAgentProfile, type BrandApprovalReceipt, type BrandAsset, type BrandAttrs, type BrandBook, type BrandBotTriggerOpts, type BrandCapabilityAuthority, BrandConflictError, type BrandDb, type BrandDecisionBinding, type BrandDeps, type BrandDiscussionReference, type BrandDiscussionReferenceKind, type BrandDiscussionReferenceTarget, type BrandDiscussionSwatch, type BrandDispatchBody, type BrandDispatchDeps, type BrandEntityRef, type BrandFetchedBytes, type BrandFileRecord, BrandForbiddenError, BrandGoneError, type BrandHumanAuthorityConsumption, BrandInputError, type BrandIntegrationDescriptor, type BrandIntegrationProbe, type BrandLookup, BrandNotFoundError, type BrandOp, type BrandPalette, type BrandPrincipalProjection, type BrandPromotionInput, type BrandProposal, type BrandProposalProvenance, type BrandProposalReviewSnapshot, type BrandResult, BrandReviewStateChangedError, type BrandRouteCtx, type BrandRouteOpts, type BrandRow, type BrandRule, type BrandRules, type BrandScalar, type BrandSection, type BrandSkillOpts, type BrandSkillSelf, type BrandSourceAssetSnapshot, type BrandStorage, BrandTokensSnapshot, type BrandToolCtx, type BrandTransactGuard, type BrandTransactOptions, type BrandTrigger, type BrandUploadBody, type BrandVisionCapabilities, type BrandVisionSpec, CHART_DELTA_MIN, CHAT_MESSAGE_NS, CSS_NAMED_COLORS, type ContrastKind, type CreateAssetInput, type CreateBookInput, type CreateBrandIntegrationOptions, type CreateBrandPersonaOpts, DEFAULT_BRAND_SYSTEM, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, MAX_VIEW_BYTES, type NamedColor, type NearestNamedColor, type Oklab, type Oklch, PICK_TEXT_DEFAULT_CANDIDATES, PaletteSource, PaletteStatus, ProposalKind, ProposalStatus, type ProposePaletteInput, type ProposeSectionInput, RAMP_L_MAX, RAMP_L_MIN, type RejectProposalInput, type ResolvedBrandDeps, type Rgb, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, exportBrandPromotion, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalAsWritten, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, receiptAsWritten, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, rowAsWritten, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
package/dist/index.js CHANGED
@@ -708,14 +708,14 @@ var SNAPSHOT_REQUIRED = [
708
708
  ];
709
709
  function validSnapshotShape(value) {
710
710
  if (!record3(value) || !exactKeys(value, SNAPSHOT_REQUIRED)) return false;
711
- const provenance = value.provenance;
712
- return boundedString(value.id) && boundedString(value.bookId) && typeof value.kind === "string" && PROPOSAL_KINDS.includes(value.kind) && value.status === "open" && record3(value.payload) && boundedString(value.rationale, 2e3) && record3(provenance) && exactKeys(provenance, [
711
+ const provenance2 = value.provenance;
712
+ return boundedString(value.id) && boundedString(value.bookId) && typeof value.kind === "string" && PROPOSAL_KINDS.includes(value.kind) && value.status === "open" && record3(value.payload) && boundedString(value.rationale, 2e3) && record3(provenance2) && exactKeys(provenance2, [
713
713
  "sourceAssetId",
714
714
  "sourceAsset",
715
715
  "messageId",
716
716
  "turnId",
717
717
  "taintLabels"
718
- ]) && (provenance.sourceAssetId === null || boundedString(provenance.sourceAssetId)) && (provenance.sourceAsset === null || record3(provenance.sourceAsset) && exactKeys(provenance.sourceAsset, [
718
+ ]) && (provenance2.sourceAssetId === null || boundedString(provenance2.sourceAssetId)) && (provenance2.sourceAsset === null || record3(provenance2.sourceAsset) && exactKeys(provenance2.sourceAsset, [
719
719
  "assetId",
720
720
  "contentDigest",
721
721
  "objectEtag",
@@ -724,7 +724,7 @@ function validSnapshotShape(value) {
724
724
  "contentType",
725
725
  "analysisRevision",
726
726
  "analysisDigest"
727
- ]) && boundedString(provenance.sourceAsset.assetId) && typeof provenance.sourceAsset.contentDigest === "string" && DIGEST.test(provenance.sourceAsset.contentDigest) && boundedString(provenance.sourceAsset.objectEtag) && Number.isSafeInteger(provenance.sourceAsset.objectSize) && provenance.sourceAsset.objectSize > 0 && typeof provenance.sourceAsset.pathDigest === "string" && DIGEST.test(provenance.sourceAsset.pathDigest) && (provenance.sourceAsset.contentType === null || boundedString(provenance.sourceAsset.contentType, 160)) && (provenance.sourceAsset.analysisRevision === null || Number.isSafeInteger(provenance.sourceAsset.analysisRevision) && provenance.sourceAsset.analysisRevision >= 0) && (provenance.sourceAsset.analysisDigest === null || typeof provenance.sourceAsset.analysisDigest === "string" && DIGEST.test(provenance.sourceAsset.analysisDigest))) && (provenance.sourceAssetId === null && provenance.sourceAsset === null || provenance.sourceAssetId !== null && provenance.sourceAsset !== null && provenance.sourceAsset.assetId === provenance.sourceAssetId) && (provenance.messageId === null || boundedString(provenance.messageId)) && (provenance.turnId === null || boundedString(provenance.turnId)) && Array.isArray(provenance.taintLabels) && provenance.taintLabels.length <= 16 && provenance.taintLabels.every((label) => boundedString(label, 120)) && new Set(provenance.taintLabels).size === provenance.taintLabels.length && typeof value.reviewDigest === "string" && DIGEST.test(value.reviewDigest) && Array.isArray(value.audience) && value.audience.length > 0 && value.audience.length <= 100 && value.audience.every((id) => boundedString(id)) && new Set(value.audience).size === value.audience.length && boundedString(value.createdBy) && boundedString(value.createdAuthorityRef) && safeTime(value.createdAt);
727
+ ]) && boundedString(provenance2.sourceAsset.assetId) && typeof provenance2.sourceAsset.contentDigest === "string" && DIGEST.test(provenance2.sourceAsset.contentDigest) && boundedString(provenance2.sourceAsset.objectEtag) && Number.isSafeInteger(provenance2.sourceAsset.objectSize) && provenance2.sourceAsset.objectSize > 0 && typeof provenance2.sourceAsset.pathDigest === "string" && DIGEST.test(provenance2.sourceAsset.pathDigest) && (provenance2.sourceAsset.contentType === null || boundedString(provenance2.sourceAsset.contentType, 160)) && (provenance2.sourceAsset.analysisRevision === null || Number.isSafeInteger(provenance2.sourceAsset.analysisRevision) && provenance2.sourceAsset.analysisRevision >= 0) && (provenance2.sourceAsset.analysisDigest === null || typeof provenance2.sourceAsset.analysisDigest === "string" && DIGEST.test(provenance2.sourceAsset.analysisDigest))) && (provenance2.sourceAssetId === null && provenance2.sourceAsset === null || provenance2.sourceAssetId !== null && provenance2.sourceAsset !== null && provenance2.sourceAsset.assetId === provenance2.sourceAssetId) && (provenance2.messageId === null || boundedString(provenance2.messageId)) && (provenance2.turnId === null || boundedString(provenance2.turnId)) && Array.isArray(provenance2.taintLabels) && provenance2.taintLabels.length <= 16 && provenance2.taintLabels.every((label) => boundedString(label, 120)) && new Set(provenance2.taintLabels).size === provenance2.taintLabels.length && typeof value.reviewDigest === "string" && DIGEST.test(value.reviewDigest) && Array.isArray(value.audience) && value.audience.length > 0 && value.audience.length <= 100 && value.audience.every((id) => boundedString(id)) && new Set(value.audience).size === value.audience.length && boundedString(value.createdBy) && boundedString(value.createdAuthorityRef) && safeTime(value.createdAt);
728
728
  }
729
729
  var CONSUMPTION_REQUIRED = [
730
730
  "id",
@@ -1794,6 +1794,13 @@ function contrastReport(swatches) {
1794
1794
  return report;
1795
1795
  }
1796
1796
 
1797
+ // src/link-shape.ts
1798
+ function hasExactOneLink(value, expectedId) {
1799
+ if (Array.isArray(value))
1800
+ return value.length === 1 && value[0]?.id === expectedId;
1801
+ return typeof value === "object" && value !== null && value.id === expectedId;
1802
+ }
1803
+
1797
1804
  // src/skill/asset-tools.ts
1798
1805
  var MAX_VIEW_BYTES = 4718592;
1799
1806
  var IMAGE_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
@@ -1836,7 +1843,7 @@ function assetTools(ctx) {
1836
1843
  }
1837
1844
  });
1838
1845
  const row = (res[BRAND_NS.asset] ?? [])[0];
1839
- if (!row || row.status !== "live" || row.deletedAt || !Array.isArray(row.book) || row.book.length !== 1 || row.book[0]?.id !== book.id) throw new BrandNotFoundError(`asset ${assetId}`);
1846
+ if (!row || row.status !== "live" || row.deletedAt || !hasExactOneLink(row.book, book.id)) throw new BrandNotFoundError(`asset ${assetId}`);
1840
1847
  return row;
1841
1848
  };
1842
1849
  const viewAsset = {
@@ -1924,7 +1931,7 @@ async function proposalSourceAssetId(ctx, book, value) {
1924
1931
  });
1925
1932
  const rows = result[BRAND_NS.asset] ?? [];
1926
1933
  const asset = rows.length === 1 ? rows[0] : void 0;
1927
- if (!asset || asset.id !== sourceAssetId || asset.bookId !== book.id || asset.status !== "live" || asset.deletedAt !== void 0 || !Array.isArray(asset.book) || asset.book.length !== 1 || asset.book[0]?.id !== book.id) throw new BrandInputError(
1934
+ if (!asset || asset.id !== sourceAssetId || asset.bookId !== book.id || asset.status !== "live" || asset.deletedAt !== void 0 || !hasExactOneLink(asset.book, book.id)) throw new BrandInputError(
1928
1935
  "sourceAssetId must be a live asset in this brand book"
1929
1936
  );
1930
1937
  return sourceAssetId;
@@ -2366,7 +2373,7 @@ function readTools(ctx) {
2366
2373
  book: {}
2367
2374
  }
2368
2375
  });
2369
- const linked = (rows) => rows.filter((row) => row.bookId === authorizedBook.id && Array.isArray(row.book) && row.book.length === 1 && row.book[0]?.id === authorizedBook.id);
2376
+ const linked = (rows) => rows.filter((row) => row.bookId === authorizedBook.id && hasExactOneLink(row.book, authorizedBook.id));
2370
2377
  const sections = linked(
2371
2378
  res[BRAND_NS.section] ?? []
2372
2379
  );
@@ -2416,7 +2423,7 @@ function readTools(ctx) {
2416
2423
  book: {}
2417
2424
  }
2418
2425
  });
2419
- const rows = (res[BRAND_NS.asset] ?? []).filter((asset) => asset.bookId === ctx.bookId && Array.isArray(asset.book) && asset.book.length === 1 && asset.book[0]?.id === ctx.bookId);
2426
+ const rows = (res[BRAND_NS.asset] ?? []).filter((asset) => asset.bookId === ctx.bookId && hasExactOneLink(asset.book, ctx.bookId));
2420
2427
  if (rows.length === 0) {
2421
2428
  return { content: input.kind ? `(no ${String(input.kind)} assets uploaded yet)` : "(no assets uploaded yet)" };
2422
2429
  }
@@ -2545,7 +2552,7 @@ async function linkedAsset(ctx, book, assetId, allowDeleting = false) {
2545
2552
  });
2546
2553
  const row = rowAsWritten(BRAND_NS.asset, (result[BRAND_NS.asset] ?? [])[0]);
2547
2554
  const links = row?.book;
2548
- if (!row || row.bookId !== book.id || !Array.isArray(links) || links.length !== 1 || links[0]?.id !== book.id || row.status !== "live" && !(allowDeleting && row.status === "deleting")) throw new BrandNotFoundError(`asset ${assetId}`);
2555
+ if (!row || row.bookId !== book.id || !hasExactOneLink(links, book.id) || row.status !== "live" && !(allowDeleting && row.status === "deleting")) throw new BrandNotFoundError(`asset ${assetId}`);
2549
2556
  return row;
2550
2557
  }
2551
2558
 
@@ -2748,7 +2755,7 @@ async function handleAssetsRoot(ctx, req, bookId) {
2748
2755
  });
2749
2756
  const assets = (result[BRAND_NS.asset] ?? []).filter((value) => {
2750
2757
  const row = value;
2751
- return row.bookId === book.id && Array.isArray(row.book) && row.book.length === 1 && row.book[0]?.id === book.id;
2758
+ return row.bookId === book.id && hasExactOneLink(row.book, book.id);
2752
2759
  });
2753
2760
  return json({ assets });
2754
2761
  }
@@ -3234,7 +3241,7 @@ async function proposalReceiptByMutation(ctx, mutationKey) {
3234
3241
  }
3235
3242
  });
3236
3243
  const row = (result[BRAND_NS.approvalReceipt] ?? [])[0];
3237
- if (!row || !Array.isArray(row.book) || row.book.length !== 1 || row.book[0]?.id !== row.bookId) return void 0;
3244
+ if (!row || !hasExactOneLink(row.book, row.bookId)) return void 0;
3238
3245
  const { book: _book, ...receipt2 } = row;
3239
3246
  return receiptAsWritten(receipt2);
3240
3247
  }
@@ -3269,7 +3276,7 @@ async function receipt(ctx, id, actionDigest, expected) {
3269
3276
  }
3270
3277
  });
3271
3278
  const row = (result[BRAND_NS.approvalReceipt] ?? [])[0];
3272
- if (!row || row.actionDigest !== actionDigest || row.resolution !== "accepted" || row.bookId !== expected.bookId || row.reviewedProposal.bookId !== expected.bookId || row.reviewedProposal.kind !== expected.kind || !Array.isArray(row.book) || row.book.length !== 1 || row.book[0]?.id !== expected.bookId || expected.paletteId !== void 0 && row.paletteId !== expected.paletteId || expected.proposalId !== void 0 && row.proposalId !== expected.proposalId || expected.content !== void 0 && canonicalBrandJson(row.reviewedProposal.payload.content) !== canonicalBrandJson(expected.content)) throw new BrandConflictError(`approval receipt ${id} is invalid`);
3279
+ if (!row || row.actionDigest !== actionDigest || row.resolution !== "accepted" || row.bookId !== expected.bookId || row.reviewedProposal.bookId !== expected.bookId || row.reviewedProposal.kind !== expected.kind || !hasExactOneLink(row.book, expected.bookId) || expected.paletteId !== void 0 && row.paletteId !== expected.paletteId || expected.proposalId !== void 0 && row.proposalId !== expected.proposalId || expected.content !== void 0 && canonicalBrandJson(row.reviewedProposal.payload.content) !== canonicalBrandJson(expected.content)) throw new BrandConflictError(`approval receipt ${id} is invalid`);
3273
3280
  const { book: _book, ...stored } = row;
3274
3281
  const unhydrated = receiptAsWritten(stored);
3275
3282
  if (!await verifyBrandApprovalReceipt(unhydrated))
@@ -3285,7 +3292,7 @@ async function activePalette(ctx, book) {
3285
3292
  }
3286
3293
  });
3287
3294
  const palette = (result[BRAND_NS.palette] ?? [])[0];
3288
- if (!palette || palette.bookId !== book.id || palette.status !== "active" || !palette.proposalId || !palette.approvalReceiptId || !palette.approvalActionDigest || !Array.isArray(palette.book) || palette.book.length !== 1 || palette.book[0]?.id !== book.id) throw new BrandConflictError(
3295
+ if (!palette || palette.bookId !== book.id || palette.status !== "active" || !palette.proposalId || !palette.approvalReceiptId || !palette.approvalActionDigest || !hasExactOneLink(palette.book, book.id)) throw new BrandConflictError(
3289
3296
  "active palette is missing valid approval provenance"
3290
3297
  );
3291
3298
  const approval = await receipt(
@@ -3334,7 +3341,7 @@ async function approvedTypography(ctx, book) {
3334
3341
  });
3335
3342
  const section = (result[BRAND_NS.section] ?? [])[0];
3336
3343
  if (!section || section.status !== "approved") return {};
3337
- if (section.bookId !== book.id || section.kind !== "typography" || !section.approvalReceiptId || !section.approvalActionDigest || !Array.isArray(section.book) || section.book.length !== 1 || section.book[0]?.id !== book.id) throw new BrandConflictError(
3344
+ if (section.bookId !== book.id || section.kind !== "typography" || !section.approvalReceiptId || !section.approvalActionDigest || !hasExactOneLink(section.book, book.id)) throw new BrandConflictError(
3338
3345
  "approved typography is missing valid approval provenance"
3339
3346
  );
3340
3347
  assertSectionContent("typography", section.content);
@@ -3375,7 +3382,7 @@ async function proposalDecisionState(ctx, req, book, proposal, resolution, recei
3375
3382
  }
3376
3383
  });
3377
3384
  sourceAsset = (result[BRAND_NS.asset] ?? [])[0];
3378
- if (!sourceAsset || sourceAsset.id !== source.assetId || sourceAsset.bookId !== book.id || sourceAsset.status !== "live" || sourceAsset.deletedAt !== void 0 || sourceAsset.contentDigest !== source.contentDigest || sourceAsset.size !== source.objectSize || sourceAsset.contentType !== source.contentType || await brandJsonDigest({ appId: ctx.appId, path: sourceAsset.path }) !== source.pathDigest || sourceAsset.analysisRevision !== source.analysisRevision || (sourceAsset.analysisDigest ?? null) !== source.analysisDigest || !Array.isArray(sourceAsset.book) || sourceAsset.book.length !== 1 || sourceAsset.book[0]?.id !== book.id) throw new BrandConflictError(
3385
+ if (!sourceAsset || sourceAsset.id !== source.assetId || sourceAsset.bookId !== book.id || sourceAsset.status !== "live" || sourceAsset.deletedAt !== void 0 || sourceAsset.contentDigest !== source.contentDigest || sourceAsset.size !== source.objectSize || sourceAsset.contentType !== source.contentType || await brandJsonDigest({ appId: ctx.appId, path: sourceAsset.path }) !== source.pathDigest || sourceAsset.analysisRevision !== source.analysisRevision || (sourceAsset.analysisDigest ?? null) !== source.analysisDigest || !hasExactOneLink(sourceAsset.book, book.id)) throw new BrandConflictError(
3379
3386
  "source asset changed since the proposal was reviewed"
3380
3387
  );
3381
3388
  if (!await ctx.verifySourceAssetSnapshot({
@@ -3559,7 +3566,7 @@ async function handleProposalResolution(ctx, req, bookId, proposalId) {
3559
3566
  }
3560
3567
  });
3561
3568
  const proposal = proposalAsWritten((result[BRAND_NS.proposal] ?? [])[0]);
3562
- if (!proposal || proposal.bookId !== book.id || !Array.isArray(proposal.book) || proposal.book.length !== 1 || proposal.book[0]?.id !== book.id) throw new BrandNotFoundError(`proposal ${proposalId}`);
3569
+ if (!proposal || proposal.bookId !== book.id || !hasExactOneLink(proposal.book, book.id)) throw new BrandNotFoundError(`proposal ${proposalId}`);
3563
3570
  const current = proposalReviewSnapshot(proposal);
3564
3571
  const { reviewDigest, ...unsignedReview } = current;
3565
3572
  if (await brandJsonDigest(unsignedReview) !== reviewDigest || canonicalBrandJson(current) !== canonicalBrandJson(reviewed)) throw new BrandConflictError("proposal changed since review");
@@ -3703,7 +3710,7 @@ async function acceptedReceipt(db, bookId, receiptId, actionDigest) {
3703
3710
  }
3704
3711
  });
3705
3712
  const receipt2 = (result[BRAND_NS.approvalReceipt] ?? [])[0];
3706
- if (!receipt2 || receipt2.resolution !== "accepted" || receipt2.actionDigest !== actionDigest || !Array.isArray(receipt2.book) || receipt2.book.length !== 1 || receipt2.book[0]?.id !== bookId) return missing(bookId);
3713
+ if (!receipt2 || receipt2.resolution !== "accepted" || receipt2.actionDigest !== actionDigest || !hasExactOneLink(receipt2.book, bookId)) return missing(bookId);
3707
3714
  const { book: _book, ...stored } = receipt2;
3708
3715
  const unhydrated = receiptAsWritten(stored);
3709
3716
  if (!await verifyBrandApprovalReceipt(unhydrated)) return missing(bookId);
@@ -3719,7 +3726,7 @@ async function approvedCache(db, book) {
3719
3726
  }
3720
3727
  });
3721
3728
  const palette = (paletteResult[BRAND_NS.palette] ?? [])[0];
3722
- if (!palette || palette.status !== "active" || palette.approvalReceiptId !== cache.paletteReceiptId || palette.approvalActionDigest !== cache.paletteActionDigest || !Array.isArray(palette.book) || palette.book.length !== 1 || palette.book[0]?.id !== book.id) return missing(book.id);
3729
+ if (!palette || palette.status !== "active" || palette.approvalReceiptId !== cache.paletteReceiptId || palette.approvalActionDigest !== cache.paletteActionDigest || !hasExactOneLink(palette.book, book.id)) return missing(book.id);
3723
3730
  await acceptedReceipt(
3724
3731
  db,
3725
3732
  book.id,
@@ -3737,7 +3744,7 @@ async function approvedCache(db, book) {
3737
3744
  });
3738
3745
  const typography = (sectionResult[BRAND_NS.section] ?? [])[0];
3739
3746
  if (hasTypeId) {
3740
- if (!typography || typography.bookId !== book.id || typography.kind !== "typography" || typography.status !== "approved" || typography.approvalReceiptId !== cache.typographyReceiptId || typography.approvalActionDigest !== cache.typographyActionDigest || !Array.isArray(typography.book) || typography.book.length !== 1 || typography.book[0]?.id !== book.id) return missing(book.id);
3747
+ if (!typography || typography.bookId !== book.id || typography.kind !== "typography" || typography.status !== "approved" || typography.approvalReceiptId !== cache.typographyReceiptId || typography.approvalActionDigest !== cache.typographyActionDigest || !hasExactOneLink(typography.book, book.id)) return missing(book.id);
3741
3748
  await acceptedReceipt(
3742
3749
  db,
3743
3750
  book.id,
@@ -4142,7 +4149,7 @@ async function attachedBrandAssetIds(db, book, row) {
4142
4149
  const rows = result[BRAND_NS.asset] ?? [];
4143
4150
  if (rows.length !== 1) return null;
4144
4151
  const asset = rows[0];
4145
- return asset.id === id && asset.bookId === book.id && asset.status === "live" && asset.deletedAt === void 0 && Array.isArray(asset.book) && asset.book.length === 1 && asset.book[0]?.id === book.id ? id : null;
4152
+ return asset.id === id && asset.bookId === book.id && asset.status === "live" && asset.deletedAt === void 0 && hasExactOneLink(asset.book, book.id) ? id : null;
4146
4153
  }));
4147
4154
  return assets.filter((id) => id !== null);
4148
4155
  }
@@ -4365,6 +4372,115 @@ function createBrandIntegration(options = {}) {
4365
4372
  probes: [{ path: `${basePath}/books`, expectedStatus: 401 }]
4366
4373
  };
4367
4374
  }
4375
+
4376
+ // src/promotion.ts
4377
+ import {
4378
+ canonicalPromotionValue
4379
+ } from "@odla-ai/promotion";
4380
+ var BRAND_PROMOTION_ADAPTER = "@odla-ai/brand/v1";
4381
+ var provenance = (sourceIds, receiptDigests = []) => ({
4382
+ adapter: BRAND_PROMOTION_ADAPTER,
4383
+ sourceIds: [...sourceIds].sort(),
4384
+ receiptDigests: [...receiptDigests].sort()
4385
+ });
4386
+ var exclusions = (book) => [
4387
+ {
4388
+ kind: "brand.runtime",
4389
+ id: book.slug,
4390
+ reason: "environment_local",
4391
+ paths: [`${BRAND_NS.book}.ownerId`, `${BRAND_NS.book}.memberIds`, `${BRAND_NS.book}.channelId`, `${BRAND_NS.book}.*At`],
4392
+ detail: "Ownership, roster, channel, and timestamps remain local to the target environment."
4393
+ },
4394
+ {
4395
+ kind: "brand.drafts",
4396
+ id: book.slug,
4397
+ reason: "draft_state",
4398
+ paths: [`${BRAND_NS.proposal}.*`, `${BRAND_NS.section}[status=draft]`],
4399
+ detail: "Open proposals and unapproved sections are review state, not published brand content."
4400
+ },
4401
+ {
4402
+ kind: "brand.assets",
4403
+ id: book.slug,
4404
+ reason: "provider_identity",
4405
+ paths: [`${BRAND_NS.asset}.storageObjectId`, `${BRAND_NS.asset}.path`, `${BRAND_NS.asset}.*AuthorityRef`],
4406
+ detail: "Stored files and provider object identities require a separate asset-transfer contract."
4407
+ },
4408
+ {
4409
+ kind: "brand.authority",
4410
+ id: book.slug,
4411
+ reason: "authority_history",
4412
+ paths: [`${BRAND_NS.approvalReceipt}.*`, `${BRAND_NS.palette}.audience`],
4413
+ detail: "Authority rows stay immutable in their source environment; artifacts retain only receipt digests and ids."
4414
+ }
4415
+ ];
4416
+ function exportBrandPromotion(input) {
4417
+ const { book } = input;
4418
+ if (book.status !== "active") throw new TypeError(`brand book ${book.slug} is not active`);
4419
+ const revision = `brand:${book.slug}:${book.activationRevision}`;
4420
+ const artifacts = [];
4421
+ if (book.tokens) {
4422
+ const {
4423
+ compiledAt: _compiledAt,
4424
+ paletteReceiptId,
4425
+ paletteActionDigest,
4426
+ typographyReceiptId,
4427
+ typographyActionDigest,
4428
+ sourceDigest,
4429
+ ...stableTokens
4430
+ } = book.tokens;
4431
+ artifacts.push({
4432
+ kind: "brand.tokens",
4433
+ id: book.slug,
4434
+ sourceRevision: revision,
4435
+ provenance: provenance(
4436
+ [book.id, book.tokens.paletteId, paletteReceiptId, typographyReceiptId].filter((value) => Boolean(value)),
4437
+ [sourceDigest, paletteActionDigest, typographyActionDigest].filter((value) => Boolean(value))
4438
+ ),
4439
+ content: canonicalPromotionValue({ bookSlug: book.slug, tokens: stableTokens })
4440
+ });
4441
+ }
4442
+ for (const section of input.sections.filter((row) => row.bookId === book.id && row.status === "approved")) {
4443
+ if (!section.approvalReceiptId || !section.approvalActionDigest) {
4444
+ throw new TypeError(`approved brand section ${section.key} lacks approval provenance`);
4445
+ }
4446
+ artifacts.push({
4447
+ kind: "brand.section",
4448
+ id: `${book.slug}/${section.kind}`,
4449
+ sourceRevision: revision,
4450
+ provenance: provenance([book.id, section.id, section.approvalReceiptId], [section.approvalActionDigest]),
4451
+ content: canonicalPromotionValue({ bookSlug: book.slug, kind: section.kind, content: section.content })
4452
+ });
4453
+ }
4454
+ const activePalette2 = input.palettes.find((row) => row.bookId === book.id && row.id === book.activePaletteId && row.status === "active");
4455
+ if (book.activePaletteId && !activePalette2) throw new TypeError(`active palette ${book.activePaletteId} is unavailable`);
4456
+ if (activePalette2) {
4457
+ artifacts.push({
4458
+ kind: "brand.palette",
4459
+ id: `${book.slug}/${activePalette2.id}`,
4460
+ sourceRevision: revision,
4461
+ provenance: provenance([book.id, activePalette2.id, activePalette2.proposalId, activePalette2.approvalReceiptId], [activePalette2.approvalActionDigest]),
4462
+ content: canonicalPromotionValue({
4463
+ bookSlug: book.slug,
4464
+ name: activePalette2.name,
4465
+ swatches: activePalette2.swatches,
4466
+ source: activePalette2.source,
4467
+ ...activePalette2.seedHex ? { seedHex: activePalette2.seedHex } : {},
4468
+ ...activePalette2.rationale ? { rationale: activePalette2.rationale } : {}
4469
+ })
4470
+ });
4471
+ }
4472
+ return {
4473
+ adapter: BRAND_PROMOTION_ADAPTER,
4474
+ artifacts,
4475
+ exclusions: exclusions(book),
4476
+ preconditions: [{
4477
+ code: "brand.schema",
4478
+ path: "services.brand.schemaVersion",
4479
+ expected: 1,
4480
+ detail: "The target must expose the Brand v1 approved-content schema."
4481
+ }]
4482
+ };
4483
+ }
4368
4484
  export {
4369
4485
  ASSET_CONTENT_TYPES,
4370
4486
  ASSET_KINDS,
@@ -4377,6 +4493,7 @@ export {
4377
4493
  BRAND_EMITTED_TOKENS,
4378
4494
  BRAND_INSTRUCTIONS,
4379
4495
  BRAND_NS,
4496
+ BRAND_PROMOTION_ADAPTER,
4380
4497
  BRAND_REQUIRED_TOKENS,
4381
4498
  BRAND_RULES,
4382
4499
  BRAND_SCHEMA,
@@ -4465,6 +4582,7 @@ export {
4465
4582
  digestDesignBundle,
4466
4583
  digestDesignHtml,
4467
4584
  dispatchBrandTurn,
4585
+ exportBrandPromotion,
4468
4586
  extractColors,
4469
4587
  extractDesignTokens,
4470
4588
  extractFonts,