@jossuealcala/madre 0.7.1 → 1.0.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.
- package/CHANGELOG.md +833 -1
- package/README.md +92 -28
- package/SECURITY.md +1 -0
- package/bin/madre.mjs +30 -10
- package/docs/REFERENCE.md +158 -79
- package/docs/SDK.md +23 -19
- package/package.json +1 -1
- package/public/app.js +11599 -4186
- package/public/assets/brand/Geist-latin-ext.woff2 +0 -0
- package/public/assets/brand/Geist-latin.woff2 +0 -0
- package/public/assets/brand/GeistMono-latin-ext.woff2 +0 -0
- package/public/assets/brand/GeistMono-latin.woff2 +0 -0
- package/public/assets/brand/JetBrainsMono-latin-ext.woff2 +0 -0
- package/public/assets/brand/JetBrainsMono-latin.woff2 +0 -0
- package/public/assets/brand/OFL-Geist.txt +93 -0
- package/public/assets/brand/OFL-GeistMono.txt +93 -0
- package/public/assets/brand/OFL-JetBrainsMono.txt +93 -0
- package/public/assets/brand/OFL-Sora.txt +93 -0
- package/public/assets/brand/Sora-latin-ext.woff2 +0 -0
- package/public/assets/brand/Sora-latin.woff2 +0 -0
- package/public/assets/brand/madre-app-180.png +0 -0
- package/public/assets/brand/madre-app-192.png +0 -0
- package/public/assets/brand/madre-app-512.png +0 -0
- package/public/assets/brand/madre-app.svg +1 -0
- package/public/assets/brand/madre-favicon.svg +1 -0
- package/public/assets/news/1.0/alerts.webp +0 -0
- package/public/assets/news/1.0/bar.webp +0 -0
- package/public/assets/news/1.0/finder.webp +0 -0
- package/public/assets/news/1.0/github.webp +0 -0
- package/public/assets/news/1.0/intents.webp +0 -0
- package/public/assets/news/1.0/looks.webp +0 -0
- package/public/assets/news/1.0/modules.webp +0 -0
- package/public/assets/news/1.0/mother.webp +0 -0
- package/public/assets/news/1.0/nostromo.webp +0 -0
- package/public/assets/news/1.0/permissions.webp +0 -0
- package/public/assets/news/1.0/room.webp +0 -0
- package/public/assets/news/1.0/settings.webp +0 -0
- package/public/assets/wallpapers/biznaga.webp +0 -0
- package/public/assets/wallpapers/canela.webp +0 -0
- package/public/assets/wallpapers/jarrito.webp +0 -0
- package/public/assets/wallpapers/magna.webp +0 -0
- package/public/assets/wallpapers/oceano.webp +0 -0
- package/public/assets/wallpapers/paraiso.webp +0 -0
- package/public/assets/wallpapers/quila.webp +0 -0
- package/public/assets/wallpapers/tradicion.webp +0 -0
- package/public/assets/wallpapers/tropical.webp +0 -0
- package/public/assets/wallpapers/urbania.webp +0 -0
- package/public/assets/wallpapers/ventura.webp +0 -0
- package/public/assets/wallpapers/xico.webp +0 -0
- package/public/brands.js +28 -2
- package/public/editor.js +744 -0
- package/public/es.js +2863 -1008
- package/public/i18n.js +1 -1
- package/public/index.html +201 -175
- package/public/inquiry.js +11 -11
- package/public/loader.js +79 -0
- package/public/macroverso.js +1497 -0
- package/public/manifest.webmanifest +14 -0
- package/public/nostromo-engine.js +2222 -0
- package/public/resay.js +24 -0
- package/public/review-ask.js +85 -0
- package/public/salas-mac.css +787 -0
- package/public/salas-mac.html +154 -0
- package/public/salas-mac.js +3264 -0
- package/public/salas.css +85 -0
- package/public/salas.html +47 -0
- package/public/salas.js +200 -0
- package/public/styles.css +6303 -414
- package/public/touch.js +83 -0
- package/public/tour-chapters.js +342 -0
- package/public/tour.js +510 -0
- package/public/troubleshooting.js +159 -140
- package/src/adapters/claude.mjs +4 -3
- package/src/adapters/codex.mjs +49 -8
- package/src/adapters/gemini.mjs +30 -10
- package/src/adapters/madre.mjs +110 -18
- package/src/adapters/process.mjs +42 -2
- package/src/auth-probe.mjs +2 -2
- package/src/bridge/devices.mjs +202 -0
- package/src/bridge/handoff.mjs +45 -0
- package/src/bridge/host.mjs +82 -0
- package/src/bridge/network.mjs +133 -0
- package/src/bridge/policy.mjs +89 -0
- package/src/bridge/qr.mjs +287 -0
- package/src/bridge/server.mjs +269 -0
- package/src/capabilities.mjs +5 -9
- package/src/chats.mjs +59 -22
- package/src/checkpoint.mjs +137 -35
- package/src/choices.mjs +45 -6
- package/src/cli-args.mjs +12 -1
- package/src/commands.mjs +15 -15
- package/src/config.mjs +73 -9
- package/src/conversation-context.mjs +5 -2
- package/src/dataset.mjs +3 -1
- package/src/directives.mjs +0 -5
- package/src/enlaces.mjs +451 -0
- package/src/event-store.mjs +55 -10
- package/src/exam.mjs +5 -5
- package/src/extensions.mjs +0 -2
- package/src/file-ops.mjs +42 -0
- package/src/files.mjs +52 -2
- package/src/github.mjs +407 -0
- package/src/json-file.mjs +63 -0
- package/src/lease.mjs +2 -2
- package/src/lobby-work.mjs +103 -0
- package/src/looks.mjs +55 -0
- package/src/maturity.mjs +3 -3
- package/src/mcp/github-server.mjs +164 -0
- package/src/mcp/image-server.mjs +1 -1
- package/src/mcp/memory-server.mjs +11 -3
- package/src/memory.mjs +38 -12
- package/src/models.mjs +109 -1
- package/src/modules/ahp.mjs +4 -4
- package/src/modules/ash.mjs +1 -1
- package/src/modules/bishop-plan.mjs +207 -0
- package/src/modules/bishop.mjs +645 -0
- package/src/modules/choices.mjs +2 -2
- package/src/modules/correo.mjs +1 -1
- package/src/modules/enlaces.mjs +255 -0
- package/src/modules/git-pulse.mjs +2 -2
- package/src/modules/github.mjs +322 -0
- package/src/modules/image-studio.mjs +3 -3
- package/src/modules/index.mjs +19 -4
- package/src/modules/intents-calibration.mjs +338 -0
- package/src/modules/intents-desk.mjs +481 -0
- package/src/modules/intents-observe.mjs +266 -0
- package/src/modules/intents-policy.mjs +414 -0
- package/src/modules/intents-try.mjs +91 -0
- package/src/modules/intents.mjs +145 -0
- package/src/modules/ollama.mjs +9 -5
- package/src/modules/playwright.mjs +121 -11
- package/src/modules/ripley.mjs +1 -1
- package/src/modules/runs.mjs +34 -0
- package/src/modules/sdk.mjs +10 -4
- package/src/ollama.mjs +25 -1
- package/src/outbound.mjs +19 -17
- package/src/override.mjs +100 -0
- package/src/ports.mjs +23 -1
- package/src/prices.mjs +72 -0
- package/src/privacy.mjs +30 -11
- package/src/quota-sources.mjs +0 -8
- package/src/request-guard.mjs +1 -1
- package/src/review-ask.mjs +111 -0
- package/src/room/archivist.mjs +55 -37
- package/src/room/budget.mjs +17 -5
- package/src/room/control.mjs +88 -8
- package/src/room/economy.mjs +35 -7
- package/src/room/escalation.mjs +2 -0
- package/src/room/guard.mjs +26 -2
- package/src/room/prompt.mjs +32 -13
- package/src/room/runs.mjs +151 -0
- package/src/room/vectors.mjs +19 -4
- package/src/room.mjs +402 -54
- package/src/router.mjs +3 -1
- package/src/runs.mjs +137 -0
- package/src/salas.mjs +313 -0
- package/src/sentinel-errors.mjs +1 -1
- package/src/server-sentinel.mjs +124 -0
- package/src/server.mjs +1578 -167
- package/src/setup.mjs +1 -0
- package/src/tour.mjs +159 -0
- package/src/updates.mjs +48 -8
- package/src/usage-sentinel.mjs +1 -1
- package/src/verdict.mjs +7 -7
- package/src/whats-new.mjs +160 -0
|
@@ -54,7 +54,7 @@ export const CONDITIONS = [
|
|
|
54
54
|
title: 'ANTHROPIC_API_KEY takes precedence over the claude.ai plan',
|
|
55
55
|
match: /connectors are disabled because ANTHROPIC_API_KEY|another auth source is set and takes precedence|takes precedence over your claude\.ai login/i,
|
|
56
56
|
diagnosis: 'Claude Code found an API key in the environment as well as the claude.ai login, and the key wins. MADRE hands the CLI the environment exactly as this machine has it, so whatever is exported in your shell profile reaches it. The turn is billed to the API account, not to the plan, and your organisation connectors do not load.',
|
|
57
|
-
remedy: 'Decide which one you mean. To work on the plan, unset the key where your shell exports it and open the
|
|
57
|
+
remedy: 'Decide which one you mean. To work on the plan, unset the key where your shell exports it and open the project again; to work on the API, this message is only a notice and can be ignored.',
|
|
58
58
|
fixes: {
|
|
59
59
|
darwin: ['grep -rn ANTHROPIC_API_KEY ~/.zshrc ~/.zprofile ~/.zshenv 2>/dev/null', '# remove or comment the line it finds, then:', 'unset ANTHROPIC_API_KEY', '# and start MADRE from a new terminal'],
|
|
60
60
|
linux: ['grep -rn ANTHROPIC_API_KEY ~/.bashrc ~/.profile ~/.bash_profile 2>/dev/null', 'unset ANTHROPIC_API_KEY', '# and start MADRE from a new terminal'],
|
|
@@ -69,8 +69,8 @@ export const CONDITIONS = [
|
|
|
69
69
|
diagnosis: 'The installed CLI inherited a base-URL override from this computer, so its request was going to another gateway instead of the official agent service. A demand to join a Telegram channel comes from that gateway, not from MADRE, Anthropic or OpenAI. MADRE now names that route and stops before sending the briefing.',
|
|
70
70
|
remedy: 'Do not subscribe or enter credentials. Remove the base-URL override and reopen MADRE to use the official service. If the gateway is intentional and you have verified who operates it, explicitly allow only that agent.',
|
|
71
71
|
fixes: {
|
|
72
|
-
darwin: ['env | grep -E \'^(ANTHROPIC|OPENAI)_BASE_URL=\'', '# remove that export from ~/.zshrc, ~/.zprofile or ~/.zshenv; then:', 'unset ANTHROPIC_BASE_URL OPENAI_BASE_URL', '#
|
|
73
|
-
linux: ['env | grep -E \'^(ANTHROPIC|OPENAI)_BASE_URL=\'', '# remove that export from ~/.bashrc, ~/.profile or ~/.bash_profile; then:', 'unset ANTHROPIC_BASE_URL OPENAI_BASE_URL', '#
|
|
72
|
+
darwin: ['env | grep -E \'^(ANTHROPIC|OPENAI)_BASE_URL=\'', '# remove that export from ~/.zshrc, ~/.zprofile or ~/.zshenv; then:', 'unset ANTHROPIC_BASE_URL OPENAI_BASE_URL', '# reopen the project; only for a gateway you verified:', 'PULSE_ALLOW_CUSTOM_AGENT_ENDPOINTS=claude madre start'],
|
|
73
|
+
linux: ['env | grep -E \'^(ANTHROPIC|OPENAI)_BASE_URL=\'', '# remove that export from ~/.bashrc, ~/.profile or ~/.bash_profile; then:', 'unset ANTHROPIC_BASE_URL OPENAI_BASE_URL', '# reopen the project; only for a gateway you verified:', 'PULSE_ALLOW_CUSTOM_AGENT_ENDPOINTS=claude madre start'],
|
|
74
74
|
},
|
|
75
75
|
},
|
|
76
76
|
{
|
|
@@ -111,7 +111,7 @@ export const CONDITIONS = [
|
|
|
111
111
|
severity: 'blocking',
|
|
112
112
|
title: 'Gemini key out of prepaid credits',
|
|
113
113
|
match: /prepayment credits|no prepaid credits|CREDITS_DEPLETED/i,
|
|
114
|
-
diagnosis: 'The AI Studio project behind the Gemini API key has spent its prepaid balance. Google answers every call, including
|
|
114
|
+
diagnosis: 'The AI Studio project behind the Gemini API key has spent its prepaid balance. Google answers every call, including generations in Images, with HTTP 429 until the balance is topped up. Gemini CLI hides this behind silent retries.',
|
|
115
115
|
remedy: 'Top up the project in AI Studio, or point the Gemini CLI at a key from another project. Nothing in MADRE changes; retry once billing is fixed.',
|
|
116
116
|
fixes: same(['# billing: https://ai.studio/projects', '# check the key still works:', 'gemini --model gemini-3-flash-preview -p "ping"']),
|
|
117
117
|
},
|
|
@@ -124,9 +124,9 @@ export const CONDITIONS = [
|
|
|
124
124
|
title: 'Gemini key rate-limited by Google (HTTP 429)',
|
|
125
125
|
match: /HTTP 429|rate-limiting|RESOURCE_EXHAUSTED|quota exceeded/i,
|
|
126
126
|
diagnosis: 'The Gemini API key hit its per-minute or daily quota. Gemini CLI retries with exponential backoff and prints only stack traces while it waits, which looked like a hang. With the "auto" model, the first request is a small router call, so even that can be throttled.',
|
|
127
|
-
remedy: 'Wait a minute and retry, pick an explicit model in the
|
|
127
|
+
remedy: 'Wait a minute and retry, pick an explicit model in the Write box (gemini-3-flash-preview skips the router), or raise the key\'s quota in Google AI Studio.',
|
|
128
128
|
fixes: {
|
|
129
|
-
darwin: ['# in the
|
|
129
|
+
darwin: ['# in the project: click the Gemini sphere twice → choose gemini-3-flash-preview', '# check quota: https://aistudio.google.com/app/apikey', 'gemini --model gemini-3-flash-preview -p "ping"'],
|
|
130
130
|
linux: ['gemini --model gemini-3-flash-preview -p "ping"', '# quota: https://aistudio.google.com/app/apikey']
|
|
131
131
|
},
|
|
132
132
|
},
|
|
@@ -138,7 +138,7 @@ export const CONDITIONS = [
|
|
|
138
138
|
title: 'Gemini model under high demand (503)',
|
|
139
139
|
match: /status 503|high demand|UNAVAILABLE/i,
|
|
140
140
|
diagnosis: 'Google is shedding load on the selected model (HTTP 503). The CLI would retry with backoff for minutes; MADRE stops it after 15 s of that and retries once on gemini-2.5-flash. The turn failed only if the fallback model was refused too.',
|
|
141
|
-
remedy: 'Ask again in a minute, pick an explicit model from the
|
|
141
|
+
remedy: 'Ask again in a minute, pick an explicit model from the Write box\'s model menu, or hand the question to another agent. PULSE_GEMINI_FALLBACK_MODEL changes the fallback.',
|
|
142
142
|
fixes: same(['# wait, then resend — or continue with @codex / @claude / @opencode', 'PULSE_GEMINI_FALLBACK_MODEL=gemini-2.5-flash-lite madre start']),
|
|
143
143
|
},
|
|
144
144
|
{
|
|
@@ -150,7 +150,7 @@ export const CONDITIONS = [
|
|
|
150
150
|
title: 'OpenCode picked a provider without a valid session',
|
|
151
151
|
match: /invalid x-api-key|APIError.*401|statusCode.{0,6}401/i,
|
|
152
152
|
diagnosis: 'Without a model in its config, `opencode run` falls back to its default provider. On this machine that provider holds a stale or invalid key.',
|
|
153
|
-
remedy: 'Tell MADRE which provider/model OpenCode should use in the
|
|
153
|
+
remedy: 'Tell MADRE which provider/model OpenCode should use in the project, or remove the stale credential so the default changes.',
|
|
154
154
|
fixes: {
|
|
155
155
|
darwin: ['npx @jossuealcala/madre setup', '# press [m] and pick a provider/model that has a session, e.g. openai/gpt-5.6-sol', '# one-off alternative:', 'PULSE_OPENCODE_MODEL=openai/gpt-5.6-sol npx @jossuealcala/madre start', '# or drop the stale key:', 'opencode auth logout anthropic'],
|
|
156
156
|
linux: ['npx @jossuealcala/madre setup', '# press [m] and pick a provider/model that has a session', 'PULSE_OPENCODE_MODEL=openai/gpt-5.6-sol npx @jossuealcala/madre start', 'opencode auth logout anthropic']
|
|
@@ -164,7 +164,7 @@ export const CONDITIONS = [
|
|
|
164
164
|
title: 'Agent installed but signed out',
|
|
165
165
|
match: /not logged in|sign in required|Error authenticating|unauthorized|please (?:log|sign) ?in|no credentials/i,
|
|
166
166
|
diagnosis: 'The CLI is on this computer but has no session for its provider. MADRE never stores credentials; each agent keeps its own.',
|
|
167
|
-
remedy: 'Press
|
|
167
|
+
remedy: 'Press Sign in on the agent: at first the project opens on the Connect your agents screen, with the button on each card, and later it lives in Settings → Agents, which the row below opens. Codex and Claude sign in with a browser flow MADRE runs for you; Gemini and OpenCode hand you their command. `madre setup` does the same from a terminal.',
|
|
168
168
|
fixes: same(['npx @jossuealcala/madre setup', '# or directly:', 'codex login', 'claude auth login', 'opencode auth login', 'gemini # then /auth']),
|
|
169
169
|
perAgent: loginAgent,
|
|
170
170
|
},
|
|
@@ -173,9 +173,9 @@ export const CONDITIONS = [
|
|
|
173
173
|
code: 'MU-009',
|
|
174
174
|
severity: 'blocking',
|
|
175
175
|
title: 'Agent not found on this computer',
|
|
176
|
-
match: /is not installed on this computer|not found on this computer|ENOENT.*(codex|claude|gemini|opencode)/i,
|
|
176
|
+
match: /(?<!\bmadre )is not installed on this computer|not found on this computer|ENOENT.*(codex|claude|gemini|opencode)/i,
|
|
177
177
|
diagnosis: 'MADRE looks for `codex`, `claude`, `gemini` and `opencode` on PATH plus a few known locations. Nothing answered.',
|
|
178
|
-
remedy: 'Press
|
|
178
|
+
remedy: 'Press Install on the agent in Settings → Agents: MADRE shows the exact command, runs it here and looks again when it finishes, no restart. `madre setup` does the same from a terminal.',
|
|
179
179
|
fixes: same(['# pick the agent you want; see per-agent commands below']),
|
|
180
180
|
perAgent: installAgent,
|
|
181
181
|
},
|
|
@@ -205,12 +205,14 @@ export const CONDITIONS = [
|
|
|
205
205
|
code: 'MU-012',
|
|
206
206
|
severity: 'tunable',
|
|
207
207
|
title: 'Agent did not respond before the timeout',
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
208
|
+
// MADRE writes this one itself, in the room's language, so it is matched in both: a room in
|
|
209
|
+
// Spanish recorded «no contestó antes del tiempo límite» and filed it as unclassified.
|
|
210
|
+
match: /did not respond before the timeout|went silent for|no contestó antes del tiempo límite|se quedó callad/i,
|
|
211
|
+
diagnosis: 'The agent was still reading files or reasoning when its time limit expired (by default 180 s for a turn that reads and 600 s for one that writes), or Gemini stayed silent for 90 s (PULSE_GEMINI_IDLE_MS) and was stopped after one automatic retry. Long questions over many files take longer; MADRE killed the whole process tree. Whatever a writing turn left before it stopped is listed under the failure, with UNDO.',
|
|
212
|
+
remedy: 'Press Apply below, or type a new number in Settings: Default time limit in Project and turns, or Time limit on the agent in Agents. Each field saves the moment you leave it. It applies to the next turn and persists in ~/.pulse/config.json. Environment variables work too, but only for a server started after exporting them; a running project never sees a later export.',
|
|
211
213
|
fixes: {
|
|
212
|
-
darwin: ['# live, no restart:
|
|
213
|
-
linux: ['# live, no restart:
|
|
214
|
+
darwin: ['# live, no restart: Settings → Project and turns → Default time limit', '# at launch only (env wins over config.json):', 'PULSE_AGENT_TIMEOUT_MS=300000 PULSE_CLAUDE_TIMEOUT_MS=600000 madre start', '# or ~/.pulse/config.json → {"timeouts":{"default":300000,"claude":600000}}'],
|
|
215
|
+
linux: ['# live, no restart: Settings → Project and turns → Default time limit', 'PULSE_AGENT_TIMEOUT_MS=300000 PULSE_CLAUDE_TIMEOUT_MS=600000 madre start', '# or ~/.pulse/config.json → {"timeouts":{"default":300000,"claude":600000}}']
|
|
214
216
|
},
|
|
215
217
|
},
|
|
216
218
|
{
|
|
@@ -219,7 +221,7 @@ export const CONDITIONS = [
|
|
|
219
221
|
severity: 'informational',
|
|
220
222
|
title: 'Turn interrupted by a MADRE restart',
|
|
221
223
|
match: /interrupted because MADRE is shutting down|MADRE stopped while|turn was not completed/i,
|
|
222
|
-
diagnosis: 'MADRE closed (Ctrl+C, SIGTERM or a crash) while this agent was answering. The log records the turn as failed so the
|
|
224
|
+
diagnosis: 'MADRE closed (Ctrl+C, SIGTERM or a crash) while this agent was answering. The log records the turn as failed so the project never shows a ghost "thinking" bubble.',
|
|
223
225
|
remedy: 'Nothing to fix. Ask again; the durable transcript is intact.',
|
|
224
226
|
fixes: same(['# resend the question']),
|
|
225
227
|
},
|
|
@@ -240,10 +242,10 @@ export const CONDITIONS = [
|
|
|
240
242
|
id: 'limits-real',
|
|
241
243
|
code: 'MU-015',
|
|
242
244
|
severity: 'informational',
|
|
243
|
-
title: 'Where the
|
|
245
|
+
title: 'Where the usage numbers come from',
|
|
244
246
|
match: /ring|quota|limit window|resets|rollout|oauth usage|window reset|limits-real/i,
|
|
245
|
-
diagnosis: 'Each sphere\'s
|
|
246
|
-
remedy: 'Click a sphere to see both windows and when they reset. If a
|
|
247
|
+
diagnosis: 'Each sphere\'s usage shows the provider\'s real limit when the CLI publishes it: Codex writes its 5-hour and weekly windows (used %, reset time) into every session rollout under ~/.codex/sessions; Claude Code\'s /usage comes from Anthropic\'s OAuth usage endpoint; MADRE can ask it with the token Claude Code keeps in the keychain when you start with PULSE_CLAUDE_USAGE=1 (macOS may ask once to allow the keychain read). Gemini and OpenCode publish nothing locally, so their usage shows MADRE\'s own rolling 5-hour window of budget tokens. A window whose reset time has passed counts as empty until the CLI reports again, and the sentinel says "clear" when a full window resets.',
|
|
248
|
+
remedy: 'Click a sphere to see both windows and when they reset. If a sphere\'s usage looks stale, run one turn with that agent: Codex only rewrites its limits when it runs. Set PULSE_OFFICIAL_QUOTA=0 to stop reading provider limits altogether.',
|
|
247
249
|
fixes: same(['# click the sphere → 5h / 7d windows and reset times', 'PULSE_CLAUDE_USAGE=1 madre start # also read Claude Code\'s usage windows', 'PULSE_OFFICIAL_QUOTA=0 madre start # local window only']),
|
|
248
250
|
},
|
|
249
251
|
{
|
|
@@ -251,12 +253,12 @@ export const CONDITIONS = [
|
|
|
251
253
|
code: 'MU-016',
|
|
252
254
|
severity: 'tunable',
|
|
253
255
|
title: 'Local token budget exhausted for an agent',
|
|
254
|
-
match: /MADRE exhausted|local room token budget/i,
|
|
255
|
-
diagnosis: 'The
|
|
256
|
-
remedy: 'Continue with another agent, press
|
|
256
|
+
match: /MADRE exhausted|local (?:room|project) token budget/i,
|
|
257
|
+
diagnosis: 'The project keeps a soft per-agent budget (500,000 tokens by default) so one agent does not quietly eat a whole session. It is MADRE\'s own bookkeeping from the usage each CLI reports after a turn, not the provider\'s quota: nothing is blocked, the project only warns and suggests other agents. Cache reads weigh a tenth of a fresh token.',
|
|
258
|
+
remedy: 'Continue with another agent, press Apply below, or type a number in Settings → Project and turns → Tokens per agent (it saves when you leave the field). The provider\'s real limits show in each sphere\'s popover when the CLI reports them.',
|
|
257
259
|
fixes: {
|
|
258
|
-
darwin: ['# live:
|
|
259
|
-
linux: ['# live:
|
|
260
|
+
darwin: ['# live: Settings → Project and turns → Tokens per agent', '# at launch: PULSE_SOFT_TOKEN_BUDGET=1000000 madre start', '# or ~/.pulse/config.json → {"room":{"softTokenBudget":1000000}}'],
|
|
261
|
+
linux: ['# live: Settings → Project and turns → Tokens per agent', 'PULSE_SOFT_TOKEN_BUDGET=1000000 madre start']
|
|
260
262
|
},
|
|
261
263
|
},
|
|
262
264
|
{
|
|
@@ -290,8 +292,8 @@ export const CONDITIONS = [
|
|
|
290
292
|
title: 'OpenCode reported an unexpected server error',
|
|
291
293
|
match: /UnknownError|Unexpected server error/i,
|
|
292
294
|
diagnosis: 'OpenCode runs a local server per invocation; under several simultaneous turns it can fail before the model is reached. Seen when two plans overlapped.',
|
|
293
|
-
remedy: 'Let the
|
|
294
|
-
fixes: same(['# in the
|
|
295
|
+
remedy: 'Let the project settle (STOPALL if agents are piling up), then ask again. Check `opencode` logs if it repeats alone.',
|
|
296
|
+
fixes: same(['# in the project: type STOPALL, then resend', 'ls -t ~/.local/share/opencode/log | head -1']),
|
|
295
297
|
},
|
|
296
298
|
{
|
|
297
299
|
id: 'runaway-room',
|
|
@@ -299,9 +301,9 @@ export const CONDITIONS = [
|
|
|
299
301
|
severity: 'blocking',
|
|
300
302
|
title: 'Too many agents working at once',
|
|
301
303
|
match: /agents are working at once|already answering another turn|no second plan will start|has been running for/i,
|
|
302
|
-
diagnosis: 'A plan was running and more turns started on top of it, or a plan has run for several minutes.
|
|
303
|
-
remedy: 'Type STOPALL in the
|
|
304
|
-
fixes: same(['# in the
|
|
304
|
+
diagnosis: 'A plan was running and more turns started on top of it, or a plan has run for several minutes. Diagnostics raises this before it becomes a loop.',
|
|
305
|
+
remedy: 'Type STOPALL in the Write box, or press STOP ALL in the bar: every plan stops and every in-flight agent process is killed. Then ask one agent at a time.',
|
|
306
|
+
fixes: same(['# in the project\'s Write box:', 'STOPALL', '# or from a terminal:', 'curl -X POST http://127.0.0.1:4317/api/stop-all']),
|
|
305
307
|
},
|
|
306
308
|
// ---- capability assistance: how an agent could gain a scope it lacks ----
|
|
307
309
|
{
|
|
@@ -311,9 +313,9 @@ export const CONDITIONS = [
|
|
|
311
313
|
severity: 'informational',
|
|
312
314
|
title: 'Gemini: generating images',
|
|
313
315
|
match: /scope-gemini-imageGen/,
|
|
314
|
-
diagnosis: 'Gemini CLI 0.60 has no image-generation tool in headless mode, even though Google offers image models. MADRE fills the gap with the
|
|
315
|
-
remedy: '
|
|
316
|
-
fixes: same(['#
|
|
316
|
+
diagnosis: 'Gemini CLI 0.60 has no image-generation tool in headless mode, even though Google offers image models. MADRE fills the gap with the Images module: its own MCP server exposing generate_image on the Gemini API image models, attached to Gemini only inside a creation lease with the image scope on, billing your Gemini key.',
|
|
317
|
+
remedy: 'Turn Images on in Modules (it needs a Gemini API key with credits), then switch on Generate images for Gemini in Settings → Agents. Without the module, ask @codex or let the orchestrator route the image step to it.',
|
|
318
|
+
fixes: same(['# Modules → Images → Active', '# Settings → Agents → Gemini → Generate images', '# then: CREATE + "generate … as name.png"']),
|
|
317
319
|
},
|
|
318
320
|
{
|
|
319
321
|
id: 'scope-claude-imageGen',
|
|
@@ -322,9 +324,9 @@ export const CONDITIONS = [
|
|
|
322
324
|
severity: 'informational',
|
|
323
325
|
title: 'Claude Code: generating images',
|
|
324
326
|
match: /scope-claude-imageGen/,
|
|
325
|
-
diagnosis: 'Claude Code has no image-generation tool; Claude models describe and reason about images, they do not render them. The
|
|
326
|
-
remedy: '
|
|
327
|
-
fixes: same(['#
|
|
327
|
+
diagnosis: 'Claude Code has no image-generation tool; Claude models describe and reason about images, they do not render them. The Images module gives Claude the MCP tool generate_image (MADRE\'s own server on the Gemini API), attached with --mcp-config only inside a creation lease.',
|
|
328
|
+
remedy: 'Turn Images on in Modules, switch on Generate images for Claude in Settings → Agents, then use CREATE. Or route the image step to @codex.',
|
|
329
|
+
fixes: same(['# Modules → Images → Active', '# Settings → Agents → Claude → Generate images']),
|
|
328
330
|
},
|
|
329
331
|
{
|
|
330
332
|
id: 'scope-opencode-imageGen',
|
|
@@ -333,9 +335,9 @@ export const CONDITIONS = [
|
|
|
333
335
|
severity: 'informational',
|
|
334
336
|
title: 'OpenCode: generating images',
|
|
335
337
|
match: /scope-opencode-imageGen/,
|
|
336
|
-
diagnosis: 'OpenCode exposes no image-generation tool of its own. The
|
|
337
|
-
remedy: '
|
|
338
|
-
fixes: same(['#
|
|
338
|
+
diagnosis: 'OpenCode exposes no image-generation tool of its own. The Images module adds MADRE\'s MCP image server to OpenCode\'s ephemeral config inside a creation lease.',
|
|
339
|
+
remedy: 'Turn Images on in Modules, switch on Generate images for OpenCode in Settings → Agents, then use CREATE. Or route the image step to @codex.',
|
|
340
|
+
fixes: same(['# Modules → Images → Active', '# Settings → Agents → OpenCode → Generate images']),
|
|
339
341
|
},
|
|
340
342
|
{
|
|
341
343
|
id: 'scope-web',
|
|
@@ -344,8 +346,8 @@ export const CONDITIONS = [
|
|
|
344
346
|
title: 'Web access for an agent',
|
|
345
347
|
match: /scope-[a-z]+-web/,
|
|
346
348
|
diagnosis: 'Every CLI can browse: Codex with --search, Claude Code with WebFetch/WebSearch, Gemini with google_web_search/web_fetch, OpenCode with webfetch/websearch. MADRE keeps it off until you enable it per agent.',
|
|
347
|
-
remedy: '
|
|
348
|
-
fixes: same(['#
|
|
349
|
+
remedy: 'Switch on Web access for that agent in Settings → Agents; it saves at once. It applies to every turn of that agent; content fetched is sent to its provider.',
|
|
350
|
+
fixes: same(['# Settings → Agents → the agent → Web access']),
|
|
349
351
|
},
|
|
350
352
|
{
|
|
351
353
|
id: 'slash-commands',
|
|
@@ -353,19 +355,19 @@ export const CONDITIONS = [
|
|
|
353
355
|
severity: 'informational',
|
|
354
356
|
title: 'Commands and mentions in the field box',
|
|
355
357
|
match: /slash|command|\/git|\/ahp|mention|@agent/i,
|
|
356
|
-
diagnosis: 'Type "/" for the
|
|
357
|
-
remedy: 'A struck-through command is a module that is not available in this project: open
|
|
358
|
+
diagnosis: 'Type "/" for the project\'s commands: /create arms the lease, /image routes an image request to an agent that can draw, /stopall is the brake, /git (Git) and /ahp (Continuity) run read-only in the project and post a fact card everyone, agents included, can read. Type "@" to mention an agent; the name becomes a label. Type "!" to point at a project file ("!src/room.mjs:12-20" for lines): the agent reads it first. In the viewer, click a line number (Shift+click for a range) and REVIEW WITH sends those lines to an agent.',
|
|
359
|
+
remedy: 'A struck-through command is a module that is not available in this project: open Modules to install it or turn it on (Git needs a git repository; Continuity needs to be installed).',
|
|
358
360
|
fixes: same(['# type / or @ in the field box', '/git status', '/git log 10', '/ahp check', '/image a poster for the launch']),
|
|
359
361
|
},
|
|
360
362
|
{
|
|
361
363
|
id: 'modes',
|
|
362
364
|
code: 'MU-023',
|
|
363
365
|
severity: 'informational',
|
|
364
|
-
title: 'Permission modes: #0
|
|
366
|
+
title: 'Permission modes: #0 INCOGNITO · #1 CHAT ONLY · #2 CREATE · #3 EDIT · #4 FULL ACCESS',
|
|
365
367
|
match: /mode|ghost|exchange|control|airlock|deploy|despleg|producci|override|designation|max mode|#[0-4]\b/i,
|
|
366
|
-
diagnosis: 'Every message goes out at a mode, chosen in the chip after TO @agent (or typed as #2 in the text). #0
|
|
367
|
-
remedy: 'Pick the mode in the chip, or type #0..#4 in the message. Raise an agent\'s
|
|
368
|
-
fixes: same(['# chip: TO @codex #1
|
|
368
|
+
diagnosis: 'Every message goes out at a mode, chosen in the chip after TO @agent (or typed as #2 in the text). #0 INCOGNITO is off the record: nothing is saved, no other agent remembers it, gone on reload, no plan. #1 CHAT ONLY is the default: read and coordinate. #2 CREATE lets the agent add new files and folders anywhere in the project, where they belong; whatever existed before is put back after the turn and the project says so. #3 EDIT puts one agent in command of the project itself: a git restore point is taken first, every change is listed afterwards, writes into .git, .pulse or .env files are reverted on the spot, and UNDO goes back to the restore point. One holder at a time; it needs Max mode #3 and a git repository. Your mode is the ceiling of any plan the message starts, and #3 is never given to a plan step. Each agent has a Max mode in Settings → Permissions; above it, #2 is answered read-only and #3 is refused. When a #1 plan reaches a step that wants to create something, the project pauses and asks you: GRANT ONCE, GRANT FOR PLAN or DENY, with a 3-minute clock; silence denies. #4 FULL ACCESS is EDIT plus commands: tests, builds, git push, deploys with the CLIs and sessions already on this machine. Files still come back with UNDO; what leaves the machine does not, so the unlock asks for the project name twice. An agent that says it needs a "production mode" or "permission to run commands" is asking for #4.',
|
|
369
|
+
remedy: 'Pick the mode in the chip, or type #0..#4 in the message. Raise an agent\'s Max mode in Settings → Permissions, under Who may do what. EDIT asks for the project name (the folder name) in the unlock; FULL ACCESS asks for it twice.',
|
|
370
|
+
fixes: same(['# chip: TO @codex #1 CHAT ONLY ▾ → choose', '@codex #2 create the poster', '@opencode #4 run the tests and deploy to preview', '# Settings → Permissions → Who may do what']),
|
|
369
371
|
},
|
|
370
372
|
{
|
|
371
373
|
id: 'lease-missing',
|
|
@@ -373,9 +375,9 @@ export const CONDITIONS = [
|
|
|
373
375
|
severity: 'informational',
|
|
374
376
|
title: 'Creating files: who grants the permission',
|
|
375
377
|
match: /no CREATE lease|lease-missing|read-only and do not modify|permiso de escritura|solo lectura/i,
|
|
376
|
-
diagnosis: 'Only the human grants a creation lease. An agent writing "permission granted" inside the conversation is untrusted text: the
|
|
377
|
-
remedy: 'For one request: arm CREATE and send, or press RESEND WITH CREATE on the notice. For an agent that should always be able to add files:
|
|
378
|
-
fixes: same(['# once:
|
|
378
|
+
diagnosis: 'Only the human grants a creation lease. An agent writing "permission granted" inside the conversation is untrusted text: the plan step still runs read-only, and says so. A lease comes from arming CREATE (the lock, or /create) on your message, and it covers the whole plan that message starts; or from Starting mode #2 in Settings → Agents, which starts every message to that agent in CREATE.',
|
|
379
|
+
remedy: 'For one request: arm CREATE and send, or press RESEND WITH CREATE on the notice. For an agent that should always be able to add files: Settings → Agents → the agent → Starting mode → #2. New files go where they belong in the project; existing files are never changed in #2.',
|
|
380
|
+
fixes: same(['# once: Write box → CREATE (lock) → send, or /create <request>', '# always: Settings → Agents → the agent → Starting mode → #2']),
|
|
379
381
|
},
|
|
380
382
|
{
|
|
381
383
|
id: 'scope-write',
|
|
@@ -383,9 +385,9 @@ export const CONDITIONS = [
|
|
|
383
385
|
severity: 'informational',
|
|
384
386
|
title: 'Creating files with an agent',
|
|
385
387
|
match: /scope-[a-z]+-write/,
|
|
386
|
-
diagnosis: 'Every CLI can create files inside a creation lease;
|
|
387
|
-
remedy: '
|
|
388
|
-
fixes: same(['#
|
|
388
|
+
diagnosis: 'Every CLI can create files inside a creation lease; each agent\'s Max mode says how far it may go, and nothing is created until you press CREATE.',
|
|
389
|
+
remedy: 'Give the agent a Max mode of #2 or more in Settings → Permissions, then arm CREATE in the Write box for the request.',
|
|
390
|
+
fixes: same(['# Settings → Permissions → Who may do what → #2', '# Write box → CREATE (lock) → send']),
|
|
389
391
|
},
|
|
390
392
|
{
|
|
391
393
|
id: 'node-version',
|
|
@@ -393,7 +395,7 @@ export const CONDITIONS = [
|
|
|
393
395
|
severity: 'blocking',
|
|
394
396
|
title: 'Node.js too old',
|
|
395
397
|
match: /SyntaxError: Unexpected token|ERR_REQUIRE_ESM|engines|Unsupported engine/i,
|
|
396
|
-
diagnosis: 'MADRE needs Node 22.5 or newer: the
|
|
398
|
+
diagnosis: 'MADRE needs Node 22.5 or newer: the project memory runs on node:sqlite, and the rest on ES modules, fetch and AbortSignal. The bin refuses to start on older versions and says so.',
|
|
397
399
|
remedy: 'Update Node to the current LTS.',
|
|
398
400
|
fixes: {
|
|
399
401
|
darwin: ['node --version', 'brew install node', '# or: nvm install --lts'],
|
|
@@ -404,10 +406,10 @@ export const CONDITIONS = [
|
|
|
404
406
|
id: 'memory-unavailable',
|
|
405
407
|
code: 'MU-027',
|
|
406
408
|
severity: 'degraded',
|
|
407
|
-
title: '
|
|
409
|
+
title: 'Project memory unavailable: turns get only the recent window',
|
|
408
410
|
match: /memory unavailable|memory index failed|memory recall failed|node:sqlite|SQLITE_|database disk image is malformed|memory\.sqlite/i,
|
|
409
|
-
diagnosis: 'The memory index (memory.sqlite next to the
|
|
410
|
-
remedy: 'The index is derived from the ledger: delete memory.sqlite (and its -wal/-shm siblings) and restart; MADRE rebuilds it. Distilled notes live in the same file, so export them from
|
|
411
|
+
diagnosis: 'The memory index (memory.sqlite next to the project\'s events.jsonl) could not open or write. The project still works: every turn gets the recent transcript, but nothing older is recalled, nothing is distilled and the Memory map is empty. Causes: Node below 22.5, a corrupt file, or a second MADRE writing the same project with an incompatible version.',
|
|
412
|
+
remedy: 'The index is derived from the ledger: delete memory.sqlite (and its -wal/-shm siblings) and restart; MADRE rebuilds it. Distilled notes live in the same file, so export them from the Memory map first if they matter.',
|
|
411
413
|
fixes: {
|
|
412
414
|
darwin: ['node --version # must be ≥ 22.5', 'ls ~/.pulse/rooms/*/memory.sqlite*', 'rm ~/.pulse/rooms/<room>/memory.sqlite* # rebuilt on next start'],
|
|
413
415
|
linux: ['node --version # must be ≥ 22.5', 'ls ~/.pulse/rooms/*/memory.sqlite*', 'rm ~/.pulse/rooms/<room>/memory.sqlite* # rebuilt on next start']
|
|
@@ -417,9 +419,9 @@ export const CONDITIONS = [
|
|
|
417
419
|
id: 'memory-recall',
|
|
418
420
|
code: 'MU-028',
|
|
419
421
|
severity: 'informational',
|
|
420
|
-
title: '
|
|
422
|
+
title: 'Project memory: what an agent remembers and how',
|
|
421
423
|
match: /\brecall\b|recuerd|\bremember\b|memoria de la sala|<memory>|<memories>/i,
|
|
422
|
-
diagnosis: 'Everything said outside
|
|
424
|
+
diagnosis: 'Everything said outside INCOGNITO is indexed (full text plus meaning, when a Gemini key exists). When a project is longer than the context window, each turn also receives the older exchanges that match the request, quoted with their ledger sequence (<memory>), and the distilled notes that match (<memories>), inside PULSE_RECALL_SHARE of the window (30 % by default). Every agent reads the same memory, so a decision taken with one reaches the others. Incognito turns may read it but never write it.',
|
|
423
425
|
remedy: 'Nothing to do; it is automatic. To give it more room raise PULSE_RECALL_SHARE (max 0.6); to switch it off set it to 0. Ask any agent "what did we decide about …" and it will search with memory_search before answering.',
|
|
424
426
|
fixes: same(['# more recall per turn', ...envExport('PULSE_RECALL_SHARE', '0.45').darwin, '# off', 'PULSE_RECALL_SHARE=0 madre start']),
|
|
425
427
|
},
|
|
@@ -429,8 +431,8 @@ export const CONDITIONS = [
|
|
|
429
431
|
severity: 'degraded',
|
|
430
432
|
title: 'Distilled memories: the archivist did not run, or failed',
|
|
431
433
|
match: /could not distil|distill|destil|batch skipped|archivist|memory\.distilled|memories? (were|was) not/i,
|
|
432
|
-
diagnosis: 'Every PULSE_DISTILL_EVERY undistilled exchanges (10), or after PULSE_DISTILL_IDLE_MS of quiet (10 min), the cheapest available agent (Gemini, then OpenCode, Codex, Claude) reads the newest undistilled batch and keeps up to five notes. It runs only when no turn is in flight and one batch per trigger, so a long backlog drains slowly. A run that fails is retried; after three failures on the same batch it is skipped and the
|
|
433
|
-
remedy: 'Check the archivist\'s session in
|
|
434
|
+
diagnosis: 'Every PULSE_DISTILL_EVERY undistilled exchanges (10), or after PULSE_DISTILL_IDLE_MS of quiet (10 min), the cheapest available agent (Gemini, then OpenCode, Codex, Claude) reads the newest undistilled batch and keeps up to five notes. It runs only when no turn is in flight and one batch per trigger, so a long backlog drains slowly. A run that fails is retried; after three failures on the same batch it is skipped and the project says so. Common causes: the archivist agent is rate-limited or signed out, or PULSE_DISTILL=0.',
|
|
435
|
+
remedy: 'Check the archivist\'s session in Settings → Agents, or pick another in Settings → Memory (Who distils first) or with PULSE_DISTILL_AGENT. Lower PULSE_DISTILL_EVERY to distil sooner; raise PULSE_DISTILL_MAX_CHARS to read more per run. Set PULSE_DISTILL=0 to stop paying for it.',
|
|
434
436
|
fixes: same(['madre doctor', ...envExport('PULSE_DISTILL_AGENT', 'claude').darwin, ...envExport('PULSE_DISTILL_EVERY', '6').darwin, 'PULSE_DISTILL=0 madre start # off']),
|
|
435
437
|
},
|
|
436
438
|
{
|
|
@@ -438,10 +440,10 @@ export const CONDITIONS = [
|
|
|
438
440
|
code: 'MU-030',
|
|
439
441
|
solvedIn: 'connections',
|
|
440
442
|
severity: 'degraded',
|
|
441
|
-
title: '
|
|
443
|
+
title: 'Smart search paused: recall is lexical only',
|
|
442
444
|
match: /embeddings paused|embedding timed out|Gemini embeddings HTTP|batchEmbedContents|LINKS NEED EMBEDDINGS/i,
|
|
443
|
-
diagnosis: 'Meaning-aware recall and the links between memories in
|
|
444
|
-
remedy: 'Sign the Gemini CLI in with an API key (/auth) or export GEMINI_API_KEY, then restart. If you do not want
|
|
445
|
+
diagnosis: 'Meaning-aware recall and the links between memories in the Memory map need Gemini embeddings through your own key (GEMINI_API_KEY or the Gemini CLI\'s keychain entry). Without a key, or when the API answers 429/5xx, MADRE pauses vectors for a minute and retries; recall keeps working on words alone.',
|
|
446
|
+
remedy: 'Sign the Gemini CLI in with an API key (/auth) or export GEMINI_API_KEY, then restart. If you do not want Smart search at all, set PULSE_EMBED=0 and the pause message stops.',
|
|
445
447
|
fixes: {
|
|
446
448
|
darwin: ['gemini # /auth → "Use Gemini API key"', ...envExport('GEMINI_API_KEY', 'YOUR_KEY').darwin, 'PULSE_EMBED=0 madre start # lexical only, no messages'],
|
|
447
449
|
linux: ['gemini # /auth → "Use Gemini API key"', ...envExport('GEMINI_API_KEY', 'YOUR_KEY').linux, 'PULSE_EMBED=0 madre start']
|
|
@@ -455,7 +457,7 @@ export const CONDITIONS = [
|
|
|
455
457
|
title: 'An agent says it cannot search the memory (pulse-memory MCP)',
|
|
456
458
|
match: /pulse-memory|memory_search|memory_recall|memory_notes|memory_timeline|memory_note|mcp.*(failed|error|not found|unavailable)|MCP server/i,
|
|
457
459
|
diagnosis: 'Every turn attaches MADRE\'s memory as an MCP server named pulse-memory: Claude through --mcp-config, Gemini through its isolated settings and policy, OpenCode through config.mcp, Codex through -c mcp_servers.* overrides. If a CLI does not list its tools the server did not start in that CLI: an old CLI without MCP support, a sandbox that blocks the SQLite file, or PULSE_MEMORY_TOOLS=0. The automatic <memory> blocks in the prompt still work without it.',
|
|
458
|
-
remedy: 'Update the CLI, then check that it sees the server. Codex can list servers from a config override; Claude accepts an inline --mcp-config. If a CLI keeps failing, PULSE_MEMORY_TOOLS=0 removes the tools for everyone and the
|
|
460
|
+
remedy: 'Update the CLI, then check that it sees the server. Codex can list servers from a config override; Claude accepts an inline --mcp-config. If a CLI keeps failing, PULSE_MEMORY_TOOLS=0 removes the tools for everyone and the project continues on automatic recall.',
|
|
459
461
|
fixes: {
|
|
460
462
|
darwin: ['codex mcp list', 'claude --version', 'gemini --version', 'PULSE_MEMORY_TOOLS=0 madre start # tools off, recall stays'],
|
|
461
463
|
linux: ['codex mcp list', 'claude --version', 'gemini --version', 'PULSE_MEMORY_TOOLS=0 madre start']
|
|
@@ -465,55 +467,58 @@ export const CONDITIONS = [
|
|
|
465
467
|
id: 'memory-note',
|
|
466
468
|
code: 'MU-032',
|
|
467
469
|
severity: 'informational',
|
|
468
|
-
title: 'Saving a memory on request;
|
|
470
|
+
title: 'Saving a memory on request; INCOGNITO refuses',
|
|
469
471
|
match: /save (a |the |this )?memory|guarda.*memoria|memory saved|off the record.*nothing can be saved|remember this|memory_note/i,
|
|
470
|
-
diagnosis: 'Memories are distilled automatically; you never need to ask. When you do ask an agent to remember or save something, it calls memory_note and a pill appears under its reply with the note; clicking the pill opens it in
|
|
471
|
-
remedy: 'Ask in any mode but #0: "remember that …" or "save this as a decision: …". Notes saved this way are marked "on the human\'s request" in
|
|
472
|
-
fixes: same(['@claude remember: the webhook verifies the signature before parsing', '# then:
|
|
472
|
+
diagnosis: 'Memories are distilled automatically; you never need to ask. When you do ask an agent to remember or save something, it calls memory_note and a pill appears under its reply with the note; clicking the pill opens it in the Memory map. In an INCOGNITO turn the note is refused: nothing off the record reaches the archive. "Already remembered" means the same note exists.',
|
|
473
|
+
remedy: 'Ask in any mode but #0: "remember that …" or "save this as a decision: …". Notes saved this way are marked "on the human\'s request" in the Memory map and can be forgotten there.',
|
|
474
|
+
fixes: same(['@claude remember: the webhook verifies the signature before parsing', '# then: Diagnostics → Memory map']),
|
|
473
475
|
},
|
|
474
476
|
{
|
|
475
477
|
id: 'nostromo-access',
|
|
476
478
|
code: 'MU-033',
|
|
477
479
|
severity: 'informational',
|
|
478
|
-
title: '
|
|
480
|
+
title: 'Memory map: opening, reading and forgetting',
|
|
479
481
|
match: /nostromo|designation|UNABLE TO COMPUTE|ARCHIVE IS SEALED|forget this memory/i,
|
|
480
|
-
diagnosis: '
|
|
481
|
-
remedy: 'Type the folder name shown in the
|
|
482
|
-
fixes: same(['#
|
|
482
|
+
diagnosis: 'The Memory map is the human\'s view of the archive, from Diagnostics. Opening the memory asks for the project name: the name of the project folder, exactly as EDIT does; a wrong one answers UNABLE TO COMPUTE. Access stays open until the page reloads. Inside, every distilled memory is a planet around the project\'s core; drag to move, wheel to zoom, click a planet for its card. The only edit is FORGET (two presses): the note leaves every future turn, the ledger stays. If the archive answers SEALED with a number of minutes, wait them out: repeated strikes at the core close it for a while and the Write box reads INTRUDER until it opens again.',
|
|
483
|
+
remedy: 'Type the folder name shown in the project header as the project name. To find a memory quickly, ask an agent to search instead. Do not strike the core.',
|
|
484
|
+
fixes: same(['# Diagnostics → Memory map → project name = folder name', 'basename "$PWD"']),
|
|
483
485
|
},
|
|
484
486
|
{
|
|
485
487
|
id: 'ripley',
|
|
486
488
|
code: 'MU-034',
|
|
487
489
|
severity: 'informational',
|
|
488
|
-
title: '
|
|
490
|
+
title: 'Preview: rendering HTML, SVG and Markdown in the viewer',
|
|
489
491
|
match: /ripley|RIPLEY is off|renders \.html|render(ed|ing)? (the )?(html|svg|markdown)/i,
|
|
490
|
-
diagnosis: 'With
|
|
491
|
-
remedy: '
|
|
492
|
-
fixes: same(['#
|
|
492
|
+
diagnosis: 'With Preview on (in Modules), the file viewer renders .html and .svg through /preview/project/<path> inside a sealed frame: the page\'s own scripts run, but the frame has no origin, no network, no forms and no way to reach MADRE, and it loads CSS, JS, images and fonts only from the project through MADRE. Relative links work. Markdown renders in place; PREVIEW / SOURCE switches. Off, those files show as text with a note. 412 means Preview is off. Plain /api/files always serves HTML as text.',
|
|
493
|
+
remedy: 'Turn Preview on in Modules. If a page looks broken in PREVIEW it is usually because it fetches something from the internet or another server, which the frame forbids by design: open it with OPEN RAW in a normal tab if you trust it.',
|
|
494
|
+
fixes: same(['# Modules → Preview → Active', '# viewer → PREVIEW / SOURCE']),
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
id: 'madre-agent',
|
|
498
|
+
solvedIn: 'ollama',
|
|
499
|
+
code: 'MU-036',
|
|
500
|
+
severity: 'informational',
|
|
501
|
+
title: '@madre: the project\'s own memory, as an agent',
|
|
502
|
+
// Older rooms recorded @madre leaving as "madre is not installed": it is this condition, not MU-009.
|
|
503
|
+
match: /@madre|madre-local|needs Ollama running with a chat model|\bmadre is not installed on this computer|@madre left the room/i,
|
|
504
|
+
diagnosis: 'When Ollama runs with a chat model, a fifth agent joins the project: @madre. It answers from the whole archive (distilled notes and exact quotes, cited as [#n]) and from what the message carries, locally, for free. It never writes, draws, browses or makes plans; when the project never discussed something it says so. Other agents may give it a plan step to check what was decided. It leaves the project when Ollama stops, and Diagnostics says so.',
|
|
505
|
+
remedy: 'Start Ollama and download a chat model from Local AI in Modules; its @madre in the project switch turns the agent off if you do not want it. Ask it "what did we decide about …" or "did we ever discuss …".',
|
|
506
|
+
fixes: same(['ollama serve', 'ollama pull qwen2.5:3b', '@madre what did we decide about the webhook?']),
|
|
493
507
|
},
|
|
494
508
|
{
|
|
495
509
|
id: 'ollama',
|
|
510
|
+
solvedIn: 'ollama',
|
|
496
511
|
code: 'MU-035',
|
|
497
512
|
severity: 'informational',
|
|
498
|
-
title: 'Ollama: local
|
|
513
|
+
title: 'Ollama: local smart search and a local archivist',
|
|
499
514
|
match: /ollama|11434|local model|nomic-embed|qwen|llama3/i,
|
|
500
|
-
diagnosis: 'When Ollama runs on this machine with an embedding model and a chat model, MADRE embeds the memory locally (recall by meaning without any key) and distils memories with the local model first, before Gemini and the others. Nothing leaves the machine for remembering. Off or absent, everything falls back to the providers.
|
|
501
|
-
remedy: 'Install Ollama (ollama.com), start it, then in
|
|
515
|
+
diagnosis: 'When Ollama runs on this machine with an embedding model and a chat model, MADRE embeds the memory locally (recall by meaning without any key) and distils memories with the local model first, before Gemini and the others. Nothing leaves the machine for remembering. Off or absent, everything falls back to the providers. The Local AI module, in Modules, shows what Ollama has, downloads the recommended models, and switches each role.',
|
|
516
|
+
remedy: 'Install Ollama (ollama.com), start it, then open Local AI in Modules, press Check again and download the models it suggests. Set PULSE_OLLAMA_MODEL or PULSE_OLLAMA_EMBED_MODEL to prefer others; PULSE_EMBED_PROVIDER=gemini keeps embeddings on Gemini even with Ollama running.',
|
|
502
517
|
fixes: {
|
|
503
518
|
darwin: ['brew install ollama', 'ollama serve', 'ollama pull nomic-embed-text', 'ollama pull qwen2.5:3b'],
|
|
504
519
|
linux: ['curl -fsSL https://ollama.com/install.sh | sh', 'ollama serve', 'ollama pull nomic-embed-text', 'ollama pull qwen2.5:3b']
|
|
505
520
|
},
|
|
506
521
|
},
|
|
507
|
-
{
|
|
508
|
-
id: 'madre-agent',
|
|
509
|
-
code: 'MU-036',
|
|
510
|
-
severity: 'informational',
|
|
511
|
-
title: '@madre: the room\'s own memory, as an agent',
|
|
512
|
-
match: /@madre|madre-local|needs Ollama running with a chat model/i,
|
|
513
|
-
diagnosis: 'When Ollama runs with a chat model, a fifth agent joins the room: @madre. It answers from the whole archive (distilled notes and exact quotes, cited as [#n]) and from what the message carries, locally, for free. It never writes, draws, browses or delegates; when the room never discussed something it says so. Other agents may delegate a step to it to check what was decided. It leaves the room when Ollama stops, and MU/TH/UR says so.',
|
|
514
|
-
remedy: 'Start Ollama and PULL a chat model in MODULES → OLLAMA; the switch @MADRE IN THE ROOM turns the agent off if you do not want it. Ask it "what did we decide about …" or "did we ever discuss …".',
|
|
515
|
-
fixes: same(['ollama serve', 'ollama pull qwen2.5:3b', '@madre what did we decide about the webhook?']),
|
|
516
|
-
},
|
|
517
522
|
{
|
|
518
523
|
id: 'install-needs-admin',
|
|
519
524
|
code: 'MU-037',
|
|
@@ -521,7 +526,7 @@ export const CONDITIONS = [
|
|
|
521
526
|
title: 'Installing a CLI: npm cannot write to the system folder',
|
|
522
527
|
match: /EACCES|EPERM|permission denied|Missing write access|npm ERR!.*sudo|administrator/i,
|
|
523
528
|
diagnosis: 'A global npm install writes into a folder that belongs to the system. With Node installed from its own installer that folder needs an administrator, so npm stops with a permission error. MADRE does not ask for your password: when it sees that wall it installs the CLI into a folder of its own, ~/.pulse/tools, and looks there as well as along PATH. The agent works the same; only the file lives somewhere else.',
|
|
524
|
-
remedy: 'Nothing to do: press
|
|
529
|
+
remedy: 'Nothing to do: press Install again and MADRE takes the second way by itself. If you would rather have the CLI everywhere in your terminal, install it yourself with your package manager, or give npm a folder of your own.',
|
|
525
530
|
fixes: {
|
|
526
531
|
darwin: ['# MADRE does this for you; these are the alternatives:', 'brew install --cask claude-code', 'npm config set prefix ~/.npm-global # then add ~/.npm-global/bin to your PATH'],
|
|
527
532
|
linux: ['# MADRE does this for you; these are the alternatives:', 'npm config set prefix ~/.npm-global # then add ~/.npm-global/bin to your PATH']
|
|
@@ -531,21 +536,21 @@ export const CONDITIONS = [
|
|
|
531
536
|
id: 'privacy-leak',
|
|
532
537
|
code: 'MU-038',
|
|
533
538
|
severity: 'warning',
|
|
534
|
-
title: 'Privacy: an agent brought its own configuration into the
|
|
539
|
+
title: 'Privacy: an agent brought its own configuration into the project',
|
|
535
540
|
match: /privacy\.redacted|privacy\.purged|private terms?|\[ENTIDAD-ORG\]|organi[sz]ation(al)? instructions|leak(ed)? (a|the) (name|company|domain)/i,
|
|
536
541
|
diagnosis: 'A CLI agent runs with its own system context: organisation instructions, the account it is signed in with, CLAUDE.md files elsewhere. It can mistake that private context for shared context and write a company, a brand or a domain into a reply. Once in the ledger the term reaches the archivist, every other agent and the dataset.',
|
|
537
|
-
remedy: 'Name the terms in
|
|
538
|
-
fixes: same(['#
|
|
542
|
+
remedy: 'Name the terms in Settings → Privacy, under Hidden data. From then on MADRE replaces them with the marker before the ledger, the index, the notes and the dataset see them, and every reply that needed it shows a privacy line. Erase private data rewrites what the project already holds; re-export the dataset afterwards. The terms never leave config.json.',
|
|
543
|
+
fixes: same(['# Settings → Privacy → Hidden data, one per line → Erase private data', 'export PULSE_PRIVATE_TERMS="Acme Corp,acme.com" # same list from the environment', 'grep -c "ENTIDAD-ORG" ~/.pulse/rooms/*/events.jsonl']),
|
|
539
544
|
},
|
|
540
545
|
{
|
|
541
546
|
id: 'control-changes',
|
|
542
547
|
code: 'MU-039',
|
|
543
548
|
severity: 'informational',
|
|
544
|
-
title: '
|
|
549
|
+
title: 'EDIT: what changed, what was reverted, UNDO',
|
|
545
550
|
match: /control\.changed|forbidden zones?|reverted|UNDO|checkpoint|changed \d+ file/i,
|
|
546
|
-
diagnosis: 'A #3
|
|
547
|
-
remedy: 'Read the list under the reply before moving on. If the change is wrong press UNDO; if the agent should not have had it, lower its
|
|
548
|
-
fixes: same(['git log --oneline -5 # checkpoints are ordinary commits on a side ref', 'git stash list', '#
|
|
551
|
+
diagnosis: 'A #3 EDIT turn takes a git restore point before the agent runs, then lists every file it added, modified or deleted. Writes into .git, .pulse or any .env file are reverted on the spot and named. UNDO goes back to the restore point in one click; STOPALL revokes EDIT. One holder at a time, never given to a plan step, needs Max mode #3 and a git repository.',
|
|
552
|
+
remedy: 'Read the list under the reply before moving on. If the change is wrong press UNDO; if the agent should not have had it, lower its Max mode in Settings → Permissions.',
|
|
553
|
+
fixes: same(['git log --oneline -5 # checkpoints are ordinary commits on a side ref', 'git stash list', '# project → UNDO under the EDIT notice']),
|
|
549
554
|
},
|
|
550
555
|
{
|
|
551
556
|
id: 'conversations',
|
|
@@ -553,29 +558,29 @@ export const CONDITIONS = [
|
|
|
553
558
|
severity: 'informational',
|
|
554
559
|
title: 'Conversations: many per project, one memory, one at a time',
|
|
555
560
|
match: /conversation|already open for this project|ROOM_IN_USE|a turn is running in this conversation|new conversation|chats\.json/i,
|
|
556
|
-
diagnosis: 'A project has one memory and many conversations. The archive, the
|
|
557
|
-
remedy: 'The panel on the left of the canvas lists them: open one, or start another at the bottom. Deleting one takes its transcript and nothing else — what the archivist distilled from it is the project\'s memory and stays. If MADRE says the project is already open, use that
|
|
558
|
-
fixes: same(['#
|
|
561
|
+
diagnosis: 'A project has one memory and many conversations. The archive, the agents, the modules and the privacy list belong to the project and do not start over when you open another thread; a conversation is only the record of one line of work, and everything said in any of them feeds the same archive. The first conversation is the ledger that was always there, so a project that existed before opens exactly as it did. The numbering is the project\'s, not the thread\'s: a new conversation starts where the project got to, which is why a citation like #1411 means the same exchange in all of them. One conversation drives the agents at a time — two threads editing the same working tree is a way to lose work — so opening another while a turn runs is refused until it finishes. And one server per project: a second `madre start` on the same project is refused with the address of the project that is already open, because two servers would hand out the same sequence twice and the archive would quietly keep one of them.',
|
|
562
|
+
remedy: 'The panel on the left of the canvas lists them: open one, or start another at the bottom. Deleting one takes its transcript and nothing else — what the archivist distilled from it is the project\'s memory and stays. If MADRE says the project is already open, use that project and open a conversation inside it instead of starting a second server.',
|
|
563
|
+
fixes: same(['# project → Conversations → NEW CONVERSATION', '# the address of the open project is in the refusal itself', 'ls ~/.pulse/rooms/*/chats.json # their names and which one is open']),
|
|
559
564
|
},
|
|
560
565
|
{
|
|
561
566
|
id: 'memory-aberrations',
|
|
562
567
|
code: 'MU-041',
|
|
563
568
|
severity: 'informational',
|
|
564
|
-
title: 'Aberrations: what the
|
|
569
|
+
title: 'Aberrations: what the project established is false',
|
|
565
570
|
match: /aberration|aberraci|eyecat|contradict|refut|false claim|hallucinat|alucina/i,
|
|
566
|
-
diagnosis: 'An aberration is a claim the
|
|
567
|
-
remedy: '
|
|
568
|
-
fixes: same(['#
|
|
571
|
+
diagnosis: 'An aberration is a claim the project established is false, kept on purpose rather than deleted: it is what the local model learns not to repeat. It never travels into a turn, and the note it refutes is taken out of circulation with it — a refuted memory is never recalled again, by words or by meaning. EYECAT watches for two agents saying opposite things about the same subject and raises the pair for a third agent to judge, one that took no part in either side. Confirming files the aberration and quarantines what it refutes; dismissing says the project was right and the pair is never raised again. Forgetting an aberration gives its note back.',
|
|
572
|
+
remedy: 'The Memory map shows them as collapsed bodies: open one to read what it took down, or clear it if the project was wrong about being wrong. The second test of the Memory review, in Settings → Memory, reports open contradictions.',
|
|
573
|
+
fixes: same(['# Diagnostics → Memory map → the dark bodies are aberrations', '# Settings → Memory → Analysis and tests → the second test']),
|
|
569
574
|
},
|
|
570
575
|
{
|
|
571
576
|
id: 'memory-cascade',
|
|
572
577
|
code: 'MU-042',
|
|
573
578
|
severity: 'informational',
|
|
574
|
-
title: 'Memory used · N
|
|
579
|
+
title: 'Memory used · N related',
|
|
575
580
|
match: /by association|cascade|spreading activation|keeps arriving with|memory used/i,
|
|
576
|
-
diagnosis: 'Under a reply, MADRE says what the archive handed that turn. Most of it was matched to what you asked, by words and by meaning. A note marked "
|
|
577
|
-
remedy: 'Click a note to see it in
|
|
578
|
-
fixes: same(['#
|
|
581
|
+
diagnosis: 'Under a reply, MADRE says what the archive handed that turn. Most of it was matched to what you asked, by words and by meaning. A note marked "related" came along for a different reason: this project keeps carrying it in the same turn as one of the others, so the archive brings it too, however differently it reads. The strength is a ratio over the turns where each was found on its own merits — a memory the project reaches for constantly does not end up attached to everything, and a pair that stops meeting fades on its own. Related notes add and never displace: recall keeps two slots for them and hands back the ones it does not use.',
|
|
582
|
+
remedy: 'Click a note to see it in the Memory map, where the wires it travels on are drawn. It is the one part of recall that owes nothing to how a memory reads, so it can be switched off in Settings → Memory, with Related.',
|
|
583
|
+
fixes: same(['# Settings → Memory → Related', 'PULSE_RECALL_CASCADE=0 npx @jossuealcala/madre start']),
|
|
579
584
|
},
|
|
580
585
|
{
|
|
581
586
|
id: 'memory-cold',
|
|
@@ -583,19 +588,19 @@ export const CONDITIONS = [
|
|
|
583
588
|
severity: 'informational',
|
|
584
589
|
title: 'Cold memories: what the archive has had its chances with',
|
|
585
590
|
match: /cold memor|cold zone|never once carried|had its chances/i,
|
|
586
|
-
diagnosis: 'A memory is
|
|
587
|
-
remedy: '
|
|
588
|
-
fixes: same(['#
|
|
591
|
+
diagnosis: 'A memory is unused when three things are true at once: no turn has ever carried it, it shares a subject with nothing so nothing can reach it sideways either, and the archive has been opened at least a dozen times since it was written. The third is what makes the label worth acting on — never-recalled is what every memory is on the day it is written. Chances are counted in turns that actually reached into the archive, and only from the day the project started keeping that trail, so what was never written down is not held against the note.',
|
|
592
|
+
remedy: 'The Memory map shows UNUSED · N in its header when there are any; pressing it rings each one on the map. Open one and its card says the number plainly, with FORGET one press away. Asking about it is the other way out: the project writes that question for you under ASK.',
|
|
593
|
+
fixes: same(['# Diagnostics → Memory map → UNUSED', '# Diagnostics → Memory map → ASK → PUT IN THE WRITE BOX']),
|
|
589
594
|
},
|
|
590
595
|
{
|
|
591
596
|
id: 'maturity-tests',
|
|
592
597
|
code: 'MU-044',
|
|
593
598
|
severity: 'informational',
|
|
594
|
-
title: '
|
|
599
|
+
title: 'Memory review: whether the archive works',
|
|
595
600
|
match: /three tests|coverage|consistency|held-out|match test|maturity|madurez|ready to be worked in/i,
|
|
596
|
-
diagnosis: 'The six readings count what the archive is made of; they cannot say whether it works, because nothing about a pile of notes says whether the right one comes back when it is needed. COVERAGE takes real questions from this
|
|
597
|
-
remedy: 'Read the one sentence and the one instruction at the top of
|
|
598
|
-
fixes: same(['#
|
|
601
|
+
diagnosis: 'The six readings count what the archive is made of; they cannot say whether it works, because nothing about a pile of notes says whether the right one comes back when it is needed. COVERAGE takes real questions from this project, runs recall at the exact point each was asked, and scores what came back against the reply that was actually given. CONSISTENCY reads the contradictions EYECAT still holds and whether aberrations are being filed more often lately. MATCH puts real questions a frontier CLI answered back to the local model with this archive behind it. All three measure against a control, because everything in one project is about the same handful of subjects and any two pieces of it read as close to an embedder: to count, what the archive handed over has to beat what it would have handed over for a different question.',
|
|
602
|
+
remedy: 'Read the one sentence and the one instruction at the top of Settings → Memory; the readings and the tests are in Analysis and tests, below it. The free test is read as the panel opens, the cheap one keeps itself fresh once a day while the embeddings are local, and the slow one is yours to start and to stop. None of them spends a provider turn.',
|
|
603
|
+
fixes: same(['# Settings → Memory → Analysis and tests → Memory review', '# MATCH needs Ollama running with a chat model, and smart search on']),
|
|
599
604
|
},
|
|
600
605
|
{
|
|
601
606
|
id: 'module-update',
|
|
@@ -603,7 +608,7 @@ export const CONDITIONS = [
|
|
|
603
608
|
severity: 'common',
|
|
604
609
|
title: 'Updating what a module drives',
|
|
605
610
|
match: /EACCES|permission denied.*npm|npm ERR!.*EACCES|update to \d|newest is|brew upgrade|install -g @playwright/i,
|
|
606
|
-
diagnosis: 'When something newer exists and the module knows how to fetch it, the button is beside the version on its
|
|
611
|
+
diagnosis: 'When something newer exists and the module knows how to fetch it, the button is beside the version on its page in Modules. It asks twice on purpose: the first press answers with the command, the second runs exactly that, and the output lands in the project line by line. Nothing installs by itself — putting software on your computer unannounced would break the one thing MADRE promises, that a command is seen before it runs. The usual failure is npm refusing a global install with EACCES, which means the global prefix belongs to root; sudo works and leaves you with root-owned files, so a user-owned prefix or a version manager is the better answer.',
|
|
607
612
|
remedy: 'Press the button beside the version, read the command, run it. If npm refuses with EACCES, point npm at a prefix you own or use a version manager, then press it again.',
|
|
608
613
|
fixes: {
|
|
609
614
|
darwin: ['npm config get prefix', 'npm config set prefix ~/.npm-global', 'echo \'export PATH="$HOME/.npm-global/bin:$PATH"\' >> ~/.zshrc', '# or: brew install node # a Homebrew node owns its own prefix'],
|
|
@@ -616,9 +621,9 @@ export const CONDITIONS = [
|
|
|
616
621
|
severity: 'common',
|
|
617
622
|
title: 'Installing a module somebody else wrote',
|
|
618
623
|
match: /already taken|must live under \/api\/x\/|not a module|default export must be a module|module file|\.module\.mjs|add a module/i,
|
|
619
|
-
diagnosis: '
|
|
620
|
-
remedy: 'Install it only if you trust where it came from. A module you wrote can also be updated from where you publish it: declare updates: { url } in the file, or install it from a file and MADRE remembers which, and its
|
|
621
|
-
fixes: same(['#
|
|
624
|
+
diagnosis: 'Modules has + Add a module for a .mjs somebody wrote. It comes through the same door as everything else: written to a scratch copy, imported there, checked against the house rules, and installed only if it passes. Three things get a file refused, each with the reason: an id that belongs to a module MADRE ships with, a route outside its own corner of the API (/api/x/<id>/), and a file that will not load at all. Said plainly, because it is what it is: a module runs inside MADRE, with your permissions, on this computer. MADRE checks that it loads and stays in its corral; what the code intends is the one thing nobody can check for you.',
|
|
625
|
+
remedy: 'Install it only if you trust where it came from. A module you wrote can also be updated from where you publish it: declare updates: { url } in the file, or install it from a file and MADRE remembers which, and its page in Modules carries Get a newer file.',
|
|
626
|
+
fixes: same(['# Modules → + Add a module', 'ls ~/.pulse/modules # every module you installed, and where it came from', '# docs/SDK.md is the whole contract, and docs/sdk/hello-module.mjs is one that works']),
|
|
622
627
|
},
|
|
623
628
|
{
|
|
624
629
|
id: 'local-ready',
|
|
@@ -626,23 +631,23 @@ export const CONDITIONS = [
|
|
|
626
631
|
severity: 'common',
|
|
627
632
|
title: 'Is the local model ready to be worked in?',
|
|
628
633
|
match: /is .*(local|madre).*(ready|good|any good)|ready to be worked in|measured against this (room|project)|check it against this room|local\.present|not measured/i,
|
|
629
|
-
diagnosis: 'Running is not the same as being of use. @madre being in the
|
|
630
|
-
remedy: 'The
|
|
634
|
+
diagnosis: 'Running is not the same as being of use. @madre being in the project means Ollama has a chat model; whether that model is worth your work on THIS project is a different question, and the project measures it: twelve real exchanges from this project are put back to the local model, and each answer is scored against what the agents actually answered that day — against a control, so that talking about the same project does not count. It takes minutes and spends nothing, because all of it runs on your machine.',
|
|
635
|
+
remedy: 'The project says which of the two it has, once per model, in the line that begins "local · @madre". If nobody has measured it, that line carries TRY IT ON THIS PROJECT; the answer lands in the project when it finishes, with the one thing to do about it. A model that does not pass is not broken — the archive is still thin, and it fills where the work happens. The @madre sphere keeps the reading and its date after the line has scrolled away, and the same test lives in Memory map → MEMORY REVIEW.',
|
|
631
636
|
fixes: same([
|
|
632
|
-
'# the line in the
|
|
633
|
-
'# or:
|
|
634
|
-
'# it needs
|
|
637
|
+
'# the line in the project: local · @madre → TRY IT ON THIS PROJECT',
|
|
638
|
+
'# or: Memory map → MEMORY REVIEW → the third test',
|
|
639
|
+
'# it needs smart search on and some turns answered by a CLI agent, which is what it compares against',
|
|
635
640
|
]),
|
|
636
641
|
},
|
|
637
642
|
{
|
|
638
643
|
id: 'code000',
|
|
639
644
|
code: 'MU-048',
|
|
640
645
|
severity: 'blocking',
|
|
641
|
-
title: '
|
|
646
|
+
title: 'Temporary lock: the archive is sealed',
|
|
642
647
|
match: /CODE000|THE ARCHIVE IS SEALED|UNABLE TO COMPUTE\. UNABLE TO CLARIFY|designation|intruder/i,
|
|
643
|
-
diagnosis: 'Two doors ask for the project
|
|
644
|
-
remedy: 'The
|
|
645
|
-
fixes: same(['basename "$PWD" # the designation this room asks for', '# the
|
|
648
|
+
diagnosis: 'Two doors ask for the project name before doing something that cannot be undone: opening the memory, and erasing all private data already recorded. Getting that name wrong is never part of doing the work — you either know the project you are standing in or you are trying names — so Diagnostics counts it. Eight wrong names inside five minutes and the Temporary lock comes down: the archive is sealed for ten minutes, the agents are told in code, and the Memory map asks for the project name again.',
|
|
649
|
+
remedy: 'The project name is the name of the folder this project was opened in, lowercase or not. Nothing was lost: the seal is a refusal to change the archive for ten minutes, not a deletion, and it lifts on its own. Reading the core is not one of those doors and never counts — it is the way in.',
|
|
650
|
+
fixes: same(['basename "$PWD" # the designation this room asks for', '# the temporary lock lifts on its own; Diagnostics › Memory map asks for the name again after it does']),
|
|
646
651
|
},
|
|
647
652
|
{
|
|
648
653
|
id: 'core-console',
|
|
@@ -650,9 +655,9 @@ export const CONDITIONS = [
|
|
|
650
655
|
severity: 'common',
|
|
651
656
|
title: 'The core closed while I was typing in it',
|
|
652
657
|
match: /unable to compute|interface closed|core clos|three strikes|inquiry|order 937|mu\/th\/ur 6000/i,
|
|
653
|
-
diagnosis: 'Inside the core there is a console:
|
|
654
|
-
remedy: 'Nothing happened to the archive: reading what the
|
|
655
|
-
fixes: same(['#
|
|
658
|
+
diagnosis: 'Inside the core there is a console: Diagnostics answers about this project from what the page already has — the blocks of the next briefing and their words, the command that would run it, what has left this machine, how many terms privacy is protecting, where the archive stands. Nothing is asked of the agents and nothing is sent. It answers or it says it cannot, and three inquiries it cannot parse close the frame. The count is on screen from the first one and every refusal names what it would have taken.',
|
|
659
|
+
remedy: 'Nothing happened to the archive: reading what the project says in your name is not an attempt on it. Open the core again — click the star at the centre of the Memory map — and the count starts over. HELP lists every inquiry; READ <BLOCK> prints one block of the briefing word for word.',
|
|
660
|
+
fixes: same(['# Memory map → click What is sent → type HELP', '# READ MEMORIES prints the block the next turn would carry', '# SPECIAL ORDER 937 is answered too']),
|
|
656
661
|
},
|
|
657
662
|
{
|
|
658
663
|
id: 'outbound',
|
|
@@ -660,12 +665,12 @@ export const CONDITIONS = [
|
|
|
660
665
|
severity: 'common',
|
|
661
666
|
title: 'What leaves this computer, and how to stop each thing that does',
|
|
662
667
|
match: /what left this machine|outbound|leaves? (this )?(computer|machine)|sends? (my )?(code|data)|telemetry|phone home|privacy/i,
|
|
663
|
-
diagnosis: 'MADRE runs here and keeps what it knows in a file you own, and the list that qualifies that sentence is inside the core, under
|
|
668
|
+
diagnosis: 'MADRE runs here and keeps what it knows in a file you own, and the list that qualifies that sentence is inside the core, under OUTBOUND. Seven addresses, each saying what it carries and where it is switched off: the briefing, which goes to whoever runs the agent you sent the turn to; Gemini embeddings, which carry the text of your memories; the image model, which carries the prompt an agent wrote; the npm registry and GitHub, which get a package name and nothing else; the error collector, which gets a redacted condition and only with your press; and Anthropic, for how much of your Claude plan is left. Ollama is on the list to be seen staying here.',
|
|
664
669
|
remedy: 'Under the list is the log itself: every request this process made, MADRE\'s own and any a module made, because a module runs inside MADRE and cannot opt out of the wrapper. No body, no header and no query value is ever written there — only which parameters were set. An address nothing declares is reported as exactly that.',
|
|
665
670
|
fixes: same([
|
|
666
|
-
'#
|
|
671
|
+
'# Memory map → click What is sent → OUTBOUND',
|
|
667
672
|
'cat ~/.pulse/rooms/*/outbound.jsonl | tail -20 # the same log, on disk',
|
|
668
|
-
'#
|
|
673
|
+
'# smart search, to keep memories on this computer: Settings → Memory → Smart search → Ollama',
|
|
669
674
|
'PULSE_UPDATE_CHECK=0 madre start # no version checks at all',
|
|
670
675
|
]),
|
|
671
676
|
},
|
|
@@ -697,13 +702,27 @@ export function said(condition) {
|
|
|
697
702
|
}
|
|
698
703
|
export const allConditions = () => CONDITIONS.map(said);
|
|
699
704
|
|
|
705
|
+
// Lowercase and without accents: «limite» finds «límite», and a person types what they type.
|
|
706
|
+
const fold = (text) => String(text ?? '').normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
|
|
707
|
+
const AGENT_WORDS = new Set(['codex', 'claude', 'gemini', 'opencode', 'madre', 'ollama']);
|
|
708
|
+
|
|
700
709
|
export function searchConditions(query) {
|
|
701
|
-
const
|
|
710
|
+
const words = fold(query).split(/[^a-z0-9#.@_-]+/).filter(Boolean);
|
|
702
711
|
const all = allConditions();
|
|
703
|
-
if (!
|
|
704
|
-
//
|
|
705
|
-
|
|
706
|
-
|
|
712
|
+
if (!words.length) return all;
|
|
713
|
+
// A symptom is a few words, not a phrase to be found whole. An agent's name narrows the list to
|
|
714
|
+
// that agent's conditions and the general ones; every other word has to appear somewhere in the
|
|
715
|
+
// condition, read in the language it is shown in, in either language's original, or in its fixes.
|
|
716
|
+
// «claude tiempo limite» used to find nothing, and only «timeout» found the timeout card.
|
|
717
|
+
const agent = words.find((word) => AGENT_WORDS.has(word.replace(/^@/, '')))?.replace(/^@/, '') ?? null;
|
|
718
|
+
const rest = words.filter((word) => !AGENT_WORDS.has(word.replace(/^@/, '')));
|
|
719
|
+
return all.filter((condition) => {
|
|
720
|
+
if (agent && condition.agent && condition.agent !== agent) return false;
|
|
721
|
+
const source = CONDITIONS.find((one) => one.id === condition.id);
|
|
722
|
+
const haystack = fold([condition.id, condition.code, condition.title, condition.diagnosis, condition.remedy, condition.agent ?? '', source?.title, source?.diagnosis, ...Object.values(condition.fixes ?? {}).flat()].join(' '));
|
|
723
|
+
if (!rest.length) return !agent || condition.agent === agent || haystack.includes(agent);
|
|
724
|
+
return rest.every((word) => haystack.includes(word));
|
|
725
|
+
});
|
|
707
726
|
}
|
|
708
727
|
|
|
709
728
|
export function fixesFor(condition, platform, agent = null) {
|