@jaimevalasek/aioson 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/CHANGELOG.md +456 -0
  2. package/CODE_OF_CONDUCT.md +12 -0
  3. package/CONTRIBUTING.md +13 -0
  4. package/LICENSE +21 -0
  5. package/README.md +254 -0
  6. package/bin/aioson.js +4 -0
  7. package/docs/en/cli-reference.md +398 -0
  8. package/docs/en/i18n.md +52 -0
  9. package/docs/en/json-schemas.md +41 -0
  10. package/docs/en/mcp.md +56 -0
  11. package/docs/en/parallel.md +82 -0
  12. package/docs/en/qa-browser.md +339 -0
  13. package/docs/en/release-flow.md +22 -0
  14. package/docs/en/release-notes-template.md +41 -0
  15. package/docs/en/release.md +28 -0
  16. package/docs/en/schemas/agent-prompt.schema.json +17 -0
  17. package/docs/en/schemas/agents.schema.json +32 -0
  18. package/docs/en/schemas/context-validate.schema.json +36 -0
  19. package/docs/en/schemas/doctor.schema.json +89 -0
  20. package/docs/en/schemas/error.schema.json +24 -0
  21. package/docs/en/schemas/i18n-add.schema.json +15 -0
  22. package/docs/en/schemas/index.json +116 -0
  23. package/docs/en/schemas/info.schema.json +39 -0
  24. package/docs/en/schemas/init.schema.json +48 -0
  25. package/docs/en/schemas/install.schema.json +60 -0
  26. package/docs/en/schemas/locale-apply.schema.json +30 -0
  27. package/docs/en/schemas/mcp-doctor.schema.json +95 -0
  28. package/docs/en/schemas/mcp-init.schema.json +122 -0
  29. package/docs/en/schemas/package-test.schema.json +24 -0
  30. package/docs/en/schemas/parallel-assign.schema.json +57 -0
  31. package/docs/en/schemas/parallel-doctor.schema.json +86 -0
  32. package/docs/en/schemas/parallel-init.schema.json +53 -0
  33. package/docs/en/schemas/parallel-status.schema.json +94 -0
  34. package/docs/en/schemas/setup-context.schema.json +39 -0
  35. package/docs/en/schemas/smoke.schema.json +23 -0
  36. package/docs/en/schemas/update.schema.json +48 -0
  37. package/docs/en/schemas/workflow-plan.schema.json +30 -0
  38. package/docs/en/web3.md +54 -0
  39. package/docs/pt/README.md +46 -0
  40. package/docs/pt/advisor-spec.md +335 -0
  41. package/docs/pt/agentes.md +453 -0
  42. package/docs/pt/cenarios.md +1230 -0
  43. package/docs/pt/clientes-ai.md +224 -0
  44. package/docs/pt/comandos-cli.md +511 -0
  45. package/docs/pt/genome-3.0-spec.md +296 -0
  46. package/docs/pt/guia-engineer.md +226 -0
  47. package/docs/pt/inicio-rapido.md +138 -0
  48. package/docs/pt/profiler-system.md +214 -0
  49. package/docs/pt/runtime-observability.md +72 -0
  50. package/docs/pt/squad-genoma.md +777 -0
  51. package/docs/pt/web3.md +797 -0
  52. package/docs/testing/genome-2.0-manual-regression.md +23 -0
  53. package/docs/testing/genome-2.0-matrix.md +36 -0
  54. package/docs/testing/genome-2.0-rollout.md +184 -0
  55. package/package.json +50 -0
  56. package/src/agents.js +56 -0
  57. package/src/cli.js +497 -0
  58. package/src/commands/agents.js +142 -0
  59. package/src/commands/cloud.js +1767 -0
  60. package/src/commands/config.js +90 -0
  61. package/src/commands/context-validate.js +91 -0
  62. package/src/commands/doctor.js +123 -0
  63. package/src/commands/genome-doctor.js +41 -0
  64. package/src/commands/genome-migrate.js +49 -0
  65. package/src/commands/i18n-add.js +56 -0
  66. package/src/commands/info.js +41 -0
  67. package/src/commands/init.js +75 -0
  68. package/src/commands/install.js +68 -0
  69. package/src/commands/locale-apply.js +51 -0
  70. package/src/commands/locale-diff.js +126 -0
  71. package/src/commands/mcp-doctor.js +406 -0
  72. package/src/commands/mcp-init.js +379 -0
  73. package/src/commands/package-e2e.js +273 -0
  74. package/src/commands/parallel-assign.js +403 -0
  75. package/src/commands/parallel-doctor.js +437 -0
  76. package/src/commands/parallel-init.js +249 -0
  77. package/src/commands/parallel-status.js +290 -0
  78. package/src/commands/qa-doctor.js +185 -0
  79. package/src/commands/qa-init.js +161 -0
  80. package/src/commands/qa-report.js +58 -0
  81. package/src/commands/qa-run.js +873 -0
  82. package/src/commands/qa-scan.js +337 -0
  83. package/src/commands/runtime.js +948 -0
  84. package/src/commands/scan-project.js +1107 -0
  85. package/src/commands/setup-context.js +650 -0
  86. package/src/commands/smoke.js +426 -0
  87. package/src/commands/squad-doctor.js +358 -0
  88. package/src/commands/squad-export.js +46 -0
  89. package/src/commands/squad-pipeline.js +97 -0
  90. package/src/commands/squad-repair-genomes.js +39 -0
  91. package/src/commands/squad-status.js +424 -0
  92. package/src/commands/squad-validate.js +230 -0
  93. package/src/commands/test-agents.js +194 -0
  94. package/src/commands/update.js +55 -0
  95. package/src/commands/workflow-next.js +594 -0
  96. package/src/commands/workflow-plan.js +108 -0
  97. package/src/constants.js +314 -0
  98. package/src/context-parse-reason.js +22 -0
  99. package/src/context-writer.js +150 -0
  100. package/src/context.js +217 -0
  101. package/src/detector.js +261 -0
  102. package/src/doctor.js +289 -0
  103. package/src/execution-gateway.js +461 -0
  104. package/src/genome-files.js +198 -0
  105. package/src/genome-format.js +442 -0
  106. package/src/genome-schema.js +215 -0
  107. package/src/genomes/bindings.js +281 -0
  108. package/src/genomes.js +467 -0
  109. package/src/i18n/index.js +103 -0
  110. package/src/i18n/messages/en.js +784 -0
  111. package/src/i18n/messages/es.js +718 -0
  112. package/src/i18n/messages/fr.js +725 -0
  113. package/src/i18n/messages/pt-BR.js +818 -0
  114. package/src/i18n/scaffold.js +64 -0
  115. package/src/installer.js +232 -0
  116. package/src/lib/genomes/compat.js +206 -0
  117. package/src/lib/genomes/migrate.js +90 -0
  118. package/src/lib/squads/genome-repair.js +49 -0
  119. package/src/locales.js +84 -0
  120. package/src/onboarding.js +305 -0
  121. package/src/parser.js +53 -0
  122. package/src/prompt-tool.js +20 -0
  123. package/src/qa-html-report.js +472 -0
  124. package/src/runtime-store.js +1527 -0
  125. package/src/squads/apply-genome.js +21 -0
  126. package/src/squads/genome-binding-service.js +154 -0
  127. package/src/updater.js +32 -0
  128. package/src/utils.js +46 -0
  129. package/src/version.js +50 -0
  130. package/template/.aioson/advisors/.gitkeep +1 -0
  131. package/template/.aioson/agents/analyst.md +225 -0
  132. package/template/.aioson/agents/architect.md +221 -0
  133. package/template/.aioson/agents/dev.md +201 -0
  134. package/template/.aioson/agents/discovery-design-doc.md +196 -0
  135. package/template/.aioson/agents/genoma.md +300 -0
  136. package/template/.aioson/agents/orchestrator.md +107 -0
  137. package/template/.aioson/agents/pm.md +89 -0
  138. package/template/.aioson/agents/product.md +361 -0
  139. package/template/.aioson/agents/profiler-enricher.md +266 -0
  140. package/template/.aioson/agents/profiler-forge.md +188 -0
  141. package/template/.aioson/agents/profiler-researcher.md +245 -0
  142. package/template/.aioson/agents/qa.md +344 -0
  143. package/template/.aioson/agents/setup.md +381 -0
  144. package/template/.aioson/agents/squad.md +837 -0
  145. package/template/.aioson/agents/ux-ui.md +416 -0
  146. package/template/.aioson/config.md +56 -0
  147. package/template/.aioson/context/.gitkeep +0 -0
  148. package/template/.aioson/context/parallel/.gitkeep +0 -0
  149. package/template/.aioson/context/spec.md.template +37 -0
  150. package/template/.aioson/genomas/.gitkeep +0 -0
  151. package/template/.aioson/locales/en/agents/analyst.md +214 -0
  152. package/template/.aioson/locales/en/agents/architect.md +210 -0
  153. package/template/.aioson/locales/en/agents/dev.md +187 -0
  154. package/template/.aioson/locales/en/agents/discovery-design-doc.md +27 -0
  155. package/template/.aioson/locales/en/agents/genoma.md +212 -0
  156. package/template/.aioson/locales/en/agents/orchestrator.md +105 -0
  157. package/template/.aioson/locales/en/agents/pm.md +77 -0
  158. package/template/.aioson/locales/en/agents/product.md +310 -0
  159. package/template/.aioson/locales/en/agents/profiler-enricher.md +5 -0
  160. package/template/.aioson/locales/en/agents/profiler-forge.md +5 -0
  161. package/template/.aioson/locales/en/agents/profiler-researcher.md +5 -0
  162. package/template/.aioson/locales/en/agents/qa.md +214 -0
  163. package/template/.aioson/locales/en/agents/setup.md +342 -0
  164. package/template/.aioson/locales/en/agents/squad.md +247 -0
  165. package/template/.aioson/locales/en/agents/ux-ui.md +320 -0
  166. package/template/.aioson/locales/es/agents/analyst.md +203 -0
  167. package/template/.aioson/locales/es/agents/architect.md +208 -0
  168. package/template/.aioson/locales/es/agents/dev.md +183 -0
  169. package/template/.aioson/locales/es/agents/discovery-design-doc.md +19 -0
  170. package/template/.aioson/locales/es/agents/genoma.md +102 -0
  171. package/template/.aioson/locales/es/agents/orchestrator.md +108 -0
  172. package/template/.aioson/locales/es/agents/pm.md +81 -0
  173. package/template/.aioson/locales/es/agents/product.md +310 -0
  174. package/template/.aioson/locales/es/agents/profiler-enricher.md +5 -0
  175. package/template/.aioson/locales/es/agents/profiler-forge.md +5 -0
  176. package/template/.aioson/locales/es/agents/profiler-researcher.md +5 -0
  177. package/template/.aioson/locales/es/agents/qa.md +163 -0
  178. package/template/.aioson/locales/es/agents/setup.md +347 -0
  179. package/template/.aioson/locales/es/agents/squad.md +247 -0
  180. package/template/.aioson/locales/es/agents/ux-ui.md +201 -0
  181. package/template/.aioson/locales/fr/agents/analyst.md +203 -0
  182. package/template/.aioson/locales/fr/agents/architect.md +208 -0
  183. package/template/.aioson/locales/fr/agents/dev.md +183 -0
  184. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +19 -0
  185. package/template/.aioson/locales/fr/agents/genoma.md +102 -0
  186. package/template/.aioson/locales/fr/agents/orchestrator.md +108 -0
  187. package/template/.aioson/locales/fr/agents/pm.md +81 -0
  188. package/template/.aioson/locales/fr/agents/product.md +310 -0
  189. package/template/.aioson/locales/fr/agents/profiler-enricher.md +5 -0
  190. package/template/.aioson/locales/fr/agents/profiler-forge.md +5 -0
  191. package/template/.aioson/locales/fr/agents/profiler-researcher.md +5 -0
  192. package/template/.aioson/locales/fr/agents/qa.md +163 -0
  193. package/template/.aioson/locales/fr/agents/setup.md +347 -0
  194. package/template/.aioson/locales/fr/agents/squad.md +247 -0
  195. package/template/.aioson/locales/fr/agents/ux-ui.md +201 -0
  196. package/template/.aioson/locales/pt-BR/agents/analyst.md +217 -0
  197. package/template/.aioson/locales/pt-BR/agents/architect.md +213 -0
  198. package/template/.aioson/locales/pt-BR/agents/dev.md +198 -0
  199. package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +198 -0
  200. package/template/.aioson/locales/pt-BR/agents/genoma.md +297 -0
  201. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +108 -0
  202. package/template/.aioson/locales/pt-BR/agents/pm.md +81 -0
  203. package/template/.aioson/locales/pt-BR/agents/product.md +316 -0
  204. package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +5 -0
  205. package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +5 -0
  206. package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +5 -0
  207. package/template/.aioson/locales/pt-BR/agents/qa.md +217 -0
  208. package/template/.aioson/locales/pt-BR/agents/setup.md +371 -0
  209. package/template/.aioson/locales/pt-BR/agents/squad.md +772 -0
  210. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +322 -0
  211. package/template/.aioson/mcp/servers.md +24 -0
  212. package/template/.aioson/profiler-reports/.gitkeep +1 -0
  213. package/template/.aioson/schemas/content-blueprint.schema.json +30 -0
  214. package/template/.aioson/schemas/genome-meta.schema.json +150 -0
  215. package/template/.aioson/schemas/genome.schema.json +115 -0
  216. package/template/.aioson/schemas/readiness.schema.json +27 -0
  217. package/template/.aioson/schemas/squad-blueprint.schema.json +172 -0
  218. package/template/.aioson/schemas/squad-manifest.schema.json +276 -0
  219. package/template/.aioson/skills/dynamic/README.md +30 -0
  220. package/template/.aioson/skills/dynamic/cardano-docs.md +16 -0
  221. package/template/.aioson/skills/dynamic/ethereum-docs.md +17 -0
  222. package/template/.aioson/skills/dynamic/flux-ui-docs.md +13 -0
  223. package/template/.aioson/skills/dynamic/laravel-docs.md +41 -0
  224. package/template/.aioson/skills/dynamic/npm-packages.md +16 -0
  225. package/template/.aioson/skills/dynamic/solana-docs.md +16 -0
  226. package/template/.aioson/skills/references/premium-command-center-ui/master-application-prompt.md +79 -0
  227. package/template/.aioson/skills/references/premium-command-center-ui/operational-ux-playbook.md +253 -0
  228. package/template/.aioson/skills/references/premium-command-center-ui/quality-validation-checklist.md +82 -0
  229. package/template/.aioson/skills/references/premium-command-center-ui/visual-system-and-component-patterns.md +270 -0
  230. package/template/.aioson/skills/static/django-patterns.md +342 -0
  231. package/template/.aioson/skills/static/fastapi-patterns.md +344 -0
  232. package/template/.aioson/skills/static/filament-patterns.md +267 -0
  233. package/template/.aioson/skills/static/flux-ui-components.md +262 -0
  234. package/template/.aioson/skills/static/git-conventions.md +227 -0
  235. package/template/.aioson/skills/static/interface-design.md +372 -0
  236. package/template/.aioson/skills/static/jetstream-setup.md +200 -0
  237. package/template/.aioson/skills/static/laravel-conventions.md +491 -0
  238. package/template/.aioson/skills/static/nextjs-patterns.md +321 -0
  239. package/template/.aioson/skills/static/node-express-patterns.md +317 -0
  240. package/template/.aioson/skills/static/node-typescript-patterns.md +282 -0
  241. package/template/.aioson/skills/static/premium-command-center-ui.md +190 -0
  242. package/template/.aioson/skills/static/rails-conventions.md +307 -0
  243. package/template/.aioson/skills/static/react-motion-patterns.md +577 -0
  244. package/template/.aioson/skills/static/static-html-patterns.md +1935 -0
  245. package/template/.aioson/skills/static/tall-stack-patterns.md +286 -0
  246. package/template/.aioson/skills/static/ui-ux-modern.md +75 -0
  247. package/template/.aioson/skills/static/web3-cardano-patterns.md +337 -0
  248. package/template/.aioson/skills/static/web3-ethereum-patterns.md +310 -0
  249. package/template/.aioson/skills/static/web3-security-checklist.md +284 -0
  250. package/template/.aioson/skills/static/web3-solana-patterns.md +324 -0
  251. package/template/.aioson/squads/.artisan/.gitkeep +0 -0
  252. package/template/.aioson/squads/.gitkeep +0 -0
  253. package/template/.aioson/squads/memory.md +5 -0
  254. package/template/.aioson/tasks/squad-analyze.md +83 -0
  255. package/template/.aioson/tasks/squad-create.md +99 -0
  256. package/template/.aioson/tasks/squad-design.md +100 -0
  257. package/template/.aioson/tasks/squad-export.md +20 -0
  258. package/template/.aioson/tasks/squad-extend.md +68 -0
  259. package/template/.aioson/tasks/squad-pipeline.md +122 -0
  260. package/template/.aioson/tasks/squad-repair.md +85 -0
  261. package/template/.aioson/tasks/squad-validate.md +58 -0
  262. package/template/.aioson/templates/squads/content-basic/template.json +21 -0
  263. package/template/.aioson/templates/squads/media-channel/template.json +24 -0
  264. package/template/.aioson/templates/squads/research-analysis/template.json +22 -0
  265. package/template/.aioson/templates/squads/software-delivery/template.json +21 -0
  266. package/template/.claude/commands/aioson/analyst.md +5 -0
  267. package/template/.claude/commands/aioson/architect.md +5 -0
  268. package/template/.claude/commands/aioson/dev.md +5 -0
  269. package/template/.claude/commands/aioson/orchestrator.md +5 -0
  270. package/template/.claude/commands/aioson/pm.md +5 -0
  271. package/template/.claude/commands/aioson/qa.md +5 -0
  272. package/template/.claude/commands/aioson/setup.md +5 -0
  273. package/template/.claude/commands/aioson/ux-ui.md +5 -0
  274. package/template/.gemini/GEMINI.md +10 -0
  275. package/template/.gemini/commands/aios-analyst.toml +4 -0
  276. package/template/.gemini/commands/aios-architect.toml +7 -0
  277. package/template/.gemini/commands/aios-dev.toml +8 -0
  278. package/template/.gemini/commands/aios-discovery-design-doc.toml +4 -0
  279. package/template/.gemini/commands/aios-orchestrator.toml +8 -0
  280. package/template/.gemini/commands/aios-pm.toml +8 -0
  281. package/template/.gemini/commands/aios-product.toml +4 -0
  282. package/template/.gemini/commands/aios-qa.toml +6 -0
  283. package/template/.gemini/commands/aios-setup.toml +3 -0
  284. package/template/.gemini/commands/aios-ux-ui.toml +8 -0
  285. package/template/AGENTS.md +67 -0
  286. package/template/CLAUDE.md +31 -0
  287. package/template/OPENCODE.md +24 -0
  288. package/template/aioson-models.json +40 -0
