@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
@@ -0,0 +1,442 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ GENOME_SECTION_KEYS,
5
+ countGenomeSections,
6
+ normalizeGenome
7
+ } = require('./genomes');
8
+
9
+ const SECTION_ORDER = [
10
+ ['knowledge', 'O que saber'],
11
+ ['philosophies', 'Filosofias'],
12
+ ['mentalModels', 'Modelos mentais'],
13
+ ['heuristics', 'Heurísticas'],
14
+ ['frameworks', 'Frameworks'],
15
+ ['methodologies', 'Metodologias'],
16
+ ['mentes', 'Mentes'],
17
+ ['skills', 'Skills'],
18
+ ['cognitiveProfile', 'Perfil Cognitivo'],
19
+ ['communicationStyle', 'Estilo de Comunicação'],
20
+ ['biases', 'Vieses e Pontos Cegos'],
21
+ ['conflictResolution', 'Conflict Resolution'],
22
+ ['evidence', 'Evidence'],
23
+ ['applicationNotes', 'Application notes']
24
+ ];
25
+
26
+ const SECTION_ALIASES = new Map([
27
+ ['o que saber', 'knowledge'],
28
+ ['what to know', 'knowledge'],
29
+ ['filosofias', 'philosophies'],
30
+ ['philosophies', 'philosophies'],
31
+ ['modelos mentais', 'mentalModels'],
32
+ ['mental models', 'mentalModels'],
33
+ ['heuristicas', 'heuristics'],
34
+ ['heuristics', 'heuristics'],
35
+ ['frameworks', 'frameworks'],
36
+ ['metodologias', 'methodologies'],
37
+ ['methodologies', 'methodologies'],
38
+ ['mentes', 'mentes'],
39
+ ['minds', 'mentes'],
40
+ ['skills', 'skills'],
41
+ ['habilidades', 'skills'],
42
+ ['perfil cognitivo', 'cognitiveProfile'],
43
+ ['cognitive profile', 'cognitiveProfile'],
44
+ ['estilo de comunicacao', 'communicationStyle'],
45
+ ['communication style', 'communicationStyle'],
46
+ ['vieses e pontos cegos', 'biases'],
47
+ ['biases and blind spots', 'biases'],
48
+ ['conflict resolution', 'conflictResolution'],
49
+ ['resolucao de conflito', 'conflictResolution'],
50
+ ['evidence', 'evidence'],
51
+ ['evidencias', 'evidence'],
52
+ ['application notes', 'applicationNotes'],
53
+ ['notas de aplicacao', 'applicationNotes']
54
+ ]);
55
+
56
+ function stripBOM(value) {
57
+ return String(value || '').replace(/^\uFEFF/, '');
58
+ }
59
+
60
+ function normalizeHeading(value) {
61
+ return String(value || '')
62
+ .trim()
63
+ .toLowerCase()
64
+ .normalize('NFD')
65
+ .replace(/[\u0300-\u036f]/g, '');
66
+ }
67
+
68
+ function parseScalar(rawValue) {
69
+ const value = String(rawValue || '').trim();
70
+ if (!value) return '';
71
+ if (
72
+ (value.startsWith('[') && value.endsWith(']')) ||
73
+ (value.startsWith('{') && value.endsWith('}'))
74
+ ) {
75
+ try {
76
+ return JSON.parse(value);
77
+ } catch {
78
+ return value;
79
+ }
80
+ }
81
+ if (
82
+ (value.startsWith('"') && value.endsWith('"')) ||
83
+ (value.startsWith("'") && value.endsWith("'"))
84
+ ) {
85
+ return value.slice(1, -1);
86
+ }
87
+ if (/^-?\d+$/.test(value)) return Number.parseInt(value, 10);
88
+ if (value === 'true') return true;
89
+ if (value === 'false') return false;
90
+ return value;
91
+ }
92
+
93
+ function extractFrontmatter(markdown) {
94
+ const text = stripBOM(markdown);
95
+ if (!text.startsWith('---\n') && !text.startsWith('---\r\n')) {
96
+ return {
97
+ attributes: {},
98
+ body: text,
99
+ hasFrontmatter: false
100
+ };
101
+ }
102
+
103
+ const lines = text.split(/\r?\n/);
104
+ let closingIndex = -1;
105
+ for (let index = 1; index < lines.length; index += 1) {
106
+ if (lines[index].trim() === '---') {
107
+ closingIndex = index;
108
+ break;
109
+ }
110
+ }
111
+
112
+ if (closingIndex === -1) {
113
+ throw new Error('Invalid genome markdown: unclosed frontmatter block.');
114
+ }
115
+
116
+ const attributes = {};
117
+ for (let index = 1; index < closingIndex; index += 1) {
118
+ const line = lines[index].trim();
119
+ if (!line || line.startsWith('#')) continue;
120
+
121
+ const match = line.match(/^([a-zA-Z0-9_-]+)\s*:\s*(.*)$/);
122
+ if (!match) {
123
+ throw new Error(`Invalid genome frontmatter line: ${line}`);
124
+ }
125
+
126
+ attributes[match[1]] = parseScalar(match[2]);
127
+ }
128
+
129
+ return {
130
+ attributes,
131
+ body: lines.slice(closingIndex + 1).join('\n'),
132
+ hasFrontmatter: true
133
+ };
134
+ }
135
+
136
+ function splitParagraphBlocks(text) {
137
+ const lines = String(text || '').split(/\r?\n/);
138
+ const blocks = [];
139
+ let current = [];
140
+
141
+ function pushCurrent() {
142
+ if (current.length === 0) return;
143
+ const block = current.join('\n').trim();
144
+ if (block) blocks.push(block);
145
+ current = [];
146
+ }
147
+
148
+ for (const line of lines) {
149
+ if (!line.trim()) {
150
+ pushCurrent();
151
+ continue;
152
+ }
153
+ current.push(line);
154
+ }
155
+
156
+ pushCurrent();
157
+ return blocks;
158
+ }
159
+
160
+ function splitSubheadingBlocks(text) {
161
+ const lines = String(text || '').split(/\r?\n/);
162
+ const blocks = [];
163
+ let current = [];
164
+
165
+ function pushCurrent() {
166
+ if (current.length === 0) return;
167
+ const block = current.join('\n').trim();
168
+ if (block) blocks.push(block);
169
+ current = [];
170
+ }
171
+
172
+ for (const line of lines) {
173
+ if (/^###\s+/.test(line.trim())) {
174
+ pushCurrent();
175
+ current = [line];
176
+ continue;
177
+ }
178
+
179
+ if (!line.trim() && current.length === 0) continue;
180
+ current.push(line);
181
+ }
182
+
183
+ pushCurrent();
184
+ return blocks;
185
+ }
186
+
187
+ function splitListBlocks(text) {
188
+ const lines = String(text || '').split(/\r?\n/);
189
+ const blocks = [];
190
+ let current = [];
191
+
192
+ function pushCurrent() {
193
+ if (current.length === 0) return;
194
+ const block = current.join('\n').trim();
195
+ if (block) blocks.push(block);
196
+ current = [];
197
+ }
198
+
199
+ for (const line of lines) {
200
+ const trimmed = line.trim();
201
+ const isListStart = /^[-*]\s+/.test(trimmed) || /^\d+\.\s+/.test(trimmed);
202
+
203
+ if (isListStart) {
204
+ pushCurrent();
205
+ current = [line];
206
+ continue;
207
+ }
208
+
209
+ if (!trimmed && current.length === 0) continue;
210
+ current.push(line);
211
+ }
212
+
213
+ pushCurrent();
214
+ return blocks;
215
+ }
216
+
217
+ function emptySections() {
218
+ return GENOME_SECTION_KEYS.reduce((accumulator, key) => {
219
+ accumulator[key] = [];
220
+ return accumulator;
221
+ }, {});
222
+ }
223
+
224
+ function materializeSection(sectionKey, content) {
225
+ if (!content.trim()) return [];
226
+ if (sectionKey === 'mentes') {
227
+ const blocks = splitSubheadingBlocks(content);
228
+ return blocks.length > 0 ? blocks : splitParagraphBlocks(content);
229
+ }
230
+ if (sectionKey === 'skills') {
231
+ const blocks = splitListBlocks(content);
232
+ return blocks.length > 0 ? blocks : splitParagraphBlocks(content);
233
+ }
234
+ return splitParagraphBlocks(content);
235
+ }
236
+
237
+ function parseGenomeSections(markdown) {
238
+ const sections = emptySections();
239
+ const lines = String(markdown || '').split(/\r?\n/);
240
+ let currentSection = null;
241
+ let buffer = [];
242
+
243
+ function flush() {
244
+ if (!currentSection) {
245
+ buffer = [];
246
+ return;
247
+ }
248
+ sections[currentSection] = materializeSection(currentSection, buffer.join('\n'));
249
+ buffer = [];
250
+ }
251
+
252
+ for (const line of lines) {
253
+ const match = line.match(/^##\s+(.+?)\s*$/);
254
+ if (match) {
255
+ flush();
256
+ currentSection = SECTION_ALIASES.get(normalizeHeading(match[1])) || null;
257
+ continue;
258
+ }
259
+
260
+ if (!currentSection) continue;
261
+ buffer.push(line);
262
+ }
263
+
264
+ flush();
265
+ return sections;
266
+ }
267
+
268
+ function extractTitle(markdown) {
269
+ const lines = String(markdown || '').split(/\r?\n/);
270
+ for (const line of lines) {
271
+ const match = line.match(/^#\s+(.+?)\s*$/);
272
+ if (!match) continue;
273
+ return match[1]
274
+ .replace(/^(Genome|Genoma)\s*:\s*/i, '')
275
+ .trim();
276
+ }
277
+ return '';
278
+ }
279
+
280
+ function bodyWithoutTitle(markdown) {
281
+ const lines = String(markdown || '').split(/\r?\n/);
282
+ const output = [];
283
+ let titleSkipped = false;
284
+
285
+ for (const line of lines) {
286
+ if (!titleSkipped && /^#\s+/.test(line.trim())) {
287
+ titleSkipped = true;
288
+ continue;
289
+ }
290
+ output.push(line);
291
+ }
292
+
293
+ return output.join('\n').trim();
294
+ }
295
+
296
+ function hasNewSectionContent(sections) {
297
+ const keys = GENOME_SECTION_KEYS.filter((key) => !['knowledge', 'mentes', 'skills'].includes(key));
298
+ return keys.some((key) => Array.isArray(sections[key]) && sections[key].length > 0);
299
+ }
300
+
301
+ function parseGenomeMarkdown(markdown) {
302
+ const extracted = extractFrontmatter(markdown);
303
+ const title = extractTitle(extracted.body);
304
+ const sections = parseGenomeSections(extracted.body);
305
+ const counts = countGenomeSections({ sections });
306
+ const hasSectionContent = Object.values(counts).some((count) => count > 0);
307
+ const fallbackKnowledge = !hasSectionContent ? splitParagraphBlocks(bodyWithoutTitle(extracted.body)) : [];
308
+ const frontmatter = extracted.attributes;
309
+
310
+ const detectedV2 =
311
+ Number.parseInt(String(frontmatter.version || ''), 10) >= 2 ||
312
+ ['genome-v2', 'genome-v3'].includes(String(frontmatter.format || '').trim().toLowerCase()) ||
313
+ Boolean(frontmatter.type) ||
314
+ Boolean(frontmatter.evidence_mode) ||
315
+ Boolean(frontmatter.sources_count) ||
316
+ hasNewSectionContent(sections);
317
+
318
+ const genome = normalizeGenome({
319
+ slug: frontmatter.genome || frontmatter.slug,
320
+ domain: frontmatter.domain || title,
321
+ type: frontmatter.type,
322
+ language: frontmatter.language,
323
+ depth: frontmatter.depth,
324
+ evidenceMode: frontmatter.evidence_mode || frontmatter.evidenceMode,
325
+ sourceCount: frontmatter.sources_count ?? frontmatter.sourceCount,
326
+ generated: frontmatter.generated,
327
+ version: frontmatter.version,
328
+ format: frontmatter.format,
329
+ personaSource: frontmatter.persona_source || frontmatter.personaSource,
330
+ personaSources: frontmatter.persona_sources || frontmatter.personaSources,
331
+ disc: frontmatter.disc,
332
+ enneagram: frontmatter.enneagram,
333
+ bigFive: frontmatter.big_five || frontmatter.bigFive,
334
+ mbti: frontmatter.mbti,
335
+ confidence: frontmatter.confidence,
336
+ profilerReport: frontmatter.profiler_report || frontmatter.profilerReport,
337
+ hybridMode: frontmatter.hybrid_mode || frontmatter.hybridMode,
338
+ hasFrontmatter: extracted.hasFrontmatter,
339
+ legacyFormat: !detectedV2,
340
+ sections: hasSectionContent
341
+ ? sections
342
+ : {
343
+ ...sections,
344
+ knowledge: fallbackKnowledge
345
+ }
346
+ });
347
+
348
+ return genome;
349
+ }
350
+
351
+ function formatFrontmatterValue(value) {
352
+ if (Array.isArray(value)) return JSON.stringify(value);
353
+ if (typeof value === 'number' || typeof value === 'boolean') return String(value);
354
+ const text = String(value || '').replace(/\r?\n/g, ' ').trim();
355
+ if (!text) return '""';
356
+ if (/[:#]/.test(text)) return JSON.stringify(text);
357
+ return text;
358
+ }
359
+
360
+ function renderSectionEntries(entries) {
361
+ if (!Array.isArray(entries) || entries.length === 0) return '';
362
+ return entries.map((entry) => String(entry || '').trim()).filter(Boolean).join('\n\n');
363
+ }
364
+
365
+ function shouldRenderSection(genome, key) {
366
+ if (['cognitiveProfile', 'communicationStyle', 'biases'].includes(key)) {
367
+ return genome.version >= 3;
368
+ }
369
+
370
+ if (key === 'conflictResolution') {
371
+ return genome.version >= 3 && (genome.hybridMode === 'multi-persona' || genome.sections[key].length > 0);
372
+ }
373
+
374
+ return true;
375
+ }
376
+
377
+ function serializeGenomeMarkdown(input) {
378
+ const genome = normalizeGenome(input);
379
+ const counts = countGenomeSections(genome);
380
+ const generated = genome.generated || new Date().toISOString().slice(0, 10);
381
+ const frontmatter = [
382
+ '---',
383
+ `genome: ${formatFrontmatterValue(genome.slug)}`,
384
+ `domain: ${formatFrontmatterValue(genome.domain)}`,
385
+ `type: ${formatFrontmatterValue(genome.type)}`,
386
+ `language: ${formatFrontmatterValue(genome.language)}`,
387
+ `depth: ${formatFrontmatterValue(genome.depth)}`,
388
+ `version: ${formatFrontmatterValue(genome.version)}`,
389
+ `format: ${formatFrontmatterValue(genome.format)}`,
390
+ `evidence_mode: ${formatFrontmatterValue(genome.evidenceMode)}`,
391
+ `generated: ${formatFrontmatterValue(generated)}`,
392
+ `sources_count: ${formatFrontmatterValue(genome.sourceCount)}`,
393
+ `mentes: ${formatFrontmatterValue(counts.mentes)}`,
394
+ `skills: ${formatFrontmatterValue(counts.skills)}`,
395
+ '---'
396
+ ];
397
+
398
+ if (genome.version >= 3) {
399
+ frontmatter.splice(
400
+ frontmatter.length - 1,
401
+ 0,
402
+ `persona_source: ${formatFrontmatterValue(genome.personaSource)}`,
403
+ `persona_sources: ${formatFrontmatterValue(genome.personaSources)}`,
404
+ `disc: ${formatFrontmatterValue(genome.disc)}`,
405
+ `enneagram: ${formatFrontmatterValue(genome.enneagram)}`,
406
+ `big_five: ${formatFrontmatterValue(genome.bigFive)}`,
407
+ `mbti: ${formatFrontmatterValue(genome.mbti)}`,
408
+ `confidence: ${formatFrontmatterValue(genome.confidence)}`,
409
+ `profiler_report: ${formatFrontmatterValue(genome.profilerReport)}`,
410
+ `hybrid_mode: ${formatFrontmatterValue(genome.hybridMode)}`
411
+ );
412
+ }
413
+
414
+ const parts = [
415
+ frontmatter.join('\n'),
416
+ `# Genome: ${genome.domain}`
417
+ ];
418
+
419
+ for (const [key, heading] of SECTION_ORDER) {
420
+ if (!shouldRenderSection(genome, key)) continue;
421
+ const body = renderSectionEntries(genome.sections[key]);
422
+ parts.push(body ? `## ${heading}\n\n${body}` : `## ${heading}`);
423
+ }
424
+
425
+ return `${parts.join('\n\n')}\n`;
426
+ }
427
+
428
+ function supportsLegacyGenomeMarkdown(markdown) {
429
+ const genome = parseGenomeMarkdown(markdown);
430
+ if (!genome.legacyFormat) return false;
431
+ const counts = countGenomeSections(genome);
432
+ return counts.knowledgeNodes > 0 || counts.mentes > 0 || counts.skills > 0 || Boolean(genome.domain);
433
+ }
434
+
435
+ module.exports = {
436
+ SECTION_ORDER,
437
+ extractFrontmatter,
438
+ parseGenomeMarkdown,
439
+ serializeGenomeMarkdown,
440
+ parseGenomeSections,
441
+ supportsLegacyGenomeMarkdown
442
+ };
@@ -0,0 +1,215 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ GENOME_DEPTHS,
5
+ GENOME_EVIDENCE_MODES,
6
+ GENOME_FORMATS,
7
+ GENOME_CONFIDENCE_LEVELS,
8
+ GENOME_TYPES,
9
+ countGenomeSections,
10
+ normalizeGenome,
11
+ normalizeGenomeMeta
12
+ } = require('./genomes');
13
+
14
+ function buildResult(errors, payload, key) {
15
+ return {
16
+ valid: errors.length === 0,
17
+ errors,
18
+ [key]: payload
19
+ };
20
+ }
21
+
22
+ function hasOwn(input, key) {
23
+ return Boolean(input) && Object.prototype.hasOwnProperty.call(input, key);
24
+ }
25
+
26
+ function validateEnumField(input, key, allowedValues, errors) {
27
+ if (!hasOwn(input, key)) return;
28
+ const value = String(input[key] || '').trim().toLowerCase();
29
+ if (!value || allowedValues.includes(value)) return;
30
+ errors.push(`${key} must be one of: ${allowedValues.join(', ')}`);
31
+ }
32
+
33
+ function validateVersionField(input, key, errors) {
34
+ if (!hasOwn(input, key)) return;
35
+ const parsed = Number.parseInt(String(input[key] || ''), 10);
36
+ if (parsed === 2 || parsed === 3) return;
37
+ errors.push(`${key} must be 2 or 3`);
38
+ }
39
+
40
+ function validateFormatAndVersion(normalized, errors, versionKey = 'version', formatKey = 'format') {
41
+ if (!GENOME_FORMATS.includes(normalized.format)) {
42
+ errors.push(`${formatKey} must be one of: ${GENOME_FORMATS.join(', ')}`);
43
+ }
44
+
45
+ if (![2, 3].includes(normalized.version)) {
46
+ errors.push(`${versionKey} must be 2 or 3`);
47
+ }
48
+
49
+ if (normalized.format === 'genome-v3' && normalized.version !== 3) {
50
+ errors.push('format genome-v3 requires version 3');
51
+ }
52
+
53
+ if (normalized.version === 3 && normalized.format !== 'genome-v3') {
54
+ errors.push('version 3 requires format genome-v3');
55
+ }
56
+ }
57
+
58
+ function validatePersonaV3Requirements(normalized, sections, errors) {
59
+ if (normalized.version < 3 || normalized.type !== 'persona') return;
60
+
61
+ const requiredFields = [
62
+ ['personaSource', normalized.personaSource],
63
+ ['disc', normalized.disc],
64
+ ['enneagram', normalized.enneagram],
65
+ ['bigFive', normalized.bigFive],
66
+ ['mbti', normalized.mbti],
67
+ ['confidence', normalized.confidence],
68
+ ['profilerReport', normalized.profilerReport]
69
+ ];
70
+
71
+ for (const [key, value] of requiredFields) {
72
+ if (!String(value || '').trim()) {
73
+ errors.push(`${key} is required for genome-v3 persona profiles`);
74
+ }
75
+ }
76
+
77
+ for (const key of ['cognitiveProfile', 'communicationStyle', 'biases']) {
78
+ if (!Array.isArray(sections[key]) || sections[key].length === 0) {
79
+ errors.push(`sections.${key} must contain at least one entry for genome-v3 persona profiles`);
80
+ }
81
+ }
82
+ }
83
+
84
+ function validateGenomeObject(input) {
85
+ const genome = normalizeGenome(input);
86
+ const errors = [];
87
+ const sections = input && typeof input.sections === 'object' ? genome.sections : null;
88
+
89
+ if (!genome.slug) errors.push('slug is required');
90
+ if (!genome.domain) errors.push('domain is required');
91
+ validateEnumField(input, 'type', GENOME_TYPES, errors);
92
+ validateEnumField(input, 'depth', GENOME_DEPTHS, errors);
93
+ validateEnumField(input, 'evidenceMode', GENOME_EVIDENCE_MODES, errors);
94
+ validateEnumField(input, 'evidence_mode', GENOME_EVIDENCE_MODES, errors);
95
+ validateEnumField(input, 'confidence', GENOME_CONFIDENCE_LEVELS, errors);
96
+ validateVersionField(input, 'version', errors);
97
+ if (hasOwn(input, 'format')) {
98
+ const value = String(input.format || '').trim().toLowerCase();
99
+ if (!GENOME_FORMATS.includes(value)) {
100
+ errors.push(`format must be one of: ${GENOME_FORMATS.join(', ')}`);
101
+ }
102
+ }
103
+ validateFormatAndVersion(genome, errors);
104
+
105
+ if (!sections) {
106
+ errors.push('sections must be an object');
107
+ } else {
108
+ for (const key of ['knowledge', 'mentes', 'skills', 'cognitiveProfile', 'communicationStyle', 'biases', 'conflictResolution']) {
109
+ if (!Array.isArray(sections[key])) {
110
+ errors.push(`sections.${key} must be an array`);
111
+ }
112
+ }
113
+ }
114
+
115
+ validatePersonaV3Requirements(genome, genome.sections, errors);
116
+
117
+ return buildResult(errors, genome, 'genome');
118
+ }
119
+
120
+ function validateGenomeMeta(input) {
121
+ const meta = normalizeGenomeMeta(input);
122
+ const errors = [];
123
+
124
+ if (!hasOwn(input, 'schemaVersion') || ![2, 3].includes(Number.parseInt(String(input.schemaVersion), 10))) {
125
+ errors.push('schemaVersion must be 2 or 3');
126
+ }
127
+ validateVersionField(input, 'version', errors);
128
+ if (hasOwn(input, 'format')) {
129
+ const value = String(input.format || '').trim().toLowerCase();
130
+ if (!GENOME_FORMATS.includes(value)) {
131
+ errors.push(`format must be one of: ${GENOME_FORMATS.join(', ')}`);
132
+ }
133
+ }
134
+ validateFormatAndVersion(meta, errors);
135
+ if (!meta.slug) errors.push('slug is required');
136
+ if (!meta.domain) errors.push('domain is required');
137
+ validateEnumField(input, 'type', GENOME_TYPES, errors);
138
+ validateEnumField(input, 'depth', GENOME_DEPTHS, errors);
139
+ validateEnumField(input, 'evidenceMode', GENOME_EVIDENCE_MODES, errors);
140
+ validateEnumField(input, 'evidence_mode', GENOME_EVIDENCE_MODES, errors);
141
+ validateEnumField(input, 'confidence', GENOME_CONFIDENCE_LEVELS, errors);
142
+ if (!meta.counts || typeof meta.counts !== 'object') {
143
+ errors.push('counts must be an object');
144
+ } else {
145
+ const counts = countGenomeSections({
146
+ sections: {
147
+ knowledge: Array(meta.counts.knowledgeNodes).fill('x'),
148
+ philosophies: Array(meta.counts.philosophies).fill('x'),
149
+ mentalModels: Array(meta.counts.mentalModels).fill('x'),
150
+ heuristics: Array(meta.counts.heuristics).fill('x'),
151
+ frameworks: Array(meta.counts.frameworks).fill('x'),
152
+ methodologies: Array(meta.counts.methodologies).fill('x'),
153
+ mentes: Array(meta.counts.mentes).fill('x'),
154
+ skills: Array(meta.counts.skills).fill('x'),
155
+ cognitiveProfile: Array(meta.counts.cognitiveProfile).fill('x'),
156
+ communicationStyle: Array(meta.counts.communicationStyle).fill('x'),
157
+ biases: Array(meta.counts.biases).fill('x'),
158
+ conflictResolution: Array(meta.counts.conflictResolution).fill('x'),
159
+ evidence: Array(meta.counts.evidence).fill('x'),
160
+ applicationNotes: Array(meta.counts.applicationNotes).fill('x')
161
+ }
162
+ });
163
+ for (const key of Object.keys(counts)) {
164
+ if (counts[key] !== meta.counts[key]) {
165
+ errors.push(`counts.${key} must be a non-negative integer`);
166
+ }
167
+ }
168
+ }
169
+ if (!meta.createdAt) errors.push('createdAt is required');
170
+ if (!meta.updatedAt) errors.push('updatedAt is required');
171
+ validatePersonaV3Requirements(
172
+ {
173
+ version: meta.version,
174
+ type: meta.type,
175
+ personaSource: meta.personaSource,
176
+ disc: meta.disc,
177
+ enneagram: meta.enneagram,
178
+ bigFive: meta.bigFive,
179
+ mbti: meta.mbti,
180
+ confidence: meta.confidence,
181
+ profilerReport: meta.profilerReport
182
+ },
183
+ {
184
+ cognitiveProfile: Array(meta.counts.cognitiveProfile).fill('x'),
185
+ communicationStyle: Array(meta.counts.communicationStyle).fill('x'),
186
+ biases: Array(meta.counts.biases).fill('x')
187
+ },
188
+ errors
189
+ );
190
+
191
+ return buildResult(errors, meta, 'meta');
192
+ }
193
+
194
+ function assertValidGenome(input) {
195
+ const result = validateGenomeObject(input);
196
+ if (!result.valid) {
197
+ throw new Error(`Invalid genome: ${result.errors.join('; ')}`);
198
+ }
199
+ return result.genome;
200
+ }
201
+
202
+ function assertValidGenomeMeta(input) {
203
+ const result = validateGenomeMeta(input);
204
+ if (!result.valid) {
205
+ throw new Error(`Invalid genome meta: ${result.errors.join('; ')}`);
206
+ }
207
+ return result.meta;
208
+ }
209
+
210
+ module.exports = {
211
+ validateGenomeObject,
212
+ validateGenomeMeta,
213
+ assertValidGenome,
214
+ assertValidGenomeMeta
215
+ };