@anthusai/papyrus 0.0.0 → 1.0.0-next.10

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 (282) hide show
  1. package/LICENSE +21 -0
  2. package/amplify/auth/resource.js +61 -0
  3. package/amplify/auth/resource.ts +65 -0
  4. package/amplify/data/resource.js +2069 -0
  5. package/amplify/data/resource.ts +2185 -0
  6. package/amplify/data/schema.js +1882 -0
  7. package/amplify/data/schema.ts +1990 -0
  8. package/amplify/functions/assignment-action/handler.ts +1416 -0
  9. package/amplify/functions/assignment-action/resource.js +8 -0
  10. package/amplify/functions/assignment-action/resource.ts +9 -0
  11. package/amplify/functions/category-action/handler.ts +2259 -0
  12. package/amplify/functions/category-action/resource.js +8 -0
  13. package/amplify/functions/category-action/resource.ts +9 -0
  14. package/amplify/functions/console-chat-responder/Cargo.lock +3456 -0
  15. package/amplify/functions/console-chat-responder/Cargo.toml +26 -0
  16. package/amplify/functions/console-chat-responder/Dockerfile +19 -0
  17. package/amplify/functions/console-chat-responder/py/execute_tactus_runner.py +116 -0
  18. package/amplify/functions/console-chat-responder/resource.js +153 -0
  19. package/amplify/functions/console-chat-responder/resource.ts +179 -0
  20. package/amplify/functions/console-chat-responder/src/main.rs +3242 -0
  21. package/amplify/functions/content-actions/handler.py +149 -0
  22. package/amplify/functions/content-actions/requirements.txt +4 -0
  23. package/amplify/functions/content-actions/resource.js +40 -0
  24. package/amplify/functions/content-actions/resource.ts +54 -0
  25. package/amplify/functions/email-submission-processor/handler.py +46 -0
  26. package/amplify/functions/email-submission-processor/requirements.txt +2 -0
  27. package/amplify/functions/email-submission-processor/resource.js +56 -0
  28. package/amplify/functions/email-submission-processor/resource.ts +69 -0
  29. package/amplify/functions/graphql-jwt-authorizer/handler.ts +193 -0
  30. package/amplify/functions/graphql-jwt-authorizer/resource.js +14 -0
  31. package/amplify/functions/graphql-jwt-authorizer/resource.ts +15 -0
  32. package/amplify/functions/knowledge-query/handler.py +1 -0
  33. package/amplify/functions/knowledge-query/requirements.txt +3 -0
  34. package/amplify/functions/knowledge-query/resource.js +50 -0
  35. package/amplify/functions/knowledge-query/resource.ts +61 -0
  36. package/amplify/functions/manage-user-role/handler.ts +799 -0
  37. package/amplify/functions/manage-user-role/resource.js +8 -0
  38. package/amplify/functions/manage-user-role/resource.ts +9 -0
  39. package/amplify/functions/model-attachment-upload/handler.ts +387 -0
  40. package/amplify/functions/model-attachment-upload/resource.js +8 -0
  41. package/amplify/functions/model-attachment-upload/resource.ts +9 -0
  42. package/amplify/functions/newsroom-summary/handler.ts +321 -0
  43. package/amplify/functions/newsroom-summary/resource.js +8 -0
  44. package/amplify/functions/newsroom-summary/resource.ts +9 -0
  45. package/amplify/functions/procedure-action/handler.ts +621 -0
  46. package/amplify/functions/procedure-action/resource.js +8 -0
  47. package/amplify/functions/procedure-action/resource.ts +9 -0
  48. package/amplify/functions/reader-settings/handler.ts +322 -0
  49. package/amplify/functions/reader-settings/resource.js +8 -0
  50. package/amplify/functions/reader-settings/resource.ts +9 -0
  51. package/amplify/functions/ses-inbound-receive/handler.ts +493 -0
  52. package/amplify/functions/ses-inbound-receive/resource.js +8 -0
  53. package/amplify/functions/ses-inbound-receive/resource.ts +9 -0
  54. package/amplify/functions/shared/amplify-secrets.ts +65 -0
  55. package/amplify/functions/shared/console-chat-enqueue.ts +117 -0
  56. package/amplify/functions/shared/email-mime-intake.ts +196 -0
  57. package/amplify/functions/shared/email-submission.ts +415 -0
  58. package/amplify/functions/shared/inbound-email-intake.ts +37 -0
  59. package/amplify/functions/shared/lambda-data-client.ts +21 -0
  60. package/amplify/functions/shared/model-payloads.ts +186 -0
  61. package/amplify/functions/shared/python-bundle.js +130 -0
  62. package/amplify/functions/shared/python-bundle.ts +162 -0
  63. package/amplify/functions/shared/slack-events.ts +111 -0
  64. package/amplify/functions/slack-delivery/handler.py +112 -0
  65. package/amplify/functions/slack-delivery/requirements.txt +2 -0
  66. package/amplify/functions/slack-delivery/resource.js +38 -0
  67. package/amplify/functions/slack-delivery/resource.ts +51 -0
  68. package/amplify/functions/slack-events/handler.ts +155 -0
  69. package/amplify/functions/slack-events/resource.js +11 -0
  70. package/amplify/functions/slack-events/resource.ts +12 -0
  71. package/amplify/inbound-email/stack.js +46 -0
  72. package/amplify/inbound-email/stack.ts +61 -0
  73. package/amplify/package.json +3 -0
  74. package/amplify/rebuild-trigger-settings.js +22 -0
  75. package/amplify/rebuild-trigger-settings.ts +42 -0
  76. package/amplify/site-backend-config.js +1 -0
  77. package/amplify/site-backend-config.ts +36 -0
  78. package/amplify/site-backend.js +615 -0
  79. package/amplify/site-backend.ts +739 -0
  80. package/amplify/storage/resource.js +21 -0
  81. package/amplify/storage/resource.ts +22 -0
  82. package/app/%5F_preview/[[...path]]/route.ts +8 -0
  83. package/app/[year]/[month]/[day]/[articleSlug]/page.tsx +62 -0
  84. package/app/[year]/[month]/[day]/edition-route-page.tsx +53 -0
  85. package/app/[year]/[month]/[day]/page/[pageNumber]/page.tsx +32 -0
  86. package/app/[year]/[month]/[day]/page.tsx +22 -0
  87. package/app/[year]/[month]/[day]/section/[sectionKey]/page.tsx +32 -0
  88. package/app/api/archive/editions/route.ts +18 -0
  89. package/app/api/media/[...path]/route.ts +35 -0
  90. package/app/api/revalidate/route.ts +94 -0
  91. package/app/archive/page.tsx +24 -0
  92. package/app/articles/[slug]/page.tsx +35 -0
  93. package/app/globals.css +10345 -0
  94. package/app/layout.tsx +142 -0
  95. package/app/newsroom/[section]/[...selection]/page.tsx +50 -0
  96. package/app/newsroom/[section]/page.tsx +47 -0
  97. package/app/newsroom/articles/[id]/page.tsx +15 -0
  98. package/app/newsroom/articles/page.tsx +13 -0
  99. package/app/newsroom/forum/[threadId]/page.tsx +35 -0
  100. package/app/newsroom/insights/[threadId]/page.tsx +22 -0
  101. package/app/newsroom/insights/page.tsx +14 -0
  102. package/app/newsroom/layout.tsx +12 -0
  103. package/app/newsroom/page.tsx +31 -0
  104. package/app/newsroom/sections/[sectionId]/page.tsx +17 -0
  105. package/app/page.tsx +272 -0
  106. package/app/papyrus-theme.css +11 -0
  107. package/app/robots.ts +11 -0
  108. package/app/settings/page.tsx +14 -0
  109. package/app/tailwind.css +65 -0
  110. package/bin/papyrus-app.mjs +20 -0
  111. package/bin/papyrus-infra.mjs +95 -0
  112. package/components/ai-elements/conversation.tsx +168 -0
  113. package/components/ai-elements/message.tsx +360 -0
  114. package/components/ai-elements/model-selector.tsx +30 -0
  115. package/components/ai-elements/prompt-input.tsx +1461 -0
  116. package/components/ai-elements/shimmer.tsx +76 -0
  117. package/components/ai-elements/suggestion.tsx +54 -0
  118. package/components/ai-elements/tool.tsx +173 -0
  119. package/components/amplify-client-provider.tsx +140 -0
  120. package/components/archive-grid.tsx +89 -0
  121. package/components/archive-shell.tsx +41 -0
  122. package/components/article-video.tsx +156 -0
  123. package/components/blog-page-background.tsx +20 -0
  124. package/components/dev-sandbox-editor-sign-in.tsx +60 -0
  125. package/components/markus-ir-preview.tsx +300 -0
  126. package/components/news-desk-client-provider.tsx +211 -0
  127. package/components/news-desk-page.tsx +116 -0
  128. package/components/news-desk-taxonomy-client.ts +3684 -0
  129. package/components/newspaper.tsx +1929 -0
  130. package/components/newsroom-access-gate.tsx +66 -0
  131. package/components/newsroom-article-editor.tsx +741 -0
  132. package/components/newsroom-articles-view.tsx +129 -0
  133. package/components/newsroom-assignments-view.tsx +664 -0
  134. package/components/newsroom-ops-overview.tsx +226 -0
  135. package/components/newsroom-ops-shell.tsx +321 -0
  136. package/components/newsroom-references-view.tsx +598 -0
  137. package/components/newsroom-topics-view.tsx +425 -0
  138. package/components/papyrus-console-shell.tsx +1912 -0
  139. package/components/pictogram-figure.tsx +65 -0
  140. package/components/presentation-footer.tsx +146 -0
  141. package/components/reader-auth-control.tsx +162 -0
  142. package/components/reader-auth-state.ts +122 -0
  143. package/components/reader-settings.ts +332 -0
  144. package/components/reader-theme-control.tsx +85 -0
  145. package/components/reference-source-preview.tsx +163 -0
  146. package/components/settings-page.tsx +239 -0
  147. package/components/staging-banner.tsx +11 -0
  148. package/components/topic-steering-workspace.tsx +18005 -0
  149. package/components/ui/badge.tsx +30 -0
  150. package/components/ui/button-group.tsx +87 -0
  151. package/components/ui/button.tsx +58 -0
  152. package/components/ui/card.tsx +32 -0
  153. package/components/ui/command.tsx +194 -0
  154. package/components/ui/dialog.tsx +158 -0
  155. package/components/ui/dropdown-menu.tsx +266 -0
  156. package/components/ui/hover-card.tsx +51 -0
  157. package/components/ui/input-group.tsx +158 -0
  158. package/components/ui/input.tsx +20 -0
  159. package/components/ui/scroll-area.tsx +16 -0
  160. package/components/ui/select.tsx +199 -0
  161. package/components/ui/separator.tsx +23 -0
  162. package/components/ui/sheet.tsx +92 -0
  163. package/components/ui/spinner.tsx +10 -0
  164. package/components/ui/tabs.tsx +113 -0
  165. package/components/ui/textarea.tsx +18 -0
  166. package/components/ui/tooltip.tsx +66 -0
  167. package/components/use-resolved-papyrus-theme.ts +47 -0
  168. package/infra/amplify-app-shell.js +234 -0
  169. package/infra/amplify-app-shell.ts +284 -0
  170. package/infra/build-specs.js +85 -0
  171. package/infra/build-specs.ts +131 -0
  172. package/infra/github-oidc-provider.js +24 -0
  173. package/infra/github-oidc-provider.ts +30 -0
  174. package/infra/index.js +15 -0
  175. package/infra/site-config.js +186 -0
  176. package/infra/site-config.ts +235 -0
  177. package/lib/amplify-outputs-guard.ts +24 -0
  178. package/lib/amplify-outputs-path.ts +16 -0
  179. package/lib/amplify-server-runtime.ts +63 -0
  180. package/lib/archive-data.ts +30 -0
  181. package/lib/archive-types.ts +15 -0
  182. package/lib/articles.ts +320 -0
  183. package/lib/cached-content-repository.ts +90 -0
  184. package/lib/category-dashboard.ts +37 -0
  185. package/lib/category-repository.ts +1907 -0
  186. package/lib/console-chat-client.ts +1316 -0
  187. package/lib/console-web-context.ts +118 -0
  188. package/lib/content-actions-client.ts +98 -0
  189. package/lib/content-actions-demo.ts +190 -0
  190. package/lib/content-load-timing.ts +23 -0
  191. package/lib/content-repository.ts +43 -0
  192. package/lib/content-source-context.ts +26 -0
  193. package/lib/content-types.ts +104 -0
  194. package/lib/define-site.js +3 -0
  195. package/lib/define-site.ts +21 -0
  196. package/lib/demo-amplify-outputs.ts +15 -0
  197. package/lib/dev-sandbox-editor-auth.ts +18 -0
  198. package/lib/doctrine.ts +128 -0
  199. package/lib/edition-routes.ts +155 -0
  200. package/lib/edition-sections.ts +111 -0
  201. package/lib/empty-edition-layout-plan.ts +109 -0
  202. package/lib/empty-theme.css +1 -0
  203. package/lib/excerpts.ts +8 -0
  204. package/lib/graphql-content-repository.ts +1140 -0
  205. package/lib/image-url.ts +10 -0
  206. package/lib/layout-plan.ts +981 -0
  207. package/lib/layout-scenarios.ts +564 -0
  208. package/lib/markus-body.ts +168 -0
  209. package/lib/markus-ir.ts +235 -0
  210. package/lib/markus-projection.ts +243 -0
  211. package/lib/markus-to-article.ts +93 -0
  212. package/lib/news-desk-session.ts +160 -0
  213. package/lib/newspaper-layout.ts +3459 -0
  214. package/lib/newsroom-articles.ts +325 -0
  215. package/lib/newsroom-assignments.ts +173 -0
  216. package/lib/newsroom-base-path.ts +48 -0
  217. package/lib/newsroom-card-layout.ts +102 -0
  218. package/lib/newsroom-category-drilldown.ts +133 -0
  219. package/lib/newsroom-demo-articles.ts +90 -0
  220. package/lib/newsroom-demo-dashboard.ts +267 -0
  221. package/lib/newsroom-demo-profile.ts +46 -0
  222. package/lib/newsroom-forum-routes.ts +153 -0
  223. package/lib/newsroom-index-filters.ts +202 -0
  224. package/lib/newsroom-knowledge-query-request.ts +51 -0
  225. package/lib/newsroom-list-selection.ts +42 -0
  226. package/lib/newsroom-media-backend.ts +142 -0
  227. package/lib/newsroom-media.ts +182 -0
  228. package/lib/newsroom-nav.ts +44 -0
  229. package/lib/newsroom-references.ts +116 -0
  230. package/lib/newsroom-sections.ts +52 -0
  231. package/lib/newsroom-topics.ts +118 -0
  232. package/lib/papyrus-object-kinds.ts +24 -0
  233. package/lib/papyrus-web-locations.ts +480 -0
  234. package/lib/pilobol-sample.ts +167 -0
  235. package/lib/presentation-footer.ts +92 -0
  236. package/lib/pretext-layout.ts +179 -0
  237. package/lib/public-placeholder-config.ts +102 -0
  238. package/lib/publication-items.ts +181 -0
  239. package/lib/reader-route-config.ts +1 -0
  240. package/lib/reader-static-params.ts +56 -0
  241. package/lib/reader-storage-url.ts +63 -0
  242. package/lib/reference-display.ts +74 -0
  243. package/lib/reference-policy.ts +97 -0
  244. package/lib/reference-source-preview.ts +175 -0
  245. package/lib/renderer-config.ts +50 -0
  246. package/lib/renderer.ts +87 -0
  247. package/lib/reporting-story-budget.ts +638 -0
  248. package/lib/semantic-graph.ts +554 -0
  249. package/lib/site-brand-tenant.ts +22 -0
  250. package/lib/site-brand.ts +194 -0
  251. package/lib/site-env.ts +52 -0
  252. package/lib/site-renderer.ts +17 -0
  253. package/lib/site-stack.ts +195 -0
  254. package/lib/staging-gate.ts +37 -0
  255. package/lib/staging-preview-object.ts +98 -0
  256. package/lib/themed-image.ts +30 -0
  257. package/lib/utils.ts +6 -0
  258. package/lib/video-mode.ts +42 -0
  259. package/lib/video-script.ts +63 -0
  260. package/middleware.ts +103 -0
  261. package/package.json +318 -1
  262. package/renderers/markus/index.ts +25 -0
  263. package/renderers/markus/stubs.tsx +33 -0
  264. package/renderers/pretext/article-page.tsx +169 -0
  265. package/renderers/pretext/index.ts +30 -0
  266. package/renderers/pretext/layouts.ts +16 -0
  267. package/renderers/pretext/presentation-shell.tsx +470 -0
  268. package/routes.manifest.json +208 -0
  269. package/scripts/fixtures/pilobol-sample.ast.json +234 -0
  270. package/scripts/videoml/build-browser-bundle.mjs +22 -0
  271. package/scripts/videoml/build-preview-bundle.mjs +50 -0
  272. package/scripts/videoml/bundle-common.mjs +129 -0
  273. package/scripts/videoml/preview/preview-entry.tsx +381 -0
  274. package/scripts/videoml/preview/preview-stage-fit.ts +28 -0
  275. package/scripts/videoml/preview/preview-timing.ts +42 -0
  276. package/scripts/videoml/preview.html +77 -0
  277. package/scripts/videoml/standard-entry.tsx +46 -0
  278. package/src/backend.js +1 -0
  279. package/src/backend.ts +3 -0
  280. package/src/sync.mjs +87 -0
  281. package/src/with-papyrus.d.mts +2 -0
  282. package/src/with-papyrus.mjs +60 -0
