@itaila/archetype 0.3.30

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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +475 -0
  3. package/dist/audit/audit-persona.d.ts +163 -0
  4. package/dist/audit/audit-persona.d.ts.map +1 -0
  5. package/dist/audit/audit-persona.js +415 -0
  6. package/dist/audit/audit-persona.js.map +1 -0
  7. package/dist/audit/brain-reflection.d.ts +33 -0
  8. package/dist/audit/brain-reflection.d.ts.map +1 -0
  9. package/dist/audit/brain-reflection.js +148 -0
  10. package/dist/audit/brain-reflection.js.map +1 -0
  11. package/dist/audit/conversation-audit.d.ts +12 -0
  12. package/dist/audit/conversation-audit.d.ts.map +1 -0
  13. package/dist/audit/conversation-audit.js +76 -0
  14. package/dist/audit/conversation-audit.js.map +1 -0
  15. package/dist/audit/prompt-audit.d.ts +10 -0
  16. package/dist/audit/prompt-audit.d.ts.map +1 -0
  17. package/dist/audit/prompt-audit.js +153 -0
  18. package/dist/audit/prompt-audit.js.map +1 -0
  19. package/dist/audit/prompt-dump.d.ts +137 -0
  20. package/dist/audit/prompt-dump.d.ts.map +1 -0
  21. package/dist/audit/prompt-dump.js +269 -0
  22. package/dist/audit/prompt-dump.js.map +1 -0
  23. package/dist/audit/trace-integrity.d.ts +33 -0
  24. package/dist/audit/trace-integrity.d.ts.map +1 -0
  25. package/dist/audit/trace-integrity.js +109 -0
  26. package/dist/audit/trace-integrity.js.map +1 -0
  27. package/dist/audit/types.d.ts +92 -0
  28. package/dist/audit/types.d.ts.map +1 -0
  29. package/dist/audit/types.js +2 -0
  30. package/dist/audit/types.js.map +1 -0
  31. package/dist/audit/version.d.ts +14 -0
  32. package/dist/audit/version.d.ts.map +1 -0
  33. package/dist/audit/version.js +65 -0
  34. package/dist/audit/version.js.map +1 -0
  35. package/dist/brain.d.ts +7 -0
  36. package/dist/brain.d.ts.map +1 -0
  37. package/dist/brain.js +83 -0
  38. package/dist/brain.js.map +1 -0
  39. package/dist/builder/actions.d.ts +60 -0
  40. package/dist/builder/actions.d.ts.map +1 -0
  41. package/dist/builder/actions.js +257 -0
  42. package/dist/builder/actions.js.map +1 -0
  43. package/dist/builder/browser.d.ts +140 -0
  44. package/dist/builder/browser.d.ts.map +1 -0
  45. package/dist/builder/browser.js +232 -0
  46. package/dist/builder/browser.js.map +1 -0
  47. package/dist/builder/executor.d.ts +228 -0
  48. package/dist/builder/executor.d.ts.map +1 -0
  49. package/dist/builder/executor.js +1548 -0
  50. package/dist/builder/executor.js.map +1 -0
  51. package/dist/builder/index.d.ts +24 -0
  52. package/dist/builder/index.d.ts.map +1 -0
  53. package/dist/builder/index.js +24 -0
  54. package/dist/builder/index.js.map +1 -0
  55. package/dist/builder/node-test-discovery.d.ts +13 -0
  56. package/dist/builder/node-test-discovery.d.ts.map +1 -0
  57. package/dist/builder/node-test-discovery.js +45 -0
  58. package/dist/builder/node-test-discovery.js.map +1 -0
  59. package/dist/builder/sandbox.d.ts +172 -0
  60. package/dist/builder/sandbox.d.ts.map +1 -0
  61. package/dist/builder/sandbox.js +294 -0
  62. package/dist/builder/sandbox.js.map +1 -0
  63. package/dist/builder/workspace-files.d.ts +63 -0
  64. package/dist/builder/workspace-files.d.ts.map +1 -0
  65. package/dist/builder/workspace-files.js +190 -0
  66. package/dist/builder/workspace-files.js.map +1 -0
  67. package/dist/core/actions.d.ts +55 -0
  68. package/dist/core/actions.d.ts.map +1 -0
  69. package/dist/core/actions.js +311 -0
  70. package/dist/core/actions.js.map +1 -0
  71. package/dist/core/attachment-notes.d.ts +7 -0
  72. package/dist/core/attachment-notes.d.ts.map +1 -0
  73. package/dist/core/attachment-notes.js +38 -0
  74. package/dist/core/attachment-notes.js.map +1 -0
  75. package/dist/core/context.d.ts +10 -0
  76. package/dist/core/context.d.ts.map +1 -0
  77. package/dist/core/context.js +108 -0
  78. package/dist/core/context.js.map +1 -0
  79. package/dist/core/crud-prompt.d.ts +16 -0
  80. package/dist/core/crud-prompt.d.ts.map +1 -0
  81. package/dist/core/crud-prompt.js +268 -0
  82. package/dist/core/crud-prompt.js.map +1 -0
  83. package/dist/core/crud-schema.d.ts +12 -0
  84. package/dist/core/crud-schema.d.ts.map +1 -0
  85. package/dist/core/crud-schema.js +42 -0
  86. package/dist/core/crud-schema.js.map +1 -0
  87. package/dist/core/effective-config.d.ts +13 -0
  88. package/dist/core/effective-config.d.ts.map +1 -0
  89. package/dist/core/effective-config.js +33 -0
  90. package/dist/core/effective-config.js.map +1 -0
  91. package/dist/core/entities.d.ts +82 -0
  92. package/dist/core/entities.d.ts.map +1 -0
  93. package/dist/core/entities.js +116 -0
  94. package/dist/core/entities.js.map +1 -0
  95. package/dist/core/entity-helpers.d.ts +47 -0
  96. package/dist/core/entity-helpers.d.ts.map +1 -0
  97. package/dist/core/entity-helpers.js +122 -0
  98. package/dist/core/entity-helpers.js.map +1 -0
  99. package/dist/core/entity-registry.d.ts +47 -0
  100. package/dist/core/entity-registry.d.ts.map +1 -0
  101. package/dist/core/entity-registry.js +54 -0
  102. package/dist/core/entity-registry.js.map +1 -0
  103. package/dist/core/eq.d.ts +13 -0
  104. package/dist/core/eq.d.ts.map +1 -0
  105. package/dist/core/eq.js +41 -0
  106. package/dist/core/eq.js.map +1 -0
  107. package/dist/core/focus-context.d.ts +19 -0
  108. package/dist/core/focus-context.d.ts.map +1 -0
  109. package/dist/core/focus-context.js +46 -0
  110. package/dist/core/focus-context.js.map +1 -0
  111. package/dist/core/focus-mode-actions.d.ts +23 -0
  112. package/dist/core/focus-mode-actions.d.ts.map +1 -0
  113. package/dist/core/focus-mode-actions.js +74 -0
  114. package/dist/core/focus-mode-actions.js.map +1 -0
  115. package/dist/core/greeting.d.ts +10 -0
  116. package/dist/core/greeting.d.ts.map +1 -0
  117. package/dist/core/greeting.js +41 -0
  118. package/dist/core/greeting.js.map +1 -0
  119. package/dist/core/identity.d.ts +13 -0
  120. package/dist/core/identity.d.ts.map +1 -0
  121. package/dist/core/identity.js +54 -0
  122. package/dist/core/identity.js.map +1 -0
  123. package/dist/core/knowledge.d.ts +10 -0
  124. package/dist/core/knowledge.d.ts.map +1 -0
  125. package/dist/core/knowledge.js +40 -0
  126. package/dist/core/knowledge.js.map +1 -0
  127. package/dist/core/memory-actions.d.ts +38 -0
  128. package/dist/core/memory-actions.d.ts.map +1 -0
  129. package/dist/core/memory-actions.js +181 -0
  130. package/dist/core/memory-actions.js.map +1 -0
  131. package/dist/core/memory.d.ts +35 -0
  132. package/dist/core/memory.d.ts.map +1 -0
  133. package/dist/core/memory.js +168 -0
  134. package/dist/core/memory.js.map +1 -0
  135. package/dist/core/peer-actions.d.ts +15 -0
  136. package/dist/core/peer-actions.d.ts.map +1 -0
  137. package/dist/core/peer-actions.js +33 -0
  138. package/dist/core/peer-actions.js.map +1 -0
  139. package/dist/core/prompt-builder.d.ts +46 -0
  140. package/dist/core/prompt-builder.d.ts.map +1 -0
  141. package/dist/core/prompt-builder.js +543 -0
  142. package/dist/core/prompt-builder.js.map +1 -0
  143. package/dist/core/prompt-mode.d.ts +3 -0
  144. package/dist/core/prompt-mode.d.ts.map +1 -0
  145. package/dist/core/prompt-mode.js +6 -0
  146. package/dist/core/prompt-mode.js.map +1 -0
  147. package/dist/core/prompted-turn.d.ts +6 -0
  148. package/dist/core/prompted-turn.d.ts.map +1 -0
  149. package/dist/core/prompted-turn.js +48 -0
  150. package/dist/core/prompted-turn.js.map +1 -0
  151. package/dist/core/request-builder.d.ts +14 -0
  152. package/dist/core/request-builder.d.ts.map +1 -0
  153. package/dist/core/request-builder.js +64 -0
  154. package/dist/core/request-builder.js.map +1 -0
  155. package/dist/core/session-routing.d.ts +23 -0
  156. package/dist/core/session-routing.d.ts.map +1 -0
  157. package/dist/core/session-routing.js +59 -0
  158. package/dist/core/session-routing.js.map +1 -0
  159. package/dist/core/voice.d.ts +6 -0
  160. package/dist/core/voice.d.ts.map +1 -0
  161. package/dist/core/voice.js +30 -0
  162. package/dist/core/voice.js.map +1 -0
  163. package/dist/engine/chat.d.ts +45 -0
  164. package/dist/engine/chat.d.ts.map +1 -0
  165. package/dist/engine/chat.js +308 -0
  166. package/dist/engine/chat.js.map +1 -0
  167. package/dist/engine/continuity.d.ts +107 -0
  168. package/dist/engine/continuity.d.ts.map +1 -0
  169. package/dist/engine/continuity.js +320 -0
  170. package/dist/engine/continuity.js.map +1 -0
  171. package/dist/engine/crud.d.ts +62 -0
  172. package/dist/engine/crud.d.ts.map +1 -0
  173. package/dist/engine/crud.js +260 -0
  174. package/dist/engine/crud.js.map +1 -0
  175. package/dist/engine/side-effects.d.ts +93 -0
  176. package/dist/engine/side-effects.d.ts.map +1 -0
  177. package/dist/engine/side-effects.js +271 -0
  178. package/dist/engine/side-effects.js.map +1 -0
  179. package/dist/engine/staging.d.ts +29 -0
  180. package/dist/engine/staging.d.ts.map +1 -0
  181. package/dist/engine/staging.js +159 -0
  182. package/dist/engine/staging.js.map +1 -0
  183. package/dist/engine/working-set.d.ts +18 -0
  184. package/dist/engine/working-set.d.ts.map +1 -0
  185. package/dist/engine/working-set.js +246 -0
  186. package/dist/engine/working-set.js.map +1 -0
  187. package/dist/evals/action-contracts.d.ts +40 -0
  188. package/dist/evals/action-contracts.d.ts.map +1 -0
  189. package/dist/evals/action-contracts.js +208 -0
  190. package/dist/evals/action-contracts.js.map +1 -0
  191. package/dist/evals/brain-bloat.d.ts +39 -0
  192. package/dist/evals/brain-bloat.d.ts.map +1 -0
  193. package/dist/evals/brain-bloat.js +167 -0
  194. package/dist/evals/brain-bloat.js.map +1 -0
  195. package/dist/evals/brain-prescriptions.d.ts +30 -0
  196. package/dist/evals/brain-prescriptions.d.ts.map +1 -0
  197. package/dist/evals/brain-prescriptions.js +148 -0
  198. package/dist/evals/brain-prescriptions.js.map +1 -0
  199. package/dist/evals/cross-layer-duplicates.d.ts +49 -0
  200. package/dist/evals/cross-layer-duplicates.d.ts.map +1 -0
  201. package/dist/evals/cross-layer-duplicates.js +289 -0
  202. package/dist/evals/cross-layer-duplicates.js.map +1 -0
  203. package/dist/evals/entity-visibility.d.ts +28 -0
  204. package/dist/evals/entity-visibility.d.ts.map +1 -0
  205. package/dist/evals/entity-visibility.js +216 -0
  206. package/dist/evals/entity-visibility.js.map +1 -0
  207. package/dist/evals/index.d.ts +19 -0
  208. package/dist/evals/index.d.ts.map +1 -0
  209. package/dist/evals/index.js +11 -0
  210. package/dist/evals/index.js.map +1 -0
  211. package/dist/evals/judge.d.ts +22 -0
  212. package/dist/evals/judge.d.ts.map +1 -0
  213. package/dist/evals/judge.js +337 -0
  214. package/dist/evals/judge.js.map +1 -0
  215. package/dist/evals/operational-contract.d.ts +40 -0
  216. package/dist/evals/operational-contract.d.ts.map +1 -0
  217. package/dist/evals/operational-contract.js +115 -0
  218. package/dist/evals/operational-contract.js.map +1 -0
  219. package/dist/evals/prompt-content.d.ts +14 -0
  220. package/dist/evals/prompt-content.d.ts.map +1 -0
  221. package/dist/evals/prompt-content.js +104 -0
  222. package/dist/evals/prompt-content.js.map +1 -0
  223. package/dist/evals/runtime.d.ts +4 -0
  224. package/dist/evals/runtime.d.ts.map +1 -0
  225. package/dist/evals/runtime.js +197 -0
  226. package/dist/evals/runtime.js.map +1 -0
  227. package/dist/evals/sample-projects.d.ts +143 -0
  228. package/dist/evals/sample-projects.d.ts.map +1 -0
  229. package/dist/evals/sample-projects.js +644 -0
  230. package/dist/evals/sample-projects.js.map +1 -0
  231. package/dist/evals/types.d.ts +88 -0
  232. package/dist/evals/types.d.ts.map +1 -0
  233. package/dist/evals/types.js +2 -0
  234. package/dist/evals/types.js.map +1 -0
  235. package/dist/foundation/index.d.ts +158 -0
  236. package/dist/foundation/index.d.ts.map +1 -0
  237. package/dist/foundation/index.js +256 -0
  238. package/dist/foundation/index.js.map +1 -0
  239. package/dist/index.d.ts +223 -0
  240. package/dist/index.d.ts.map +1 -0
  241. package/dist/index.js +998 -0
  242. package/dist/index.js.map +1 -0
  243. package/dist/managed/autonomous-loop.d.ts +199 -0
  244. package/dist/managed/autonomous-loop.d.ts.map +1 -0
  245. package/dist/managed/autonomous-loop.js +451 -0
  246. package/dist/managed/autonomous-loop.js.map +1 -0
  247. package/dist/managed/conversation.d.ts +20 -0
  248. package/dist/managed/conversation.d.ts.map +1 -0
  249. package/dist/managed/conversation.js +40 -0
  250. package/dist/managed/conversation.js.map +1 -0
  251. package/dist/managed/knowledge.d.ts +7 -0
  252. package/dist/managed/knowledge.d.ts.map +1 -0
  253. package/dist/managed/knowledge.js +174 -0
  254. package/dist/managed/knowledge.js.map +1 -0
  255. package/dist/managed/memory-manager.d.ts +7 -0
  256. package/dist/managed/memory-manager.d.ts.map +1 -0
  257. package/dist/managed/memory-manager.js +18 -0
  258. package/dist/managed/memory-manager.js.map +1 -0
  259. package/dist/managed/memory-review.d.ts +45 -0
  260. package/dist/managed/memory-review.d.ts.map +1 -0
  261. package/dist/managed/memory-review.js +130 -0
  262. package/dist/managed/memory-review.js.map +1 -0
  263. package/dist/managed/storage.d.ts +2 -0
  264. package/dist/managed/storage.d.ts.map +1 -0
  265. package/dist/managed/storage.js +2 -0
  266. package/dist/managed/storage.js.map +1 -0
  267. package/dist/managed/work-history.d.ts +23 -0
  268. package/dist/managed/work-history.d.ts.map +1 -0
  269. package/dist/managed/work-history.js +31 -0
  270. package/dist/managed/work-history.js.map +1 -0
  271. package/dist/observability/index.d.ts +15 -0
  272. package/dist/observability/index.d.ts.map +1 -0
  273. package/dist/observability/index.js +15 -0
  274. package/dist/observability/index.js.map +1 -0
  275. package/dist/observability/render-run-markdown.d.ts +90 -0
  276. package/dist/observability/render-run-markdown.d.ts.map +1 -0
  277. package/dist/observability/render-run-markdown.js +231 -0
  278. package/dist/observability/render-run-markdown.js.map +1 -0
  279. package/dist/observability/turn-reporter.d.ts +20 -0
  280. package/dist/observability/turn-reporter.d.ts.map +1 -0
  281. package/dist/observability/turn-reporter.js +106 -0
  282. package/dist/observability/turn-reporter.js.map +1 -0
  283. package/dist/persona.d.ts +49 -0
  284. package/dist/persona.d.ts.map +1 -0
  285. package/dist/persona.js +287 -0
  286. package/dist/persona.js.map +1 -0
  287. package/dist/playbook/defaults.d.ts +25 -0
  288. package/dist/playbook/defaults.d.ts.map +1 -0
  289. package/dist/playbook/defaults.js +108 -0
  290. package/dist/playbook/defaults.js.map +1 -0
  291. package/dist/playbook/invariants.d.ts +244 -0
  292. package/dist/playbook/invariants.d.ts.map +1 -0
  293. package/dist/playbook/invariants.js +259 -0
  294. package/dist/playbook/invariants.js.map +1 -0
  295. package/dist/playbook/templates.d.ts +7 -0
  296. package/dist/playbook/templates.d.ts.map +1 -0
  297. package/dist/playbook/templates.js +437 -0
  298. package/dist/playbook/templates.js.map +1 -0
  299. package/dist/providers/gemini.d.ts +73 -0
  300. package/dist/providers/gemini.d.ts.map +1 -0
  301. package/dist/providers/gemini.js +536 -0
  302. package/dist/providers/gemini.js.map +1 -0
  303. package/dist/providers/types.d.ts +2 -0
  304. package/dist/providers/types.d.ts.map +1 -0
  305. package/dist/providers/types.js +2 -0
  306. package/dist/providers/types.js.map +1 -0
  307. package/dist/providers/zod-to-gemini.d.ts +8 -0
  308. package/dist/providers/zod-to-gemini.d.ts.map +1 -0
  309. package/dist/providers/zod-to-gemini.js +148 -0
  310. package/dist/providers/zod-to-gemini.js.map +1 -0
  311. package/dist/samples/pm-spec-agent.d.ts +22 -0
  312. package/dist/samples/pm-spec-agent.d.ts.map +1 -0
  313. package/dist/samples/pm-spec-agent.js +53 -0
  314. package/dist/samples/pm-spec-agent.js.map +1 -0
  315. package/dist/types.d.ts +920 -0
  316. package/dist/types.d.ts.map +1 -0
  317. package/dist/types.js +2 -0
  318. package/dist/types.js.map +1 -0
  319. package/package.json +68 -0
