@wenathlan/saddle 1.8.17 → 1.8.18

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 (219) hide show
  1. package/README.md +38 -13
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/isolation/contracts.d.ts +118 -0
  7. package/dist/isolation/contracts.d.ts.map +1 -0
  8. package/dist/isolation/contracts.js +84 -0
  9. package/dist/isolation/contracts.js.map +1 -0
  10. package/dist/mcp/server.d.ts +2 -2
  11. package/dist/scrape/robots.js +1 -1
  12. package/docs/artifactavailability.md +6 -0
  13. package/docs/releasenotes-1.8.17.md +6 -0
  14. package/docs/releasenotes-1.8.18.md +32 -0
  15. package/docs/research-1.8.18-isolation.md +43 -0
  16. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  17. package/docs/todo-1.8.16.md +56 -1
  18. package/docs/todo-1.8.18.md +152 -0
  19. package/extension/manifest.json +1 -1
  20. package/package.json +3 -2
  21. package/docs/logs/.gitkeep +0 -0
  22. package/docs/plans/00.index.md +0 -50
  23. package/docs/plans/01.architecture.md +0 -86
  24. package/docs/plans/02.research.computer.use.md +0 -58
  25. package/docs/plans/03.research.captcha.bypass.md +0 -68
  26. package/docs/plans/04.research.sandbox.ai.md +0 -52
  27. package/docs/plans/05.capture.platform.md +0 -57
  28. package/docs/plans/06.dependencies.md +0 -97
  29. package/docs/plans/07.captcha.test.page.md +0 -41
  30. package/docs/plans/08.production.infra.md +0 -70
  31. package/docs/plans/09.database.schema.md +0 -121
  32. package/docs/plans/10.cloudinary.storage.md +0 -57
  33. package/docs/plans/11.movement.logs.json.md +0 -72
  34. package/docs/plans/12.research.atlas.agent.browser.md +0 -79
  35. package/docs/plans/13.research.anti.detection.md +0 -898
  36. package/docs/plans/14.research.proxy.md +0 -1495
  37. package/docs/plans/15.research.retry.rate.limit.md +0 -1958
  38. package/docs/plans/16.research.crawling.md +0 -1417
  39. package/docs/plans/17.research.caching.md +0 -1610
  40. package/docs/plans/18.research.content.extraction.md +0 -1952
  41. package/docs/plans/19.research.errors.events.md +0 -1523
  42. package/docs/plans/20.research.zod.validation.md +0 -1350
  43. package/docs/plans/21.research.batch.concurrency.md +0 -1888
  44. package/docs/plans/22.research.universal.runtime.md +0 -944
  45. package/docs/plans/23.research.ai.integration.md +0 -1465
  46. package/docs/plans/24.research.memory.persistence.md +0 -1979
  47. package/docs/plans/25.research.server.api.md +0 -342
  48. package/docs/plans/26.research.compilation.md +0 -249
  49. package/docs/plans/27.research.html.parsing.md +0 -251
  50. package/docs/plans/28.action.plan.md +0 -50
  51. package/docs/plans/29.api.reference.md +0 -174
  52. package/docs/plans/30.architecture.plan.md +0 -94
  53. package/docs/plans/31.auditoria.dados.md +0 -163
  54. package/docs/plans/32.bots.automacao.computacional.md +0 -214
  55. package/docs/plans/33.bots.codigo.revisao.md +0 -220
  56. package/docs/plans/34.bots.seguranca.cicd.md +0 -366
  57. package/docs/plans/35.comparativo.concorrencia.md +0 -464
  58. package/docs/plans/36.computational.memory.md +0 -340
  59. package/docs/plans/37.deploystrategy.md +0 -394
  60. package/docs/plans/38.flow.md +0 -155
  61. package/docs/plans/39.multi.platform.bot.md +0 -252
  62. package/docs/plans/40.npm.publish.md +0 -250
  63. package/docs/plans/41.o.que.falta.md +0 -407
  64. package/docs/plans/42.pesquisa.concorrencia.md +0 -721
  65. package/docs/plans/43.plan.universal.architecture.md +0 -496
  66. package/docs/plans/44.reference.md +0 -100
  67. package/docs/plans/45.robotarchitecture.md +0 -237
  68. package/docs/plans/46.scdnintegration.md +0 -284
  69. package/docs/plans/47.multiforge.readme.md +0 -129
  70. package/docs/plans/48.theory.v4.repo.os.md +0 -152
  71. package/docs/plans/49.third.party.infra.md +0 -12
  72. package/docs/plans/50.file.as.compute.md +0 -39
  73. package/docs/plans/51.architecture.virtual.processor.md +0 -80
  74. package/docs/plans/52.manifesto.v8.md +0 -11
  75. package/docs/plans/58.cdn.list.md +0 -23
  76. package/docs/plans/59.sql.frameworks.md +0 -33
  77. package/docs/plans/60.sql.thirdparty.md +0 -26
  78. package/docs/plans/61.objective.multiforge.md +0 -63
  79. package/docs/plans/62.huggingface.upload.md +0 -26
  80. package/docs/plans/63.kaggle.upload.md +0 -24
  81. package/docs/plans/64.npm.storage.md +0 -30
  82. package/docs/plans/65.rclone.terabox.md +0 -32
  83. package/docs/plans/66.buckets.and.models.todo.md +0 -14
  84. package/docs/plans/67.database.todo.md +0 -13
  85. package/docs/plans/68.deploy.packages.todo.md +0 -12
  86. package/docs/plans/69.report.human.operator.md +0 -133
  87. package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
  88. package/docs/plans/71.report.hd.infinito.vram.md +0 -155
  89. package/docs/plans/72.plan.hd.infinito.node.md +0 -146
  90. package/docs/plans/73.plan.scifi.repos.md +0 -125
  91. package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
  92. package/docs/plans/README.md +0 -489
  93. package/docs/plans/aggregate_platforms.mjs +0 -146
  94. package/docs/plans/examplesession.json +0 -36
  95. package/docs/plans/missing-facts.md +0 -192
  96. package/docs/plans/models.md +0 -64
  97. package/docs/plans/organize.cjs +0 -270
  98. package/docs/plans/platforms.md +0 -2887
  99. package/docs/plans/sites.md +0 -31322
  100. package/docs/sources/farm.py +0 -117
  101. package/docs/sources/html/saddle1.html +0 -132
  102. package/docs/sources/html/saddle2.html +0 -157
  103. package/docs/sources/html/saddle3.html +0 -119
  104. package/docs/sources/html/saddle4.html +0 -144
  105. package/docs/sources/html/saddle5.html +0 -72
  106. package/docs/sources/html/saddle6.html +0 -171
  107. package/docs/sources/html/saddle7.html +0 -236
  108. package/docs/sources/saddle.ts +0 -74
  109. package/docs/sources/schema.prisma +0 -88
  110. package/docs/sources/script.sh +0 -64
  111. package/docs/sources/workflows.yml +0 -458
  112. package/docs/talks1/_body.txt +0 -14
  113. package/docs/talks1/_index.md +0 -15
  114. package/docs/talks1/_screenshot.png +0 -0
  115. package/docs/talks1/assistant-01.md +0 -5
  116. package/docs/talks1/assistant-02.md +0 -5
  117. package/docs/talks1/assistant-03.md +0 -531
  118. package/docs/talks1/assistant-04.md +0 -26
  119. package/docs/talks1/assistant-05.md +0 -774
  120. package/docs/talks1/assistant-06.md +0 -1718
  121. package/docs/talks1/scrape-share.cjs +0 -185
  122. package/docs/talks1/scrape-share.ts +0 -183
  123. package/docs/talks1/user-01.md +0 -3
  124. package/docs/talks1/user-02.md +0 -3
  125. package/docs/talks1/user-03.md +0 -88
  126. package/docs/talks1/user-04.md +0 -3
  127. package/docs/talks1/user-05.md +0 -3
  128. package/docs/talks1/user-06.md +0 -88
  129. package/docs/talks1/user-07.md +0 -88
  130. package/docs/talks2/_body.txt +0 -14
  131. package/docs/talks2/_index.md +0 -16
  132. package/docs/talks2/_screenshot.png +0 -0
  133. package/docs/talks2/assistant-01.md +0 -5
  134. package/docs/talks2/assistant-02.md +0 -5
  135. package/docs/talks2/assistant-03.md +0 -424
  136. package/docs/talks2/assistant-04.md +0 -598
  137. package/docs/talks2/assistant-05.md +0 -1280
  138. package/docs/talks2/assistant-06.md +0 -1227
  139. package/docs/talks2/assistant-07.md +0 -1252
  140. package/docs/talks2/user-01.md +0 -3
  141. package/docs/talks2/user-02.md +0 -3
  142. package/docs/talks2/user-03.md +0 -88
  143. package/docs/talks2/user-04.md +0 -88
  144. package/docs/talks2/user-05.md +0 -88
  145. package/docs/talks2/user-06.md +0 -88
  146. package/docs/talks2/user-07.md +0 -3
  147. package/docs/talks3/_body.txt +0 -467
  148. package/docs/talks3/_index.md +0 -10
  149. package/docs/talks3/_screenshot.png +0 -0
  150. package/docs/talks3/assistant-01.md +0 -417
  151. package/docs/talks3/assistant-02.md +0 -417
  152. package/docs/talks3/assistant-03.md +0 -29
  153. package/docs/talks3/assistant-04.md +0 -727
  154. package/docs/talks3/user-01.md +0 -88
  155. package/docs/talks3/user-02.md +0 -88
  156. package/docs/talks3/user-03.md +0 -3
  157. package/docs/talks3/user-04.md +0 -3
  158. package/docs/talks4/_body.txt +0 -14
  159. package/docs/talks4/_index.md +0 -12
  160. package/docs/talks4/_screenshot.png +0 -0
  161. package/docs/talks4/assistant-01.md +0 -5
  162. package/docs/talks4/assistant-02.md +0 -5
  163. package/docs/talks4/assistant-03.md +0 -35
  164. package/docs/talks4/assistant-04.md +0 -512
  165. package/docs/talks4/assistant-05.md +0 -599
  166. package/docs/talks4/user-01.md +0 -3
  167. package/docs/talks4/user-02.md +0 -3
  168. package/docs/talks4/user-03.md +0 -88
  169. package/docs/talks4/user-04.md +0 -88
  170. package/docs/talks4/user-05.md +0 -7
  171. package/docs/talks5/_body.txt +0 -14
  172. package/docs/talks5/_index.md +0 -13
  173. package/docs/talks5/_screenshot.png +0 -0
  174. package/docs/talks5/assistant-01.md +0 -5
  175. package/docs/talks5/assistant-02.md +0 -5
  176. package/docs/talks5/assistant-03.md +0 -690
  177. package/docs/talks5/assistant-04.md +0 -758
  178. package/docs/talks5/assistant-05.md +0 -974
  179. package/docs/talks5/user-01.md +0 -3
  180. package/docs/talks5/user-02.md +0 -3
  181. package/docs/talks5/user-03.md +0 -105
  182. package/docs/talks5/user-04.md +0 -105
  183. package/docs/talks5/user-05.md +0 -63
  184. package/docs/talks5/user-06.md +0 -105
  185. package/docs/talks6/_body.txt +0 -14
  186. package/docs/talks6/_index.md +0 -9
  187. package/docs/talks6/_screenshot.png +0 -0
  188. package/docs/talks6/assistant-01.md +0 -5
  189. package/docs/talks6/assistant-02.md +0 -5
  190. package/docs/talks6/assistant-03.md +0 -1499
  191. package/docs/talks6/user-01.md +0 -3
  192. package/docs/talks6/user-02.md +0 -3
  193. package/docs/talks6/user-03.md +0 -88
  194. package/docs/talks6/user-04.md +0 -88
  195. package/docs/talks7/_body.txt +0 -14
  196. package/docs/talks7/_index.md +0 -10
  197. package/docs/talks7/_screenshot.png +0 -0
  198. package/docs/talks7/assistant-01.md +0 -5
  199. package/docs/talks7/assistant-02.md +0 -5
  200. package/docs/talks7/assistant-03.md +0 -523
  201. package/docs/talks7/assistant-04.md +0 -617
  202. package/docs/talks7/user-01.md +0 -3
  203. package/docs/talks7/user-02.md +0 -3
  204. package/docs/talks7/user-03.md +0 -105
  205. package/docs/talks7/user-04.md +0 -67
  206. package/docs/talks8/conversa1.txt +0 -1322
  207. package/docs/talks8/conversa2.txt +0 -237
  208. package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +0 -174
  209. package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +0 -59
  210. package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +0 -91
  211. package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +0 -116
  212. package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +0 -128
  213. package/docs/talks9/README (2).md +0 -489
  214. package/docs/talks9/README.md +0 -198
  215. package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +0 -80
  216. package/docs/talks9/conversa.txt +0 -544
  217. package/docs/talks9/other (2).md +0 -39
  218. package/docs/talks9/other.md +0 -57
  219. package/docs/talks9/outro.txt +0 -24
