@jossuealcala/madre 1.0.2 → 1.0.3

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 (76) hide show
  1. package/CHANGELOG.en.md +69 -1
  2. package/CHANGELOG.md +69 -1
  3. package/README.en.md +11 -15
  4. package/README.md +3 -3
  5. package/bin/madre.cjs +40 -0
  6. package/bin/madre.mjs +5 -0
  7. package/docs/REFERENCE.md +29 -3
  8. package/docs/SDK.md +4 -2
  9. package/docs/en/REFERENCE.md +29 -3
  10. package/docs/en/SDK.md +4 -2
  11. package/docs/training/README.md +28 -1
  12. package/docs/training/train.sh +5 -1
  13. package/package.json +3 -3
  14. package/public/app.js +1626 -151
  15. package/public/attribution.js +44 -1
  16. package/public/brands.js +20 -5
  17. package/public/code-tools.js +143 -0
  18. package/public/editor.js +20 -4
  19. package/public/es.js +393 -25
  20. package/public/hardware.js +50 -0
  21. package/public/index.html +5 -1
  22. package/public/macroverso.js +187 -96
  23. package/public/market-art.js +161 -0
  24. package/public/market-view.js +529 -0
  25. package/public/market.js +189 -0
  26. package/public/neural.js +110 -0
  27. package/public/nostromo-engine.js +412 -47
  28. package/public/power.js +100 -0
  29. package/public/resay.js +5 -0
  30. package/public/salas-mac.css +98 -14
  31. package/public/salas-mac.html +9 -1
  32. package/public/salas-mac.js +307 -30
  33. package/public/styles.css +838 -61
  34. package/public/tour.js +48 -6
  35. package/public/troubleshooting.js +6 -1
  36. package/public/wallpaper.js +275 -0
  37. package/src/adapters/cursor.mjs +96 -0
  38. package/src/adapters/gemini.mjs +10 -3
  39. package/src/adapters/madre.mjs +2 -1
  40. package/src/auth-probe.mjs +143 -12
  41. package/src/bridge/policy.mjs +1 -1
  42. package/src/capabilities.mjs +9 -0
  43. package/src/checkpoint.mjs +16 -1
  44. package/src/credentials.mjs +3 -0
  45. package/src/dataset.mjs +76 -4
  46. package/src/enlaces.mjs +208 -2
  47. package/src/extensions.mjs +11 -3
  48. package/src/i18n.mjs +16 -0
  49. package/src/looks.mjs +125 -2
  50. package/src/market-key.mjs +8 -0
  51. package/src/market-remote.mjs +239 -0
  52. package/src/models.mjs +4 -0
  53. package/src/module-scope.mjs +68 -0
  54. package/src/modules/ahp.mjs +102 -7
  55. package/src/modules/bishop-exam.mjs +122 -0
  56. package/src/modules/bishop.mjs +71 -12
  57. package/src/modules/enlaces.mjs +87 -6
  58. package/src/modules/image-studio.mjs +10 -1
  59. package/src/modules/intents.mjs +3 -1
  60. package/src/modules/local-models.mjs +124 -0
  61. package/src/modules/ollama.mjs +12 -3
  62. package/src/modules/playwright.mjs +73 -15
  63. package/src/modules/sdk.mjs +61 -9
  64. package/src/npm-launch.mjs +18 -0
  65. package/src/ollama.mjs +6 -5
  66. package/src/outbound.mjs +9 -1
  67. package/src/ports.mjs +4 -2
  68. package/src/room/control.mjs +1 -1
  69. package/src/room/prompt.mjs +13 -2
  70. package/src/room.mjs +14 -4
  71. package/src/router.mjs +1 -1
  72. package/src/runs.mjs +4 -1
  73. package/src/runtime-detection.mjs +9 -0
  74. package/src/salas.mjs +26 -0
  75. package/src/server.mjs +617 -48
  76. package/src/setup.mjs +1 -1
