@protoyard/blueprint 0.0.0-stage → 1.1.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.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1145 -2
  3. package/dist/aggregate.d.ts +83 -0
  4. package/dist/aggregate.js +268 -0
  5. package/dist/app-model.d.ts +76 -0
  6. package/dist/app-model.js +287 -0
  7. package/dist/archetypes/index.d.ts +1 -0
  8. package/dist/archetypes/index.js +1 -0
  9. package/dist/archetypes/schema.d.ts +126 -0
  10. package/dist/archetypes/schema.js +77 -0
  11. package/dist/audit.d.ts +52 -0
  12. package/dist/audit.js +149 -0
  13. package/dist/authoring/deck-lint.d.ts +32 -0
  14. package/dist/authoring/deck-lint.js +567 -0
  15. package/dist/authoring/index.d.ts +1 -0
  16. package/dist/authoring/index.js +1 -0
  17. package/dist/authoring/select-deck-layouts.d.ts +50 -0
  18. package/dist/authoring/select-deck-layouts.js +213 -0
  19. package/dist/authoring-apis.d.ts +13 -0
  20. package/dist/authoring-apis.js +13 -0
  21. package/dist/authoring-validation.d.ts +65 -0
  22. package/dist/authoring-validation.js +267 -0
  23. package/dist/avatar.d.ts +25 -0
  24. package/dist/avatar.js +30 -0
  25. package/dist/brand.d.ts +70 -0
  26. package/dist/brand.js +294 -0
  27. package/dist/brief/archetypes.d.ts +28 -0
  28. package/dist/brief/archetypes.js +798 -0
  29. package/dist/brief/content-synthesize.d.ts +31 -0
  30. package/dist/brief/content-synthesize.js +210 -0
  31. package/dist/brief/deck-outlines.d.ts +96 -0
  32. package/dist/brief/deck-outlines.js +561 -0
  33. package/dist/brief/draft-bodies.d.ts +29 -0
  34. package/dist/brief/draft-bodies.js +224 -0
  35. package/dist/brief/fields.d.ts +19 -0
  36. package/dist/brief/fields.js +229 -0
  37. package/dist/brief/index.d.ts +8 -0
  38. package/dist/brief/index.js +8 -0
  39. package/dist/brief/kind-detection.d.ts +69 -0
  40. package/dist/brief/kind-detection.js +353 -0
  41. package/dist/brief/limits.d.ts +117 -0
  42. package/dist/brief/limits.js +217 -0
  43. package/dist/brief/page-doc-outlines.d.ts +80 -0
  44. package/dist/brief/page-doc-outlines.js +485 -0
  45. package/dist/brief/synthesize.d.ts +59 -0
  46. package/dist/brief/synthesize.js +511 -0
  47. package/dist/brief/text.d.ts +13 -0
  48. package/dist/brief/text.js +59 -0
  49. package/dist/canvas-screen.d.ts +31 -0
  50. package/dist/canvas-screen.js +33 -0
  51. package/dist/canvas-seed.d.ts +58 -0
  52. package/dist/canvas-seed.js +82 -0
  53. package/dist/computed/evaluate.d.ts +11 -0
  54. package/dist/computed/evaluate.js +101 -0
  55. package/dist/computed/index.d.ts +4 -0
  56. package/dist/computed/index.js +3 -0
  57. package/dist/computed/public.d.ts +14 -0
  58. package/dist/computed/public.js +19 -0
  59. package/dist/computed/schema.d.ts +10 -0
  60. package/dist/computed/schema.js +140 -0
  61. package/dist/computed/types.d.ts +70 -0
  62. package/dist/computed/types.js +1 -0
  63. package/dist/computed/validate.d.ts +6 -0
  64. package/dist/computed/validate.js +146 -0
  65. package/dist/csv-guard.d.ts +15 -0
  66. package/dist/csv-guard.js +29 -0
  67. package/dist/csv.d.ts +85 -0
  68. package/dist/csv.js +288 -0
  69. package/dist/files.d.ts +35 -0
  70. package/dist/files.js +246 -0
  71. package/dist/form-schema.d.ts +124 -0
  72. package/dist/form-schema.js +300 -0
  73. package/dist/generator-version.d.ts +11 -0
  74. package/dist/generator-version.js +51 -0
  75. package/dist/generator.d.ts +34 -0
  76. package/dist/generator.js +445 -0
  77. package/dist/identity.d.ts +34 -0
  78. package/dist/identity.js +91 -0
  79. package/dist/import/csv-shape.d.ts +40 -0
  80. package/dist/import/csv-shape.js +265 -0
  81. package/dist/import/json-shape.d.ts +55 -0
  82. package/dist/import/json-shape.js +491 -0
  83. package/dist/import/limits.d.ts +13 -0
  84. package/dist/import/limits.js +14 -0
  85. package/dist/import/sqlite-schema.d.ts +36 -0
  86. package/dist/import/sqlite-schema.js +729 -0
  87. package/dist/index.d.ts +60 -0
  88. package/dist/index.js +58 -0
  89. package/dist/kinds/anchors.d.ts +18 -0
  90. package/dist/kinds/anchors.js +46 -0
  91. package/dist/kinds/bodies.d.ts +6 -0
  92. package/dist/kinds/bodies.js +32 -0
  93. package/dist/kinds/brand-runtime.d.ts +19 -0
  94. package/dist/kinds/brand-runtime.js +35 -0
  95. package/dist/kinds/deck.d.ts +8 -0
  96. package/dist/kinds/deck.js +34 -0
  97. package/dist/kinds/doc.d.ts +19 -0
  98. package/dist/kinds/doc.js +41 -0
  99. package/dist/kinds/embed/index.d.ts +39 -0
  100. package/dist/kinds/embed/index.js +91 -0
  101. package/dist/kinds/envelope.d.ts +159 -0
  102. package/dist/kinds/envelope.js +78 -0
  103. package/dist/kinds/index.d.ts +11 -0
  104. package/dist/kinds/index.js +11 -0
  105. package/dist/kinds/kind.d.ts +36 -0
  106. package/dist/kinds/kind.js +55 -0
  107. package/dist/kinds/limits.d.ts +64 -0
  108. package/dist/kinds/limits.js +190 -0
  109. package/dist/kinds/page-doc-runtime.d.ts +37 -0
  110. package/dist/kinds/page-doc-runtime.js +55 -0
  111. package/dist/kinds/page.d.ts +16 -0
  112. package/dist/kinds/page.js +67 -0
  113. package/dist/kinds/parse.d.ts +18 -0
  114. package/dist/kinds/parse.js +27 -0
  115. package/dist/kinds/runtime.d.ts +128 -0
  116. package/dist/kinds/runtime.js +206 -0
  117. package/dist/kinds/services.d.ts +49 -0
  118. package/dist/kinds/services.js +249 -0
  119. package/dist/kinds/testing.d.ts +9 -0
  120. package/dist/kinds/testing.js +16 -0
  121. package/dist/migrations.d.ts +97 -0
  122. package/dist/migrations.js +351 -0
  123. package/dist/motion.d.ts +50 -0
  124. package/dist/motion.js +52 -0
  125. package/dist/notifications.d.ts +19 -0
  126. package/dist/notifications.js +177 -0
  127. package/dist/patch.d.ts +122 -0
  128. package/dist/patch.js +322 -0
  129. package/dist/policy.d.ts +23 -0
  130. package/dist/policy.js +105 -0
  131. package/dist/runtime-definition.d.ts +39 -0
  132. package/dist/runtime-definition.js +74 -0
  133. package/dist/scenarios.d.ts +9 -0
  134. package/dist/scenarios.js +49 -0
  135. package/dist/schema/blueprint.schema.json +10191 -0
  136. package/dist/schema-json.d.ts +6 -0
  137. package/dist/schema-json.js +36 -0
  138. package/dist/schema.d.ts +6348 -0
  139. package/dist/schema.js +1269 -0
  140. package/dist/search.d.ts +16 -0
  141. package/dist/search.js +96 -0
  142. package/dist/services.d.ts +89 -0
  143. package/dist/services.js +898 -0
  144. package/dist/share.d.ts +78 -0
  145. package/dist/share.js +234 -0
  146. package/dist/sheet-screen.d.ts +49 -0
  147. package/dist/sheet-screen.js +91 -0
  148. package/dist/storage.d.ts +43 -0
  149. package/dist/storage.js +179 -0
  150. package/dist/stream.d.ts +26 -0
  151. package/dist/stream.js +173 -0
  152. package/dist/untrusted.d.ts +63 -0
  153. package/dist/untrusted.js +502 -0
  154. package/dist/validation-tasks.d.ts +178 -0
  155. package/dist/validation-tasks.js +199 -0
  156. package/dist/validation.d.ts +35 -0
  157. package/dist/validation.js +312 -0
  158. package/dist/variants.d.ts +112 -0
  159. package/dist/variants.js +283 -0
  160. package/dist/workflows/index.d.ts +3 -0
  161. package/dist/workflows/index.js +3 -0
  162. package/dist/workflows/schema.d.ts +50 -0
  163. package/dist/workflows/schema.js +34 -0
  164. package/dist/workflows/transition.d.ts +15 -0
  165. package/dist/workflows/transition.js +25 -0
  166. package/dist/workflows/validate.d.ts +17 -0
  167. package/dist/workflows/validate.js +140 -0
  168. package/package.json +120 -3