@@ -0,0 +1,1907 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import YAML from "yaml";
4
+ import { createEmptyCategorySteeringDashboard } from "./category-dashboard";
5
+ import { applyPilobolusDemoDashboardContent } from "./newsroom-demo-dashboard";
6
+ import { getNewsroomDemoProfile, isPilobolusDemoBrand } from "./newsroom-demo-profile";
7
+ import { resolveSiteBrandId, type SiteBrandId } from "./site-brand";
8
+
9
+ export { createEmptyCategorySteeringDashboard };
10
+
11
+ export type CategorySteeringCorpus = {
12
+ id: string;
13
+ name: string;
14
+ role: string;
15
+ itemCount?: number | null;
16
+ generatedAt?: string | null;
17
+ latestImportRunId?: string | null;
18
+ };
19
+
20
+ export type CategorySteeringImportRun = {
21
+ id: string;
22
+ corpusId: string;
23
+ importKind: string;
24
+ classifierId?: string | null;
25
+ status: string;
26
+ importedAt: string;
27
+ itemCount?: number | null;
28
+ categoryCount?: number | null;
29
+ proposalCount?: number | null;
30
+ referenceCount?: number | null;
31
+ relationCount?: number | null;
32
+ warningCount?: number | null;
33
+ };
34
+
35
+ export type CategorySteeringCategorySet = {
36
+ id: string;
37
+ lineageId?: string | null;
38
+ versionNumber?: number | null;
39
+ versionState?: string | null;
40
+ corpusId: string;
41
+ classifierId: string;
42
+ displayName: string;
43
+ description?: string | null;
44
+ status: string;
45
+ generatedAt?: string | null;
46
+ categoryCount?: number | null;
47
+ importRunId?: string | null;
48
+ createdAt?: string | null;
49
+ updatedAt?: string | null;
50
+ nodeCount?: number | null;
51
+ rootCount?: number | null;
52
+ };
53
+
54
+ export type CategorySteeringCategory = {
55
+ id: string;
56
+ lineageId?: string | null;
57
+ versionNumber?: number | null;
58
+ previousVersionId?: string | null;
59
+ versionState?: string | null;
60
+ versionCreatedAt?: string | null;
61
+ versionCreatedBy?: string | null;
62
+ changeReason?: string | null;
63
+ contentHash?: string | null;
64
+ categorySetId: string;
65
+ corpusId: string;
66
+ categoryKey: string;
67
+ parentCategoryId?: string | null;
68
+ parentCategoryKey?: string | null;
69
+ displayName: string;
70
+ shortTitle?: string | null;
71
+ subtitle?: string | null;
72
+ description?: string | null;
73
+ aliases?: Array<string | null> | null;
74
+ status: string;
75
+ seedItemIds?: Array<string | null> | null;
76
+ holdoutItemIds?: Array<string | null> | null;
77
+ rank?: number | null;
78
+ depth?: number | null;
79
+ isPinned?: boolean | null;
80
+ importRunId?: string | null;
81
+ updatedAt?: string | null;
82
+ };
83
+
84
+ export type CategorySteeringCategoryTree = CategorySteeringCategorySet;
85
+
86
+ export type CategorySteeringCategoryTreeNode = CategorySteeringCategory;
87
+
88
+ export type CategoryKeywordRecord = {
89
+ id: string;
90
+ categorySetId: string;
91
+ corpusId: string;
92
+ categoryKey: string;
93
+ categoryLineageId?: string | null;
94
+ categoryId?: string | null;
95
+ keyword: string;
96
+ normalizedKeyword: string;
97
+ weight?: number | null;
98
+ rank?: number | null;
99
+ source: string;
100
+ sourceTopicId?: string | null;
101
+ importRunId?: string | null;
102
+ metadata?: unknown;
103
+ createdAt: string;
104
+ updatedAt?: string | null;
105
+ };
106
+
107
+ export type LexicalSteeringRuleRecord = {
108
+ id: string;
109
+ ruleKind: string;
110
+ term: string;
111
+ normalizedTerm: string;
112
+ scope: string;
113
+ status: string;
114
+ corpusId?: string | null;
115
+ classifierId?: string | null;
116
+ categorySetId?: string | null;
117
+ categoryKey?: string | null;
118
+ note?: string | null;
119
+ source?: string | null;
120
+ createdBy?: string | null;
121
+ createdAt: string;
122
+ updatedAt?: string | null;
123
+ metadata?: unknown;
124
+ };
125
+
126
+ export type NewsroomSectionType = "canonical" | "floating" | "rotating";
127
+
128
+ export type NewsroomSectionRecord = {
129
+ id: string;
130
+ title: string;
131
+ shortTitle: string;
132
+ type: NewsroomSectionType;
133
+ editorialMission: string;
134
+ editorialPolicy: string;
135
+ enabled: boolean;
136
+ enabledStatus?: string | null;
137
+ sortOrder: number;
138
+ defaultArticleTypes?: Array<string | null> | null;
139
+ defaultPageBudget?: number | null;
140
+ assignmentGuidance?: string | null;
141
+ killCriteria?: string | null;
142
+ visualGuidance?: string | null;
143
+ createdAt?: string | null;
144
+ updatedAt?: string | null;
145
+ };
146
+
147
+ export type ProcedureDefinitionRecord = {
148
+ id: string;
149
+ procedureKey: string;
150
+ title: string;
151
+ category: string;
152
+ description?: string | null;
153
+ enabled: boolean;
154
+ enabledStatus?: string | null;
155
+ currentVersionId?: string | null;
156
+ createdBy?: string | null;
157
+ createdAt?: string | null;
158
+ updatedBy?: string | null;
159
+ updatedAt?: string | null;
160
+ newsroomFeedKey?: string | null;
161
+ };
162
+
163
+ export type ProcedureVersionRecord = {
164
+ id: string;
165
+ procedureId: string;
166
+ procedureKey: string;
167
+ versionNumber: number;
168
+ status: string;
169
+ isCurrent: boolean;
170
+ label?: string | null;
171
+ tactusSource: string;
172
+ parameterSchema?: unknown;
173
+ defaults?: unknown;
174
+ changelog?: string | null;
175
+ createdBy?: string | null;
176
+ createdAt?: string | null;
177
+ updatedBy?: string | null;
178
+ updatedAt?: string | null;
179
+ };
180
+
181
+ export type ProcedureRunRecord = {
182
+ id: string;
183
+ procedureId: string;
184
+ procedureKey: string;
185
+ procedureVersionId: string;
186
+ procedureVersionNumber?: number | null;
187
+ assignmentId?: string | null;
188
+ runStatus: string;
189
+ requestedBy?: string | null;
190
+ requestedAt?: string | null;
191
+ startedAt?: string | null;
192
+ finishedAt?: string | null;
193
+ input?: unknown;
194
+ normalizedInput?: unknown;
195
+ resultSummary?: string | null;
196
+ errorSummary?: string | null;
197
+ output?: unknown;
198
+ error?: unknown;
199
+ attempt?: number | null;
200
+ newsroomFeedKey?: string | null;
201
+ };
202
+
203
+ const DEFAULT_NEWSROOM_SECTIONS_CONFIG_PATH = path.join(process.cwd(), "corpora", "papyrus-newsroom-sections.yml");
204
+ const NEWSROOM_SECTION_TYPES = new Set<NewsroomSectionType>(["canonical", "floating", "rotating"]);
205
+ type NewsroomSectionSeedRow = Omit<NewsroomSectionRecord, "sortOrder" | "enabled" | "enabledStatus" | "createdAt" | "updatedAt"> & {
206
+ enabled: boolean;
207
+ sortOrder: number;
208
+ };
209
+ const newsroomSectionSeedRowsCache = new Map<string, NewsroomSectionSeedRow[]>();
210
+
211
+ export type SteeringProposal = {
212
+ id: string;
213
+ categorySetId?: string | null;
214
+ corpusId: string;
215
+ proposalKind: string;
216
+ steeringDomain: string;
217
+ status: string;
218
+ title: string;
219
+ summary?: string | null;
220
+ categoryKey?: string | null;
221
+ targetCategoryKey?: string | null;
222
+ graphEntityId?: string | null;
223
+ relationshipType?: string | null;
224
+ displayName?: string | null;
225
+ shortTitle?: string | null;
226
+ subtitle?: string | null;
227
+ description?: string | null;
228
+ evidenceItemIds?: Array<string | null> | null;
229
+ suggestedSeedItemIds?: Array<string | null> | null;
230
+ suggestedHoldoutItemIds?: Array<string | null> | null;
231
+ sourceSnapshotId?: string | null;
232
+ proposedAt?: string | null;
233
+ reviewedAt?: string | null;
234
+ reviewedBy?: string | null;
235
+ updatedAt?: string | null;
236
+ };
237
+
238
+ export type CategorySteeringProposal = SteeringProposal;
239
+
240
+ export type KnowledgeArtifact = {
241
+ id: string;
242
+ corpusId: string;
243
+ artifactKind: string;
244
+ artifactId: string;
245
+ snapshotId?: string | null;
246
+ displayName?: string | null;
247
+ createdAt?: string | null;
248
+ };
249
+
250
+ export type CategorySteeringArtifact = KnowledgeArtifact;
251
+
252
+ export type ReferenceRecord = {
253
+ id: string;
254
+ lineageId?: string | null;
255
+ versionNumber?: number | null;
256
+ previousVersionId?: string | null;
257
+ versionState?: string | null;
258
+ versionCreatedAt?: string | null;
259
+ versionCreatedBy?: string | null;
260
+ changeReason?: string | null;
261
+ contentHash?: string | null;
262
+ corpusId: string;
263
+ externalItemId: string;
264
+ title?: string | null;
265
+ authors?: Array<string | null> | null;
266
+ sourceUri?: string | null;
267
+ storagePath?: string | null;
268
+ mediaType?: string | null;
269
+ byteSize?: number | null;
270
+ sha256?: string | null;
271
+ sourcePublishedAt?: string | null;
272
+ sourceUpdatedAt?: string | null;
273
+ retrievedAt?: string | null;
274
+ inboundCitationCount?: number | null;
275
+ outboundCitationCount?: number | null;
276
+ importRunId?: string | null;
277
+ importedAt?: string | null;
278
+ createdAt?: string | null;
279
+ curationStatus?: string | null;
280
+ curationStatusKey?: string | null;
281
+ curationStatusUpdatedAt?: string | null;
282
+ curationStatusUpdatedBy?: string | null;
283
+ curationStatusReason?: string | null;
284
+ newsroomFeedKey?: string | null;
285
+ reviewedFeedKey?: string | null;
286
+ metadata?: unknown;
287
+ updatedAt?: string | null;
288
+ };
289
+
290
+ export type ReferenceAttachmentRecord = {
291
+ id: string;
292
+ referenceId: string;
293
+ referenceLineageId: string;
294
+ referenceVersionNumber?: number | null;
295
+ referenceVersionKey: string;
296
+ role: string;
297
+ sortKey: string;
298
+ storagePath?: string | null;
299
+ sourceUri?: string | null;
300
+ filename?: string | null;
301
+ mediaType?: string | null;
302
+ byteSize?: number | null;
303
+ sha256?: string | null;
304
+ etag?: string | null;
305
+ importRunId?: string | null;
306
+ importedAt?: string | null;
307
+ metadata?: unknown;
308
+ };
309
+
310
+ export type ModelAttachmentRecord = {
311
+ id: string;
312
+ ownerKind: string;
313
+ ownerId: string;
314
+ ownerLineageId?: string | null;
315
+ ownerVersionNumber?: number | null;
316
+ ownerVersionKey?: string | null;
317
+ role: string;
318
+ sortKey: string;
319
+ storagePath: string;
320
+ filename?: string | null;
321
+ mediaType: string;
322
+ byteSize?: number | null;
323
+ sha256?: string | null;
324
+ etag?: string | null;
325
+ importRunId?: string | null;
326
+ createdAt?: string | null;
327
+ updatedAt?: string | null;
328
+ status?: string | null;
329
+ };
330
+
331
+ export type HydratedModelPayload = {
332
+ attachment: ModelAttachmentRecord;
333
+ text: string | null;
334
+ json: unknown | null;
335
+ error: string | null;
336
+ };
337
+
338
+ export type SemanticNodeRecord = {
339
+ id: string;
340
+ lineageId?: string | null;
341
+ versionNumber?: number | null;
342
+ previousVersionId?: string | null;
343
+ versionState?: string | null;
344
+ versionCreatedAt?: string | null;
345
+ versionCreatedBy?: string | null;
346
+ changeReason?: string | null;
347
+ contentHash?: string | null;
348
+ nodeKey: string;
349
+ nodeKind: string;
350
+ corpusId?: string | null;
351
+ categorySetId?: string | null;
352
+ categoryLineageId?: string | null;
353
+ categoryKey?: string | null;
354
+ displayName?: string | null;
355
+ description?: string | null;
356
+ aliases?: Array<string | null> | null;
357
+ authorityScore?: number | null;
358
+ authorityRank?: number | null;
359
+ acceptedReferenceMentionCount?: number | null;
360
+ distinctSourceKindCount?: number | null;
361
+ relationCount?: number | null;
362
+ status: string;
363
+ importRunId?: string | null;
364
+ createdAt?: string | null;
365
+ newsroomFeedKey?: string | null;
366
+ updatedAt?: string | null;
367
+ };
368
+
369
+ export type SemanticRelationRecord = {
370
+ id: string;
371
+ relationState: string;
372
+ predicate: string;
373
+ relationTypeId?: string | null;
374
+ relationTypeKey?: string | null;
375
+ relationDomain?: string | null;
376
+ subjectKind: string;
377
+ subjectId: string;
378
+ subjectLineageId: string;
379
+ subjectVersionNumber?: number | null;
380
+ objectKind: string;
381
+ objectId: string;
382
+ objectLineageId: string;
383
+ objectVersionNumber?: number | null;
384
+ subjectStateKey: string;
385
+ objectStateKey: string;
386
+ objectSubjectStateKey: string;
387
+ predicateObjectStateKey: string;
388
+ subjectVersionKey: string;
389
+ objectVersionKey: string;
390
+ score?: number | null;
391
+ confidence?: number | null;
392
+ rank?: number | null;
393
+ classifierId?: string | null;
394
+ modelVersion?: string | null;
395
+ reviewRecommended?: boolean | null;
396
+ sourceSnapshotId?: string | null;
397
+ importRunId?: string | null;
398
+ importedAt?: string | null;
399
+ createdAt?: string | null;
400
+ updatedAt?: string | null;
401
+ newsroomFeedKey?: string | null;
402
+ metadata?: unknown;
403
+ };
404
+
405
+ export type MessageRecord = {
406
+ id: string;
407
+ messageKind: string;
408
+ messageDomain: string;
409
+ status: string;
410
+ summary?: string | null;
411
+ source?: string | null;
412
+ importRunId?: string | null;
413
+ authorSub?: string | null;
414
+ authorUserProfileId?: string | null;
415
+ authorLabel?: string | null;
416
+ threadId?: string | null;
417
+ parentMessageId?: string | null;
418
+ sequenceNumber?: number | null;
419
+ role?: string | null;
420
+ messageType?: string | null;
421
+ content?: string | null;
422
+ semanticLayer?: string | null;
423
+ searchVisibility?: string | null;
424
+ responseTarget?: string | null;
425
+ responseStatus?: string | null;
426
+ responseOwner?: string | null;
427
+ responseStartedAt?: string | null;
428
+ responseCompletedAt?: string | null;
429
+ responseError?: string | null;
430
+ createdAt: string;
431
+ updatedAt: string;
432
+ newsroomFeedKey?: string | null;
433
+ body?: string | null;
434
+ metadata?: unknown;
435
+ };
436
+
437
+ export type MessageThreadRecord = {
438
+ id: string;
439
+ threadKind: string;
440
+ status: string;
441
+ title: string;
442
+ summary?: string | null;
443
+ primaryAnchorKind?: string | null;
444
+ primaryAnchorId?: string | null;
445
+ primaryAnchorLineageId?: string | null;
446
+ primaryAnchorKey?: string | null;
447
+ createdBySub?: string | null;
448
+ createdByUserProfileId?: string | null;
449
+ createdByLabel?: string | null;
450
+ messageCount?: number | null;
451
+ lastMessageId?: string | null;
452
+ lastMessageAt?: string | null;
453
+ contextDigest?: string | null;
454
+ activeResponseMessageId?: string | null;
455
+ responseLockOwner?: string | null;
456
+ responseLockExpiresAt?: string | null;
457
+ metadata?: unknown;
458
+ createdAt: string;
459
+ updatedAt: string;
460
+ newsroomFeedKey?: string | null;
461
+ };
462
+
463
+ export type AssignmentRecord = {
464
+ id: string;
465
+ assignmentTypeKey: string;
466
+ queueKey: string;
467
+ queueStatusKey: string;
468
+ status: string;
469
+ priority?: number | null;
470
+ title: string;
471
+ summary?: string | null;
472
+ brief?: string | null;
473
+ instructions?: string | null;
474
+ assigneeType?: string | null;
475
+ assigneeId?: string | null;
476
+ assigneeKey?: string | null;
477
+ claimedAt?: string | null;
478
+ claimExpiresAt?: string | null;
479
+ completedAt?: string | null;
480
+ canceledAt?: string | null;
481
+ corpusId?: string | null;
482
+ categorySetId?: string | null;
483
+ classifierId?: string | null;
484
+ sectionId?: string | null;
485
+ sectionKey?: string | null;
486
+ sectionType?: string | null;
487
+ sectionStatusKey?: string | null;
488
+ sectionQueueStatusKey?: string | null;
489
+ primaryFocusCategoryKey?: string | null;
490
+ topicScopeCategoryKeys?: Array<string | null> | null;
491
+ sourceSnapshotId?: string | null;
492
+ importRunId?: string | null;
493
+ createdBy?: string | null;
494
+ createdAt: string;
495
+ updatedAt: string;
496
+ newsroomFeedKey?: string | null;
497
+ metadata?: unknown;
498
+ };
499
+
500
+ export type AssignmentEventRecord = {
501
+ id: string;
502
+ assignmentId: string;
503
+ assignmentTypeKey: string;
504
+ queueKey: string;
505
+ eventType: string;
506
+ fromStatus?: string | null;
507
+ toStatus?: string | null;
508
+ actorSub?: string | null;
509
+ actorLabel?: string | null;
510
+ note?: string | null;
511
+ createdAt: string;
512
+ metadata?: unknown;
513
+ };
514
+
515
+ export type EditionSlotRecord = {
516
+ id: string;
517
+ editionId: string;
518
+ sectionKey: string;
519
+ slotRank: number;
520
+ targetType: "article" | "brief" | string;
521
+ targetLengthBand?: string | null;
522
+ minImageAssets?: number | null;
523
+ status: "open" | "assigned" | "selected" | "briefed" | "filled" | "killed" | string;
524
+ selectedAssignmentId?: string | null;
525
+ metadata?: unknown;
526
+ createdAt: string;
527
+ updatedAt: string;
528
+ };
529
+
530
+ export type EditionRecord = {
531
+ id: string;
532
+ lineageId?: string | null;
533
+ versionNumber?: number | null;
534
+ versionState?: string | null;
535
+ slug?: string | null;
536
+ title?: string | null;
537
+ status?: string | null;
538
+ editionDate?: string | null;
539
+ publishedAt?: string | null;
540
+ updatedAt?: string | null;
541
+ };
542
+
543
+ export type UserIdentityRecord = {
544
+ id: string;
545
+ userProfileId: string;
546
+ cognitoSub: string;
547
+ provider?: string | null;
548
+ email?: string | null;
549
+ status: string;
550
+ linkedAt: string;
551
+ lastSeenAt?: string | null;
552
+ };
553
+
554
+ export type UserDirectoryEntry = {
555
+ userProfileId?: string | null;
556
+ userSub?: string | null;
557
+ username?: string | null;
558
+ email?: string | null;
559
+ displayName?: string | null;
560
+ provider?: string | null;
561
+ enabled?: boolean | null;
562
+ cognitoStatus?: string | null;
563
+ profileStatus?: string | null;
564
+ mergedIntoProfileId?: string | null;
565
+ identityStatus?: string | null;
566
+ activeRoles: Array<string | null>;
567
+ identities: UserIdentityRecord[];
568
+ };
569
+
570
+ export type DoctrineRecord = {
571
+ id: string;
572
+ lineageId?: string | null;
573
+ versionNumber?: number | null;
574
+ versionState?: string | null;
575
+ versionCreatedAt?: string | null;
576
+ versionCreatedBy?: string | null;
577
+ type: string;
578
+ status: string;
579
+ typeStatus: string;
580
+ slug: string;
581
+ title?: string | null;
582
+ headline?: string | null;
583
+ body?: Array<string | null> | null;
584
+ editorial?: string | Record<string, unknown> | null;
585
+ updatedAt?: string | null;
586
+ };
587
+
588
+ export type AnalysisProfileSummary = {
589
+ key: string;
590
+ title: string;
591
+ description: string;
592
+ scope: string;
593
+ defaultMode: string;
594
+ corpusKey?: string | null;
595
+ classifierId?: string | null;
596
+ configurationName?: string | null;
597
+ biblicus: {
598
+ extractor?: string | null;
599
+ configurations: string[];
600
+ };
601
+ defaults: Record<string, unknown>;
602
+ allowedOverrides: string[];
603
+ expectedOutputs: string[];
604
+ };
605
+
606
+ export type NewsroomSummaryRecord = {
607
+ generatedAt: string;
608
+ staleAt?: string | null;
609
+ source?: string | null;
610
+ latestImportRun?: CategorySteeringImportRun | null;
611
+ counts: Record<string, number>;
612
+ facets?: NewsroomSummaryFacets | null;
613
+ assignmentStatusCounts: Record<string, number>;
614
+ assignmentTypeCounts: Record<string, number>;
615
+ referenceStatusCounts: Record<string, number>;
616
+ messageKindCounts: Record<string, number>;
617
+ messageDomainCounts: Record<string, number>;
618
+ };
619
+
620
+ export type NewsroomSummaryFacets = {
621
+ assignments?: {
622
+ byStatus?: Record<string, number>;
623
+ byType?: Record<string, number>;
624
+ bySection?: Record<string, number>;
625
+ statusByType?: Record<string, Record<string, number>>;
626
+ statusBySection?: Record<string, Record<string, number>>;
627
+ typeBySection?: Record<string, Record<string, number>>;
628
+ };
629
+ messages?: {
630
+ byKind?: Record<string, number>;
631
+ byDomain?: Record<string, number>;
632
+ byStatus?: Record<string, number>;
633
+ domainByKind?: Record<string, Record<string, number>>;
634
+ };
635
+ references?: {
636
+ byCurationStatus?: Record<string, number>;
637
+ byCorpus?: Record<string, number>;
638
+ statusByCorpus?: Record<string, Record<string, number>>;
639
+ };
640
+ semanticNodes?: {
641
+ byNodeKind?: Record<string, number>;
642
+ byStatus?: Record<string, number>;
643
+ byCorpus?: Record<string, number>;
644
+ byCategorySet?: Record<string, number>;
645
+ };
646
+ semanticRelations?: {
647
+ byRelationTypeKey?: Record<string, number>;
648
+ byRelationDomain?: Record<string, number>;
649
+ bySubjectKind?: Record<string, number>;
650
+ byObjectKind?: Record<string, number>;
651
+ };
652
+ imports?: {
653
+ byCorpus?: Record<string, number>;
654
+ };
655
+ };
656
+
657
+ export type CategorySteeringDashboard = {
658
+ isDemo?: boolean;
659
+ isPublicSkeleton?: boolean;
660
+ summaryStatus?: "loading" | "missing" | "ready";
661
+ summary?: NewsroomSummaryRecord | null;
662
+ canManageUsers?: boolean;
663
+ canonicalCorpusId?: string | null;
664
+ canonicalCategorySetId?: string | null;
665
+ userDirectory: UserDirectoryEntry[];
666
+ corpora: CategorySteeringCorpus[];
667
+ importRuns: CategorySteeringImportRun[];
668
+ categorySets: CategorySteeringCategorySet[];
669
+ categorys: CategorySteeringCategory[];
670
+ categoryTrees: CategorySteeringCategoryTree[];
671
+ categoryNodes: CategorySteeringCategoryTreeNode[];
672
+ categoryKeywords: CategoryKeywordRecord[];
673
+ lexicalSteeringRules: LexicalSteeringRuleRecord[];
674
+ proposals: CategorySteeringProposal[];
675
+ artifacts: CategorySteeringArtifact[];
676
+ references: ReferenceRecord[];
677
+ referenceAttachments: ReferenceAttachmentRecord[];
678
+ semanticNodes: SemanticNodeRecord[];
679
+ messages: MessageRecord[];
680
+ semanticRelations: SemanticRelationRecord[];
681
+ assignments: AssignmentRecord[];
682
+ assignmentEvents: AssignmentEventRecord[];
683
+ editionSlots: EditionSlotRecord[];
684
+ doctrineRecords: DoctrineRecord[];
685
+ newsroomSections: NewsroomSectionRecord[];
686
+ procedureDefinitions: ProcedureDefinitionRecord[];
687
+ procedureVersions: ProcedureVersionRecord[];
688
+ procedureRuns: ProcedureRunRecord[];
689
+ loadError?: string | null;
690
+ };
691
+
692
+ const DEFAULT_ANALYSIS_PROFILES_PATH = path.join(process.cwd(), "corpora", "papyrus-analysis-profiles.yml");
693
+ const DEFAULT_STEERING_CONFIG_PATH = path.join(process.cwd(), "corpora", "papyrus-steering.yml");
694
+
695
+ export async function loadAnalysisProfileSummaries(filepath = DEFAULT_ANALYSIS_PROFILES_PATH): Promise<AnalysisProfileSummary[]> {
696
+ try {
697
+ const parsed = YAML.parse(fs.readFileSync(filepath, "utf8")) as {
698
+ schemaVersion?: number;
699
+ profiles?: Array<Record<string, unknown>>;
700
+ } | null;
701
+ if (!parsed || parsed.schemaVersion !== 1 || !Array.isArray(parsed.profiles)) return [];
702
+ return parsed.profiles.map((entry) => ({
703
+ key: stringValue(entry.key),
704
+ title: stringValue(entry.title) || stringValue(entry.key),
705
+ description: stringValue(entry.description),
706
+ scope: stringValue(entry.scope),
707
+ defaultMode: stringValue(entry.defaultMode),
708
+ corpusKey: stringValue(entry.corpusKey) || null,
709
+ classifierId: stringValue(entry.classifierId) || null,
710
+ configurationName: stringValue(entry.configurationName) || null,
711
+ biblicus: {
712
+ extractor: stringValue(objectValue(entry.biblicus).extractor) || null,
713
+ configurations: stringArray(objectValue(entry.biblicus).configurations),
714
+ },
715
+ defaults: objectValue(entry.defaults),
716
+ allowedOverrides: stringArray(entry.allowedOverrides),
717
+ expectedOutputs: stringArray(entry.expectedOutputs),
718
+ })).filter((profile) => profile.key && profile.scope && profile.defaultMode);
719
+ } catch {
720
+ return [];
721
+ }
722
+ }
723
+
724
+ export async function loadConfiguredCorpusSummaries(filepath = DEFAULT_STEERING_CONFIG_PATH): Promise<CategorySteeringCorpus[]> {
725
+ try {
726
+ const parsed = YAML.parse(fs.readFileSync(filepath, "utf8")) as {
727
+ corpora?: Array<Record<string, unknown>>;
728
+ } | null;
729
+ if (!parsed || !Array.isArray(parsed.corpora)) return [];
730
+ return parsed.corpora.map((entry) => {
731
+ const key = stringValue(entry.key) || stringValue(entry.name);
732
+ const name = stringValue(entry.name) || key;
733
+ return {
734
+ id: knowledgeCorpusIdFromKey(key),
735
+ name,
736
+ role: stringValue(entry.role) || "source",
737
+ };
738
+ }).filter((corpus) => corpus.id && corpus.name);
739
+ } catch {
740
+ return [];
741
+ }
742
+ }
743
+
744
+ function stringValue(value: unknown): string {
745
+ return typeof value === "string" ? value.trim() : "";
746
+ }
747
+
748
+ function nullableStringValue(value: unknown): string | null {
749
+ const normalized = stringValue(value);
750
+ return normalized || null;
751
+ }
752
+
753
+ function integerValue(value: unknown): number | null {
754
+ const parsed = Number(value);
755
+ return Number.isInteger(parsed) ? parsed : null;
756
+ }
757
+
758
+ function objectValue(value: unknown): Record<string, unknown> {
759
+ return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : {};
760
+ }
761
+
762
+ function stringArray(value: unknown): string[] {
763
+ return Array.isArray(value) ? value.map(stringValue).filter(Boolean) : [];
764
+ }
765
+
766
+ function knowledgeCorpusIdFromKey(corpusKey: string): string {
767
+ const safeKey = String(corpusKey || "unknown").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "unknown";
768
+ return `knowledge-corpus-${safeKey}`;
769
+ }
770
+
771
+ export async function loadCategorySteeringDashboard(): Promise<CategorySteeringDashboard> {
772
+ const proposals = await loadServerSteeringProposals();
773
+ if (proposals.length === 0) return createEmptyCategorySteeringDashboard();
774
+ return {
775
+ ...createEmptyCategorySteeringDashboard(),
776
+ isPublicSkeleton: false,
777
+ proposals: sortProposals(proposals),
778
+ loadError: null,
779
+ };
780
+ }
781
+
782
+ const SERVER_STEERING_PROPOSALS_QUERY = `
783
+ query ListSteeringProposals($limit: Int, $nextToken: String) {
784
+ listSteeringProposals(limit: $limit, nextToken: $nextToken) {
785
+ items {
786
+ id
787
+ categorySetId
788
+ corpusId
789
+ proposalKind
790
+ steeringDomain
791
+ status
792
+ title
793
+ summary
794
+ categoryKey
795
+ targetCategoryKey
796
+ graphEntityId
797
+ relationshipType
798
+ displayName
799
+ shortTitle
800
+ subtitle
801
+ description
802
+ evidenceItemIds
803
+ suggestedSeedItemIds
804
+ suggestedHoldoutItemIds
805
+ sourceSnapshotId
806
+ proposedAt
807
+ reviewedAt
808
+ reviewedBy
809
+ updatedAt
810
+ }
811
+ nextToken
812
+ }
813
+ }
814
+ `;
815
+
816
+ async function loadServerSteeringProposals(): Promise<CategorySteeringProposal[]> {
817
+ const endpoint = process.env.PAPYRUS_GRAPHQL_ENDPOINT;
818
+ const jwt = process.env.PAPYRUS_GRAPHQL_JWT;
819
+ if (!endpoint || !jwt) return [];
820
+
821
+ const items: CategorySteeringProposal[] = [];
822
+ let nextToken: string | null = null;
823
+
824
+ for (let page = 0; page < 20; page += 1) {
825
+ const response = await fetch(endpoint, {
826
+ method: "POST",
827
+ headers: {
828
+ "content-type": "application/json",
829
+ Authorization: `Bearer ${jwt}`,
830
+ },
831
+ body: JSON.stringify({
832
+ query: SERVER_STEERING_PROPOSALS_QUERY,
833
+ variables: { limit: 500, nextToken },
834
+ }),
835
+ cache: "no-store",
836
+ });
837
+ if (!response.ok) return [];
838
+ const payload = await response.json() as {
839
+ data?: { listSteeringProposals?: { items?: Array<CategorySteeringProposal | null> | null; nextToken?: string | null } | null } | null;
840
+ errors?: Array<{ message?: string }> | null;
841
+ };
842
+ if (payload.errors?.length) return [];
843
+ const connection = payload.data?.listSteeringProposals;
844
+ if (!connection) return [];
845
+ items.push(...(connection.items ?? []).filter(Boolean) as CategorySteeringProposal[]);
846
+ nextToken = connection.nextToken ?? null;
847
+ if (!nextToken) break;
848
+ }
849
+
850
+ return items;
851
+ }
852
+
853
+ function sortCategorySets(categorySets: CategorySteeringCategorySet[], importRuns: CategorySteeringImportRun[]): CategorySteeringCategorySet[] {
854
+ const importRunById = new Map(importRuns.map((importRun) => [importRun.id, importRun]));
855
+ return [...categorySets].sort((left, right) => {
856
+ const statusDiff = categorySetStatusRank(left.status) - categorySetStatusRank(right.status);
857
+ if (statusDiff !== 0) return statusDiff;
858
+ const dateDiff = categorySetSortDate(right, importRunById).localeCompare(categorySetSortDate(left, importRunById));
859
+ if (dateDiff !== 0) return dateDiff;
860
+ return left.displayName.localeCompare(right.displayName);
861
+ });
862
+ }
863
+
864
+ function categorySetSortDate(categorySet: CategorySteeringCategorySet, importRunById: Map<string, CategorySteeringImportRun>): string {
865
+ return categorySet.generatedAt ?? (categorySet.importRunId ? importRunById.get(categorySet.importRunId)?.importedAt : null) ?? "";
866
+ }
867
+
868
+ function selectCanonicalCategorySet(corpora: CategorySteeringCorpus[], categorySets: CategorySteeringCategorySet[]): CategorySteeringCategorySet | null {
869
+ const canonicalCorpus = selectCanonicalCorpus(corpora);
870
+ const candidates = categorySets.filter((categorySet) => categorySet.status !== "deprecated");
871
+ const canonicalCandidates = canonicalCorpus ? candidates.filter((categorySet) => categorySet.corpusId === canonicalCorpus.id) : candidates;
872
+ return canonicalCandidates[0] ?? candidates[0] ?? null;
873
+ }
874
+
875
+ function selectCanonicalCorpus(corpora: CategorySteeringCorpus[]): CategorySteeringCorpus | null {
876
+ return corpora.find((corpus) => corpus.role === "canonical")
877
+ ?? corpora.find((corpus) => corpus.role === "authority")
878
+ ?? corpora[0]
879
+ ?? null;
880
+ }
881
+
882
+ function categorySetStatusRank(status: string): number {
883
+ if (status === "accepted") return 0;
884
+ if (status === "draft") return 1;
885
+ if (status === "proposed") return 2;
886
+ if (status === "deprecated") return 8;
887
+ return 5;
888
+ }
889
+
890
+ function sortCategorys(categorys: CategorySteeringCategory[]): CategorySteeringCategory[] {
891
+ return [...categorys].sort((left, right) => {
892
+ const rankDiff = (left.rank ?? 999999) - (right.rank ?? 999999);
893
+ if (rankDiff !== 0) return rankDiff;
894
+ return left.categoryKey.localeCompare(right.categoryKey);
895
+ });
896
+ }
897
+
898
+ function sortProposals(proposals: CategorySteeringProposal[]): CategorySteeringProposal[] {
899
+ const statusWeight = new Map([
900
+ ["proposed", 0],
901
+ ["deferred", 1],
902
+ ["accepted", 2],
903
+ ["rejected", 3],
904
+ ]);
905
+ return [...proposals].sort((left, right) => {
906
+ const statusDiff = (statusWeight.get(left.status) ?? 9) - (statusWeight.get(right.status) ?? 9);
907
+ if (statusDiff !== 0) return statusDiff;
908
+ return (right.proposedAt ?? right.updatedAt ?? "").localeCompare(left.proposedAt ?? left.updatedAt ?? "");
909
+ });
910
+ }
911
+
912
+ function defaultNewsroomSections(importedAt: string, sectionsConfigPath = DEFAULT_NEWSROOM_SECTIONS_CONFIG_PATH): NewsroomSectionRecord[] {
913
+ return loadNewsroomSectionSeedRows(sectionsConfigPath).map((row, index) => ({
914
+ ...row,
915
+ enabledStatus: "enabled",
916
+ sortOrder: Number.isInteger(row.sortOrder) && row.sortOrder > 0 ? row.sortOrder : index + 1,
917
+ createdAt: importedAt,
918
+ updatedAt: importedAt,
919
+ }));
920
+ }
921
+
922
+ function loadNewsroomSectionSeedRows(sectionsConfigPath = DEFAULT_NEWSROOM_SECTIONS_CONFIG_PATH) {
923
+ const cached = newsroomSectionSeedRowsCache.get(sectionsConfigPath);
924
+ if (cached) return cached;
925
+ const parsed = YAML.parse(fs.readFileSync(sectionsConfigPath, "utf8")) as {
926
+ schemaVersion?: number;
927
+ sections?: Array<Record<string, unknown>>;
928
+ };
929
+ if (!parsed || parsed.schemaVersion !== 1 || !Array.isArray(parsed.sections)) {
930
+ throw new Error(`Invalid newsroom section seed file: ${sectionsConfigPath}`);
931
+ }
932
+ const rows = parsed.sections.map((entry, index) => normalizeNewsroomSectionSeedRow(entry, index, sectionsConfigPath));
933
+ newsroomSectionSeedRowsCache.set(sectionsConfigPath, rows);
934
+ return rows;
935
+ }
936
+
937
+ function normalizeNewsroomSectionSeedRow(
938
+ entry: Record<string, unknown>,
939
+ index: number,
940
+ sectionsConfigPath: string,
941
+ ): Omit<NewsroomSectionRecord, "enabledStatus" | "createdAt" | "updatedAt"> {
942
+ const id = stringValue(entry.id);
943
+ if (!id) throw new Error(`Newsroom section at index ${index} is missing id in ${sectionsConfigPath}`);
944
+ const title = stringValue(entry.title);
945
+ if (!title) throw new Error(`Newsroom section '${id}' is missing title in ${sectionsConfigPath}`);
946
+ const shortTitle = stringValue(entry.shortTitle);
947
+ if (!shortTitle) throw new Error(`Newsroom section '${id}' is missing shortTitle in ${sectionsConfigPath}`);
948
+ const rawType = stringValue(entry.type).toLowerCase() as NewsroomSectionType;
949
+ if (!NEWSROOM_SECTION_TYPES.has(rawType)) {
950
+ throw new Error(`Newsroom section '${id}' has unsupported type '${stringValue(entry.type)}' in ${sectionsConfigPath}`);
951
+ }
952
+ const type = rawType === "rotating" ? "floating" : rawType;
953
+ const editorialMission = stringValue(entry.editorialMission);
954
+ const editorialPolicy = stringValue(entry.editorialPolicy);
955
+ if (!editorialMission || !editorialPolicy) {
956
+ throw new Error(`Newsroom section '${id}' requires editorialMission and editorialPolicy in ${sectionsConfigPath}`);
957
+ }
958
+ return {
959
+ id,
960
+ title,
961
+ shortTitle,
962
+ type,
963
+ editorialMission,
964
+ editorialPolicy,
965
+ enabled: typeof entry.enabled === "boolean" ? entry.enabled : true,
966
+ sortOrder: integerValue(entry.sortOrder) ?? index + 1,
967
+ defaultArticleTypes: stringArray(entry.defaultArticleTypes),
968
+ defaultPageBudget: integerValue(entry.defaultPageBudget),
969
+ assignmentGuidance: nullableStringValue(entry.assignmentGuidance),
970
+ killCriteria: nullableStringValue(entry.killCriteria),
971
+ visualGuidance: nullableStringValue(entry.visualGuidance),
972
+ };
973
+ }
974
+
975
+ export function createDemoCategorySteeringDashboard(
976
+ brandId: SiteBrandId = resolveSiteBrandId(),
977
+ newsroomSectionsConfigPath = DEFAULT_NEWSROOM_SECTIONS_CONFIG_PATH,
978
+ ): CategorySteeringDashboard {
979
+ const importedAt = "2026-05-16T12:00:00.000Z";
980
+ const profile = getNewsroomDemoProfile(brandId);
981
+ const pilobolus = isPilobolusDemoBrand(brandId);
982
+ const corpusId = "knowledge-corpus-demo-canonical";
983
+ const sourceCorpusId = "knowledge-corpus-demo-source";
984
+ const categorySetId = "category-set-demo-canonical";
985
+ const sourceCategorySetId = "category-set-demo-source";
986
+ const referenceHistoryOneLineageId = "reference-knowledge-corpus-demo-source-history-001";
987
+ const referenceHistoryTwoLineageId = "reference-knowledge-corpus-demo-source-history-002";
988
+ const referenceHistoryOneId = `${referenceHistoryOneLineageId}-v1`;
989
+ const referenceHistoryTwoId = `${referenceHistoryTwoLineageId}-v1`;
990
+ const assignmentHistoryOneId = "assignment-demo-reference-intake-history-001";
991
+ const assignmentHistoryTwoId = "assignment-demo-reference-intake-history-002";
992
+ const assignmentReportingId = "assignment-demo-reporting-news-001";
993
+ const reportingPacketMessageId = "message-demo-reporting-news-001-context";
994
+ const scalingCategoryLineageId = "category-category-set-demo-canonical-category-foundation-model-scaling";
995
+ const historyCategoryLineageId = "category-category-set-demo-source-category-symbolic-connectionist-history";
996
+
997
+ const dashboard: CategorySteeringDashboard = {
998
+ isDemo: true,
999
+ summary: null,
1000
+ canManageUsers: true,
1001
+ canonicalCorpusId: corpusId,
1002
+ canonicalCategorySetId: categorySetId,
1003
+ userDirectory: [
1004
+ {
1005
+ userProfileId: "user-profile-demo-editor",
1006
+ userSub: "demo-editor-sub",
1007
+ username: "demo-editor",
1008
+ email: "editor@example.com",
1009
+ displayName: "Demo Editor",
1010
+ provider: "google",
1011
+ enabled: true,
1012
+ cognitoStatus: "CONFIRMED",
1013
+ identityStatus: "active",
1014
+ activeRoles: ["editor"],
1015
+ identities: [
1016
+ {
1017
+ id: "user-identity-demo-editor-google",
1018
+ userProfileId: "user-profile-demo-editor",
1019
+ cognitoSub: "demo-editor-sub",
1020
+ provider: "google",
1021
+ email: "editor@example.com",
1022
+ status: "active",
1023
+ linkedAt: importedAt,
1024
+ lastSeenAt: importedAt,
1025
+ },
1026
+ {
1027
+ id: "user-identity-demo-editor-alt",
1028
+ userProfileId: "user-profile-demo-editor",
1029
+ cognitoSub: "demo-editor-alt-sub",
1030
+ provider: "google",
1031
+ email: "editor.alt@example.com",
1032
+ status: "active",
1033
+ linkedAt: importedAt,
1034
+ lastSeenAt: importedAt,
1035
+ },
1036
+ ],
1037
+ },
1038
+ {
1039
+ userProfileId: "user-profile-demo-reader",
1040
+ userSub: "demo-reader-sub",
1041
+ username: "demo-reader",
1042
+ email: "reader@example.com",
1043
+ displayName: "Demo Reader",
1044
+ provider: "google",
1045
+ enabled: true,
1046
+ cognitoStatus: "CONFIRMED",
1047
+ identityStatus: "active",
1048
+ activeRoles: [],
1049
+ identities: [
1050
+ {
1051
+ id: "user-identity-demo-reader-google",
1052
+ userProfileId: "user-profile-demo-reader",
1053
+ cognitoSub: "demo-reader-sub",
1054
+ provider: "google",
1055
+ email: "reader@example.com",
1056
+ status: "active",
1057
+ linkedAt: importedAt,
1058
+ lastSeenAt: importedAt,
1059
+ },
1060
+ ],
1061
+ },
1062
+ ],
1063
+ corpora: [
1064
+ {
1065
+ id: corpusId,
1066
+ name: profile.canonicalCorpusName,
1067
+ role: "canonical",
1068
+ itemCount: 3,
1069
+ latestImportRunId: "knowledge-import-demo-steering",
1070
+ },
1071
+ {
1072
+ id: sourceCorpusId,
1073
+ name: profile.sourceCorpusName,
1074
+ role: "source",
1075
+ itemCount: 2,
1076
+ latestImportRunId: "knowledge-import-demo-projection",
1077
+ },
1078
+ ],
1079
+ importRuns: [
1080
+ {
1081
+ id: "knowledge-import-demo-steering",
1082
+ corpusId,
1083
+ importKind: "steering-export",
1084
+ classifierId: "demo-canonical-classifier",
1085
+ status: "imported",
1086
+ importedAt,
1087
+ itemCount: 3,
1088
+ categoryCount: 1,
1089
+ proposalCount: 5,
1090
+ referenceCount: 3,
1091
+ relationCount: 0,
1092
+ warningCount: 0,
1093
+ },
1094
+ {
1095
+ id: "knowledge-import-demo-projection",
1096
+ corpusId: sourceCorpusId,
1097
+ importKind: "topic-projection",
1098
+ classifierId: "demo-canonical-classifier",
1099
+ status: "imported",
1100
+ importedAt,
1101
+ itemCount: 2,
1102
+ categoryCount: 0,
1103
+ proposalCount: 0,
1104
+ referenceCount: 2,
1105
+ relationCount: 2,
1106
+ warningCount: 0,
1107
+ },
1108
+ ],
1109
+ categorySets: [
1110
+ {
1111
+ id: categorySetId,
1112
+ lineageId: categorySetId,
1113
+ versionNumber: 1,
1114
+ versionState: "current",
1115
+ corpusId,
1116
+ classifierId: "demo-canonical-classifier",
1117
+ displayName: "Canonical Demo Categories",
1118
+ description: "Accepted category set imported from Biblicus artifacts.",
1119
+ status: "accepted",
1120
+ generatedAt: importedAt,
1121
+ categoryCount: 1,
1122
+ importRunId: "knowledge-import-demo-steering",
1123
+ },
1124
+ {
1125
+ id: sourceCategorySetId,
1126
+ lineageId: sourceCategorySetId,
1127
+ versionNumber: 1,
1128
+ versionState: "current",
1129
+ corpusId: sourceCorpusId,
1130
+ classifierId: "demo-source-classifier",
1131
+ displayName: "Source Demo Categories",
1132
+ description: "Local category set discovered inside the source corpus.",
1133
+ status: "accepted",
1134
+ generatedAt: importedAt,
1135
+ categoryCount: 1,
1136
+ importRunId: "knowledge-import-demo-projection",
1137
+ },
1138
+ ],
1139
+ categorys: [
1140
+ {
1141
+ id: "category-foundation-model-scaling",
1142
+ categorySetId,
1143
+ corpusId,
1144
+ categoryKey: "category.foundation-model-scaling",
1145
+ displayName: pilobolus ? "Ensemble Movement Studies" : "Foundation Model Scaling",
1146
+ subtitle: pilobolus
1147
+ ? "Rehearsal notes, ensemble patterns, and field documentation"
1148
+ : "Capability curves, benchmark saturation, and training-compute effects",
1149
+ description: pilobolus
1150
+ ? "Movement research, rehearsal capture, and ensemble coordination notes from the Pilobolus field program."
1151
+ : "Research on model size, data mixtures, compute budgets, and emergent benchmark behavior.",
1152
+ aliases: pilobolus ? ["ensemble work", "movement studies"] : ["scaling laws", "compute scaling"],
1153
+ status: "accepted",
1154
+ seedItemIds: ["research-001", "research-002"],
1155
+ holdoutItemIds: ["research-003"],
1156
+ rank: 1,
1157
+ isPinned: true,
1158
+ updatedAt: importedAt,
1159
+ },
1160
+ {
1161
+ id: "category-symbolic-connectionist-history",
1162
+ categorySetId: sourceCategorySetId,
1163
+ corpusId: sourceCorpusId,
1164
+ categoryKey: "category.symbolic-connectionist-history",
1165
+ displayName: pilobolus ? "Rehearsal Archive" : "Symbolic And Connectionist History",
1166
+ subtitle: pilobolus
1167
+ ? "Season logs, tour notes, and creative process records"
1168
+ : "Shifts between rule systems, neural nets, and hybrid AI programs",
1169
+ description: pilobolus
1170
+ ? "Historical rehearsal logs, tour documentation, and creative-process notes for Pilobolus editions."
1171
+ : "Historical coverage of symbolic AI, neural network winters, and later hybrid systems.",
1172
+ aliases: pilobolus ? ["tour archive", "season notes"] : ["AI winters", "connectionism"],
1173
+ status: "accepted",
1174
+ seedItemIds: ["history-001"],
1175
+ holdoutItemIds: ["history-002"],
1176
+ rank: 2,
1177
+ isPinned: false,
1178
+ updatedAt: importedAt,
1179
+ },
1180
+ ],
1181
+ categoryTrees: [
1182
+ {
1183
+ id: categorySetId,
1184
+ lineageId: categorySetId,
1185
+ versionNumber: 1,
1186
+ versionState: "current",
1187
+ corpusId,
1188
+ classifierId: "demo-canonical-classifier",
1189
+ displayName: "Canonical Demo Category Tree",
1190
+ description: "Accepted category tree imported from Biblicus category artifacts.",
1191
+ status: "accepted",
1192
+ generatedAt: importedAt,
1193
+ categoryCount: 3,
1194
+ nodeCount: 3,
1195
+ rootCount: 1,
1196
+ importRunId: "knowledge-import-demo-steering",
1197
+ createdAt: importedAt,
1198
+ updatedAt: importedAt,
1199
+ },
1200
+ ],
1201
+ categoryNodes: [
1202
+ {
1203
+ id: "category-demo-foundation-model-scaling",
1204
+ corpusId,
1205
+ categorySetId,
1206
+ categoryKey: "category.foundation-model-scaling",
1207
+ parentCategoryKey: null,
1208
+ displayName: "Foundation Model Scaling",
1209
+ subtitle: "Capability curves, benchmark saturation, and training-compute effects",
1210
+ description: "Accepted root category for model size, data mixtures, compute budgets, and emergent benchmark behavior.",
1211
+ status: "accepted",
1212
+ seedItemIds: ["research-001", "research-002"],
1213
+ holdoutItemIds: ["research-003"],
1214
+ rank: 1,
1215
+ depth: 0,
1216
+ importRunId: "knowledge-import-demo-steering",
1217
+ updatedAt: importedAt,
1218
+ },
1219
+ {
1220
+ id: "category-demo-agent-memory",
1221
+ corpusId,
1222
+ categorySetId,
1223
+ categoryKey: "category.agent-memory",
1224
+ parentCategoryKey: "category.foundation-model-scaling",
1225
+ displayName: "Agent Memory",
1226
+ subtitle: "Retrieval, persistence, and episodic context for agent systems",
1227
+ description: "Accepted subcategory covering long-running memory, retrieval augmentation, and context persistence in agent workflows.",
1228
+ status: "accepted",
1229
+ seedItemIds: ["research-001"],
1230
+ holdoutItemIds: [],
1231
+ rank: 1,
1232
+ depth: 1,
1233
+ importRunId: "knowledge-import-demo-steering",
1234
+ updatedAt: importedAt,
1235
+ },
1236
+ {
1237
+ id: "category-demo-benchmark-saturation",
1238
+ corpusId,
1239
+ categorySetId,
1240
+ categoryKey: "category.benchmark-saturation",
1241
+ parentCategoryKey: "category.foundation-model-scaling",
1242
+ displayName: "Benchmark Saturation",
1243
+ subtitle: "Evaluation plateaus, leakage, and capability measurement stress",
1244
+ description: "Accepted subcategory covering benchmark exhaustion and the need for new evaluation signals.",
1245
+ status: "accepted",
1246
+ seedItemIds: ["research-002"],
1247
+ holdoutItemIds: ["research-003"],
1248
+ rank: 2,
1249
+ depth: 1,
1250
+ importRunId: "knowledge-import-demo-steering",
1251
+ updatedAt: importedAt,
1252
+ },
1253
+ ],
1254
+ categoryKeywords: [
1255
+ {
1256
+ id: "category-keyword-demo-scaling-001",
1257
+ categorySetId,
1258
+ corpusId,
1259
+ categoryKey: "category.foundation-model-scaling",
1260
+ categoryLineageId: scalingCategoryLineageId,
1261
+ categoryId: "category-demo-foundation-model-scaling",
1262
+ keyword: "scaling laws",
1263
+ normalizedKeyword: "scaling laws",
1264
+ weight: 0.92,
1265
+ rank: 1,
1266
+ source: "accepted-category-tree",
1267
+ sourceTopicId: "category.foundation-model-scaling",
1268
+ importRunId: "knowledge-import-demo-steering",
1269
+ createdAt: importedAt,
1270
+ updatedAt: importedAt,
1271
+ },
1272
+ {
1273
+ id: "category-keyword-demo-scaling-002",
1274
+ categorySetId,
1275
+ corpusId,
1276
+ categoryKey: "category.foundation-model-scaling",
1277
+ categoryLineageId: scalingCategoryLineageId,
1278
+ categoryId: "category-demo-foundation-model-scaling",
1279
+ keyword: "et",
1280
+ normalizedKeyword: "et",
1281
+ weight: 0.41,
1282
+ rank: 2,
1283
+ source: "accepted-category-tree",
1284
+ sourceTopicId: "category.foundation-model-scaling",
1285
+ importRunId: "knowledge-import-demo-steering",
1286
+ createdAt: importedAt,
1287
+ updatedAt: importedAt,
1288
+ },
1289
+ {
1290
+ id: "category-keyword-demo-memory-001",
1291
+ categorySetId,
1292
+ corpusId,
1293
+ categoryKey: "category.agent-memory",
1294
+ categoryLineageId: "category-category-set-demo-canonical-category-agent-memory",
1295
+ categoryId: "category-demo-agent-memory",
1296
+ keyword: "agent memory",
1297
+ normalizedKeyword: "agent memory",
1298
+ weight: 0.87,
1299
+ rank: 1,
1300
+ source: "steering-proposal",
1301
+ sourceTopicId: "category-proposal-demo-create-category",
1302
+ importRunId: "knowledge-import-demo-steering",
1303
+ createdAt: importedAt,
1304
+ updatedAt: importedAt,
1305
+ },
1306
+ ],
1307
+ lexicalSteeringRules: [
1308
+ {
1309
+ id: "lexical-rule-demo-et",
1310
+ ruleKind: "ignored_keyword",
1311
+ term: "et",
1312
+ normalizedTerm: "et",
1313
+ scope: "publication",
1314
+ status: "active",
1315
+ note: "Citation/header noise from et al.",
1316
+ source: "papyrus-lexical-steering.yml",
1317
+ createdBy: "papyrus-config",
1318
+ createdAt: importedAt,
1319
+ updatedAt: importedAt,
1320
+ },
1321
+ {
1322
+ id: "lexical-rule-demo-al",
1323
+ ruleKind: "ignored_keyword",
1324
+ term: "al",
1325
+ normalizedTerm: "al",
1326
+ scope: "publication",
1327
+ status: "active",
1328
+ note: "Citation/header noise from et al.",
1329
+ source: "papyrus-lexical-steering.yml",
1330
+ createdBy: "papyrus-config",
1331
+ createdAt: importedAt,
1332
+ updatedAt: importedAt,
1333
+ },
1334
+ ],
1335
+ proposals: [
1336
+ {
1337
+ id: "category-proposal-demo-rename",
1338
+ categorySetId,
1339
+ corpusId,
1340
+ proposalKind: "rename-category",
1341
+ steeringDomain: "category",
1342
+ status: "proposed",
1343
+ title: "Rename scaling category",
1344
+ summary: "Several seed items use foundation model scaling terminology more consistently than generic scaling laws.",
1345
+ categoryKey: "category.foundation-model-scaling",
1346
+ displayName: "Foundation Model Scaling",
1347
+ subtitle: "Capability curves, benchmark saturation, and training-compute effects",
1348
+ evidenceItemIds: ["research-001", "research-002"],
1349
+ suggestedSeedItemIds: ["research-001"],
1350
+ proposedAt: importedAt,
1351
+ },
1352
+ {
1353
+ id: "category-proposal-demo-relationship",
1354
+ categorySetId,
1355
+ corpusId,
1356
+ proposalKind: "relationship-proposal",
1357
+ steeringDomain: "graph",
1358
+ status: "proposed",
1359
+ title: "Link scaling category to benchmark entity",
1360
+ summary: "Evidence suggests the category should relate to the benchmark-saturation entity.",
1361
+ categoryKey: "category.foundation-model-scaling",
1362
+ graphEntityId: "graph-entity-benchmark-saturation",
1363
+ relationshipType: "influences",
1364
+ evidenceItemIds: ["research-002"],
1365
+ proposedAt: importedAt,
1366
+ },
1367
+ {
1368
+ id: "category-proposal-demo-create-category",
1369
+ categorySetId,
1370
+ corpusId,
1371
+ proposalKind: "create-category",
1372
+ steeringDomain: "category",
1373
+ status: "proposed",
1374
+ title: "Create agent memory subcategory",
1375
+ summary: "Discovery found a possible child category under the foundation model scaling area.",
1376
+ categoryKey: "category.agent-memory",
1377
+ targetCategoryKey: "category.foundation-model-scaling",
1378
+ relationshipType: "subcategory_of",
1379
+ displayName: "Agent Memory",
1380
+ description: "Candidate subcategory covering memory, retrieval, and persistence in agent systems.",
1381
+ evidenceItemIds: ["research-001"],
1382
+ proposedAt: importedAt,
1383
+ },
1384
+ {
1385
+ id: "category-proposal-demo-ontology-relationship",
1386
+ categorySetId,
1387
+ corpusId,
1388
+ proposalKind: "add-ontology-relationship",
1389
+ steeringDomain: "graph",
1390
+ status: "proposed",
1391
+ title: "Add ontology assertion",
1392
+ summary: "The evidence supports a historical context relationship between two category nodes.",
1393
+ categoryKey: "category.symbolic-connectionist-history",
1394
+ targetCategoryKey: "category.agent-memory",
1395
+ graphEntityId: "assertion-agent-memory-history",
1396
+ relationshipType: "historical_context_for",
1397
+ evidenceItemIds: ["history-001"],
1398
+ proposedAt: importedAt,
1399
+ },
1400
+ {
1401
+ id: "category-proposal-demo-seeds",
1402
+ categorySetId,
1403
+ corpusId,
1404
+ proposalKind: "seed-change",
1405
+ steeringDomain: "category",
1406
+ status: "deferred",
1407
+ title: "Add history article as holdout",
1408
+ summary: "The item is useful as a negative example for modern scaling categories.",
1409
+ categoryKey: "category.foundation-model-scaling",
1410
+ suggestedHoldoutItemIds: ["history-002"],
1411
+ evidenceItemIds: ["history-002"],
1412
+ proposedAt: importedAt,
1413
+ },
1414
+ ],
1415
+ artifacts: [
1416
+ {
1417
+ id: "knowledge-artifact-demo-category-set",
1418
+ corpusId,
1419
+ artifactKind: "accepted-category-set",
1420
+ artifactId: "s3://papyrus-demo/accepted-category-set.json",
1421
+ snapshotId: "snapshot-demo-category-set",
1422
+ displayName: "Accepted Category Set JSON",
1423
+ createdAt: importedAt,
1424
+ },
1425
+ ],
1426
+ references: [
1427
+ {
1428
+ id: referenceHistoryOneId,
1429
+ lineageId: referenceHistoryOneLineageId,
1430
+ versionNumber: 1,
1431
+ versionState: "current",
1432
+ corpusId: sourceCorpusId,
1433
+ externalItemId: "history-001",
1434
+ title: "Symbolic And Connectionist History Reader",
1435
+ sourceUri: "s3://papyrus-demo/corpora/history/history-001.md",
1436
+ storagePath: "corpora/history/history-001.md",
1437
+ mediaType: "text/markdown",
1438
+ sha256: "demo-history-001",
1439
+ importRunId: "knowledge-import-demo-projection",
1440
+ importedAt,
1441
+ curationStatus: "accepted",
1442
+ curationStatusKey: `${sourceCorpusId}#accepted`,
1443
+ curationStatusUpdatedAt: importedAt,
1444
+ curationStatusUpdatedBy: "demo-import",
1445
+ },
1446
+ {
1447
+ id: referenceHistoryTwoId,
1448
+ lineageId: referenceHistoryTwoLineageId,
1449
+ versionNumber: 1,
1450
+ versionState: "current",
1451
+ corpusId: sourceCorpusId,
1452
+ externalItemId: "history-002",
1453
+ title: "Foundation Model Scaling Retrospective",
1454
+ sourceUri: "s3://papyrus-demo/corpora/history/history-002.md",
1455
+ storagePath: "corpora/history/history-002.md",
1456
+ mediaType: "text/markdown",
1457
+ sha256: "demo-history-002",
1458
+ importRunId: "knowledge-import-demo-projection",
1459
+ importedAt,
1460
+ curationStatus: "pending",
1461
+ curationStatusKey: `${sourceCorpusId}#pending`,
1462
+ curationStatusUpdatedAt: importedAt,
1463
+ curationStatusUpdatedBy: "demo-import",
1464
+ },
1465
+ ],
1466
+ referenceAttachments: [
1467
+ {
1468
+ id: "reference-attachment-demo-history-001-source",
1469
+ referenceId: referenceHistoryOneId,
1470
+ referenceLineageId: referenceHistoryOneLineageId,
1471
+ referenceVersionNumber: 1,
1472
+ referenceVersionKey: `reference#${referenceHistoryOneId}`,
1473
+ role: "source",
1474
+ sortKey: "001-source",
1475
+ storagePath: "corpora/history/history-001.md",
1476
+ sourceUri: "s3://papyrus-demo/corpora/history/history-001.md",
1477
+ filename: "history-001.md",
1478
+ mediaType: "text/markdown",
1479
+ sha256: "demo-history-001",
1480
+ importRunId: "knowledge-import-demo-projection",
1481
+ importedAt,
1482
+ },
1483
+ {
1484
+ id: "reference-attachment-demo-history-002-source",
1485
+ referenceId: referenceHistoryTwoId,
1486
+ referenceLineageId: referenceHistoryTwoLineageId,
1487
+ referenceVersionNumber: 1,
1488
+ referenceVersionKey: `reference#${referenceHistoryTwoId}`,
1489
+ role: "source",
1490
+ sortKey: "001-source",
1491
+ storagePath: "corpora/history/history-002.md",
1492
+ sourceUri: "s3://papyrus-demo/corpora/history/history-002.md",
1493
+ filename: "history-002.md",
1494
+ mediaType: "text/markdown",
1495
+ sha256: "demo-history-002",
1496
+ importRunId: "knowledge-import-demo-projection",
1497
+ importedAt,
1498
+ },
1499
+ {
1500
+ id: "reference-attachment-demo-history-001-extracted-text",
1501
+ referenceId: referenceHistoryOneId,
1502
+ referenceLineageId: referenceHistoryOneLineageId,
1503
+ referenceVersionNumber: 1,
1504
+ referenceVersionKey: `reference#${referenceHistoryOneId}`,
1505
+ role: "extracted_text",
1506
+ sortKey: "900-extracted-text",
1507
+ storagePath: "corpora/history/extracted/pipeline/snapshot-demo-history/text/history-001.txt",
1508
+ filename: "history-001.txt",
1509
+ mediaType: "text/plain",
1510
+ sha256: "demo-history-001-extracted-text",
1511
+ importRunId: "knowledge-import-demo-projection",
1512
+ importedAt,
1513
+ },
1514
+ {
1515
+ id: "reference-attachment-demo-history-002-deepgram",
1516
+ referenceId: referenceHistoryTwoId,
1517
+ referenceLineageId: referenceHistoryTwoLineageId,
1518
+ referenceVersionNumber: 1,
1519
+ referenceVersionKey: `reference#${referenceHistoryTwoId}`,
1520
+ role: "deepgram",
1521
+ sortKey: "002-deepgram",
1522
+ storagePath: "corpora/history/history-002.deepgram.json",
1523
+ filename: "history-002.deepgram.json",
1524
+ mediaType: "application/json",
1525
+ importRunId: "knowledge-import-demo-projection",
1526
+ importedAt,
1527
+ },
1528
+ ],
1529
+ semanticNodes: [
1530
+ {
1531
+ id: "semantic-node-graph-entity-benchmark-saturation-v1",
1532
+ lineageId: "semantic-node-graph-entity-benchmark-saturation",
1533
+ versionNumber: 1,
1534
+ versionState: "current",
1535
+ nodeKey: "graph-entity-benchmark-saturation",
1536
+ nodeKind: "entity",
1537
+ corpusId,
1538
+ displayName: "Benchmark Saturation",
1539
+ status: "accepted",
1540
+ importRunId: "knowledge-import-demo-steering",
1541
+ updatedAt: importedAt,
1542
+ },
1543
+ {
1544
+ id: "semantic-node-comment-ingestion-rationale-v1",
1545
+ lineageId: "semantic-node-comment-ingestion-rationale",
1546
+ versionNumber: 1,
1547
+ versionState: "current",
1548
+ nodeKey: "comment.ingestion_rationale",
1549
+ nodeKind: "commentConcept",
1550
+ corpusId: sourceCorpusId,
1551
+ displayName: "Ingestion Rationale",
1552
+ status: "accepted",
1553
+ importRunId: "knowledge-import-demo-projection",
1554
+ updatedAt: importedAt,
1555
+ },
1556
+ ],
1557
+ messages: [
1558
+ {
1559
+ id: "message-demo-history-002-rationale",
1560
+ messageKind: "ingestion_rationale",
1561
+ messageDomain: "commentary",
1562
+ status: "active",
1563
+ body: "Imported as a useful holdout against modern scaling coverage.",
1564
+ summary: "Holdout ingestion rationale",
1565
+ source: "biblicus-import",
1566
+ importRunId: "knowledge-import-demo-projection",
1567
+ createdAt: importedAt,
1568
+ updatedAt: importedAt,
1569
+ },
1570
+ {
1571
+ id: reportingPacketMessageId,
1572
+ messageKind: "reporting_context_packet",
1573
+ messageDomain: "assignment_work",
1574
+ status: "active",
1575
+ body: "Context packet for a section-ready News candidate. Editors can select, merge, brief, hold, or kill this packet without creating reader copy.",
1576
+ summary: "Reporting context packet: model-release accountability angle",
1577
+ source: "procedures/newsroom/reporter.tac",
1578
+ importRunId: "knowledge-import-demo-projection",
1579
+ authorLabel: "newsroom-reporter",
1580
+ createdAt: importedAt,
1581
+ updatedAt: importedAt,
1582
+ metadata: {
1583
+ kind: "reporting.context_packet.created",
1584
+ assignmentId: assignmentReportingId,
1585
+ reporting: {
1586
+ sectionKey: "news",
1587
+ editionId: "edition-demo-planning-v1",
1588
+ candidateRank: 1,
1589
+ editorRecommendation: "hold",
1590
+ recommendedAngle: "Focus on accountability for model-release claims.",
1591
+ acceptedReferenceIds: [referenceHistoryTwoId],
1592
+ proposedReferences: [],
1593
+ riskFlags: ["Avoid promotional framing."],
1594
+ coverageGaps: ["Need a second independent source."],
1595
+ openQuestions: ["Which users are affected first?"],
1596
+ copywriterBrief: "Use accepted evidence and recent desk memory before drafting.",
1597
+ },
1598
+ },
1599
+ },
1600
+ ],
1601
+ assignments: [
1602
+ {
1603
+ id: assignmentReportingId,
1604
+ assignmentTypeKey: "reporting.edition-candidate",
1605
+ queueKey: "edition:edition-demo:section:news:lane:reporting",
1606
+ queueStatusKey: "edition:edition-demo:section:news:lane:reporting#open",
1607
+ status: "open",
1608
+ priority: 20,
1609
+ title: "News reporting candidate 1: Model release accountability",
1610
+ summary: "Create reporting context for a candidate News article; do not create a draft Item until editor selection.",
1611
+ brief: "Report a section-ready candidate for News, option 1.",
1612
+ instructions: "Return a private reporting context packet only. Distinguish accepted references from proposed references.",
1613
+ corpusId,
1614
+ categorySetId,
1615
+ classifierId: "demo-canonical-classifier",
1616
+ sectionId: "news",
1617
+ sectionKey: "news",
1618
+ sectionType: "canonical",
1619
+ sectionStatusKey: "news#open",
1620
+ sectionQueueStatusKey: "news#edition:edition-demo:section:news:lane:reporting#open",
1621
+ primaryFocusCategoryKey: "category.foundation-model-scaling",
1622
+ topicScopeCategoryKeys: ["category.foundation-model-scaling"],
1623
+ importRunId: "knowledge-import-demo-projection",
1624
+ createdBy: "papyrus-content-cli",
1625
+ createdAt: importedAt,
1626
+ updatedAt: importedAt,
1627
+ metadata: {
1628
+ editionId: "edition-demo-planning-v1",
1629
+ editionSlug: "edition-demo",
1630
+ sectionKey: "news",
1631
+ sectionTitle: "News",
1632
+ candidateRank: 1,
1633
+ slotTarget: { sectionKey: "news", slots: 1, candidateRank: 1 },
1634
+ expectedOutput: "Private reporting context packet for editor selection and copywriting, not reader copy.",
1635
+ },
1636
+ },
1637
+ {
1638
+ id: assignmentHistoryOneId,
1639
+ assignmentTypeKey: "curation.reference-intake",
1640
+ queueKey: `curation.reference-intake#${sourceCorpusId}`,
1641
+ queueStatusKey: `curation.reference-intake#${sourceCorpusId}#open`,
1642
+ status: "open",
1643
+ priority: 40,
1644
+ title: "Curate reference: Symbolic And Connectionist History Reader",
1645
+ brief: "Review this knowledge-base reference and add durable curation notes or semantic links.",
1646
+ instructions: "Inspect linked private corpus attachments; write findings as messages, semantic relations, or proposals.",
1647
+ corpusId: sourceCorpusId,
1648
+ categorySetId,
1649
+ classifierId: "demo-canonical-classifier",
1650
+ importRunId: "knowledge-import-demo-projection",
1651
+ createdBy: "biblicus-import",
1652
+ createdAt: importedAt,
1653
+ updatedAt: importedAt,
1654
+ metadata: { referenceLineageId: referenceHistoryOneLineageId, externalItemId: "history-001" },
1655
+ },
1656
+ {
1657
+ id: assignmentHistoryTwoId,
1658
+ assignmentTypeKey: "curation.reference-intake",
1659
+ queueKey: `curation.reference-intake#${sourceCorpusId}`,
1660
+ queueStatusKey: `curation.reference-intake#${sourceCorpusId}#claimed`,
1661
+ status: "claimed",
1662
+ priority: 50,
1663
+ title: "Curate reference: Foundation Model Scaling Retrospective",
1664
+ brief: "Review this reference because it has a review-recommended category projection.",
1665
+ instructions: "Check whether the weak scaling classification deserves a message, proposal, or relation.",
1666
+ assigneeType: "agent",
1667
+ assigneeId: "archivist-demo",
1668
+ assigneeKey: "agent#archivist-demo",
1669
+ claimedAt: importedAt,
1670
+ corpusId: sourceCorpusId,
1671
+ categorySetId,
1672
+ classifierId: "demo-canonical-classifier",
1673
+ importRunId: "knowledge-import-demo-projection",
1674
+ createdBy: "biblicus-import",
1675
+ createdAt: importedAt,
1676
+ updatedAt: importedAt,
1677
+ metadata: { referenceLineageId: referenceHistoryTwoLineageId, externalItemId: "history-002" },
1678
+ },
1679
+ ],
1680
+ assignmentEvents: [
1681
+ {
1682
+ id: "assignment-event-demo-history-002-claimed",
1683
+ assignmentId: assignmentHistoryTwoId,
1684
+ assignmentTypeKey: "curation.reference-intake",
1685
+ queueKey: `curation.reference-intake#${sourceCorpusId}`,
1686
+ eventType: "claim",
1687
+ fromStatus: "open",
1688
+ toStatus: "claimed",
1689
+ actorLabel: "archivist-demo",
1690
+ createdAt: importedAt,
1691
+ },
1692
+ ],
1693
+ editionSlots: [
1694
+ {
1695
+ id: "edition-slot-demo-news-01",
1696
+ editionId: "edition-demo-weekly-v1",
1697
+ sectionKey: "news",
1698
+ slotRank: 1,
1699
+ targetType: "article",
1700
+ targetLengthBand: "standard",
1701
+ minImageAssets: 1,
1702
+ status: "open",
1703
+ selectedAssignmentId: null,
1704
+ metadata: { source: "demo" },
1705
+ createdAt: importedAt,
1706
+ updatedAt: importedAt,
1707
+ },
1708
+ ],
1709
+ newsroomSections: defaultNewsroomSections(importedAt, newsroomSectionsConfigPath),
1710
+ procedureDefinitions: [],
1711
+ procedureVersions: [],
1712
+ procedureRuns: [],
1713
+ doctrineRecords: [
1714
+ {
1715
+ id: "item-editorial-doctrine-mission-v1",
1716
+ lineageId: "item-editorial-doctrine-mission",
1717
+ versionNumber: 1,
1718
+ versionState: "current",
1719
+ versionCreatedAt: importedAt,
1720
+ versionCreatedBy: "demo-editor",
1721
+ type: "doctrine",
1722
+ status: "private",
1723
+ typeStatus: "doctrine#private",
1724
+ slug: "editorial-doctrine-mission",
1725
+ title: "Editorial Mission",
1726
+ body: [
1727
+ "Papyrus publishes bounded editions that help readers understand what changed, why it matters, and what remains uncertain.",
1728
+ "Coverage should be accurate, source-disciplined, and legible about evidence quality and editorial judgment.",
1729
+ ],
1730
+ editorial: { kind: "mission" },
1731
+ updatedAt: importedAt,
1732
+ },
1733
+ {
1734
+ id: "item-editorial-doctrine-policy-v1",
1735
+ lineageId: "item-editorial-doctrine-policy",
1736
+ versionNumber: 1,
1737
+ versionState: "current",
1738
+ versionCreatedAt: importedAt,
1739
+ versionCreatedBy: "demo-editor",
1740
+ type: "doctrine",
1741
+ status: "private",
1742
+ typeStatus: "doctrine#private",
1743
+ slug: "editorial-doctrine-policy",
1744
+ title: "Editorial Policy",
1745
+ body: [
1746
+ "Publication doctrine is the global inclusion standard; desk doctrine sets local source priorities and framing.",
1747
+ "News reporting should prioritize current, journalistic, and official sources; desk workflows may use academic research as background unless a desk policy explicitly makes research the primary evidence class.",
1748
+ "High-risk domains, including health-related claims, require stricter sourcing, explicit uncertainty handling, and clear separation between verified facts and interpretation.",
1749
+ ],
1750
+ editorial: { kind: "policy" },
1751
+ updatedAt: importedAt,
1752
+ },
1753
+ ],
1754
+ semanticRelations: [
1755
+ {
1756
+ id: "semantic-relation-demo-reporting-context-comment",
1757
+ relationState: "current",
1758
+ predicate: "comment",
1759
+ relationTypeKey: "comment",
1760
+ relationDomain: "commentary",
1761
+ subjectKind: "message",
1762
+ subjectId: reportingPacketMessageId,
1763
+ subjectLineageId: reportingPacketMessageId,
1764
+ objectKind: "assignment",
1765
+ objectId: assignmentReportingId,
1766
+ objectLineageId: assignmentReportingId,
1767
+ subjectStateKey: `message#${reportingPacketMessageId}#current`,
1768
+ objectStateKey: `assignment#${assignmentReportingId}#current`,
1769
+ objectSubjectStateKey: `assignment#${assignmentReportingId}#current#message`,
1770
+ predicateObjectStateKey: `comment#assignment#${assignmentReportingId}#current`,
1771
+ subjectVersionKey: `message#${reportingPacketMessageId}`,
1772
+ objectVersionKey: `assignment#${assignmentReportingId}`,
1773
+ rank: 1,
1774
+ reviewRecommended: false,
1775
+ importRunId: "knowledge-import-demo-projection",
1776
+ importedAt,
1777
+ },
1778
+ {
1779
+ id: "semantic-relation-demo-assignment-history-001",
1780
+ relationState: "current",
1781
+ predicate: "requests_work_on",
1782
+ subjectKind: "assignment",
1783
+ subjectId: assignmentHistoryOneId,
1784
+ subjectLineageId: assignmentHistoryOneId,
1785
+ objectKind: "reference",
1786
+ objectId: referenceHistoryOneId,
1787
+ objectLineageId: referenceHistoryOneLineageId,
1788
+ objectVersionNumber: 1,
1789
+ subjectStateKey: `assignment#${assignmentHistoryOneId}#current`,
1790
+ objectStateKey: `reference#${referenceHistoryOneLineageId}#current`,
1791
+ objectSubjectStateKey: `reference#${referenceHistoryOneLineageId}#current#assignment`,
1792
+ predicateObjectStateKey: `requests_work_on#reference#${referenceHistoryOneLineageId}#current`,
1793
+ subjectVersionKey: `assignment#${assignmentHistoryOneId}`,
1794
+ objectVersionKey: `reference#${referenceHistoryOneId}`,
1795
+ rank: 1,
1796
+ reviewRecommended: true,
1797
+ importRunId: "knowledge-import-demo-projection",
1798
+ importedAt,
1799
+ },
1800
+ {
1801
+ id: "semantic-relation-demo-assignment-history-002",
1802
+ relationState: "current",
1803
+ predicate: "requests_work_on",
1804
+ subjectKind: "assignment",
1805
+ subjectId: assignmentHistoryTwoId,
1806
+ subjectLineageId: assignmentHistoryTwoId,
1807
+ objectKind: "reference",
1808
+ objectId: referenceHistoryTwoId,
1809
+ objectLineageId: referenceHistoryTwoLineageId,
1810
+ objectVersionNumber: 1,
1811
+ subjectStateKey: `assignment#${assignmentHistoryTwoId}#current`,
1812
+ objectStateKey: `reference#${referenceHistoryTwoLineageId}#current`,
1813
+ objectSubjectStateKey: `reference#${referenceHistoryTwoLineageId}#current#assignment`,
1814
+ predicateObjectStateKey: `requests_work_on#reference#${referenceHistoryTwoLineageId}#current`,
1815
+ subjectVersionKey: `assignment#${assignmentHistoryTwoId}`,
1816
+ objectVersionKey: `reference#${referenceHistoryTwoId}`,
1817
+ rank: 1,
1818
+ reviewRecommended: true,
1819
+ importRunId: "knowledge-import-demo-projection",
1820
+ importedAt,
1821
+ },
1822
+ {
1823
+ id: "semantic-relation-demo-history-001",
1824
+ relationState: "current",
1825
+ predicate: "classified_as",
1826
+ subjectKind: "reference",
1827
+ subjectId: referenceHistoryOneId,
1828
+ subjectLineageId: referenceHistoryOneLineageId,
1829
+ subjectVersionNumber: 1,
1830
+ objectKind: "category",
1831
+ objectId: `${historyCategoryLineageId}-v1`,
1832
+ objectLineageId: historyCategoryLineageId,
1833
+ objectVersionNumber: 1,
1834
+ subjectStateKey: `reference#${referenceHistoryOneLineageId}#current`,
1835
+ objectStateKey: `category#${historyCategoryLineageId}#current`,
1836
+ objectSubjectStateKey: `category#${historyCategoryLineageId}#current#reference`,
1837
+ predicateObjectStateKey: `classified_as#category#${historyCategoryLineageId}#current`,
1838
+ subjectVersionKey: `reference#${referenceHistoryOneId}`,
1839
+ objectVersionKey: `category#${historyCategoryLineageId}-v1`,
1840
+ score: 0.91,
1841
+ rank: 1,
1842
+ classifierId: "demo-canonical-classifier",
1843
+ reviewRecommended: false,
1844
+ importRunId: "knowledge-import-demo-projection",
1845
+ importedAt,
1846
+ },
1847
+ {
1848
+ id: "semantic-relation-demo-history-002",
1849
+ relationState: "current",
1850
+ predicate: "classified_as",
1851
+ subjectKind: "reference",
1852
+ subjectId: referenceHistoryTwoId,
1853
+ subjectLineageId: referenceHistoryTwoLineageId,
1854
+ subjectVersionNumber: 1,
1855
+ objectKind: "category",
1856
+ objectId: `${scalingCategoryLineageId}-v1`,
1857
+ objectLineageId: scalingCategoryLineageId,
1858
+ objectVersionNumber: 1,
1859
+ subjectStateKey: `reference#${referenceHistoryTwoLineageId}#current`,
1860
+ objectStateKey: `category#${scalingCategoryLineageId}#current`,
1861
+ objectSubjectStateKey: `category#${scalingCategoryLineageId}#current#reference`,
1862
+ predicateObjectStateKey: `classified_as#category#${scalingCategoryLineageId}#current`,
1863
+ subjectVersionKey: `reference#${referenceHistoryTwoId}`,
1864
+ objectVersionKey: `category#${scalingCategoryLineageId}-v1`,
1865
+ score: 0.58,
1866
+ rank: 1,
1867
+ classifierId: "demo-canonical-classifier",
1868
+ reviewRecommended: true,
1869
+ importRunId: "knowledge-import-demo-projection",
1870
+ importedAt,
1871
+ },
1872
+ {
1873
+ id: "semantic-relation-demo-message-history-002-rationale",
1874
+ relationState: "current",
1875
+ predicate: "comment",
1876
+ relationTypeId: "semantic-relation-type-comment",
1877
+ relationTypeKey: "comment",
1878
+ relationDomain: "commentary",
1879
+ subjectKind: "message",
1880
+ subjectId: "message-demo-history-002-rationale",
1881
+ subjectLineageId: "message-demo-history-002-rationale",
1882
+ subjectVersionNumber: 1,
1883
+ objectKind: "reference",
1884
+ objectId: referenceHistoryTwoId,
1885
+ objectLineageId: referenceHistoryTwoLineageId,
1886
+ objectVersionNumber: 1,
1887
+ subjectStateKey: "message#message-demo-history-002-rationale#current",
1888
+ objectStateKey: `reference#${referenceHistoryTwoLineageId}#current`,
1889
+ objectSubjectStateKey: `reference#${referenceHistoryTwoLineageId}#current#message`,
1890
+ predicateObjectStateKey: `comment#reference#${referenceHistoryTwoLineageId}#current`,
1891
+ subjectVersionKey: "message#message-demo-history-002-rationale",
1892
+ objectVersionKey: `reference#${referenceHistoryTwoId}`,
1893
+ rank: 1,
1894
+ reviewRecommended: false,
1895
+ importRunId: "knowledge-import-demo-projection",
1896
+ importedAt,
1897
+ },
1898
+ ],
1899
+ loadError: null,
1900
+ };
1901
+
1902
+ if (pilobolus) {
1903
+ return applyPilobolusDemoDashboardContent(dashboard, profile);
1904
+ }
1905
+
1906
+ return dashboard;
1907
+ }