@@ -1,270 +0,0 @@
1
- const crypto = require('crypto');
2
- const fs = require('fs');
3
- const path = require('path');
4
-
5
- const ROOT = __dirname; // docs/plans
6
- const MESSY = path.join(ROOT, 'messy');
7
- const APPLY = process.argv.includes('--apply');
8
-
9
- // Boilerplate that pollutes the messy files ("mocado"):
10
- // - the whole V8-FLAT preamble block
11
- // - the repeated "SQL Sentido ..." template fragment
12
- function isBoilerplateLine(l) {
13
- return (
14
- /V8 ?FLAT/i.test(l) ||
15
- /Este arquivo faz parte da estrutura/i.test(l) ||
16
- /Todo conteudo V1-V7/i.test(l) ||
17
- /migrado para arquivos planos numerados/i.test(l) ||
18
- /^>\s*V8/i.test(l) ||
19
- /^Regra:/i.test(l) ||
20
- /^-\s*(NOME|SEM|Flat)\b/i.test(l) ||
21
- /Conteudo original de:/i.test(l) ||
22
- /^SQL Sentido/i.test(l) ||
23
- /^E DDL\. E CREATE/i.test(l) ||
24
- /^Trigger: \/api\/init/i.test(l)
25
- );
26
- }
27
-
28
- // strip every boilerplate line, collapse 3+ blank lines into 2, trim
29
- function stripStub(text) {
30
- const stripped = text
31
- .split(/\r?\n/)
32
- .filter((l) => !isBoilerplateLine(l))
33
- .join('\n');
34
- return stripped.replace(/\n{3,}/g, '\n\n').trim() + (stripped.includes('\n') ? '\n' : '');
35
- }
36
-
37
- // a file is a pure stub if, after stripping boilerplate, only a title/whitespace remains
38
- function isStub(text) {
39
- const body = stripStub(text)
40
- .replace(/^#{1,6}\s.*$/m, '')
41
- .replace(/[\r\n#*`>\-\s]/g, '')
42
- .trim();
43
- return body.length < 50;
44
- }
45
-
46
- const normExt = (n) => path.extname(n).toLowerCase().replace(/^\./, '');
47
- const hash = (b) => crypto.createHash('sha256').update(b).digest('hex');
48
-
49
- // canonical docs (md/txt) -> numbered plans doc. TXT and MD are the same: result is MD.
50
- const DOCS = [
51
- ['README.md', '47.multiforge.readme.md'],
52
- ['V4 TEORIA COMPLETA.md', '48.theory.v4.repo.os.md'],
53
- ['V5 THIRD PARTY.md', '49.third.party.infra.md'],
54
- ['V6 FILE AS COMPUTE.md', '50.file.as.compute.md'],
55
- ['ARCHITECTURE.md', '51.architecture.virtual.processor.md'],
56
- ['000 Manifesto V8 Flat.txt', '52.manifesto.v8.md'],
57
- ['001 Documentacao Objetivo.md', '53.objective.md'],
58
- ['002 Documentacao Arquitetura Flat.md', '54.architecture.flat.md'],
59
- ['003 Documentacao V7 Postmortem Pastas.md', '55.v7.postmortem.md'],
60
- ['004 Documentacao Regras Nomenclatura.md', '56.naming.rules.md'],
61
- ['005 Documentacao Indice Completo.md', '57.index.complete.md'],
62
- ['10 CDNS.md', '58.cdn.list.md'],
63
- ['SQL FRAMEWORKS.md', '59.sql.frameworks.md'],
64
- ['1 sql thirdparty.md', '60.sql.thirdparty.md'],
65
- ['1 Objetivo.md', '61.objective.multiforge.md'],
66
- ['1 huggingface upload.md', '62.huggingface.upload.md'],
67
- ['1 kaggle upload.md', '63.kaggle.upload.md'],
68
- ['1 npm storage.md', '64.npm.storage.md'],
69
- ['1 rclone terabox.md', '65.rclone.terabox.md'],
70
- ['Human-Operator-Relatório-Completo.md', '69.report.human.operator.md'],
71
- ['Relatório-Brain2Qwerty-+-Acupuntura-vs-EMS.md', '70.report.brain2qwerty.ems.md'],
72
- ['Relatório-HD-Infinito-e-VRAM-Limites-e-Arquitetura-Viável.md', '71.report.hd.infinito.vram.md'],
73
- ['Plano-30-Soluções-HD-Infinito-via-Node.md', '72.plan.hd.infinito.node.md'],
74
- ['Plano-de-Tópicos-Sci-Fi-com-Repos.md', '73.plan.scifi.repos.md'],
75
- ];
76
- const DOC_SRC_SET = new Set(DOCS.map((d) => d[0]));
77
-
78
- // stale stub-topic fragments (011-050) are routed into these consolidation docs
79
- const TODO_BASE = {
80
- '66.buckets.and.models.todo.md':
81
- '# Buckets & Models (TODO)\n\nConsolidated placeholder for stub topics originally in `docs/plans/messy` (011-018).\n\n- Hugging Face Datasets bucket\n- Hugging Face Models bucket\n- Cloudflare R2 config\n- Local file system\n- Whisper transcription\n- Embeddings / vectors\n- LLM classification\n- Vision OCR\n\nSee also: `10.cloudinary.storage.md`, `08.production.infra.md`.',
82
- '67.database.todo.md':
83
- '# Database (TODO)\n\nConsolidated placeholder for stub topics originally in `docs/plans/messy` (019-025).\n\n- Prisma schema\n- Drizzle schema\n- SQLite local\n- Turso / libSQL\n- Postgres Neon\n- Auto migrations\n- BigInt pointers\n\nSee also: `09.database.schema.md`, `06.dependencies.md`.',
84
- '68.deploy.packages.todo.md':
85
- '# Deploy & Packages (TODO)\n\nConsolidated placeholder for stub topics originally in `docs/plans/messy` (032-050).\n\n- Vercel config\n- Package scripts\n- Env vars\n- Build pipeline\n- Packages: better-sqlite3, libsql-client, drizzle-orm, prisma-client, vercel-blob, netlify-blobs, unstorage, piscina, p-queue, isolated-vm\n- Storage queue / atomic rename / pending jobs\n\nSee also: `37.deploystrategy.md`, `40.npm.publish.md`, `09.database.schema.md`, `21.research.batch.concurrency.md`, `04.research.sandbox.ai.md`, `24.research.memory.persistence.md`.',
86
- };
87
- const TODO_ORDER = [
88
- '66.buckets.and.models.todo.md',
89
- '67.database.todo.md',
90
- '68.deploy.packages.todo.md',
91
- ];
92
- const notesByTodo = {
93
- '66.buckets.and.models.todo.md': new Map(),
94
- '67.database.todo.md': new Map(),
95
- '68.deploy.packages.todo.md': new Map(),
96
- };
97
- function routeNote(dest, h, content) {
98
- const m = notesByTodo[dest];
99
- if (!m.has(h)) m.set(h, content);
100
- }
101
-
102
- // merged single-file name per code extension (formats kept separate)
103
- const CODE_NAME = {
104
- ts: 'saddle.ts',
105
- sh: 'script.sh',
106
- py: 'farm.py',
107
- prisma: 'schema.prisma',
108
- yml: 'workflows.yml',
109
- yaml: 'workflows.yaml',
110
- };
111
-
112
- function walk(dir) {
113
- const out = [];
114
- for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
115
- const full = path.join(dir, e.name);
116
- if (e.isDirectory()) walk(full).forEach((x) => out.push(x));
117
- else if (e.isFile()) out.push(full);
118
- }
119
- return out;
120
- }
121
-
122
- const all = walk(MESSY);
123
- const actions = [];
124
- const outputs = []; // { dest, content }
125
- const codeByExt = {};
126
- const htmlSeen = new Set();
127
- const htmlOut = [];
128
- const mdDocSeen = new Set();
129
- let docStray = 74;
130
- let nDoc = 0;
131
- let nCode = 0;
132
- let nHtml = 0;
133
-
134
- // 1) canonical docs
135
- for (const [src, dest] of DOCS) {
136
- const abs = path.join(MESSY, src);
137
- if (!fs.existsSync(abs)) {
138
- actions.push(`MISSING ${src}`);
139
- continue;
140
- }
141
- let raw;
142
- try {
143
- raw = fs.readFileSync(abs, 'utf8');
144
- } catch {
145
- actions.push(`READERR ${src}`);
146
- continue;
147
- }
148
- const clean = stripStub(raw);
149
- if (isStub(clean)) {
150
- actions.push(`SKIP-STUB ${src}`);
151
- continue;
152
- }
153
- mdDocSeen.add(hash(Buffer.from(clean)));
154
- outputs.push({ dest, content: clean });
155
- nDoc++;
156
- actions.push(`DOC ${src} -> ${dest}`);
157
- }
158
-
159
- // 2) everything else: merge code per ext, keep html separate, catch stray md/txt
160
- for (const f of all) {
161
- const rel = path.relative(MESSY, f);
162
- const ext = normExt(f);
163
- let raw;
164
- try {
165
- raw = fs.readFileSync(f, 'utf8');
166
- } catch {
167
- continue; // binary / unreadable -> skip
168
- }
169
- const clean = stripStub(raw);
170
- if (isStub(clean)) continue; // drop stubs (incl. the "SQL Sentido" template-only files)
171
-
172
- if (ext === 'md' || ext === 'txt') {
173
- if (DOC_SRC_SET.has(rel)) continue; // already handled as canonical doc
174
- const h = hash(Buffer.from(clean));
175
- const n = parseInt((path.basename(f).match(/^(\d+)/) || [])[1] || '0', 10);
176
- if (n >= 11 && n <= 18) { routeNote('66.buckets.and.models.todo.md', h, clean); actions.push(`NOTE 66 <- ${rel}`); continue; }
177
- if (n >= 19 && n <= 25) { routeNote('67.database.todo.md', h, clean); actions.push(`NOTE 67 <- ${rel}`); continue; }
178
- if (n >= 32 && n <= 50) { routeNote('68.deploy.packages.todo.md', h, clean); actions.push(`NOTE 68 <- ${rel}`); continue; }
179
- // other genuinely-real md/txt -> keep as separate numbered doc
180
- if (mdDocSeen.has(h)) continue;
181
- mdDocSeen.add(h);
182
- const base = path
183
- .basename(f)
184
- .replace(/\.[^.]+$/, '')
185
- .toLowerCase()
186
- .replace(/[^a-z0-9]+/g, '.');
187
- const dest = `${docStray++}.${base}.md`;
188
- outputs.push({ dest, content: clean });
189
- nDoc++;
190
- actions.push(`DOC* ${rel} -> ${dest}`);
191
- continue;
192
- }
193
-
194
- if (ext === 'html') {
195
- const h = hash(Buffer.from(clean));
196
- if (htmlSeen.has(h)) continue;
197
- htmlSeen.add(h);
198
- const name = path.basename(f).replace(/[ ()]/g, '_');
199
- htmlOut.push({ name, content: clean });
200
- nHtml++;
201
- actions.push(`HTML ${rel}`);
202
- continue;
203
- }
204
-
205
- // code / other text formats -> merge into one file per extension (no name prefixes)
206
- const arr = codeByExt[ext] || (codeByExt[ext] = []);
207
- const h = hash(Buffer.from(clean));
208
- if (arr.some((x) => x.hash === h)) continue; // skip byte-identical copies
209
- arr.push({ content: clean, hash: h });
210
- }
211
-
212
- // 3) build merged code files (one per extension; concatenated clean content, skip empty)
213
- for (const ext of Object.keys(codeByExt).sort()) {
214
- const parts = codeByExt[ext];
215
- const body = parts
216
- .map((p) => p.content)
217
- .join('\n\n')
218
- .replace(/\n{3,}/g, '\n\n')
219
- .trim();
220
- if (isStub(body)) {
221
- actions.push(`SKIP-MERGE ${ext} (boilerplate only)`);
222
- continue;
223
- }
224
- const name = CODE_NAME[ext] || `all.${ext}`;
225
- outputs.push({ dest: `sources/${name}`, content: body + '\n' });
226
- nCode++;
227
- actions.push(`MERGE ${ext} (${parts.length}) -> sources/${name}`);
228
- }
229
-
230
- // 4) html outputs
231
- for (const h of htmlOut) {
232
- outputs.push({ dest: `sources/html/${h.name}`, content: h.content });
233
- }
234
-
235
- // 5) consolidation docs (66/67/68) with any captured real fragments
236
- const todoDocs = TODO_ORDER.map((dest) => {
237
- let c = TODO_BASE[dest];
238
- const notes = [...notesByTodo[dest].values()];
239
- if (notes.length) {
240
- c += '\n\n## Captured notes (real fragments from messy/)\n';
241
- for (const note of notes) c += `\n---\n\n${note}\n`;
242
- }
243
- return [dest, c];
244
- });
245
- for (const [dest, content] of todoDocs) {
246
- outputs.push({ dest, content });
247
- actions.push(`CREATE ${dest}`);
248
- }
249
-
250
- const lines = [...actions];
251
- if (APPLY) {
252
- const srcDir = path.join(ROOT, 'sources');
253
- if (fs.existsSync(srcDir)) fs.rmSync(srcDir, { recursive: true, force: true });
254
- for (const o of outputs) {
255
- const p = path.join(ROOT, o.dest);
256
- fs.mkdirSync(path.dirname(p), { recursive: true });
257
- fs.writeFileSync(p, o.content);
258
- }
259
- try {
260
- fs.rmSync(MESSY, { recursive: true, force: true });
261
- lines.push('removed messy/');
262
- } catch (e) {
263
- lines.push('messy/ not removed: ' + e.message);
264
- }
265
- }
266
- lines.push('');
267
- lines.push(
268
- `${APPLY ? '[APPLY] ' : '[DRY-RUN] '}docs=${nDoc} codeMerge(exts)=${nCode} html=${nHtml} todo=${todoDocs.length} totalOutputs=${outputs.length}`
269
- );
270
- console.log(lines.join('\n'));