@@ -0,0 +1,161 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // MADRE · © 2026 Jossue Alcalá · GNU AGPL v3 with additional terms (Section 7): ADDITIONAL-TERMS.md
3
+ // The Market's pictures (2026-10-18): drawn here, in code, not photographed. One scene for each
4
+ // module the carousel features — what it does, shown the way a person would see it happen — and a
5
+ // poster made from the icon for every other module. No words inside the drawings, so they read the
6
+ // same in both languages; each sits on its module's own colors (market.js, `hue`), whatever the
7
+ // room's light. Every id inside a drawing is made unique, because two of them can share a page.
8
+
9
+ import { cleanSvg, moduleFace, remoteEntry } from './market.js';
10
+
11
+ let drawn = 0;
12
+ const svg = (body, { width = 560, height = 400 } = {}) => `<svg viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">${body}</svg>`;
13
+ // A soft shadow under a card, and a card itself: the glass every scene is built from.
14
+ const shadow = (id) => `<filter id="${id}" x="-20%" y="-20%" width="140%" height="150%"><feDropShadow dx="0" dy="10" stdDeviation="12" flood-color="#000" flood-opacity=".22"/></filter>`;
15
+ const bar = (x, y, w, h, fill, opacity = 1) => `<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="${h / 2}" fill="${fill}" fill-opacity="${opacity}"/>`;
16
+
17
+ // TEST BROWSER: a page open in a browser, the pointer pressing its button, the screenshot that
18
+ // comes back, and the console the agent reads.
19
+ function browserScene() {
20
+ const id = `mka${++drawn}`;
21
+ return svg(`<defs>${shadow(`${id}s`)}<linearGradient id="${id}h" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#bfdbfe"/><stop offset="1" stop-color="#60a5fa"/></linearGradient></defs>
22
+ <g filter="url(#${id}s)">
23
+ <rect x="60" y="44" width="440" height="296" rx="18" fill="#ffffff"/>
24
+ <path d="M78 44h404a18 18 0 0 1 18 18v22H60V62a18 18 0 0 1 18-18z" fill="#eef2f7"/>
25
+ <circle cx="84" cy="64" r="5.5" fill="#ff5f57"/><circle cx="101" cy="64" r="5.5" fill="#febc2e"/><circle cx="118" cy="64" r="5.5" fill="#28c840"/>
26
+ <rect x="150" y="54" width="260" height="20" rx="10" fill="#ffffff" stroke="#dbe3ee"/>
27
+ ${bar(166, 61, 120, 6, '#94a3b8', .7)}
28
+ ${bar(88, 108, 200, 16, '#1d4ed8', .92)}
29
+ ${bar(88, 134, 160, 9, '#94a3b8', .55)}${bar(88, 150, 186, 9, '#94a3b8', .4)}
30
+ <rect x="88" y="174" width="96" height="30" rx="15" fill="#1d4ed8"/>${bar(108, 186, 56, 6, '#ffffff', .9)}
31
+ <rect x="316" y="104" width="156" height="104" rx="14" fill="url(#${id}h)"/>
32
+ <circle cx="352" cy="136" r="12" fill="#ffffff" fill-opacity=".8"/><path d="M316 192l40-36 30 26 22-18 64 48v6a14 14 0 0 1-14 14H330a14 14 0 0 1-14-14z" fill="#1d4ed8" fill-opacity=".45"/>
33
+ <rect x="88" y="228" width="118" height="84" rx="14" fill="#f1f5f9"/><rect x="221" y="228" width="118" height="84" rx="14" fill="#f1f5f9"/><rect x="354" y="228" width="118" height="84" rx="14" fill="#f1f5f9"/>
34
+ ${bar(102, 244, 44, 8, '#1d4ed8', .55)}${bar(102, 262, 84, 6, '#94a3b8', .5)}${bar(102, 276, 66, 6, '#94a3b8', .4)}
35
+ ${bar(235, 244, 44, 8, '#1d4ed8', .55)}${bar(235, 262, 84, 6, '#94a3b8', .5)}${bar(235, 276, 66, 6, '#94a3b8', .4)}
36
+ ${bar(368, 244, 44, 8, '#1d4ed8', .55)}${bar(368, 262, 84, 6, '#94a3b8', .5)}${bar(368, 276, 66, 6, '#94a3b8', .4)}
37
+ </g>
38
+ <circle cx="160" cy="196" r="20" fill="#ffffff" fill-opacity=".35"/><circle cx="160" cy="196" r="11" fill="#ffffff" fill-opacity=".55"/>
39
+ <path d="M158 192l26 10-11 4-4 11z" fill="#0f172a" stroke="#ffffff" stroke-width="2.5" stroke-linejoin="round"/>
40
+ <g filter="url(#${id}s)" transform="rotate(-7 455 300)">
41
+ <rect x="380" y="250" width="150" height="104" rx="12" fill="#ffffff"/>
42
+ <rect x="390" y="260" width="130" height="70" rx="7" fill="#e0e7ff"/>${bar(398, 268, 60, 7, '#1d4ed8', .8)}${bar(398, 282, 44, 5, '#94a3b8', .6)}<rect x="398" y="294" width="32" height="12" rx="6" fill="#1d4ed8"/>
43
+ <rect x="466" y="268" width="46" height="34" rx="6" fill="url(#${id}h)"/>
44
+ ${bar(390, 338, 70, 6, '#94a3b8', .5)}
45
+ </g>
46
+ <circle cx="523" cy="252" r="16" fill="#22c55e" stroke="#ffffff" stroke-width="3"/><path d="M516 252l5 5 9-10" fill="none" stroke="#ffffff" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round"/>
47
+ <g filter="url(#${id}s)">
48
+ <rect x="24" y="292" width="178" height="78" rx="14" fill="#0f172a" fill-opacity=".94"/>
49
+ ${bar(40, 310, 12, 6, '#4ade80')}${bar(58, 310, 96, 6, '#e2e8f0', .7)}
50
+ ${bar(40, 326, 12, 6, '#4ade80')}${bar(58, 326, 120, 6, '#e2e8f0', .5)}
51
+ ${bar(40, 342, 12, 6, '#60a5fa')}${bar(58, 342, 70, 6, '#e2e8f0', .35)}
52
+ </g>`);
53
+ }
54
+
55
+ // CONTINUITY: one agent hands the work to another, and the project's state stays in .ahp/, beside
56
+ // the code, with what was checked.
57
+ function handoffScene() {
58
+ const id = `mka${++drawn}`;
59
+ const row = (y, done = true) => `<circle cx="210" cy="${y}" r="11" fill="${done ? '#10b981' : '#e2e8f0'}"/>${done ? `<path d="M205 ${y}l4 4 7-8" fill="none" stroke="#ffffff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>` : ''}${bar(232, y - 9, 118, 8, '#0f172a', .7)}${bar(232, y + 3, 82, 6, '#94a3b8', .5)}`;
60
+ return svg(`<defs>${shadow(`${id}s`)}
61
+ <linearGradient id="${id}a" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fbbf24"/><stop offset="1" stop-color="#ea580c"/></linearGradient>
62
+ <linearGradient id="${id}b" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#818cf8"/><stop offset="1" stop-color="#7c3aed"/></linearGradient></defs>
63
+ <path d="M120 150C150 80 200 70 236 82" fill="none" stroke="#ffffff" stroke-opacity=".8" stroke-width="3" stroke-dasharray="2 10" stroke-linecap="round"/>
64
+ <path d="M376 300c40 30 70 22 92-6" fill="none" stroke="#ffffff" stroke-opacity=".8" stroke-width="3" stroke-dasharray="2 10" stroke-linecap="round"/>
65
+ <g filter="url(#${id}s)">
66
+ <path d="M176 84h66l14 16h112a20 20 0 0 1 20 20v188a20 20 0 0 1-20 20H176a20 20 0 0 1-20-20V104a20 20 0 0 1 20-20z" fill="#ffffff"/>
67
+ <rect x="182" y="118" width="70" height="22" rx="11" fill="#ecfdf5"/>
68
+ <text x="217" y="133.5" text-anchor="middle" font-family="ui-monospace, Menlo, monospace" font-size="12.5" font-weight="700" fill="#047857">.ahp/</text>
69
+ ${row(170)}${row(214)}${row(258)}${row(302, false)}
70
+ </g>
71
+ <g filter="url(#${id}s)"><circle cx="96" cy="182" r="40" fill="url(#${id}a)"/></g>
72
+ <path d="M96 164l5 12.5 13 5.5-13 5.5-5 12.5-5-12.5-13-5.5 13-5.5z" fill="#ffffff"/>
73
+ <g filter="url(#${id}s)"><circle cx="474" cy="262" r="40" fill="url(#${id}b)"/></g>
74
+ <path d="M458 262l10 10 20-22" fill="none" stroke="#ffffff" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
75
+ <g filter="url(#${id}s)" transform="rotate(-18 432 112)"><rect x="404" y="98" width="62" height="26" rx="13" fill="#ffffff"/>${bar(418, 108, 34, 6, '#10b981', .9)}</g>
76
+ <circle cx="470" cy="70" r="5" fill="#ffffff" fill-opacity=".7"/><circle cx="74" cy="300" r="4" fill="#ffffff" fill-opacity=".6"/><circle cx="520" cy="170" r="3" fill="#ffffff" fill-opacity=".6"/>`);
77
+ }
78
+
79
+ // IMAGES: what was asked, in a line, and what came back: the picture, with its other takes beside it.
80
+ function imagesScene() {
81
+ const id = `mka${++drawn}`;
82
+ const take = (y, stops, chosen = false) => `<g filter="url(#${id}s)"><rect x="384" y="${y}" width="128" height="68" rx="12" fill="url(#${id}${stops})"/>${chosen ? `<rect x="381" y="${y - 3}" width="134" height="74" rx="14" fill="none" stroke="#ffffff" stroke-width="3"/>` : ''}<path d="M384 ${y + 52}l30-20 22 16 18-12 58 22v2a12 12 0 0 1-12 12H396a12 12 0 0 1-12-12z" fill="#000" fill-opacity=".22"/></g>`;
83
+ return svg(`<defs>${shadow(`${id}s`)}
84
+ <linearGradient id="${id}sky" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#fde68a"/><stop offset=".5" stop-color="#fb7185"/><stop offset="1" stop-color="#7c3aed"/></linearGradient>
85
+ <linearGradient id="${id}t1" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#a7f3d0"/><stop offset="1" stop-color="#0ea5e9"/></linearGradient>
86
+ <linearGradient id="${id}t2" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fef3c7"/><stop offset="1" stop-color="#f97316"/></linearGradient>
87
+ <linearGradient id="${id}t3" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fbcfe8"/><stop offset="1" stop-color="#9333ea"/></linearGradient>
88
+ <linearGradient id="${id}go" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="#fb7185"/><stop offset="1" stop-color="#c026d3"/></linearGradient>
89
+ <clipPath id="${id}c"><rect x="56" y="116" width="304" height="232" rx="18"/></clipPath></defs>
90
+ <g filter="url(#${id}s)">
91
+ <rect x="56" y="36" width="456" height="54" rx="27" fill="#ffffff"/>
92
+ <circle cx="84" cy="63" r="14" fill="#fdf2f8"/><path d="M84 54l2.6 6.4 6.4 2.6-6.4 2.6-2.6 6.4-2.6-6.4-6.4-2.6 6.4-2.6z" fill="#db2777"/>
93
+ ${bar(108, 54, 170, 8, '#0f172a', .65)}${bar(108, 68, 120, 6, '#94a3b8', .55)}
94
+ <rect x="404" y="45" width="96" height="36" rx="18" fill="url(#${id}go)"/>${bar(426, 60, 52, 6, '#ffffff', .9)}
95
+ </g>
96
+ <g filter="url(#${id}s)">
97
+ <rect x="56" y="116" width="304" height="232" rx="18" fill="url(#${id}sky)"/>
98
+ <g clip-path="url(#${id}c)">
99
+ <circle cx="244" cy="206" r="40" fill="#fff7ed" fill-opacity=".92"/>
100
+ <path d="M56 300l70-70 50 44 46-40 70 56 68-46v104H56z" fill="#831843" fill-opacity=".72"/>
101
+ <path d="M56 330l92-52 64 34 58-28 90 46v18H56z" fill="#4c1d95" fill-opacity=".85"/>
102
+ </g>
103
+ <rect x="56" y="116" width="304" height="232" rx="18" fill="none" stroke="#ffffff" stroke-width="5"/>
104
+ </g>
105
+ ${take(116, 't1')}${take(198, 't2', true)}${take(280, 't3')}
106
+ <path d="M30 150l3 7.5 7.5 3-7.5 3-3 7.5-3-7.5-7.5-3 7.5-3z" fill="#ffffff" fill-opacity=".85"/>
107
+ <path d="M530 116l2.2 5.4 5.4 2.2-5.4 2.2-2.2 5.4-2.2-5.4-5.4-2.2 5.4-2.2z" fill="#ffffff" fill-opacity=".8"/>
108
+ <path d="M352 104l1.8 4.4 4.4 1.8-4.4 1.8-1.8 4.4-1.8-4.4-4.4-1.8 4.4-1.8z" fill="#ffffff" fill-opacity=".8"/>`);
109
+ }
110
+
111
+ // LOCAL AI: the computer itself thinking — a memory of linked notes on its screen — with no cloud
112
+ // above it and a lock beside it: nothing leaves.
113
+ function localScene() {
114
+ const id = `mka${++drawn}`;
115
+ const nodes = [[220, 132], [300, 112], [360, 160], [326, 214], [244, 206], [200, 172], [288, 166]];
116
+ const links = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0], [6, 0], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5]];
117
+ const net = links.map(([a, b]) => `<line x1="${nodes[a][0]}" y1="${nodes[a][1]}" x2="${nodes[b][0]}" y2="${nodes[b][1]}" stroke="#86efac" stroke-opacity=".55" stroke-width="2"/>`).join('')
118
+ + nodes.map(([x, y], index) => (index === 6 ? `<circle cx="${x}" cy="${y}" r="22" fill="#4ade80" fill-opacity=".22"/><circle cx="${x}" cy="${y}" r="13" fill="#4ade80"/>` : `<circle cx="${x}" cy="${y}" r="7" fill="#bbf7d0"/>`)).join('');
119
+ return svg(`<defs>${shadow(`${id}s`)}<radialGradient id="${id}g" cx=".5" cy=".45" r=".6"><stop offset="0" stop-color="#14532d"/><stop offset="1" stop-color="#052e16"/></radialGradient></defs>
120
+ <g filter="url(#${id}s)">
121
+ <rect x="128" y="64" width="320" height="206" rx="16" fill="#ffffff"/>
122
+ <rect x="140" y="76" width="296" height="182" rx="9" fill="url(#${id}g)"/>
123
+ <path d="M96 278h384l-26 30H122z" fill="#ffffff"/><rect x="250" y="282" width="76" height="7" rx="3.5" fill="#cbd5e1"/>
124
+ </g>
125
+ ${net}
126
+ <g filter="url(#${id}s)">
127
+ <rect x="22" y="112" width="104" height="58" rx="12" fill="#ffffff"/>${bar(36, 128, 58, 7, '#15803d', .85)}${bar(36, 142, 76, 6, '#94a3b8', .55)}${bar(36, 154, 48, 6, '#94a3b8', .4)}
128
+ <rect x="452" y="186" width="104" height="58" rx="12" fill="#ffffff"/>${bar(466, 202, 58, 7, '#15803d', .85)}${bar(466, 216, 76, 6, '#94a3b8', .55)}${bar(466, 228, 48, 6, '#94a3b8', .4)}
129
+ </g>
130
+ <path d="M126 141c40 0 50-6 74 28" fill="none" stroke="#ffffff" stroke-opacity=".75" stroke-width="2.5" stroke-dasharray="2 8" stroke-linecap="round"/>
131
+ <path d="M452 215c-46 0-60 2-92-50" fill="none" stroke="#ffffff" stroke-opacity=".75" stroke-width="2.5" stroke-dasharray="2 8" stroke-linecap="round"/>
132
+ <g transform="translate(452 40)">
133
+ <path d="M22 50h52a20 20 0 0 0 2-40 28 28 0 0 0-52-6A22 22 0 0 0 22 50z" fill="#ffffff" fill-opacity=".9"/>
134
+ <path d="M14 8l70 52" stroke="#15803d" stroke-width="6" stroke-linecap="round"/>
135
+ </g>
136
+ <g filter="url(#${id}s)"><circle cx="80" cy="282" r="34" fill="#ffffff"/></g>
137
+ <rect x="66" y="280" width="28" height="22" rx="5" fill="#15803d"/><path d="M71 280v-6a9 9 0 0 1 18 0v6" fill="none" stroke="#15803d" stroke-width="4.5"/>
138
+ <circle cx="80" cy="290" r="3" fill="#ffffff"/>`);
139
+ }
140
+
141
+ const SCENES = { playwright: browserScene, ahp: handoffScene, 'image-studio': imagesScene, ollama: localScene };
142
+
143
+ // Every other module: its icon, large, with the cards of what it touches floating round it.
144
+ function poster(item) {
145
+ const id = `mka${++drawn}`;
146
+ const face = moduleFace(item);
147
+ return svg(`<defs>${shadow(`${id}s`)}<radialGradient id="${id}r" cx=".5" cy=".5" r=".5"><stop offset="0" stop-color="#ffffff" stop-opacity=".35"/><stop offset="1" stop-color="#ffffff" stop-opacity="0"/></radialGradient></defs>
148
+ <circle cx="280" cy="200" r="190" fill="url(#${id}r)"/>
149
+ <g filter="url(#${id}s)">
150
+ <rect x="58" y="74" width="138" height="72" rx="14" fill="#ffffff" fill-opacity=".92"/>${bar(74, 92, 70, 8, '#0f172a', .6)}${bar(74, 108, 100, 6, '#94a3b8', .55)}${bar(74, 122, 64, 6, '#94a3b8', .4)}
151
+ <rect x="370" y="258" width="138" height="72" rx="14" fill="#ffffff" fill-opacity=".92"/>${bar(386, 276, 70, 8, '#0f172a', .6)}${bar(386, 292, 100, 6, '#94a3b8', .55)}${bar(386, 306, 64, 6, '#94a3b8', .4)}
152
+ <rect x="200" y="120" width="160" height="160" rx="38" fill="#ffffff" fill-opacity=".2" stroke="#ffffff" stroke-opacity=".7" stroke-width="2"/>
153
+ </g>
154
+ <g transform="translate(220 140) scale(6)" color="#ffffff">${face.icon}</g>
155
+ <circle cx="420" cy="110" r="6" fill="#ffffff" fill-opacity=".7"/><circle cx="140" cy="300" r="5" fill="#ffffff" fill-opacity=".6"/>`);
156
+ }
157
+
158
+ // The picture of a module: its own scene when it has one — drawn here, or sent with the catalog
159
+ // (kept to the shapes a drawing needs, market.js) — and its poster otherwise.
160
+ export const marketArt = (item) => (SCENES[item?.id] ? SCENES[item.id]() : cleanSvg(remoteEntry(item?.id)?.art) ?? poster(item));
161
+ export const hasScene = (item) => Boolean(SCENES[item?.id] || remoteEntry(item?.id)?.art);