package/src/genomes.js ADDED
@@ -0,0 +1,467 @@
1
+ 'use strict';
2
+
3
+ const GENOME_TYPES = ['domain', 'function', 'persona', 'hybrid'];
4
+ const GENOME_DEPTHS = ['surface', 'standard', 'deep'];
5
+ const GENOME_EVIDENCE_MODES = ['inferred', 'evidenced', 'hybrid'];
6
+ const GENOME_FORMATS = ['genome-v2', 'genome-v3'];
7
+ const GENOME_CONFIDENCE_LEVELS = ['low', 'medium', 'high'];
8
+ const GENOME_HYBRID_MODES = ['domain-function', 'single-persona', 'multi-persona'];
9
+ const GENOME_CANONICAL_SECTION_KEYS = [
10
+ 'knowledge',
11
+ 'philosophies',
12
+ 'mentalModels',
13
+ 'heuristics',
14
+ 'frameworks',
15
+ 'methodologies',
16
+ 'mentes',
17
+ 'skills',
18
+ 'evidence',
19
+ 'applicationNotes'
20
+ ];
21
+ const GENOME_V3_SECTION_KEYS = [
22
+ 'cognitiveProfile',
23
+ 'communicationStyle',
24
+ 'biases',
25
+ 'conflictResolution'
26
+ ];
27
+ const GENOME_SECTION_KEYS = [...GENOME_CANONICAL_SECTION_KEYS, ...GENOME_V3_SECTION_KEYS];
28
+
29
+ function normalizeText(value, fallback = '') {
30
+ if (value === undefined || value === null) return fallback;
31
+ return String(value).trim();
32
+ }
33
+
34
+ function slugify(value) {
35
+ return normalizeText(value)
36
+ .toLowerCase()
37
+ .normalize('NFD')
38
+ .replace(/[\u0300-\u036f]/g, '')
39
+ .replace(/[^a-z0-9]+/g, '-')
40
+ .replace(/^-+|-+$/g, '')
41
+ .slice(0, 80);
42
+ }
43
+
44
+ function humanizeSlug(value) {
45
+ return normalizeText(value)
46
+ .split('-')
47
+ .filter(Boolean)
48
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
49
+ .join(' ');
50
+ }
51
+
52
+ function normalizeEnum(value, allowed, fallback) {
53
+ const normalized = normalizeText(value).toLowerCase();
54
+ if (!normalized) return fallback;
55
+ return allowed.includes(normalized) ? normalized : normalized;
56
+ }
57
+
58
+ function normalizeOptionalEnum(value, allowed) {
59
+ const normalized = normalizeText(value).toLowerCase();
60
+ if (!normalized) return '';
61
+ return allowed.includes(normalized) ? normalized : normalized;
62
+ }
63
+
64
+ function normalizeInteger(value, fallback = 0) {
65
+ if (value === undefined || value === null || value === '') return fallback;
66
+ const parsed = Number.parseInt(String(value), 10);
67
+ if (!Number.isFinite(parsed) || parsed < 0) return fallback;
68
+ return parsed;
69
+ }
70
+
71
+ function normalizeIntegerPreservingInvalid(value, fallback) {
72
+ if (value === undefined || value === null || value === '') return fallback;
73
+ const parsed = Number.parseInt(String(value), 10);
74
+ if (!Number.isFinite(parsed)) return value;
75
+ return parsed;
76
+ }
77
+
78
+ function normalizeDate(value) {
79
+ const text = normalizeText(value);
80
+ if (!text) return '';
81
+ const match = text.match(/^(\d{4}-\d{2}-\d{2})/);
82
+ return match ? match[1] : text;
83
+ }
84
+
85
+ function normalizeTimestamp(value) {
86
+ const text = normalizeText(value);
87
+ if (!text) return '';
88
+ const timestamp = new Date(text);
89
+ if (Number.isNaN(timestamp.getTime())) return '';
90
+ return timestamp.toISOString();
91
+ }
92
+
93
+ function normalizeStringArray(value) {
94
+ const source = Array.isArray(value)
95
+ ? value
96
+ : value === undefined || value === null || value === ''
97
+ ? []
98
+ : [value];
99
+
100
+ return source
101
+ .map((entry) => normalizeText(entry))
102
+ .filter(Boolean);
103
+ }
104
+
105
+ function normalizeGenomeVersion(value, fallback = 2) {
106
+ const parsed = Number.parseInt(String(value || ''), 10);
107
+ if (!Number.isFinite(parsed)) return fallback;
108
+ if (parsed >= 3) return 3;
109
+ if (parsed >= 2) return 2;
110
+ return fallback;
111
+ }
112
+
113
+ function normalizeGenomeFormat(value, version) {
114
+ const normalized = normalizeText(value).toLowerCase();
115
+ if (GENOME_FORMATS.includes(normalized)) return normalized;
116
+ return version >= 3 ? 'genome-v3' : 'genome-v2';
117
+ }
118
+
119
+ function formatMenteBlock(value) {
120
+ if (!value || typeof value !== 'object') return '';
121
+ const name = normalizeText(value.name || value.title);
122
+ const lines = [];
123
+
124
+ if (name) lines.push(`### ${name}`);
125
+
126
+ const cognitiveSignature = normalizeText(value.cognitiveSignature || value.signature);
127
+ const favouriteQuestion = normalizeText(value.favouriteQuestion || value.question);
128
+ const blindSpot = normalizeText(value.blindSpot);
129
+ const notes = normalizeText(value.notes || value.body || value.description);
130
+
131
+ if (cognitiveSignature) lines.push(`- Cognitive signature: ${cognitiveSignature}`);
132
+ if (favouriteQuestion) lines.push(`- Favourite question: ${favouriteQuestion}`);
133
+ if (blindSpot) lines.push(`- Blind spot: ${blindSpot}`);
134
+ if (notes) lines.push(notes);
135
+
136
+ return lines.join('\n').trim();
137
+ }
138
+
139
+ function formatSkillBlock(value) {
140
+ if (!value || typeof value !== 'object') return '';
141
+ const name = normalizeText(value.name || value.slug || value.title);
142
+ const description = normalizeText(value.description || value.summary || value.body);
143
+
144
+ if (name && description) return `- SKILL: ${name} — ${description}`;
145
+ if (name) return `- SKILL: ${name}`;
146
+ return description;
147
+ }
148
+
149
+ function formatGenericBlock(value) {
150
+ if (!value || typeof value !== 'object') return '';
151
+ const markdown = normalizeText(value.markdown);
152
+ if (markdown) return markdown;
153
+
154
+ const title = normalizeText(value.title || value.name);
155
+ const body = normalizeText(value.body || value.description || value.notes);
156
+ if (title && body) return `### ${title}\n${body}`;
157
+ if (title) return title;
158
+ return body;
159
+ }
160
+
161
+ function normalizeSectionEntries(sectionKey, value) {
162
+ const source = Array.isArray(value)
163
+ ? value
164
+ : value === undefined || value === null || value === ''
165
+ ? []
166
+ : [value];
167
+
168
+ return source
169
+ .map((entry) => {
170
+ if (typeof entry === 'string') return normalizeText(entry);
171
+ if (sectionKey === 'mentes') return formatMenteBlock(entry);
172
+ if (sectionKey === 'skills') return formatSkillBlock(entry);
173
+ return formatGenericBlock(entry);
174
+ })
175
+ .filter(Boolean);
176
+ }
177
+
178
+ function createEmptyGenome() {
179
+ return {
180
+ slug: '',
181
+ domain: '',
182
+ type: 'domain',
183
+ language: 'en',
184
+ depth: 'standard',
185
+ version: 2,
186
+ format: 'genome-v2',
187
+ evidenceMode: 'inferred',
188
+ sourceCount: 0,
189
+ generated: '',
190
+ personaSource: '',
191
+ personaSources: [],
192
+ disc: '',
193
+ enneagram: '',
194
+ bigFive: '',
195
+ mbti: '',
196
+ confidence: '',
197
+ profilerReport: '',
198
+ hybridMode: '',
199
+ legacyFormat: false,
200
+ hasFrontmatter: false,
201
+ sections: {
202
+ knowledge: [],
203
+ philosophies: [],
204
+ mentalModels: [],
205
+ heuristics: [],
206
+ frameworks: [],
207
+ methodologies: [],
208
+ mentes: [],
209
+ skills: [],
210
+ cognitiveProfile: [],
211
+ communicationStyle: [],
212
+ biases: [],
213
+ conflictResolution: [],
214
+ evidence: [],
215
+ applicationNotes: []
216
+ }
217
+ };
218
+ }
219
+
220
+ function normalizeGenome(input = {}) {
221
+ const genome = createEmptyGenome();
222
+ const merged = {
223
+ ...genome,
224
+ ...input,
225
+ sections: {
226
+ ...genome.sections,
227
+ ...(input.sections || {})
228
+ }
229
+ };
230
+
231
+ const domain = normalizeText(merged.domain || merged.title || merged.name);
232
+ const slug = slugify(merged.slug || merged.genome || domain);
233
+ const inputSections = input && typeof input.sections === 'object' ? input.sections : {};
234
+ const hasV3SectionSignals = ['cognitiveProfile', 'communicationStyle', 'biases', 'conflictResolution'].some((key) => {
235
+ const value = inputSections[key];
236
+ if (Array.isArray(value)) return value.length > 0;
237
+ return value !== undefined && value !== null && value !== '';
238
+ });
239
+ const hasPersonaExtensions = Boolean(
240
+ merged.personaSource ||
241
+ merged.persona_source ||
242
+ merged.personaSources ||
243
+ merged.persona_sources ||
244
+ merged.disc ||
245
+ merged.enneagram ||
246
+ merged.bigFive ||
247
+ merged.big_five ||
248
+ merged.mbti ||
249
+ merged.profilerReport ||
250
+ merged.profiler_report ||
251
+ merged.confidence ||
252
+ merged.hybridMode ||
253
+ merged.hybrid_mode ||
254
+ hasV3SectionSignals
255
+ );
256
+ const version = normalizeGenomeVersion(
257
+ merged.version,
258
+ normalizeText(merged.format).toLowerCase() === 'genome-v3' || hasPersonaExtensions ? 3 : 2
259
+ );
260
+ const format = normalizeGenomeFormat(merged.format, version);
261
+
262
+ const sections = {};
263
+ for (const key of GENOME_SECTION_KEYS) {
264
+ sections[key] = normalizeSectionEntries(key, merged.sections[key]);
265
+ }
266
+
267
+ return {
268
+ ...merged,
269
+ slug,
270
+ domain: domain || humanizeSlug(slug),
271
+ type: normalizeEnum(merged.type, GENOME_TYPES, 'domain'),
272
+ language: normalizeText(merged.language, 'en') || 'en',
273
+ depth: normalizeEnum(merged.depth, GENOME_DEPTHS, 'standard'),
274
+ version,
275
+ format,
276
+ evidenceMode: normalizeEnum(
277
+ merged.evidenceMode || merged.evidence_mode,
278
+ GENOME_EVIDENCE_MODES,
279
+ 'inferred'
280
+ ),
281
+ sourceCount: normalizeInteger(
282
+ merged.sourceCount ?? merged.sourcesCount ?? merged.sources_count,
283
+ 0
284
+ ),
285
+ generated: normalizeDate(merged.generated),
286
+ personaSource: normalizeText(merged.personaSource || merged.persona_source),
287
+ personaSources: normalizeStringArray(merged.personaSources || merged.persona_sources),
288
+ disc: normalizeText(merged.disc),
289
+ enneagram: normalizeText(merged.enneagram),
290
+ bigFive: normalizeText(merged.bigFive || merged.big_five),
291
+ mbti: normalizeText(merged.mbti),
292
+ confidence: normalizeOptionalEnum(merged.confidence, GENOME_CONFIDENCE_LEVELS),
293
+ profilerReport: normalizeText(merged.profilerReport || merged.profiler_report),
294
+ hybridMode: normalizeOptionalEnum(
295
+ merged.hybridMode || merged.hybrid_mode,
296
+ GENOME_HYBRID_MODES
297
+ ),
298
+ legacyFormat: Boolean(merged.legacyFormat),
299
+ hasFrontmatter: Boolean(merged.hasFrontmatter),
300
+ sections
301
+ };
302
+ }
303
+
304
+ function countGenomeSections(input = {}) {
305
+ const genome = normalizeGenome(input);
306
+ return {
307
+ knowledgeNodes: genome.sections.knowledge.length,
308
+ philosophies: genome.sections.philosophies.length,
309
+ mentalModels: genome.sections.mentalModels.length,
310
+ heuristics: genome.sections.heuristics.length,
311
+ frameworks: genome.sections.frameworks.length,
312
+ methodologies: genome.sections.methodologies.length,
313
+ mentes: genome.sections.mentes.length,
314
+ skills: genome.sections.skills.length,
315
+ cognitiveProfile: genome.sections.cognitiveProfile.length,
316
+ communicationStyle: genome.sections.communicationStyle.length,
317
+ biases: genome.sections.biases.length,
318
+ conflictResolution: genome.sections.conflictResolution.length,
319
+ evidence: genome.sections.evidence.length,
320
+ applicationNotes: genome.sections.applicationNotes.length
321
+ };
322
+ }
323
+
324
+ function normalizeCounts(value = {}) {
325
+ return {
326
+ knowledgeNodes: normalizeInteger(value.knowledgeNodes, 0),
327
+ philosophies: normalizeInteger(value.philosophies, 0),
328
+ mentalModels: normalizeInteger(value.mentalModels, 0),
329
+ heuristics: normalizeInteger(value.heuristics, 0),
330
+ frameworks: normalizeInteger(value.frameworks, 0),
331
+ methodologies: normalizeInteger(value.methodologies, 0),
332
+ mentes: normalizeInteger(value.mentes, 0),
333
+ skills: normalizeInteger(value.skills, 0),
334
+ cognitiveProfile: normalizeInteger(value.cognitiveProfile, 0),
335
+ communicationStyle: normalizeInteger(value.communicationStyle, 0),
336
+ biases: normalizeInteger(value.biases, 0),
337
+ conflictResolution: normalizeInteger(value.conflictResolution, 0),
338
+ evidence: normalizeInteger(value.evidence, 0),
339
+ applicationNotes: normalizeInteger(value.applicationNotes, 0)
340
+ };
341
+ }
342
+
343
+ function timestampFromGenome(genome) {
344
+ const explicit = normalizeTimestamp(genome && genome.generated);
345
+ if (explicit) return explicit;
346
+ const generated = normalizeDate(genome && genome.generated);
347
+ if (generated) {
348
+ const synthesized = normalizeTimestamp(`${generated}T00:00:00.000Z`);
349
+ if (synthesized) return synthesized;
350
+ }
351
+ return new Date().toISOString();
352
+ }
353
+
354
+ function normalizeGenomeMeta(input = {}) {
355
+ const genome = input.genome ? normalizeGenome(input.genome) : null;
356
+ const genomeCounts = genome ? countGenomeSections(genome) : normalizeCounts({});
357
+ const counts = normalizeCounts({
358
+ ...genomeCounts,
359
+ ...(input.counts || {})
360
+ });
361
+ const createdAt = normalizeTimestamp(input.createdAt) || timestampFromGenome(genome || input);
362
+ const updatedAt = normalizeTimestamp(input.updatedAt) || createdAt;
363
+ const version = normalizeGenomeVersion(input.version || (genome && genome.version), 2);
364
+ const format = normalizeGenomeFormat(input.format || (genome && genome.format), version);
365
+
366
+ return {
367
+ schemaVersion: normalizeIntegerPreservingInvalid(input.schemaVersion, version),
368
+ version,
369
+ format,
370
+ slug: slugify(input.slug || (genome && genome.slug)),
371
+ domain: normalizeText(input.domain || (genome && genome.domain)) || humanizeSlug(input.slug || (genome && genome.slug)),
372
+ type: normalizeEnum(input.type || (genome && genome.type), GENOME_TYPES, 'domain'),
373
+ language: normalizeText(input.language || (genome && genome.language), 'en') || 'en',
374
+ depth: normalizeEnum(input.depth || (genome && genome.depth), GENOME_DEPTHS, 'standard'),
375
+ evidenceMode: normalizeEnum(
376
+ input.evidenceMode || input.evidence_mode || (genome && genome.evidenceMode),
377
+ GENOME_EVIDENCE_MODES,
378
+ 'inferred'
379
+ ),
380
+ sourceCount: normalizeInteger(
381
+ input.sourceCount ??
382
+ input.sourcesCount ??
383
+ input.sources_count ??
384
+ (genome && genome.sourceCount),
385
+ 0
386
+ ),
387
+ personaSource: normalizeText(input.personaSource || input.persona_source || (genome && genome.personaSource)),
388
+ personaSources: normalizeStringArray(input.personaSources || input.persona_sources || (genome && genome.personaSources)),
389
+ disc: normalizeText(input.disc || (genome && genome.disc)),
390
+ enneagram: normalizeText(input.enneagram || (genome && genome.enneagram)),
391
+ bigFive: normalizeText(input.bigFive || input.big_five || (genome && genome.bigFive)),
392
+ mbti: normalizeText(input.mbti || (genome && genome.mbti)),
393
+ confidence: normalizeOptionalEnum(input.confidence || (genome && genome.confidence), GENOME_CONFIDENCE_LEVELS),
394
+ profilerReport: normalizeText(input.profilerReport || input.profiler_report || (genome && genome.profilerReport)),
395
+ hybridMode: normalizeOptionalEnum(
396
+ input.hybridMode || input.hybrid_mode || (genome && genome.hybridMode),
397
+ GENOME_HYBRID_MODES
398
+ ),
399
+ counts,
400
+ origin: {
401
+ mode: normalizeText(input.origin && input.origin.mode, 'llm') || 'llm',
402
+ sourceFiles: normalizeStringArray(input.origin && input.origin.sourceFiles),
403
+ sourceUrls: normalizeStringArray(input.origin && input.origin.sourceUrls)
404
+ },
405
+ compat: {
406
+ legacyMarkdownCompatible:
407
+ input.compat && Object.prototype.hasOwnProperty.call(input.compat, 'legacyMarkdownCompatible')
408
+ ? Boolean(input.compat.legacyMarkdownCompatible)
409
+ : true,
410
+ synthesizedFromLegacy:
411
+ input.compat && Object.prototype.hasOwnProperty.call(input.compat, 'synthesizedFromLegacy')
412
+ ? Boolean(input.compat.synthesizedFromLegacy)
413
+ : false
414
+ },
415
+ bindings: {
416
+ squads: normalizeStringArray(input.bindings && input.bindings.squads),
417
+ agents: normalizeStringArray(input.bindings && input.bindings.agents)
418
+ },
419
+ createdAt,
420
+ updatedAt
421
+ };
422
+ }
423
+
424
+ function isGenomeV2(genome) {
425
+ if (!genome || typeof genome !== 'object') return false;
426
+ if (genome.legacyFormat) return false;
427
+ const format = normalizeText(genome.format).toLowerCase();
428
+ const version = Number.parseInt(String(genome.version || ''), 10);
429
+ return GENOME_FORMATS.includes(format) || version >= 2;
430
+ }
431
+
432
+ function synthesizeMetaFromLegacy(genome, input = {}) {
433
+ const normalizedGenome = normalizeGenome({
434
+ ...genome,
435
+ legacyFormat: true
436
+ });
437
+
438
+ return normalizeGenomeMeta({
439
+ ...input,
440
+ genome: normalizedGenome,
441
+ compat: {
442
+ ...(input.compat || {}),
443
+ legacyMarkdownCompatible: true,
444
+ synthesizedFromLegacy: true
445
+ },
446
+ createdAt: input.createdAt || timestampFromGenome(normalizedGenome),
447
+ updatedAt: input.updatedAt || timestampFromGenome(normalizedGenome)
448
+ });
449
+ }
450
+
451
+ module.exports = {
452
+ GENOME_TYPES,
453
+ GENOME_DEPTHS,
454
+ GENOME_EVIDENCE_MODES,
455
+ GENOME_FORMATS,
456
+ GENOME_CONFIDENCE_LEVELS,
457
+ GENOME_HYBRID_MODES,
458
+ GENOME_SECTION_KEYS,
459
+ GENOME_CANONICAL_SECTION_KEYS,
460
+ GENOME_V3_SECTION_KEYS,
461
+ createEmptyGenome,
462
+ normalizeGenome,
463
+ normalizeGenomeMeta,
464
+ isGenomeV2,
465
+ synthesizeMetaFromLegacy,
466
+ countGenomeSections
467
+ };
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const MESSAGES_DIR = path.join(__dirname, 'messages');
7
+
8
+ function getByPath(obj, dottedPath) {
9
+ return dottedPath.split('.').reduce((acc, key) => {
10
+ if (!acc || typeof acc !== 'object') return undefined;
11
+ return acc[key];
12
+ }, obj);
13
+ }
14
+
15
+ function applyParams(template, params = {}) {
16
+ return String(template).replace(/\{([a-zA-Z0-9_]+)\}/g, (match, key) => {
17
+ if (Object.prototype.hasOwnProperty.call(params, key)) {
18
+ return String(params[key]);
19
+ }
20
+ return match;
21
+ });
22
+ }
23
+
24
+ function loadMessages() {
25
+ const messages = {};
26
+
27
+ if (!fs.existsSync(MESSAGES_DIR)) {
28
+ return { en: {} };
29
+ }
30
+
31
+ const files = fs.readdirSync(MESSAGES_DIR);
32
+ for (const file of files) {
33
+ if (!file.endsWith('.js')) continue;
34
+
35
+ const locale = path.basename(file, '.js').toLowerCase();
36
+ try {
37
+ const modulePath = path.join(MESSAGES_DIR, file);
38
+ delete require.cache[require.resolve(modulePath)];
39
+ const dict = require(modulePath);
40
+ if (dict && typeof dict === 'object') {
41
+ messages[locale] = dict;
42
+ }
43
+ } catch {
44
+ // Ignore invalid locale files and rely on fallback locales.
45
+ }
46
+ }
47
+
48
+ if (!messages.en) {
49
+ messages.en = {};
50
+ }
51
+
52
+ return messages;
53
+ }
54
+
55
+ function normalizeLocale(raw, messages = loadMessages()) {
56
+ const supported = Object.keys(messages);
57
+ if (supported.length === 0) return 'en';
58
+
59
+ if (!raw) return supported.includes('en') ? 'en' : supported[0];
60
+
61
+ const clean = String(raw).trim().toLowerCase();
62
+ const canonical = clean.replace(/_/g, '-');
63
+ if (supported.includes(canonical)) return canonical;
64
+
65
+ const base = canonical.split('-')[0];
66
+ if (supported.includes(base)) return base;
67
+
68
+ const regionalMatch = supported
69
+ .slice()
70
+ .sort()
71
+ .find((locale) => locale.startsWith(`${base}-`));
72
+ if (regionalMatch) return regionalMatch;
73
+
74
+ if (supported.includes('en')) return 'en';
75
+ return supported[0];
76
+ }
77
+
78
+ function createTranslator(locale) {
79
+ const messages = loadMessages();
80
+ const resolvedLocale = normalizeLocale(locale, messages);
81
+ const dictionary = messages[resolvedLocale] || messages.en || {};
82
+
83
+ function t(key, params) {
84
+ const fromLocale = getByPath(dictionary, key);
85
+ if (fromLocale !== undefined) return applyParams(fromLocale, params);
86
+
87
+ const fallback = getByPath(messages.en || {}, key);
88
+ if (fallback !== undefined) return applyParams(fallback, params);
89
+
90
+ return key;
91
+ }
92
+
93
+ return {
94
+ locale: resolvedLocale,
95
+ t
96
+ };
97
+ }
98
+
99
+ module.exports = {
100
+ createTranslator,
101
+ normalizeLocale,
102
+ loadMessages
103
+ };