@@ -0,0 +1,31 @@
1
+ import type { ContentKind } from '../kinds/kind.ts';
2
+ import type { BriefKindDetection } from './kind-detection.ts';
3
+ /** Longer briefs are cut here (same cap as app synthesis). */
4
+ export declare const MAX_CONTENT_BRIEF_LENGTH = 5000;
5
+ export interface ContentBriefOptions {
6
+ /** Product / document name; default: a fictional name from the brief. */
7
+ name?: string;
8
+ }
9
+ export interface ContentBriefResult {
10
+ kind: ContentKind;
11
+ kindDetection: BriefKindDetection;
12
+ /** Outline family id (generic until richer templates ship). */
13
+ outline: string;
14
+ /**
15
+ * Draft content blueprint as plain JSON (formatVersion, name, kind, body).
16
+ * Not validated against engine body schemas until those are wired.
17
+ */
18
+ json: Record<string, unknown>;
19
+ rationale: string[];
20
+ }
21
+ /**
22
+ * Deck brief → outline templates (pitch/QBR/…) + deterministic layout selection.
23
+ * Free-slide blocks stay as draft scaffolding; catalog layouts get minimal props
24
+ * from the slide title when selection leaves `free`.
25
+ */
26
+ export declare function synthesizeDeckFromBrief(brief: string, detection: BriefKindDetection, options?: ContentBriefOptions): ContentBriefResult;
27
+ /** Page outlines (landing, pricing, waitlist, generic) with bounded blocks. */
28
+ export declare function synthesizePageFromBrief(brief: string, detection: BriefKindDetection, options?: ContentBriefOptions): ContentBriefResult;
29
+ /** Doc outlines (report, handbook, one-pager, proposal, generic) with bounded blocks. */
30
+ export declare function synthesizeDocFromBrief(brief: string, detection: BriefKindDetection, options?: ContentBriefOptions): ContentBriefResult;
31
+ export declare function synthesizeContentFromBrief(kind: ContentKind, brief: string, detection: BriefKindDetection, options?: ContentBriefOptions): ContentBriefResult;
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Kind-specific brief synthesizers for deck, page and doc (ADR-036).
3
+ * Called by `blueprintFromBrief` after kind detection, before any app
4
+ * archetype scoring. Output is honest draft scaffolding: stable ids, no
5
+ * fabricated facts. Page and doc section outlines live in `page-doc-outlines.ts`.
6
+ */
7
+ import { hashString } from '@protoyard/core';
8
+ import { propsForSelectedLayout, selectDeckLayouts } from "../authoring/select-deck-layouts.js";
9
+ import { synthesizeDeckOutline } from "./deck-outlines.js";
10
+ import { docBodyFromOutline, draftSlugId, pageBodyFromOutline } from "./draft-bodies.js";
11
+ import { applyOutlineBounds, boundBriefInput, MAX_CONTENT_BRIEF_LENGTH as CONTENT_CAP, } from "./limits.js";
12
+ import { buildDocOutline, buildPageOutline } from "./page-doc-outlines.js";
13
+ import { normalize, titleCase } from "./text.js";
14
+ /** Longer briefs are cut here (same cap as app synthesis). */
15
+ export const MAX_CONTENT_BRIEF_LENGTH = CONTENT_CAP;
16
+ const NAME_WORDS = [
17
+ 'Harbor',
18
+ 'Lumen',
19
+ 'Cedar',
20
+ 'Beacon',
21
+ 'Juniper',
22
+ 'Copper',
23
+ 'Willow',
24
+ 'Lantern',
25
+ 'Meadow',
26
+ 'Summit',
27
+ 'Quarry',
28
+ 'Tidal',
29
+ 'Ember',
30
+ 'Orchard',
31
+ 'Kestrel',
32
+ 'Maple',
33
+ ];
34
+ function pickName(source, kind, forced) {
35
+ if (forced?.trim())
36
+ return forced.trim().slice(0, 80);
37
+ const normalized = normalize(source);
38
+ const word = NAME_WORDS[hashString(normalized || kind) % NAME_WORDS.length];
39
+ const label = kind === 'deck' ? 'Deck' : kind === 'page' ? 'Page' : 'Doc';
40
+ return `${word} ${label}`.slice(0, 80);
41
+ }
42
+ function brandSeed(name) {
43
+ const seeds = [
44
+ '#0284c7',
45
+ '#059669',
46
+ '#0f766e',
47
+ '#1d4ed8',
48
+ '#4338ca',
49
+ '#7c3aed',
50
+ '#b45309',
51
+ '#be123c',
52
+ ];
53
+ return seeds[hashString(name) % seeds.length];
54
+ }
55
+ function base(kind, name, description) {
56
+ return {
57
+ formatVersion: 1,
58
+ name,
59
+ description: description || `${titleCase(kind)} draft.`,
60
+ tags: [kind],
61
+ brand: {
62
+ name: name.slice(0, 40),
63
+ seed: brandSeed(name),
64
+ styleProfile: 'soft',
65
+ font: 'humanist',
66
+ },
67
+ kind,
68
+ };
69
+ }
70
+ /**
71
+ * Deck brief → outline templates (pitch/QBR/…) + deterministic layout selection.
72
+ * Free-slide blocks stay as draft scaffolding; catalog layouts get minimal props
73
+ * from the slide title when selection leaves `free`.
74
+ */
75
+ export function synthesizeDeckFromBrief(brief, detection, options = {}) {
76
+ const bound = boundBriefInput(brief, { maxLength: MAX_CONTENT_BRIEF_LENGTH });
77
+ const source = bound.brief;
78
+ const name = pickName(source, 'deck', options.name);
79
+ const outline = synthesizeDeckOutline(source, {
80
+ title: options.name?.trim() ? options.name.trim().slice(0, 80) : undefined,
81
+ });
82
+ const selections = selectDeckLayouts(outline.plan.map((slide, index) => {
83
+ const body = outline.deck.slides[index];
84
+ const blockTypes = body && Array.isArray(body.blocks)
85
+ ? body.blocks
86
+ .map((block) => block && typeof block === 'object' && 'type' in block
87
+ ? String(block.type)
88
+ : '')
89
+ .filter(Boolean)
90
+ : [];
91
+ return {
92
+ id: slide.id,
93
+ role: slide.role,
94
+ pacing: slide.pacing,
95
+ purpose: slide.purpose,
96
+ blockTypes,
97
+ };
98
+ }), { aspect: outline.deck.aspect });
99
+ const slides = outline.deck.slides.map((slide, index) => {
100
+ const choice = selections[index];
101
+ const layout = choice?.layout ?? 'free';
102
+ if (layout === 'free') {
103
+ return slide;
104
+ }
105
+ return {
106
+ id: slide.id,
107
+ title: slide.title,
108
+ layout,
109
+ props: propsForSelectedLayout(layout, { title: slide.title, purpose: slide.notes }),
110
+ notes: slide.notes,
111
+ };
112
+ });
113
+ const rationale = [
114
+ detection.reason,
115
+ ...bound.notices,
116
+ ...outline.rationale,
117
+ ...selections.map((row) => `${row.id}: ${row.rationale}`),
118
+ 'Slide bodies are draft placeholders — no fabricated facts.',
119
+ ];
120
+ return {
121
+ kind: 'deck',
122
+ kindDetection: detection,
123
+ outline: outline.outline,
124
+ rationale,
125
+ json: {
126
+ ...base('deck', name, outline.deck.title.slice(0, 280)),
127
+ // DeckBodySchema is DeckSchema: style + slides only (no title/aspect keys).
128
+ deck: {
129
+ style: { aspect: outline.deck.aspect },
130
+ slides,
131
+ },
132
+ },
133
+ };
134
+ }
135
+ /** Page outlines (landing, pricing, waitlist, generic) with bounded blocks. */
136
+ export function synthesizePageFromBrief(brief, detection, options = {}) {
137
+ const bound = boundBriefInput(brief, { maxLength: MAX_CONTENT_BRIEF_LENGTH });
138
+ const source = bound.brief;
139
+ const built = buildPageOutline(source, { title: options.name });
140
+ const clipped = applyOutlineBounds({
141
+ kind: 'page',
142
+ title: built.title,
143
+ sections: built.sections,
144
+ });
145
+ const title = (clipped.outline.title ?? built.title).slice(0, 120);
146
+ const name = options.name?.trim()
147
+ ? options.name.trim().slice(0, 80)
148
+ : pickName(source, 'page', title);
149
+ const rationale = [detection.reason, ...bound.notices, ...clipped.notices, ...built.rationale];
150
+ const sections = (clipped.outline.sections ?? built.sections);
151
+ const page = pageBodyFromOutline({
152
+ id: draftSlugId(name, 'page-draft'),
153
+ title,
154
+ description: title,
155
+ sections,
156
+ });
157
+ return {
158
+ kind: 'page',
159
+ kindDetection: detection,
160
+ outline: built.outline,
161
+ rationale,
162
+ json: {
163
+ ...base('page', name, title.slice(0, 280)),
164
+ page,
165
+ },
166
+ };
167
+ }
168
+ /** Doc outlines (report, handbook, one-pager, proposal, generic) with bounded blocks. */
169
+ export function synthesizeDocFromBrief(brief, detection, options = {}) {
170
+ const bound = boundBriefInput(brief, { maxLength: MAX_CONTENT_BRIEF_LENGTH });
171
+ const source = bound.brief;
172
+ const built = buildDocOutline(source, { title: options.name });
173
+ const clipped = applyOutlineBounds({
174
+ kind: 'doc',
175
+ title: built.title,
176
+ sections: built.sections,
177
+ });
178
+ const title = (clipped.outline.title ?? built.title).slice(0, 120);
179
+ const name = options.name?.trim()
180
+ ? options.name.trim().slice(0, 80)
181
+ : pickName(source, 'doc', title);
182
+ const rationale = [detection.reason, ...bound.notices, ...clipped.notices, ...built.rationale];
183
+ const sections = (clipped.outline.sections ?? built.sections);
184
+ const doc = docBodyFromOutline({
185
+ id: draftSlugId(name, 'doc-draft'),
186
+ title,
187
+ description: title,
188
+ sections,
189
+ });
190
+ return {
191
+ kind: 'doc',
192
+ kindDetection: detection,
193
+ outline: built.outline,
194
+ rationale,
195
+ json: {
196
+ ...base('doc', name, title.slice(0, 280)),
197
+ doc,
198
+ },
199
+ };
200
+ }
201
+ export function synthesizeContentFromBrief(kind, brief, detection, options = {}) {
202
+ switch (kind) {
203
+ case 'deck':
204
+ return synthesizeDeckFromBrief(brief, detection, options);
205
+ case 'page':
206
+ return synthesizePageFromBrief(brief, detection, options);
207
+ case 'doc':
208
+ return synthesizeDocFromBrief(brief, detection, options);
209
+ }
210
+ }
@@ -0,0 +1,96 @@
1
+ export declare const DECK_OUTLINE_IDS: readonly ["pitch", "qbr", "launch", "status", "training", "lesson", "report", "talk"];
2
+ export type DeckOutlineId = (typeof DECK_OUTLINE_IDS)[number];
3
+ /** How long a slide holds the room (A punch, B idea, C diagram, D story). */
4
+ export type DeckPacing = 'punch' | 'idea' | 'diagram' | 'story';
5
+ /** Caps for synthesized outlines (far inside the deck schema's own limits). */
6
+ export declare const DECK_OUTLINE_LIMITS: Readonly<{
7
+ /** No template has more slides than this. */
8
+ maxSlides: 16;
9
+ /** Title text taken from the brief. */
10
+ titleLength: 80;
11
+ /** Characters of the brief read when picking a template. */
12
+ briefLength: 5000;
13
+ }>;
14
+ /** The block builders a template slide can use. */
15
+ type SlideBody = 'title' | 'agenda' | 'statement' | 'bullets' | 'checklist' | 'metrics' | 'chart-note' | 'steps' | 'timeline' | 'comparison' | 'cards' | 'quote' | 'people' | 'risk' | 'poll' | 'quiz' | 'close';
16
+ interface TemplateSlide {
17
+ /** Stable id suffix: the slide id is `slide-<key>`. */
18
+ key: string;
19
+ /** Semantic role, read by layout selection. */
20
+ role: string;
21
+ pacing: DeckPacing;
22
+ title: string;
23
+ body: SlideBody;
24
+ /** What the author should put here (also the speaker-note guidance). */
25
+ purpose: string;
26
+ /** Core slides are always included; optional ones fill a requested count. */
27
+ core: boolean;
28
+ }
29
+ interface DeckOutlineTemplate {
30
+ id: DeckOutlineId;
31
+ label: string;
32
+ /** Whole-word phrases in the brief that select this template. */
33
+ cues: readonly string[];
34
+ slides: readonly TemplateSlide[];
35
+ }
36
+ export declare const DECK_OUTLINES: readonly DeckOutlineTemplate[];
37
+ /** A slide count the brief asks for: "12 slides", "ten-slide", "a 15-minute talk" (one slide a minute). */
38
+ export declare function requestedSlideCount(brief: string): number | null;
39
+ /** The template a brief asks for, with the cues that matched (longest phrase wins ties). */
40
+ export declare function chooseDeckOutline(brief: string): {
41
+ id: DeckOutlineId;
42
+ cues: string[];
43
+ };
44
+ /** A deck title from the brief: the topic after "about/on/for", else the first sentence. */
45
+ export declare function deckTitleFromBrief(brief: string, fallback?: string): string;
46
+ /** Plain JSON blocks; the test validates every one with `@protoyard/blocks`. */
47
+ type BlockJson = Record<string, unknown>;
48
+ export interface DeckOutlineOptions {
49
+ /** Use this template instead of reading cues from the brief. */
50
+ outline?: DeckOutlineId;
51
+ /** Slide count; overrides a count read from the brief. Clamped to the template. */
52
+ slides?: number;
53
+ /** Deck title; default: the topic of the brief. */
54
+ title?: string;
55
+ }
56
+ /** One slide of the synthesized deck body: a free slide of blocks. */
57
+ export interface DeckOutlineSlide {
58
+ id: string;
59
+ title: string;
60
+ layout: 'free';
61
+ blocks: BlockJson[];
62
+ notes: string;
63
+ }
64
+ /** Per-slide data for layout selection and lint. */
65
+ export interface DeckSlidePlan {
66
+ id: string;
67
+ role: string;
68
+ pacing: DeckPacing;
69
+ purpose: string;
70
+ core: boolean;
71
+ }
72
+ export interface DeckOutlineResult {
73
+ outline: DeckOutlineId;
74
+ label: string;
75
+ /** The deck body (the blueprint's `deck` key). */
76
+ deck: {
77
+ title: string;
78
+ aspect: '16:9';
79
+ slides: DeckOutlineSlide[];
80
+ };
81
+ plan: DeckSlidePlan[];
82
+ rationale: string[];
83
+ /** The count asked for (options or brief), before clamping; null when none. */
84
+ requestedSlides: number | null;
85
+ }
86
+ /** The slide-count range a template supports: its core slides up to all slides. */
87
+ export declare function deckOutlineRange(id: DeckOutlineId): {
88
+ min: number;
89
+ max: number;
90
+ };
91
+ /**
92
+ * Builds a draft deck outline from a brief. Pure and deterministic: the same
93
+ * brief and options give the same slide ids, order, blocks and rationale.
94
+ */
95
+ export declare function synthesizeDeckOutline(brief: string, options?: DeckOutlineOptions): DeckOutlineResult;
96
+ export {};