@wenathlan/saddle 1.8.16 → 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 (223) hide show
  1. package/README.md +38 -13
  2. package/dist/apps/registry.d.ts +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/isolation/contracts.d.ts +118 -0
  8. package/dist/isolation/contracts.d.ts.map +1 -0
  9. package/dist/isolation/contracts.js +84 -0
  10. package/dist/isolation/contracts.js.map +1 -0
  11. package/dist/mcp/server.d.ts +2 -2
  12. package/dist/scrape/robots.js +1 -1
  13. package/docs/artifactavailability.md +18 -2
  14. package/docs/containerplatforms-1.8.17.md +29 -0
  15. package/docs/releasenotes-1.8.16.md +6 -2
  16. package/docs/releasenotes-1.8.17.md +43 -0
  17. package/docs/releasenotes-1.8.18.md +32 -0
  18. package/docs/research-1.8.18-isolation.md +43 -0
  19. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  20. package/docs/todo-1.8.16.md +92 -8
  21. package/docs/todo-1.8.18.md +152 -0
  22. package/docs/workflowoperations.md +32 -0
  23. package/extension/manifest.json +1 -1
  24. package/package.json +3 -2
  25. package/docs/logs/.gitkeep +0 -0
  26. package/docs/plans/00.index.md +0 -50
  27. package/docs/plans/01.architecture.md +0 -86
  28. package/docs/plans/02.research.computer.use.md +0 -58
  29. package/docs/plans/03.research.captcha.bypass.md +0 -68
  30. package/docs/plans/04.research.sandbox.ai.md +0 -52
  31. package/docs/plans/05.capture.platform.md +0 -57
  32. package/docs/plans/06.dependencies.md +0 -97
  33. package/docs/plans/07.captcha.test.page.md +0 -41
  34. package/docs/plans/08.production.infra.md +0 -70
  35. package/docs/plans/09.database.schema.md +0 -121
  36. package/docs/plans/10.cloudinary.storage.md +0 -57
  37. package/docs/plans/11.movement.logs.json.md +0 -72
  38. package/docs/plans/12.research.atlas.agent.browser.md +0 -79
  39. package/docs/plans/13.research.anti.detection.md +0 -898
  40. package/docs/plans/14.research.proxy.md +0 -1495
  41. package/docs/plans/15.research.retry.rate.limit.md +0 -1958
  42. package/docs/plans/16.research.crawling.md +0 -1417
  43. package/docs/plans/17.research.caching.md +0 -1610
  44. package/docs/plans/18.research.content.extraction.md +0 -1952
  45. package/docs/plans/19.research.errors.events.md +0 -1523
  46. package/docs/plans/20.research.zod.validation.md +0 -1350
  47. package/docs/plans/21.research.batch.concurrency.md +0 -1888
  48. package/docs/plans/22.research.universal.runtime.md +0 -944
  49. package/docs/plans/23.research.ai.integration.md +0 -1465
  50. package/docs/plans/24.research.memory.persistence.md +0 -1979
  51. package/docs/plans/25.research.server.api.md +0 -342
  52. package/docs/plans/26.research.compilation.md +0 -249
  53. package/docs/plans/27.research.html.parsing.md +0 -251
  54. package/docs/plans/28.action.plan.md +0 -50
  55. package/docs/plans/29.api.reference.md +0 -174
  56. package/docs/plans/30.architecture.plan.md +0 -94
  57. package/docs/plans/31.auditoria.dados.md +0 -163
  58. package/docs/plans/32.bots.automacao.computacional.md +0 -214
  59. package/docs/plans/33.bots.codigo.revisao.md +0 -220
  60. package/docs/plans/34.bots.seguranca.cicd.md +0 -366
  61. package/docs/plans/35.comparativo.concorrencia.md +0 -464
  62. package/docs/plans/36.computational.memory.md +0 -340
  63. package/docs/plans/37.deploystrategy.md +0 -394
  64. package/docs/plans/38.flow.md +0 -155
  65. package/docs/plans/39.multi.platform.bot.md +0 -252
  66. package/docs/plans/40.npm.publish.md +0 -250
  67. package/docs/plans/41.o.que.falta.md +0 -407
  68. package/docs/plans/42.pesquisa.concorrencia.md +0 -721
  69. package/docs/plans/43.plan.universal.architecture.md +0 -496
  70. package/docs/plans/44.reference.md +0 -100
  71. package/docs/plans/45.robotarchitecture.md +0 -237
  72. package/docs/plans/46.scdnintegration.md +0 -284
  73. package/docs/plans/47.multiforge.readme.md +0 -129
  74. package/docs/plans/48.theory.v4.repo.os.md +0 -152
  75. package/docs/plans/49.third.party.infra.md +0 -12
  76. package/docs/plans/50.file.as.compute.md +0 -39
  77. package/docs/plans/51.architecture.virtual.processor.md +0 -80
  78. package/docs/plans/52.manifesto.v8.md +0 -11
  79. package/docs/plans/58.cdn.list.md +0 -23
  80. package/docs/plans/59.sql.frameworks.md +0 -33
  81. package/docs/plans/60.sql.thirdparty.md +0 -26
  82. package/docs/plans/61.objective.multiforge.md +0 -63
  83. package/docs/plans/62.huggingface.upload.md +0 -26
  84. package/docs/plans/63.kaggle.upload.md +0 -24
  85. package/docs/plans/64.npm.storage.md +0 -30
  86. package/docs/plans/65.rclone.terabox.md +0 -32
  87. package/docs/plans/66.buckets.and.models.todo.md +0 -14
  88. package/docs/plans/67.database.todo.md +0 -13
  89. package/docs/plans/68.deploy.packages.todo.md +0 -12
  90. package/docs/plans/69.report.human.operator.md +0 -133
  91. package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
  92. package/docs/plans/71.report.hd.infinito.vram.md +0 -155
  93. package/docs/plans/72.plan.hd.infinito.node.md +0 -146
  94. package/docs/plans/73.plan.scifi.repos.md +0 -125
  95. package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
  96. package/docs/plans/README.md +0 -489
  97. package/docs/plans/aggregate_platforms.mjs +0 -146
  98. package/docs/plans/examplesession.json +0 -36
  99. package/docs/plans/missing-facts.md +0 -192
  100. package/docs/plans/models.md +0 -64
  101. package/docs/plans/organize.cjs +0 -270
  102. package/docs/plans/platforms.md +0 -2887
  103. package/docs/plans/sites.md +0 -31322
  104. package/docs/sources/farm.py +0 -117
  105. package/docs/sources/html/saddle1.html +0 -132
  106. package/docs/sources/html/saddle2.html +0 -157
  107. package/docs/sources/html/saddle3.html +0 -119
  108. package/docs/sources/html/saddle4.html +0 -144
  109. package/docs/sources/html/saddle5.html +0 -72
  110. package/docs/sources/html/saddle6.html +0 -171
  111. package/docs/sources/html/saddle7.html +0 -236
  112. package/docs/sources/saddle.ts +0 -74
  113. package/docs/sources/schema.prisma +0 -88
  114. package/docs/sources/script.sh +0 -64
  115. package/docs/sources/workflows.yml +0 -458
  116. package/docs/talks1/_body.txt +0 -14
  117. package/docs/talks1/_index.md +0 -15
  118. package/docs/talks1/_screenshot.png +0 -0
  119. package/docs/talks1/assistant-01.md +0 -5
  120. package/docs/talks1/assistant-02.md +0 -5
  121. package/docs/talks1/assistant-03.md +0 -531
  122. package/docs/talks1/assistant-04.md +0 -26
  123. package/docs/talks1/assistant-05.md +0 -774
  124. package/docs/talks1/assistant-06.md +0 -1718
  125. package/docs/talks1/scrape-share.cjs +0 -185
  126. package/docs/talks1/scrape-share.ts +0 -183
  127. package/docs/talks1/user-01.md +0 -3
  128. package/docs/talks1/user-02.md +0 -3
  129. package/docs/talks1/user-03.md +0 -88
  130. package/docs/talks1/user-04.md +0 -3
  131. package/docs/talks1/user-05.md +0 -3
  132. package/docs/talks1/user-06.md +0 -88
  133. package/docs/talks1/user-07.md +0 -88
  134. package/docs/talks2/_body.txt +0 -14
  135. package/docs/talks2/_index.md +0 -16
  136. package/docs/talks2/_screenshot.png +0 -0
  137. package/docs/talks2/assistant-01.md +0 -5
  138. package/docs/talks2/assistant-02.md +0 -5
  139. package/docs/talks2/assistant-03.md +0 -424
  140. package/docs/talks2/assistant-04.md +0 -598
  141. package/docs/talks2/assistant-05.md +0 -1280
  142. package/docs/talks2/assistant-06.md +0 -1227
  143. package/docs/talks2/assistant-07.md +0 -1252
  144. package/docs/talks2/user-01.md +0 -3
  145. package/docs/talks2/user-02.md +0 -3
  146. package/docs/talks2/user-03.md +0 -88
  147. package/docs/talks2/user-04.md +0 -88
  148. package/docs/talks2/user-05.md +0 -88
  149. package/docs/talks2/user-06.md +0 -88
  150. package/docs/talks2/user-07.md +0 -3
  151. package/docs/talks3/_body.txt +0 -467
  152. package/docs/talks3/_index.md +0 -10
  153. package/docs/talks3/_screenshot.png +0 -0
  154. package/docs/talks3/assistant-01.md +0 -417
  155. package/docs/talks3/assistant-02.md +0 -417
  156. package/docs/talks3/assistant-03.md +0 -29
  157. package/docs/talks3/assistant-04.md +0 -727
  158. package/docs/talks3/user-01.md +0 -88
  159. package/docs/talks3/user-02.md +0 -88
  160. package/docs/talks3/user-03.md +0 -3
  161. package/docs/talks3/user-04.md +0 -3
  162. package/docs/talks4/_body.txt +0 -14
  163. package/docs/talks4/_index.md +0 -12
  164. package/docs/talks4/_screenshot.png +0 -0
  165. package/docs/talks4/assistant-01.md +0 -5
  166. package/docs/talks4/assistant-02.md +0 -5
  167. package/docs/talks4/assistant-03.md +0 -35
  168. package/docs/talks4/assistant-04.md +0 -512
  169. package/docs/talks4/assistant-05.md +0 -599
  170. package/docs/talks4/user-01.md +0 -3
  171. package/docs/talks4/user-02.md +0 -3
  172. package/docs/talks4/user-03.md +0 -88
  173. package/docs/talks4/user-04.md +0 -88
  174. package/docs/talks4/user-05.md +0 -7
  175. package/docs/talks5/_body.txt +0 -14
  176. package/docs/talks5/_index.md +0 -13
  177. package/docs/talks5/_screenshot.png +0 -0
  178. package/docs/talks5/assistant-01.md +0 -5
  179. package/docs/talks5/assistant-02.md +0 -5
  180. package/docs/talks5/assistant-03.md +0 -690
  181. package/docs/talks5/assistant-04.md +0 -758
  182. package/docs/talks5/assistant-05.md +0 -974
  183. package/docs/talks5/user-01.md +0 -3
  184. package/docs/talks5/user-02.md +0 -3
  185. package/docs/talks5/user-03.md +0 -105
  186. package/docs/talks5/user-04.md +0 -105
  187. package/docs/talks5/user-05.md +0 -63
  188. package/docs/talks5/user-06.md +0 -105
  189. package/docs/talks6/_body.txt +0 -14
  190. package/docs/talks6/_index.md +0 -9
  191. package/docs/talks6/_screenshot.png +0 -0
  192. package/docs/talks6/assistant-01.md +0 -5
  193. package/docs/talks6/assistant-02.md +0 -5
  194. package/docs/talks6/assistant-03.md +0 -1499
  195. package/docs/talks6/user-01.md +0 -3
  196. package/docs/talks6/user-02.md +0 -3
  197. package/docs/talks6/user-03.md +0 -88
  198. package/docs/talks6/user-04.md +0 -88
  199. package/docs/talks7/_body.txt +0 -14
  200. package/docs/talks7/_index.md +0 -10
  201. package/docs/talks7/_screenshot.png +0 -0
  202. package/docs/talks7/assistant-01.md +0 -5
  203. package/docs/talks7/assistant-02.md +0 -5
  204. package/docs/talks7/assistant-03.md +0 -523
  205. package/docs/talks7/assistant-04.md +0 -617
  206. package/docs/talks7/user-01.md +0 -3
  207. package/docs/talks7/user-02.md +0 -3
  208. package/docs/talks7/user-03.md +0 -105
  209. package/docs/talks7/user-04.md +0 -67
  210. package/docs/talks8/conversa1.txt +0 -1322
  211. package/docs/talks8/conversa2.txt +0 -237
  212. 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
  213. 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
  214. 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
  215. 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
  216. 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
  217. package/docs/talks9/README (2).md +0 -489
  218. package/docs/talks9/README.md +0 -198
  219. 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
  220. package/docs/talks9/conversa.txt +0 -544
  221. package/docs/talks9/other (2).md +0 -39
  222. package/docs/talks9/other.md +0 -57
  223. 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'));