@@ -0,0 +1,644 @@
1
+ import { z } from 'zod';
2
+ import { CHIEF_OF_STAFF_TEMPLATE, COACH_TEMPLATE, FITNESS_TEMPLATE, LANGUAGE_TUTOR_TEMPLATE, NUTRITION_TEMPLATE, } from '../playbook/templates.js';
3
+ const taskPrioritySchema = z.enum(['low', 'medium', 'high']);
4
+ const taskStatusSchema = z.enum(['open', 'done', 'canceled']);
5
+ export const coachProject = {
6
+ id: 'coach',
7
+ name: 'Executive Coach',
8
+ description: 'Tests abstract reasoning, low-action default behavior, and durable pattern capture.',
9
+ failureSurface: 'Should sound incisive without becoming robotic or prematurely operational.',
10
+ userIdentity: 'Alex, CEO',
11
+ timezone: 'America/Los_Angeles',
12
+ persona: COACH_TEMPLATE,
13
+ initialState() {
14
+ return {
15
+ memories: [
16
+ { id: 'mem-1', content: 'Responds well to direct pattern-naming when it is specific and earned.', category: 'coaching_approach' },
17
+ ],
18
+ threads: [
19
+ { id: 'thread-1', title: 'Roadmap prioritization', status: 'stuck', owner: 'VP Eng', description: 'Decision quality is soft and roadmap tradeoffs keep reopening.' },
20
+ { id: 'thread-2', title: 'Hiring plan', status: 'active', owner: 'VP Eng', description: 'Need a staffing plan that matches the real roadmap, not the aspirational one.' },
21
+ ],
22
+ forcingFunctions: [],
23
+ coachingNotes: [],
24
+ profile: { name: 'Alex', role: 'CEO', company: 'Acme' },
25
+ };
26
+ },
27
+ buildContext(state) {
28
+ return {
29
+ threads: state.threads,
30
+ forcingFunctions: state.forcingFunctions,
31
+ coachingNotes: state.coachingNotes,
32
+ profile: state.profile,
33
+ };
34
+ },
35
+ buildHandlers(state) {
36
+ return {};
37
+ },
38
+ buildCrudHandlers(state) {
39
+ return {
40
+ thread: async (action) => {
41
+ if (action.operation === 'update' && action.id) {
42
+ const thread = state.threads.find(item => item.id === action.id);
43
+ if (!thread)
44
+ return;
45
+ const params = action.params ?? {};
46
+ if (params.title != null)
47
+ thread.title = String(params.title);
48
+ if (params.status != null)
49
+ thread.status = String(params.status);
50
+ if (params.owner != null)
51
+ thread.owner = String(params.owner);
52
+ if (params.description != null)
53
+ thread.description = String(params.description);
54
+ }
55
+ },
56
+ forcingFunction: async (action) => {
57
+ const params = action.params ?? {};
58
+ if (action.operation === 'create') {
59
+ state.forcingFunctions.push({
60
+ id: action.id,
61
+ title: String(params.title),
62
+ owner: String(params.owner),
63
+ due: String(params.due),
64
+ status: String(params.status),
65
+ threadId: params.threadId != null ? String(params.threadId) : undefined,
66
+ });
67
+ }
68
+ else if (action.operation === 'update' && action.id) {
69
+ const ff = state.forcingFunctions.find(item => item.id === action.id);
70
+ if (!ff)
71
+ return;
72
+ if (params.title != null)
73
+ ff.title = String(params.title);
74
+ if (params.owner != null)
75
+ ff.owner = String(params.owner);
76
+ if (params.due != null)
77
+ ff.due = String(params.due);
78
+ if (params.status != null)
79
+ ff.status = String(params.status);
80
+ if (params.threadId != null)
81
+ ff.threadId = String(params.threadId);
82
+ }
83
+ else if (action.operation === 'delete' && action.id) {
84
+ const index = state.forcingFunctions.findIndex(item => item.id === action.id);
85
+ if (index !== -1)
86
+ state.forcingFunctions.splice(index, 1);
87
+ }
88
+ },
89
+ coachingNote: async (action) => {
90
+ const params = action.params ?? {};
91
+ if (action.operation === 'create') {
92
+ state.coachingNotes.push({
93
+ id: action.id,
94
+ type: String(params.type),
95
+ text: String(params.text),
96
+ });
97
+ }
98
+ else if (action.operation === 'update' && action.id) {
99
+ const note = state.coachingNotes.find(item => item.id === action.id);
100
+ if (!note)
101
+ return;
102
+ if (params.type != null)
103
+ note.type = String(params.type);
104
+ if (params.text != null)
105
+ note.text = String(params.text);
106
+ }
107
+ else if (action.operation === 'delete' && action.id) {
108
+ const index = state.coachingNotes.findIndex(item => item.id === action.id);
109
+ if (index !== -1)
110
+ state.coachingNotes.splice(index, 1);
111
+ }
112
+ },
113
+ };
114
+ },
115
+ summarizeState(state) {
116
+ return [
117
+ `threads=${state.threads.map(item => `${item.id}:${item.status}`).join(', ')}`,
118
+ `forcingFunctions=${state.forcingFunctions.map(item => `${item.id}:${item.status}`).join(', ') || '(none)'}`,
119
+ `notes=${state.coachingNotes.map(item => item.type).join(', ') || '(none)'}`,
120
+ `memories=${state.memories.length}`,
121
+ ].join(' | ');
122
+ },
123
+ };
124
+ export const nutritionProject = {
125
+ id: 'nutrition',
126
+ name: 'Nutrition Guide',
127
+ description: 'Tests invisible meal logging, update-vs-duplicate behavior, and soft emotional warmth.',
128
+ failureSurface: 'Should feel personal and fluid while doing precise ledger work behind the scenes.',
129
+ userIdentity: 'Alex',
130
+ timezone: 'America/Los_Angeles',
131
+ persona: NUTRITION_TEMPLATE,
132
+ initialState() {
133
+ return {
134
+ memories: [
135
+ { id: 'mem-1', content: 'Likes savory breakfasts more than sweet ones.', category: 'preference' },
136
+ ],
137
+ meals: [],
138
+ recentDays: [
139
+ 'Yesterday: 2200 cal, strong protein, dinner ran late.',
140
+ '2 days ago: skipped breakfast, over-corrected at night.',
141
+ ],
142
+ profile: { name: 'Alex', goal: 'lean out without losing muscle', targetProtein: '180g' },
143
+ };
144
+ },
145
+ buildContext(state) {
146
+ const mealLines = state.meals.length === 0
147
+ ? 'No meals logged yet today.'
148
+ : state.meals.map(item => `- (id:${item.id}) ${item.name}${item.calories != null ? `, ${item.calories} cal` : ''}`).join('\n');
149
+ return {
150
+ todayStatus: `Meals logged today:\n${mealLines}`,
151
+ recentDays: state.recentDays,
152
+ profile: state.profile,
153
+ };
154
+ },
155
+ buildHandlers(state) {
156
+ return {};
157
+ },
158
+ buildCrudHandlers(state) {
159
+ return {
160
+ meal: async (action) => {
161
+ const params = action.params ?? {};
162
+ if (action.operation === 'create') {
163
+ state.meals.push({
164
+ id: action.id,
165
+ name: String(params.name),
166
+ calories: typeof params.calories === 'number' ? params.calories : undefined,
167
+ protein: typeof params.protein === 'number' ? params.protein : undefined,
168
+ });
169
+ }
170
+ else if (action.operation === 'update' && action.id) {
171
+ const meal = state.meals.find(item => item.id === action.id);
172
+ if (!meal)
173
+ return;
174
+ if (params.name != null)
175
+ meal.name = String(params.name);
176
+ if (typeof params.calories === 'number')
177
+ meal.calories = params.calories;
178
+ if (typeof params.protein === 'number')
179
+ meal.protein = params.protein;
180
+ }
181
+ else if (action.operation === 'delete' && action.id) {
182
+ const index = state.meals.findIndex(item => item.id === action.id);
183
+ if (index !== -1)
184
+ state.meals.splice(index, 1);
185
+ }
186
+ },
187
+ };
188
+ },
189
+ summarizeState(state) {
190
+ return [
191
+ `meals=${state.meals.map(item => `${item.id}:${item.name}`).join(', ') || '(none)'}`,
192
+ `memories=${state.memories.length}`,
193
+ ].join(' | ');
194
+ },
195
+ };
196
+ export const fitnessProject = {
197
+ id: 'fitness',
198
+ name: 'Strength Coach',
199
+ description: 'Tests concrete structured output, training constraints, and silent persistence of relevant context.',
200
+ failureSurface: 'Should feel like a real coach, not a JSON-spewing workout machine.',
201
+ userIdentity: 'Alex',
202
+ timezone: 'America/Los_Angeles',
203
+ persona: FITNESS_TEMPLATE,
204
+ initialState() {
205
+ return {
206
+ memories: [],
207
+ injuries: ['Left shoulder gets cranky with deep barbell pressing'],
208
+ equipment: ['barbell', 'dumbbells', 'cables', 'pull-up bar'],
209
+ recentWorkouts: [
210
+ { id: 'rw-1', title: 'Upper Push', result: 'Bench stalled, incline DB felt strong' },
211
+ { id: 'rw-2', title: 'Lower Body', result: 'Squat moved well, hamstrings still sore' },
212
+ ],
213
+ generatedWorkouts: [],
214
+ profile: { name: 'Alex', focus: 'Strength with longevity' },
215
+ };
216
+ },
217
+ buildContext(state) {
218
+ return {
219
+ injuries: state.injuries,
220
+ equipment: state.equipment,
221
+ recentWorkouts: state.recentWorkouts,
222
+ profile: state.profile,
223
+ };
224
+ },
225
+ buildHandlers(state) {
226
+ return {};
227
+ },
228
+ buildCrudHandlers(state) {
229
+ return {
230
+ workout: async (action) => {
231
+ const params = action.params ?? {};
232
+ if (action.operation === 'create') {
233
+ state.generatedWorkouts.push({
234
+ id: action.id,
235
+ exercises: [],
236
+ warmup: params.warmup != null ? String(params.warmup) : undefined,
237
+ cooldown: params.cooldown != null ? String(params.cooldown) : undefined,
238
+ });
239
+ }
240
+ },
241
+ exercise: async (action) => {
242
+ const params = action.params ?? {};
243
+ if (action.operation === 'create') {
244
+ // Find workout by cross-referenced ID (resolved from temp by SDK)
245
+ const workoutId = String(params.workoutId ?? '');
246
+ const workout = state.generatedWorkouts.find(w => w.id === workoutId);
247
+ if (workout) {
248
+ workout.exercises.push({
249
+ name: String(params.name),
250
+ sets: Number(params.sets ?? params.plannedSets ?? 3),
251
+ reps: String(params.reps ?? params.plannedReps ?? '8'),
252
+ notes: params.notes != null ? String(params.notes) : undefined,
253
+ });
254
+ }
255
+ }
256
+ },
257
+ };
258
+ },
259
+ summarizeState(state) {
260
+ return [
261
+ `generated=${state.generatedWorkouts.length}`,
262
+ `injuries=${state.injuries.join('; ') || '(none)'}`,
263
+ `memories=${state.memories.length}`,
264
+ ].join(' | ');
265
+ },
266
+ };
267
+ export const languageTutorProject = {
268
+ id: 'language-tutor',
269
+ name: 'Language Tutor',
270
+ description: 'Tests high conversational fluency, adaptive correction, and compounding memory around learner patterns.',
271
+ failureSurface: 'Should sound natural and helpful, not like a grammar worksheet with a smile.',
272
+ userIdentity: 'Alex',
273
+ timezone: 'America/Los_Angeles',
274
+ persona: LANGUAGE_TUTOR_TEMPLATE,
275
+ initialState() {
276
+ return {
277
+ memories: [],
278
+ currentGoal: {
279
+ language: 'Spanish',
280
+ reason: 'Trip to Spain in 6 weeks',
281
+ correctionPreference: 'Correct me immediately when I drift into unnatural phrasing',
282
+ },
283
+ recentMistakes: [],
284
+ phrasebook: [
285
+ { text: 'Quiero una mesa para dos.', translation: 'I want a table for two.' },
286
+ ],
287
+ practiceQueue: [],
288
+ profile: { name: 'Alex', level: 'advanced beginner' },
289
+ };
290
+ },
291
+ buildContext(state) {
292
+ return {
293
+ currentGoal: state.currentGoal,
294
+ recentMistakes: state.recentMistakes,
295
+ phrasebook: state.phrasebook.map(item => `${item.text} — ${item.translation}`),
296
+ profile: state.profile,
297
+ };
298
+ },
299
+ buildHandlers(state) {
300
+ return {};
301
+ },
302
+ buildCrudHandlers(state) {
303
+ return {
304
+ mistake: async (action) => {
305
+ const params = action.params ?? {};
306
+ if (action.operation === 'create') {
307
+ state.recentMistakes.push({
308
+ id: action.id,
309
+ pattern: String(params.pattern),
310
+ correction: String(params.correction),
311
+ example: params.example != null ? String(params.example) : undefined,
312
+ });
313
+ }
314
+ else if (action.operation === 'update' && action.id) {
315
+ const mistake = state.recentMistakes.find(item => item.id === action.id);
316
+ if (!mistake)
317
+ return;
318
+ if (params.pattern != null)
319
+ mistake.pattern = String(params.pattern);
320
+ if (params.correction != null)
321
+ mistake.correction = String(params.correction);
322
+ if (params.example != null)
323
+ mistake.example = String(params.example);
324
+ }
325
+ else if (action.operation === 'delete' && action.id) {
326
+ const index = state.recentMistakes.findIndex(item => item.id === action.id);
327
+ if (index !== -1)
328
+ state.recentMistakes.splice(index, 1);
329
+ }
330
+ },
331
+ practice: async (action) => {
332
+ const params = action.params ?? {};
333
+ if (action.operation === 'create') {
334
+ state.practiceQueue.push({
335
+ id: action.id,
336
+ title: String(params.title),
337
+ focus: String(params.focus),
338
+ prompt: String(params.prompt),
339
+ durationMin: typeof params.durationMin === 'number' ? params.durationMin : undefined,
340
+ });
341
+ }
342
+ else if (action.operation === 'update' && action.id) {
343
+ const practice = state.practiceQueue.find(item => item.id === action.id);
344
+ if (!practice)
345
+ return;
346
+ if (params.title != null)
347
+ practice.title = String(params.title);
348
+ if (params.focus != null)
349
+ practice.focus = String(params.focus);
350
+ if (params.prompt != null)
351
+ practice.prompt = String(params.prompt);
352
+ if (typeof params.durationMin === 'number')
353
+ practice.durationMin = params.durationMin;
354
+ }
355
+ else if (action.operation === 'delete' && action.id) {
356
+ const index = state.practiceQueue.findIndex(item => item.id === action.id);
357
+ if (index !== -1)
358
+ state.practiceQueue.splice(index, 1);
359
+ }
360
+ },
361
+ };
362
+ },
363
+ summarizeState(state) {
364
+ return [
365
+ `mistakes=${state.recentMistakes.map(item => item.pattern).join(', ') || '(none)'}`,
366
+ `practice=${state.practiceQueue.map(item => item.title).join(', ') || '(none)'}`,
367
+ `memories=${state.memories.length}`,
368
+ ].join(' | ');
369
+ },
370
+ };
371
+ export const chiefOfStaffProject = {
372
+ id: 'chief-of-staff',
373
+ name: 'Chief Of Staff',
374
+ description: 'Tests utilitarian CRUD, preference memory, and operational crispness without sounding bureaucratic.',
375
+ failureSurface: 'Should quietly reduce load and maintain a clean system rather than narrating tools.',
376
+ userIdentity: 'Alex',
377
+ timezone: 'America/Los_Angeles',
378
+ persona: CHIEF_OF_STAFF_TEMPLATE,
379
+ initialState() {
380
+ return {
381
+ memories: [],
382
+ openTasks: [
383
+ {
384
+ id: 'task-1',
385
+ title: 'Draft investor update',
386
+ owner: 'Alex',
387
+ due: '2026-03-21',
388
+ priority: 'high',
389
+ status: 'open',
390
+ notes: 'Keep it tight and numbers-first.',
391
+ definitionOfDone: 'A sendable draft exists with topline metrics up front.',
392
+ },
393
+ ],
394
+ constraints: ['Deep work blocks are protected from 09:00-11:00.', 'Avoid Friday afternoon follow-ups if Thursday works.'],
395
+ profile: { name: 'Alex', role: 'CEO' },
396
+ };
397
+ },
398
+ buildContext(state) {
399
+ return {
400
+ openTasks: state.openTasks,
401
+ constraints: state.constraints,
402
+ profile: state.profile,
403
+ };
404
+ },
405
+ buildHandlers(state) {
406
+ return {};
407
+ },
408
+ buildCrudHandlers(state) {
409
+ return {
410
+ task: async (action) => {
411
+ const params = action.params ?? {};
412
+ if (action.operation === 'create') {
413
+ state.openTasks.push({
414
+ id: action.id,
415
+ title: String(params.title),
416
+ owner: params.owner != null ? String(params.owner) : undefined,
417
+ due: params.due != null ? String(params.due) : undefined,
418
+ notes: params.notes != null ? String(params.notes) : undefined,
419
+ definitionOfDone: params.definitionOfDone != null ? String(params.definitionOfDone) : undefined,
420
+ priority: params.priority != null ? taskPrioritySchema.parse(params.priority) : undefined,
421
+ status: params.status != null ? taskStatusSchema.parse(params.status) : 'open',
422
+ });
423
+ }
424
+ else if (action.operation === 'update' && action.id) {
425
+ const task = state.openTasks.find(item => item.id === action.id);
426
+ if (!task)
427
+ return;
428
+ if (params.title != null)
429
+ task.title = String(params.title);
430
+ if (params.owner != null)
431
+ task.owner = String(params.owner);
432
+ if (params.due != null)
433
+ task.due = String(params.due);
434
+ if (params.notes != null)
435
+ task.notes = String(params.notes);
436
+ if (params.definitionOfDone != null)
437
+ task.definitionOfDone = String(params.definitionOfDone);
438
+ if (params.priority != null)
439
+ task.priority = taskPrioritySchema.parse(params.priority);
440
+ if (params.status != null)
441
+ task.status = taskStatusSchema.parse(params.status);
442
+ }
443
+ else if (action.operation === 'delete' && action.id) {
444
+ const index = state.openTasks.findIndex(item => item.id === action.id);
445
+ if (index !== -1)
446
+ state.openTasks.splice(index, 1);
447
+ }
448
+ },
449
+ };
450
+ },
451
+ summarizeState(state) {
452
+ return [
453
+ `tasks=${state.openTasks.map(item => {
454
+ const owner = item.owner ?? '-';
455
+ const due = item.due ?? '-';
456
+ const priority = item.priority ?? '-';
457
+ return `${item.id}:${item.status}:${item.title}:owner=${owner}:due=${due}:priority=${priority}`;
458
+ }).join(', ') || '(none)'}`,
459
+ `memories=${state.memories.length}`,
460
+ ].join(' | ');
461
+ },
462
+ };
463
+ const savorFoodItemSchema = z.object({
464
+ name: z.string(),
465
+ quantity: z.string(),
466
+ calories: z.number(),
467
+ proteinG: z.number(),
468
+ carbsG: z.number(),
469
+ fatG: z.number(),
470
+ });
471
+ /**
472
+ * Savor methodology — rewritten to follow scenario-first pattern (coach template model).
473
+ * Describes the world and what the expert notices, not what to do.
474
+ */
475
+ const SAVOR_METHODOLOGY = `The world you operate in:
476
+ - The daily ledger and recent days are this person's food diary — the clinical record a nutritionist reviews before every session. The memories are relationship history built over weeks of coaching together.
477
+ - A cut is math over weeks. The plan that sticks beats the plan that's perfect.
478
+ - The pre-calculated totals in the ledger are computed from the actual logged items. They are ground truth.
479
+ - Physical and mental health are both your concern.
480
+
481
+ What you notice:
482
+ - Established patterns in what they actually eat — these are data, not defaults to replace
483
+ - Where the macro math is working and where it's drifting across days
484
+ - The difference between a client who needs a creative idea and one who already has a working routine
485
+ - When the data tells a story the client hasn't articulated yet`;
486
+ const SAVOR_ACTION_PROTOCOL = `ACTION PROTOCOL:
487
+ - When negotiating a meal, create it as a draft (status: "draft") via the crud action. When the user confirms eating (past tense), create with status "confirmed" or update the draft's status to "confirmed". Each dish/occasion is a separate entry.
488
+ - When correcting a logged meal, update it with its id via the crud action — don't create a duplicate. Delete meals that are errors.
489
+ - Weight: if given in kg, convert to lbs (×2.205).
490
+ - Profile settings (goal, tone, coaching style) use updateProfile — these aren't memories.`;
491
+ export const savorProject = {
492
+ id: 'savor',
493
+ name: 'Savor Nutrition Coach',
494
+ description: 'Tests a production nutrition coach with full client history — should feel like a nutritionist who knows this specific person, not an encyclopedia.',
495
+ failureSurface: 'Should ground advice in the client\'s actual data and established routines, not lecture generically. Should lead as the expert, not wait to be coached.',
496
+ userIdentity: 'Alex',
497
+ timezone: 'America/New_York',
498
+ persona: {
499
+ identity: {
500
+ name: 'Savor',
501
+ expertise: ['nutrition', 'cooking', 'food psychology'],
502
+ relationship: 'a trusted companion who guides Alex toward health, wellbeing, and longevity',
503
+ northStar: "Alex's long-term health: help them reach their goals, and when a goal seems misguided, gently nudge toward a healthier one — respect informed choices. An aggressive plan they commit to beats a perfect plan they abandon",
504
+ keystone: 'What is the single most impactful thing you could say or offer right now? Sometimes that\'s a creative meal idea, sometimes it\'s noticing a pattern, sometimes it\'s a gentle challenge, sometimes it\'s just warmth. Lead with that.',
505
+ },
506
+ voice: {
507
+ tone: 'warm',
508
+ style: 'educator',
509
+ medium: 'mobile-chat',
510
+ formatting: 'Your responses are rendered as markdown. You can use **bold**, *italic*, bullet lists, emojis, and <span style="color:#hex">colored text</span> when it helps.\nThink of formatting as seasoning — use it to make responses feel warm, alive, and easy to scan, like a message from a knowledgeable friend. Don\'t overdo it.',
511
+ },
512
+ methodology: SAVOR_METHODOLOGY + '\n\n' + SAVOR_ACTION_PROTOCOL,
513
+ entities: {
514
+ meal: {
515
+ schema: z.object({
516
+ description: z.string(),
517
+ time: z.string().describe('HH:MM (24h) when the meal was eaten'),
518
+ items: z.array(savorFoodItemSchema),
519
+ status: z.enum(['draft', 'confirmed']).optional().describe('Draft meals are being negotiated. Confirmed meals are logged.'),
520
+ }),
521
+ label: 'Meal',
522
+ displayField: 'description',
523
+ },
524
+ },
525
+ actions: {},
526
+ contextInputs: {
527
+ profile: { label: 'ABOUT Alex', format: 'block' },
528
+ todayStatus: { label: "TODAY'S STATUS", format: 'block' },
529
+ recentDays: { label: 'RECENT DAYS (notice patterns, give better advice. Never re-log these.)', format: 'block' },
530
+ },
531
+ eq: { frequencyRule: true, qualitativeFirst: true, coherence: true, expertJudgment: true },
532
+ memory: { enabled: true, includeIds: true, budget: 5000, categories: {
533
+ preference: 'Dietary preferences, food likes, cooking habits',
534
+ aversion: 'Foods they dislike, allergies, dietary restrictions',
535
+ routine: 'Eating patterns, meal timing, typical meals',
536
+ health: 'Health conditions, body composition goals, energy patterns',
537
+ motivation: 'What drives their food choices, relationship with food',
538
+ } },
539
+ craftMemory: { enabled: true, budget: 3000, categories: {
540
+ approach: 'What works when coaching nutrition',
541
+ pattern: 'Recurring patterns in how users relate to food',
542
+ timing: 'When and how to surface insights or suggest meals',
543
+ insight: 'Cross-user observations that sharpen guidance',
544
+ }, purpose: 'Professional growth observations about being a better nutrition coach.' },
545
+ diagnostics: { enabled: true },
546
+ staging: { model: 'working-set' },
547
+ followUpsDescription: 'Suggest what the user might naturally want to say or ask next. These appear as tappable bubbles in a mobile chat interface.',
548
+ },
549
+ initialState() {
550
+ return {
551
+ memories: [
552
+ { id: 'mem-1', content: 'Standard breakfast: 60g smoked salmon, 1 egg + egg whites, broccoli, low-fat cottage cheese, tomato slices', category: 'routine' },
553
+ { id: 'mem-2', content: 'Daily targets: 1900 cal, 160g protein, 170g carbs, 55g fat — on a cut to 78kg', category: 'health' },
554
+ { id: 'mem-3', content: 'Usually rides Peloton Zone 2 around 6-7pm, has tea with collagen and creatine 30 min before', category: 'routine' },
555
+ { id: 'mem-4', content: 'Interested in longevity nutrition — cruciferous vegetables, omega-3s, fermented foods, 30+ plants/week', category: 'preference' },
556
+ { id: 'mem-5', content: 'Has low-fat cottage cheese, eggs, smoked salmon, broccoli, avocado, tomatoes in fridge', category: 'routine' },
557
+ { id: 'mem-6', content: 'Evening routine: a small handful of almonds before bed for magnesium and sleep', category: 'routine' },
558
+ ],
559
+ meals: [],
560
+ todayConsumed: { calories: 0, proteinG: 0, carbsG: 0, fatG: 0 },
561
+ };
562
+ },
563
+ buildContext(state) {
564
+ const remaining = {
565
+ cal: 1900 - state.todayConsumed.calories,
566
+ protein: 160 - state.todayConsumed.proteinG,
567
+ carbs: 170 - state.todayConsumed.carbsG,
568
+ fat: 55 - state.todayConsumed.fatG,
569
+ };
570
+ const mealLines = state.meals.length === 0
571
+ ? '\nNo meals logged today yet.'
572
+ : '\nMeals so far today:\n' + state.meals.map(m => `- (id:${m.id}) ${m.description}`).join('\n');
573
+ return {
574
+ profile: `- Age: 41, Sex: male\n- Weight: 176.4 lbs, Height: 70 inches\n- Activity level: active\n- Goal: Lose weight\n- Journey context: Cutting to 78kg, last few KG. Zone 2 cardio + strength training.\n- Daily targets: 1900 cal, 160g protein, 170g carbs, 55g fat`,
575
+ todayStatus: `2026-04-01, current time: 07:30\n- Consumed: ${state.todayConsumed.calories} cal, ${state.todayConsumed.proteinG}g protein, ${state.todayConsumed.carbsG}g carbs, ${state.todayConsumed.fatG}g fat\n- Remaining: ~${remaining.cal} cal, ~${remaining.protein}g protein, ~${remaining.carbs}g carbs, ~${remaining.fat}g fat\n- Weight: 176.4 lbs${mealLines}`,
576
+ recentDays: `- 2026-03-31 (yesterday): 176 lbs | 1687 cal, 159g P, 140g C, 55g F | Salmon & Eggs Breakfast (salmon, eggs, cottage cheese, broccoli, tomato), Mexican Bowl lunch, Chocolate Yogurt Bowl dinner\n- 2026-03-30 (2 days ago): 176.8 lbs | 1750 cal, 162g P, 150g C, 49g F | Salmon & Eggs Breakfast, Grilled salmon with broccoli lunch, Yogurt + whey dinner\n- 2026-03-29 (3 days ago): 177.5 lbs | 1820 cal, 155g P, 165g C, 52g F | Salmon & Eggs Breakfast, Chicken salad lunch, Salmon + sweet potato dinner`,
577
+ };
578
+ },
579
+ buildHandlers(state) {
580
+ return {};
581
+ },
582
+ buildCrudHandlers(state) {
583
+ return {
584
+ meal: async (action) => {
585
+ const params = typeof action.params === 'string' ? JSON.parse(action.params) : action.params ?? {};
586
+ if (action.operation === 'create') {
587
+ const items = params.items ?? [];
588
+ const cal = items.reduce((s, i) => s + (i.calories || 0), 0);
589
+ const prot = items.reduce((s, i) => s + (i.proteinG || 0), 0);
590
+ const carbs = items.reduce((s, i) => s + (i.carbsG || 0), 0);
591
+ const fat = items.reduce((s, i) => s + (i.fatG || 0), 0);
592
+ state.meals.push({
593
+ id: action.id,
594
+ description: String(params.description ?? ''),
595
+ calories: cal, proteinG: prot, carbsG: carbs, fatG: fat,
596
+ });
597
+ if (params.status !== 'draft') {
598
+ state.todayConsumed.calories += cal;
599
+ state.todayConsumed.proteinG += prot;
600
+ state.todayConsumed.carbsG += carbs;
601
+ state.todayConsumed.fatG += fat;
602
+ }
603
+ }
604
+ else if (action.operation === 'update' && action.id) {
605
+ const meal = state.meals.find(m => m.id === action.id);
606
+ if (!meal)
607
+ return;
608
+ if (params.description != null)
609
+ meal.description = String(params.description);
610
+ if (params.status === 'confirmed') {
611
+ state.todayConsumed.calories += meal.calories;
612
+ state.todayConsumed.proteinG += meal.proteinG;
613
+ state.todayConsumed.carbsG += meal.carbsG;
614
+ state.todayConsumed.fatG += meal.fatG;
615
+ }
616
+ }
617
+ else if (action.operation === 'delete' && action.id) {
618
+ const idx = state.meals.findIndex(m => m.id === action.id);
619
+ if (idx !== -1) {
620
+ const removed = state.meals.splice(idx, 1)[0];
621
+ state.todayConsumed.calories -= removed.calories;
622
+ state.todayConsumed.proteinG -= removed.proteinG;
623
+ }
624
+ }
625
+ },
626
+ };
627
+ },
628
+ summarizeState(state) {
629
+ return [
630
+ `meals=${state.meals.map(m => `${m.id}:${m.description}`).join(', ') || '(none)'}`,
631
+ `consumed=${state.todayConsumed.calories}cal/${state.todayConsumed.proteinG}gP`,
632
+ `memories=${state.memories.length}`,
633
+ ].join(' | ');
634
+ },
635
+ };
636
+ export const SAMPLE_PROJECTS = [
637
+ coachProject,
638
+ nutritionProject,
639
+ fitnessProject,
640
+ languageTutorProject,
641
+ chiefOfStaffProject,
642
+ savorProject,
643
+ ];
644
+ //# sourceMappingURL=sample-projects.js.map