ultimate-brain 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.agents/skills/brain-apply/SKILL.md +35 -22
  2. package/.agents/skills/brain-catch-up/SKILL.md +51 -36
  3. package/.agents/skills/brain-connect-notion/SKILL.md +29 -2
  4. package/.agents/skills/brain-howto/SKILL.md +1 -1
  5. package/.agents/skills/brain-howto/references/guide.md +117 -48
  6. package/.agents/skills/brain-ingest/SKILL.md +14 -6
  7. package/.agents/skills/brain-ingest/references/cli-inputs.md +31 -5
  8. package/.agents/skills/brain-ingest/references/extraction.md +36 -1
  9. package/.agents/skills/brain-ingest/references/notion.md +8 -6
  10. package/.agents/skills/brain-ingest/references/sources.md +36 -14
  11. package/.agents/skills/brain-notion-change/SKILL.md +2 -0
  12. package/.agents/skills/brain-query/SKILL.md +18 -8
  13. package/.agents/skills/brain-sync/SKILL.md +31 -12
  14. package/.agents/skills/brain-sync/references/formats.md +28 -1
  15. package/dist/cli.js +5 -4
  16. package/dist/commands/modules.js +54 -0
  17. package/dist/commands/report.js +81 -4
  18. package/dist/commands/source.js +27 -35
  19. package/dist/commands/status.js +5 -5
  20. package/dist/commands/sync.js +3 -1
  21. package/dist/commands/upgrade.js +33 -18
  22. package/dist/lib/apply.js +237 -33
  23. package/dist/lib/diff.js +31 -0
  24. package/dist/lib/errors.js +2 -0
  25. package/dist/lib/ids.js +2 -0
  26. package/dist/lib/index-builder.js +6 -1
  27. package/dist/lib/lint.js +46 -8
  28. package/dist/lib/modules.js +91 -0
  29. package/dist/lib/note-new.js +111 -18
  30. package/dist/lib/paths.js +1 -0
  31. package/dist/lib/proposals.js +74 -18
  32. package/dist/lib/query.js +1 -1
  33. package/dist/lib/schemas.js +1 -1
  34. package/dist/lib/sync.js +246 -86
  35. package/package.json +1 -1
  36. package/spec/schemas/brain.schema.json +36 -0
  37. package/spec/schemas/note.schema.json +105 -18
  38. package/templates/brain/brain.json +3 -1
  39. package/templates/brain/knowledge/references/.gitkeep +0 -0
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: brain-apply
3
- description: Apply the user's decisions on proposed changes to the brain. Shows pending proposals in chat and applies what the user approves, rejects or edits, or reads the decisions and Notes the user left in the Notion Review queue and applies them, then rebuilds and republishes. Use when the user says "apply my reviews", "what needs my decision", "approve the launch change", "apply the Review queue", or after deciding proposals in Notion.
3
+ description: Apply the user's decisions on proposed changes to the brain. Shows pending proposals in chat and applies what the user approves, rejects or fixes, or reads the calls and What to fix texts the user left in the Notion Review queue and applies them, then rebuilds and republishes. Use when the user says "apply my reviews", "what needs my decision", "approve the launch change", "apply the Review queue", or after deciding proposals in Notion.
4
4
  ---
5
5
 
6
6
  # Apply review decisions
7
7
 
8
- Proposals are changes the brain wants to make to existing notes (decision 0003). The user decides each one: approve, reject, or edit (edit means approve, but with the user's own value). This skill records those decisions and applies them through the CLI. Only the user decides. Never approve, reject or edit on their behalf, and never infer a decision from the minutes or from earlier chat.
8
+ Proposals are changes the brain wants to make to existing notes (decision 0003). The user decides each one: **Approve**, **Reject**, or **Fix** (apply it, corrected as the user says in plain words; decision 0045). This skill records those decisions and applies them through the CLI. Only the user decides. Never approve, reject or fix on their behalf, and never infer a decision from the minutes or from earlier chat.
9
9
 
10
10
  Run every CLI command as `brain <command> --brain <brain> --json`. Exit 1 means some items need attention; read them. Exit 2 or 4 means your command or input was wrong: fix it. Exit 3 or 5 means stop and report. Exit 10: report a bug. If `brain` is not found (`command not found`), install it with `npm install -g ultimate-brain`, then retry.
11
11
 
@@ -22,24 +22,26 @@ Run every CLI command as `brain <command> --brain <brain> --json`. Exit 1 means
22
22
  `3. Acme website: budget 80000 EUR → 95000 EUR. "Budget raised to 95000 EUR to cover the CMS licence." (Acme launch review, 10 Dec)`
23
23
  For each kind:
24
24
  - `update_fact`: old → new value.
25
- - `contradiction`: both values, and say approving keeps both as contested, while editing picks the true one.
25
+ - `contradiction`: both values, and say approving keeps both as contested, while a fix picks the true one.
26
26
  - `add_to_note`: the text to add.
27
+ - `update_body` (decision 0045): the reference note and the lines that change, `-` old and `+` new.
27
28
  - `add_link`: what gets linked to what. A grouped row lists every link, lettered: "Acme website: add a) Lucía Fernández, b) Tomás Vidal to People, c) alias 'acme site'".
28
29
  - `supersede`: the new note replaces the old one.
29
30
  - `merge`: the duplicate is folded into the survivor.
30
31
  - `new_item`: the note that would be created.
31
- - `review_notes` (decisions 0041, 0043): the new notes and routine links of one input, lettered as the Review row's After letters them: notes first, then links. "Accept 6 new notes from Acme launch review, and 2 links: a) Decision: Use Contentful as the blog CMS, b) Question: …, g) People on Acme website: Lucía Fernández, h) Aliases on Maria López: Mari López". Approving makes the notes `reviewed` and applies the links; rejecting archives the notes still `draft` and closes the links.
32
+ - `review_notes` (decisions 0041, 0043, 0045): everything one input proposes, lettered as the Review row's Proposed letters them: the **changes** first (every fact change marked ⚠, a new fact as `(new) → <value>`; then new text for a reference; then text added to a note), then the new **notes**, then the **links**. "From Acme launch review: a) ⚠ Launch date on Acme website: 2027-02 → 2027-03, b) Add to Row-level security: Carlos will use RLS…, c) Decision: Use Contentful as the blog CMS, …, h) People on Acme website: Lucía Fernández". End the line with the source and date ("(Acme sync, 3 Dec)"), with no quote: each item has its own `why`, shown when the user asks. Approving applies the changes, makes the notes `reviewed` and applies the links; rejecting archives the notes still `draft` and applies nothing.
32
33
  - `answer`: the question and its answer, and the note that answers it: "Who owns the mobile app? → Carlos Ruiz owns it (decision: Carlos owns the mobile app)". Approving closes the question; it shows as Answered in Notion.
33
34
 
34
35
  Look up titles with `brain index --json` instead of showing ids. Mention the ones already decided but not applied.
35
- 3. **Ask** which to approve, reject or edit. Accept replies like "approve 1 and 3, reject 2, edit 4 to 90000 EUR". Edit is only possible for `update_fact`, `contradiction`, `add_to_note` and `answer` (the user's text becomes the answer); say so if the user asks to edit another kind. On a grouped `add_link` or a `review_notes`, "approve 5 except b" approves it with those items excluded. **If a reply is unclear, ask again.** Don't guess.
36
+ 3. **Ask** which to approve, reject or fix. Accept replies like "approve 1 and 3, reject 2, fix 4: 90000 EUR", "approve 5 except b" or "fix 5: a is March, c belongs to Acme app". Fix works on every kind: read the user's words into `fixes` as "Reading What to fix" below says. On a grouped `add_link` or a `review_notes`, "except b" leaves those items out: on a `review_notes` they move to a new pending row (deferred, not rejected). When a reply names a row by its source and two rows share it, the letter or title only one of them has settles it; otherwise ask. **If a reply is unclear, ask again.** Don't guess.
36
37
  4. **Apply.** Write the input and run `brain apply --input <file>`:
37
38
  ```json
38
39
  { "decisions": [
39
40
  { "proposal": "prp-…", "action": "approve", "decided_at": "<now, ISO 8601 UTC>", "decided_by": "chat" },
40
- { "proposal": "prp-…", "action": "edit", "value": "90000 EUR", "decided_at": "<now>", "decided_by": "chat" },
41
+ { "proposal": "prp-…", "action": "fix", "note": "90000 EUR", "fixes": [ { "value": "90000 EUR" } ], "decided_at": "<now>", "decided_by": "chat" },
41
42
  { "proposal": "prp-…", "action": "approve", "exclude": [ { "field": "people", "value": "per-…" } ], "decided_at": "<now>", "decided_by": "chat" },
42
- { "proposal": "prp-…", "action": "approve", "note": "all except b, h", "exclude": [ { "note": "que-…" }, { "target": "per-…", "field": "aliases", "value": "Mari López" } ], "decided_at": "<now>", "decided_by": "chat" }
43
+ { "proposal": "prp-…", "action": "approve", "note": "all except a, h", "exclude": [ { "change": 0 }, { "target": "per-…", "field": "aliases", "value": "Mari López" } ], "decided_at": "<now>", "decided_by": "chat" },
44
+ { "proposal": "prp-…", "action": "fix", "note": "a is March", "fixes": [ { "change": 0, "value": "2027-03" } ], "decided_at": "<now>", "decided_by": "chat" }
43
45
  ] }
44
46
  ```
45
47
  To apply only what was decided earlier, run `brain apply` with no `--input`.
@@ -47,22 +49,32 @@ Run every CLI command as `brain <command> --brain <brain> --json`. Exit 1 means
47
49
 
48
50
  ## Notion mode
49
51
 
50
- 1. **Read** the Review database through the Notion MCP: the rows where **Decision** is set and **State** is Pending. Normalize each row into the snapshot format of spec/cli.md §5.14.1:
52
+ 1. **Read** the Review database through the Notion MCP: the rows where **Your call** is set and **State** is Pending. Normalize each row into the snapshot format of spec/cli.md §5.14.1:
51
53
  - `database: "review"`, the `page_id` and `last_edited`;
52
- - the properties Name, Kind, Decision, Note, State and Brain ID.
54
+ - the properties Name, Kind, Your call, What to fix, State and Brain ID. A space not yet migrated (migration 0009) still has Decision and Note: send them under those names, and the CLI reads them the same way, Edit as Fix.
53
55
  2. **Plan.** Run `brain sync plan --input <snapshot>`. It writes nothing. Save the reply's **`data` object** (not the whole JSON reply) as the plan file; `sync apply` rejects the full reply. Read:
54
56
  - `decisions`: what will be applied;
55
- - `conflicts`: `NOTE_TO_READ` is an Approve or Reject with a Note: read it as "Reading a Note" below says. Others the user fixes in Notion: `EDIT_WITHOUT_VALUE` (Edit with an empty Note), `EDIT_NOT_ALLOWED` (Edit on a kind that can't be edited, such as a link row or a Review notes row: suggest Approve or Reject, with a Note);
57
+ - `conflicts`: `NOTE_TO_READ` is an Approve or Reject with text in What to fix, and `FIX_TO_READ` a Fix with its text: read each as "Reading What to fix" below says. `FIX_WITHOUT_TEXT` is a Fix with What to fix empty: the user says what's wrong in Notion (or here);
56
58
  - `ignored`: e.g. `ALREADY_TERMINAL`. Nothing to do.
57
- 3. **Apply.** Run `brain sync apply --input <plan file>`, adding `--record-only` when unattended. Then apply the decisions you resolved from Notes with `brain apply --input` (unattended: leave `NOTE_TO_READ` rows for an attended run).
59
+ 3. **Apply.** Run `brain sync apply --input <plan file>`, adding `--record-only` when unattended. Then apply the decisions you resolved from What to fix with `brain apply --input <file>` (unattended: leave `NOTE_TO_READ` and `FIX_TO_READ` rows for an attended run).
58
60
  4. Continue with **Finish** below.
59
61
 
60
- ## Reading a Note
62
+ ## Reading What to fix
61
63
 
62
- The Note is the user's instruction for that one row (decision 0037). The CLI never interprets it; you do, and you **never apply a change the Note doesn't clearly ask for**. Decide each `NOTE_TO_READ` row as one of:
63
- - **A narrower decision on this row:** "all except Tomás" or "only Ana" on a grouped `add_link` → `approve` with `exclude` listing the other links (by their `{field, value}` in the proposal's `links`). "All except b, e" on a **Review notes** row → `approve` with one `exclude` entry per letter, counted as the row's After letters them: `notes` first, in order, as `{ "note": "<id>" }`, then `links`, in order, as `{ "target", "field", "value" }`. Read the letters against the proposal's own `notes` and `links` (`brain proposal list --target <a note id>`), never against what you remember of the row. A letter the row doesn't have → ask. A Note naming a note by title ("all except the risk") works the same way. "Yes, but it's March" on an `update_fact` → `edit` with that value. Pass `note` = the Note as written, `decided_at` = the row's `last_edited`, `decided_by: notion`.
64
- - **A different change** (a role typed on a link row, a fact about another note) → apply this row as its Decision says, and write the other change as its own proposal with `brain proposal new` (`why` = the Note, `source` = the proposal's `source`), so it gets its own Review row.
65
- - **Unclear** → ask the user, quoting the Note, and leave the row as it is until they answer.
64
+ What to fix is the user's instruction for that one row, in plain words (decisions 0037, 0045). The CLI never interprets it; you do, and you **never apply a change the text doesn't clearly ask for**. Read the letters against the proposal itself (`brain proposal list --target <a note id>`, then its `changes`, `notes` and `links`), never against what you remember of the row. Letters run over the items in the order of spec/schema.md §11.3: every entry of `changes` (as stored), then `notes`, then `links`; `a` is `{ "change": 0 }` when the row has changes. A letter the row doesn't have → ask. A title works like a letter ("all except the risk"). Every decision you write carries `note` = the text as written, `decided_at` = the row's `last_edited`, `decided_by: notion` (in chat: now and `chat`).
65
+
66
+ - **Approve with a narrower scope** ("all except b, e", "only Ana"): `approve` with one `exclude` entry per item left out: `{ "change": <index> }`, `{ "note": "<id>" }` or `{ "target", "field", "value" }` on a Review notes row, `{ "field", "value" }` from `links` on an `add_link` row. On a Review notes row the excluded items move to a new pending row; say so in the report.
67
+ - **Fix** (Your call is Fix, or an Approve whose text corrects a value: "yes, but it's March"): `fix` with `fixes`, by kind (spec/schema.md §11.3):
68
+ - a fact, a contradiction, text to add, a reference's new text or an answer: one `{ "value": … }`, the corrected value or text. For a fact, write the value in the shape the fact has (`2027-03`, not "March");
69
+ - a supersede or merge: one `{ "value": "<id>" }`, the note it should be instead;
70
+ - a possible new note: `{ "field": "title" | <a frontmatter key>, "value": … }`;
71
+ - an add_link row: `{ "link": { "field", "value" }, "value": <the corrected value> }`;
72
+ - a Review notes row: `{ "change": <index>, "value": … }` for a change ("a: March"), `{ "note": "<id>", "field", "value" }` for a new note ("c belongs to Acme app" → `field: projects`, `value: ["prj-…"]`; a title, summary or area works the same way), `{ "link": { "target", "field", "value" }, "value": … }` for a link ("Lucía is on Acme website, not Acme app").
73
+
74
+ A fix and an "except" can come together ("all except b, and a is March"): `fix` with both `fixes` and `exclude`, never on the same item. Names become ids through `brain index --json`; a name that matches no note, or two → ask.
75
+ - **Reject with a reason** ("wrong meeting"): `reject`; the reason is kept in `note`.
76
+ - **A different change** (a role typed on a link row, a fact about another note) → apply this row as Your call says, and write the other change as its own proposal with `brain proposal new` (`why` = the text, `source` = the proposal's `source`), so it gets its own Review row.
77
+ - **Unclear** → ask the user, quoting the text, and leave the row as it is until they answer.
66
78
 
67
79
  In a catch-up these are decided in its read-only pass and confirmed in its one batch of questions.
68
80
 
@@ -73,8 +85,8 @@ In a catch-up these are decided in its read-only pass and confirmed in its one b
73
85
  - **`closed`:** a rejection, or `STALE_PROPOSAL`. Stale means the note changed after the proposal was written (for example your own Notion edit), so the brain did not apply it. Tell the user the current value; the next ingest may propose again.
74
86
  - **`recorded`:** decided but not applied (`--record-only`).
75
87
  - **`skipped` with `ALREADY_TERMINAL`:** it was already done.
76
- - **`review_notes` items** also list `notes`, one result each: `reviewed`, `archived` (rejected), `kept_draft` (excluded) and `unchanged` (no longer `draft` when applied: the user changed its Lifecycle in Notion). Name the `kept_draft` and `unchanged` notes once, under Check.
77
- - **`failed`:** report the `reason` and `message`. `INVALID_RESULT` means applying it would break a rule, such as a value of the wrong shape. `EDIT_NOT_ALLOWED` means an edit on a kind that can't be edited. `EXCLUDE_UNKNOWN` means an `exclude` named a link or note the row doesn't have: re-read the Note. `UNKNOWN_ID` means the proposal or its note is gone.
88
+ - **`review_notes` items** also list `notes`, one result each: `reviewed`, `archived` (rejected), `kept_draft` (excluded) and `unchanged` (no longer `draft` when applied: the user changed its Lifecycle in Notion). An applied one lists `changes`, each `applied`, `dropped` (`STALE_PROPOSAL`: its note changed since the row was written, so only that item was closed) or `deferred` (excluded), and `deferred`: the new pending row that holds the excluded items. Name the `kept_draft`, `unchanged`, dropped and deferred items once, under Check.
89
+ - **`failed`:** report the `reason` and `message`. `INVALID_RESULT` means applying it would break a rule, such as a value of the wrong shape. `FIX_UNKNOWN` means a fix named an item the row doesn't have, and `EXCLUDE_UNKNOWN` the same for an "except": re-read What to fix against the proposal. `UNKNOWN_ID` means the proposal or its note is gone.
78
90
  2. **Rebuild:** run `brain index`, `brain views`, then `brain lint`. If lint reports an error in a file this run changed, stop and report; don't commit.
79
91
  3. **Commit:** `apply: <n> applied, <n> closed`, listing the proposal titles in the body. If this run does not publish (step 4), push now, per `settings.push` (the brain's AGENTS.md, "Write path").
80
92
  4. **Publish** *(Notion mode, attended runs only, per `settings.publish`)*. A chat run does not publish: its changes go out with the next Notion-mode run or `brain sync` (spec/cli.md §6, "Apply in chat"). In Notion mode:
@@ -84,8 +96,8 @@ In a catch-up these are decided in its read-only pass and confirmed in its one b
84
96
  5. **Report** in three lines (decision 0037):
85
97
  ```
86
98
  Done: 8 applied · 1 closed (stale) · 12 pages published
87
- Needs you: 1 failed (EDIT_NOT_ALLOWED on "add Ivo to Acme rollout") · 2 rows still pending
88
- Next: fix that row in Notion, then "apply my reviews"
99
+ Needs you: 1 failed ("all except k" on Acme launch review: the row has no k) · 2 rows still pending
100
+ Next: say which item you meant, here or in What to fix
89
101
  ```
90
102
  - **Done:** counts only, and only the ones that aren't zero.
91
103
  - **Needs you:** what failed and why in a few words, a stale proposal with the note's current value, what is still pending. `Needs you: nothing` when there is none.
@@ -93,12 +105,13 @@ In a catch-up these are decided in its read-only pass and confirmed in its one b
93
105
 
94
106
  **Below the three lines, the report grows with what was applied** (decision 0037, amended 2026-10-18), uncapped, one line each:
95
107
  - **What changed:** each applied change in words ("Acme budget is now 95000 EUR", "Ivo joins Acme rollout", "6 notes from Acme launch review accepted", "Who owns the mobile app? answered: Carlos Ruiz").
96
- - **Check:** each proposal closed as stale, with the note's current value; each failure with its reason in a few words; each Edit or Note the user should look at again; each change proposed from a Note. Only things the user can act on: a note the render skipped because it has nothing to publish (its type has no database, or nothing changed) is not a finding.
108
+ - **Fixes:** every correction you read and applied, repeated back with its letter and row ("Acme launch review, a: launch set to 2027-03, not 2027-02"; "c: Use Contentful now belongs to Acme app"), so the user can check you read them right.
109
+ - **Check:** each item or proposal closed as stale, with the note's current value; each deferred row, with what it holds; each failure with its reason in a few words; each What to fix the user should look at again; each change proposed from What to fix. Only things the user can act on: a note the render skipped because it has nothing to publish (its type has no database, or nothing changed) is not a finding.
97
110
 
98
111
  A run with nothing applied stops at three lines. Never ids, file paths, commands or commit names.
99
112
 
100
113
  ## Don'ts
101
114
 
102
115
  - **Don't apply anything the user didn't decide in this chat or in Notion.**
103
- - **Don't edit notes directly** to "help" a proposal along. If a proposal is wrong, the user rejects it.
116
+ - **Don't edit notes or proposal files directly** (`sed`, a text editor, a script; U-18) to "help" a proposal along, nor to mark one applied. If a proposal is wrong, the user rejects or fixes it, and `brain sync apply` or `brain apply` writes the result.
104
117
  - **Don't re-run `apply` after a failure** without changing the input. Apply is atomic per item, and the failed item is unchanged; fix the cause first.
@@ -1,15 +1,17 @@
1
1
  ---
2
2
  name: brain-catch-up
3
- description: Do everything that is waiting in one run. Pulls the user's Notion edits, applies the reviews they decided, ingests reviewed meetings, new Inbox rows, their attachments, the drop folder and linked repos, writes the reports asked for on Ask rows and the full texts asked for on Inbox rows, publishes and pushes, asking every question once at the start and then finishing without stopping. Use when the user says "catch up", "what's next", "do what's waiting" or "process everything".
3
+ description: Do everything that is waiting in one run. Pulls the user's Notion edits, applies the reviews they decided (Fix included), ingests reviewed meetings, Inbox rows that are Ready, their attachments, the drop folder and linked repos, reads again the inputs the user corrected, keeps the documents asked for (whole or in part) and promotes the notes asked for, writes and refreshes the reports asked for, publishes and pushes, asking every question once at the start and then finishing without stopping. Skips the steps of modules that are off. Use when the user says "catch up", "what's next", "do what's waiting" or "process everything".
4
4
  ---
5
5
 
6
6
  # Catch up
7
7
 
8
8
  One run for everything waiting (decision 0037). It has two halves: a **read-only pass** that finds the work and every question it raises, then **one batch of questions**, then a run that finishes without asking again. Anything that becomes blocked during the run is **skipped** and listed in the report; the rest goes on.
9
9
 
10
- This skill orders the work; the other skills hold the steps. Read each one before running its part: brain-sync (pull and publish), brain-apply (decisions), brain-ingest with its references (meetings, sources, attachments, the drop folder, linked repos), brain-query (reports). Their rules apply unchanged, including the trust rules in the brain's AGENTS.md.
10
+ This skill orders the work; the other skills hold the steps. Read each one before running its part: brain-sync (pull and publish), brain-apply (decisions), brain-ingest with its references (meetings, sources, attachments, the drop folder, linked repos, Documents), brain-query (reports). Their rules apply unchanged, including the trust rules in the brain's AGENTS.md.
11
11
 
12
- **The bar** (decision 0043): over two meetings and one capture, from "go" to the report in under 5 minutes, without the session running out of context. So each input is analysed in its own sub-agent (step 3), Notion is written in one batch at the end (step 4), and nothing already in Notion is written twice.
12
+ **The bar** (decision 0043): over two meetings and one capture, from "go" to the report in under 5 minutes, without the session running out of context. So each input is analysed in its own sub-agent (step 3), Notion is written in one batch at the end (step 4), and nothing already in Notion is written twice. Note the time when the user says "catch up" (or the run starts), and count the notes whose full text the run and its sub-agents read: the run logs both at the end (decision 0045).
13
+
14
+ **Modules** (decision 0048): `brain status` gives `modules`. A step marked with a module (*Knowledge*, *Orgs*, *Documents*, *Reports*, *Tasks*, *Planning*) runs only when that module is on; when it's off, skip the step and its questions without a word. Core (Inbox, Meetings, Projects, Areas, People, Review) always runs. A module that is on but whose database id is still empty (`brain modules` lists it under `missing`) is named once on the report's Needs you line: "Documents is on but its database isn't set up: say "set up documents"".
13
15
 
14
16
  Run every CLI command as `brain <command> --brain <brain> --json`. If `brain` is not found (`command not found`), install it with `npm install -g ultimate-brain`, then retry.
15
17
 
@@ -17,18 +19,20 @@ Run every CLI command as `brain <command> --brain <brain> --json`. If `brain` is
17
19
 
18
20
  This step changes no knowledge: no note, proposal, `brain.json`, commit, Notion page or drop-folder file. Two writes are allowed because they change nothing the user owns: `brain index` may regenerate a stale `index.md` (generated, rebuilt again later in the run), and the working files (`snapshot.json`, `plan.json`, conversions) go in a temporary folder outside the brain.
19
21
 
20
- 1. **Status.** Run `brain status`; run `brain index` if `index_stale`. Note `settings` (absent means `publish: ask`, `push: auto`) and which databases are configured. Each Notion part below needs its database configured; skip the ones that aren't and name them once on the report's Needs you line.
21
- 2. **Pull plan.** Brain-sync "Pull", steps 2–4, with the snapshot and plan in the temporary folder: snapshot the databases brain-sync step 2 reads (Areas, Goals, Key Results, Projects, People, Orgs, Decisions, Questions, Concepts, Review; never Meetings), whichever are configured, plus the **Inbox rows whose Full text box is ticked** (with their Full text and Brain ID properties only); run `sync plan` once, save `plan.json`. It holds the imports, your corrections, the decided Review rows, the conflicts, and `full_text_requests`: one per ticked box on a source the brain wrote.
22
- 3. **Notes on Review rows.** For each `NOTE_TO_READ` conflict, read the Note against its proposal and decide what it means (brain-apply, "Reading a Note"). Write down the decision you would apply, or the question it raises.
23
- 4. **Meetings** *(Notion)*. Brain-ingest steps 2 and 3, up to the duplicate check: the Reviewed meetings, oldest first, and each one's pre-check blockers. Minutes files are ingested only when the user names them, never looked for.
24
- 5. **Inbox.** The New rows (brain-ingest references/sources.md, "capture"), oldest first, each with its pre-check blockers. A row with Project or Area set needs no project question. A row with Kind = **Ask** is a request for a report, not a capture: never ingest it; note its question (the Name) and its Project or Area for the report ("Run", step 6). A capture that repeats a source the brain already has: default skip, naming that source and linking its row (sources.md, "Pre-check").
25
- **Attachments** on the New rows and the Reviewed meetings: list each file (sources.md, "Attachments"), all selected by default.
26
- 6. **Drop folder.** The queue and its question (sources.md, "The drop folder", steps 1–2), without moving anything.
27
- 7. **Linked repos.** For each entry of `repos` in `brain status`: `brain repo changes <name>` (sources.md, "Linked repos"). A repo with `found: false` is named on the Needs you line. More than 10 files: they go in the batch as a list, default all.
28
- 8. **The full-text choice.** For each input that will get its own Inbox row (not a capture, an attachment or minutes), the default by kind: emails and chats full, documents and decks digest. Without an Inbox database (`inbox` missing), there is no row: leave the choice out of the batch, and the CLI's default stands for a later publish.
29
- 9. **The backlog.** `brain proposal backlog --dry-run`: the Review notes rows the run will write once for notes from before 0.4.0. They need no question; name them in the batch's opening line ("I'll also write 2 Review notes rows for older notes").
30
- 10. **Pending proposals in chat.** Without a Review database, run `brain proposal list --status pending,approved,edited,rejected`: these go in the batch as chat decisions (brain-apply, chat mode, steps 2–3).
31
- 11. **Your identities.** If `brain.json` has no `owner.person`, add the identities question (brain-connect-notion, step 6).
22
+ 1. **Status.** Run `brain status`; run `brain index` if `index_stale`. Note `settings` (absent means `publish: ask`, `push: auto`), `modules`, and which databases are configured. Each Notion part below needs its database configured; skip the ones that aren't and name them once on the report's Needs you line.
23
+ 2. **Pull plan.** Brain-sync "Pull", steps 2–4, with the snapshot and plan in the temporary folder. Read **every** configured database of a module that is on (brain-sync step 2 lists them, Goals, Key Results and Documents included; never Meetings), all pages of each, plus the Inbox rows brain-sync step 2 names. Run `sync plan` once and save `plan.json`. It holds the imports, your corrections, the decided Review rows, the conflicts, `document_requests` and `promote_requests` (*Documents*), and `refresh_requests` and `report_fixes` (*Reports*).
24
+ 3. **What to fix on Review rows.** For each `NOTE_TO_READ` and `FIX_TO_READ` conflict, read What to fix against its proposal and decide what it means (brain-apply, "Reading What to fix"). Write down the decision you would apply ("a: launch 2027-03"), or the question it raises. A `FIX_WITHOUT_TEXT` row goes in the batch as a question: "Acme launch review: Fix, but What to fix is empty: what's wrong?"
25
+ 4. **Meetings** *(Notion)*. Brain-ingest steps 2 and 3, up to the duplicate check: the Reviewed meetings, oldest first, and each one's pre-check blockers. A meeting the brain already ingested and that is Reviewed again is a **re-read** (decision 0045): the user fixed its minutes; say so in the batch ("Acme sync, read again: only what changed"). Minutes files are ingested only when the user names them, never looked for.
26
+ 5. **Inbox.** The rows with Brain Status **Ready**, and only those (decision 0048): never a New or Done row, whatever its Kind or age. Oldest first, each with its pre-check blockers (brain-ingest references/sources.md, "capture"). A Ready row with a Brain ID is a **re-read**, as for meetings. A row with Project or Area set needs no project question. A row's **Only keep** and **Document asked** come with it; an empty Only keep is never asked about (decision 0049). A capture that repeats a source the brain already has: default skip, naming that source and linking its row (sources.md, "Pre-check").
27
+ **Ask rows** *(Reports)* (Kind = Ask, Brain Status New or Ready) are requests for a report, not captures: never ingest one; note its question (the Name) and its Project or Area for the report ("Run", step 6).
28
+ **Attachments** on the rows taken in and the Reviewed meetings: list each file (sources.md, "Attachments"), all selected by default. On a row with Document asked ticked, each file becomes a Document (step 1.7).
29
+ 6. **Drop folder.** The queue and its question (sources.md, "The drop folder", steps 1–2: whether to keep each file as a document, and whether one is a new version), without moving anything.
30
+ 7. **Documents asked for** *(Documents)*. From `plan.json`, each `document_requests` item (a row already taken in whose Document asked box is ticked) and each `promote_requests` item (a decision or concept whose Promote asked box is ticked), plus the Ready rows of step 5 with Document asked ticked and the drop-folder files the user may keep. An item with `existing` is already done: the run only clears its box. None of these asks a question; name them in the batch's opening line ("I'll also keep 2 documents and promote 1 decision").
31
+ 8. **Linked repos.** For each entry of `repos` in `brain status`: `brain repo changes <name>` (sources.md, "Linked repos"). A repo with `found: false` is named on the Needs you line. More than 10 files: they go in the batch as a list, default all.
32
+ 9. **Reports** *(Reports)*. From `plan.json`: each `refresh_requests` item, and each `report_fixes` item with the proposals its text would become (brain-query, "What to fix on a report"), written down like a Review row's What to fix. Also each report whose last `fixes` entry lists only proposals now applied, rejected or closed, and that wasn't refreshed since: it is due a refresh.
33
+ 10. **The backlog.** `brain proposal backlog --dry-run`: the Review notes rows the run will write once for notes from before 0.4.0. They need no question; name them in the batch's opening line ("I'll also write 2 Review notes rows for older notes").
34
+ 11. **Pending proposals in chat.** Without a Review database, run `brain proposal list --status pending,approved,edited,rejected`: these go in the batch as chat decisions (brain-apply, chat mode, steps 2–3).
35
+ 12. **Your identities.** If `brain.json` has no `owner.person`, add the identities question (brain-connect-notion, step 6).
32
36
 
33
37
  The pass is done when every input that is waiting has been found and each of its blockers is written down as a question or a default.
34
38
 
@@ -36,13 +40,13 @@ The pass is done when every input that is waiting has been found and each of its
36
40
 
37
41
  Ask once, in one message, numbered and grouped by input, each with the answer you will use if the user says "go" (the **default**):
38
42
  - sync conflicts (`BOTH_CHANGED`, `MISSING_REQUIRED`, `UNRESOLVED_RELATION`, …) and your corrections, as brain-sync step 5 shows them;
39
- - each Note you read, as "Note 'all except Tomás' → approve 3 of 4 links (leave out Tomás)";
43
+ - each What to fix you read, as "Acme sync: 'all except b' → approve the rest, b waits in a row of its own" or "Acme sync: Fix 'a: March' → launch date 2027-03";
40
44
  - each meeting's and input's pre-check blockers;
41
45
  - the pending proposals, as brain-apply's chat list (default: leave them pending);
42
- - the drop-folder list, all files selected;
46
+ - the drop-folder list, all files selected, each with "keep as document? no / all / only …" (default **no**) when Documents is on;
43
47
  - each attachment, all selected, and each linked repo's files when there are more than 10;
44
- - the full-text choice, one line per input that gets an Inbox row, saying what it puts in Notion: "4. Requirements doc (40 p) → **digest**: Notion gets a summary and key points; to read the document itself you open the file. Say "4 full" to have the whole text in Notion." Parts work too: "5 full, slides 3–9";
45
- - each Ask row, as "Report on <its question> (default: yes)";
48
+ - each likely new version (default yes);
49
+ - *(Reports)* each Ask row, as "Report on <its question> (default: yes)"; each Report row to refresh, and each report What to fix with the proposals it becomes ("Acme launch report: 'Lucía left Acme in June' → Lucía's org: Acme → none, from June");
46
50
  - the identities question (default: skip for now, ask again next catch-up). The user's answer is their approval of those aliases;
47
51
  - with `settings.publish: ask` and Notion configured: "Publish to Notion at the end?" (default yes). This is the run's only publish question. Without Notion there is nothing to publish: leave it out.
48
52
 
@@ -51,29 +55,40 @@ When nothing blocks, don't ask: say what you will do in one line and start. When
51
55
  ## 3. Run, in this order
52
56
 
53
57
  0. **The backlog, once** (decision 0041): `brain proposal backlog`. On a brain from before 0.4.0, the first run writes one Review notes row per source over its `draft` notes; every later run writes nothing. Commit any rows it wrote: `review: <n> Review notes rows for the backlog`.
54
- 1. **Pull and apply.** `sync apply plan.json` (brain-sync steps 6–8), then with `brain apply --input`: the decisions you resolved from Notes (brain-apply, "Reading a Note"), the chat decisions from the batch (`decided_by: chat`), and the identities. For the identities, run brain-connect-notion step 6 in full, with the batch answer as the user's approval: the owner-ruling source and, when the owner's person note exists, one `add_link` alias proposal per value applied with `decided_by: chat`; when it doesn't, a new person note (`brain note new`) carrying the aliases; then `brain config set owner.person`. Rebuild and commit as brain-apply "Finish", steps 1–3. Conflicts the user didn't answer stay conflicts.
55
- 2. **Full texts asked for:** `brain source full-text <source> [--parts …]` for each of `plan.json`'s `full_text_requests`, and for each "full text for …" the user asked in chat. Commit: `full-text: <n> sources`.
56
- 3. **Analyse each input in its own sub-agent** (decision 0043): each meeting, Inbox row (with its attachments) and chosen file. A run with one input, or inputs of a page or two each, can analyse them inline instead, one at a time: the sub-agents are there to keep long inputs out of the run's context. Inline is also the way when the session can't start sub-agents. Give each one the brain path, the input (or how to read it), its batch answers and the brain-ingest skill with its references, and have it run, read-only, brain-ingest steps 4–6 and the dry runs of step 7, then return the `note new` batch, the `proposal new` batch (with the input's one `review_notes` and any `answer`), the task items and the report lines. A sub-agent never runs a write, a commit or a Notion call. Run up to 4 at a time.
57
- 4. **Write them, one input at a time,** in the order of step 1 (meetings oldest first, then Inbox rows, then files): before each batch, check its new notes against what the inputs before it wrote (`brain index`): a person, project or concept another input already created is linked to that note instead of created twice. Then brain-ingest steps 7.3–10 (the real `note new`, `proposal new`, rebuild, check, log, commit). On `INPUT_INVALID` from a path that changed since the dry run, run the dry run again and fix the links.
58
- 5. **Linked repos:** their files are inputs of steps 3–4 too; after a repo's last file, `brain repo record`, unless a file failed or the user wants some later (sources.md, "Linked repos", step 4).
59
- 6. **Reports:** for each Ask row the user didn't decline, brain-query "Report mode" with `asked_in` = the row's page id, its Project and Area. Commit: `report: <title>`.
60
-
61
- For each input, publishing waits for step 4 below. **Skipped, not asked:** an input whose ingest raises a new question or fails is left as it is (the meeting stays Reviewed, the row New, the file in the queue) and goes on the report's Needs you line. The one hard stop: a lint error in a file this run wrote. Stop the run there, commit nothing more, and report.
58
+ 1. **Pull and apply.** `brain sync apply --input plan.json` (brain-sync steps 6–8), then with `brain apply --input <file>`: the decisions you resolved from What to fix (brain-apply, "Reading What to fix"), the chat decisions from the batch (`decided_by: chat`), and the identities. For the identities, run brain-connect-notion step 6 in full, with the batch answer as the user's approval: the owner-ruling source and, when the owner's person note exists, one `add_link` alias proposal per value applied with `decided_by: chat`; when it doesn't, a new person note (`brain note new`) carrying the aliases; then `brain config set owner.person '"<per- id>"'`. Rebuild and commit as brain-apply "Finish", steps 1–3. Conflicts the user didn't answer stay conflicts.
59
+ 2. **Analyse each input in its own sub-agent** (decision 0043): each meeting, Inbox row (with its attachments) and chosen file. A run with one input, or inputs of a page or two each, can analyse them inline instead, one at a time: the sub-agents are there to keep long inputs out of the run's context. Inline is also the way when the session can't start sub-agents. Give each one the brain path, the input (or how to read it), its batch answers, its Only keep and Document asked, and the brain-ingest skill with its references, and have it run, read-only, brain-ingest steps 4–6 and the dry runs of step 7, then return the `note new` batch (with any Documents, brain-ingest references/extraction.md "Documents"), the `proposal new` batch (with the input's one `review_notes` and any `answer`), the task items and the report lines. A sub-agent never runs a write, a commit or a Notion call. Run up to 4 at a time. A **re-read** is analysed inline in step 3 instead: its diff needs the new source written first (brain-ingest references/sources.md, "Re-reads and new versions"), and the changed lines are short.
60
+ 3. **Write them, one input at a time,** in the order of step 1 (meetings oldest first, then Inbox rows, then files): before each batch, check its new notes against what the inputs before it wrote (`brain index`): a person, project or concept another input already created is linked to that note instead of created twice. Then brain-ingest steps 7.3–10 (the real `note new`, `proposal new`, rebuild, check, log, commit). On `INPUT_INVALID` from a path that changed since the dry run, run the dry run again and fix the links.
61
+ 4. **Linked repos:** their files are inputs of steps 2–3 too; after a repo's last file, `brain repo record`, unless a file failed or the user wants some later (sources.md, "Linked repos", step 4).
62
+ 5. **Documents** *(Documents)*, for the inputs already in the brain (step 1.7; the inputs taken in this run wrote theirs in step 3), with brain-ingest references/extraction.md "Documents":
63
+ 1. each `document_requests` item without `existing`: with `only_keep` null, one `whole` Document per file in `files`, or of `source` when `files` is empty; with `only_keep` set, one `part` Document of what it names, in a new `review_notes` for that source;
64
+ 2. each `promote_requests` item without `existing`: one `promoted` Document seeded from the note;
65
+ 3. what the user asked in chat ("also keep the budget from the Acme doc"): a `part` Document from the source the brain already has.
66
+
67
+ `ALREADY_KEPT` in `skipped` is fine: that whole Document exists. Rebuild and commit: `documents: <n> kept, <n> promoted`. Each item written, skipped as `ALREADY_KEPT` or carrying `existing` has its box cleared in the publish (step 4.1.4); one that failed keeps it, so the next catch-up tries again.
68
+ 6. **Reports** *(Reports)*, with brain-query "Report mode":
69
+ 1. each report What to fix: its proposals and `brain report fix` (brain-query, "What to fix on a report"). Commit: `report: fix <title>`;
70
+ 2. each refresh: a Report row with Refresh asked ticked, or a report whose last `fixes` entry lists only proposals that are applied, rejected or closed (one recorded with `--record-only` waits). Commit: `report: refresh <title>`;
71
+ 3. each Ask row the user didn't decline: a new report with `asked_in` = the row's page id, its Project and Area. Commit: `report: <title>`.
72
+
73
+ For each input, publishing waits for step 4 below. **Skipped, not asked:** an input whose ingest raises a new question or fails is left as it is (the meeting stays Reviewed, the row Ready, the file in the queue) and goes on the report's Needs you line. The one hard stop: a lint error in a file this run wrote. Stop the run there, commit nothing more, and report.
62
74
 
63
75
  ## 4. Publish, push, report
64
76
 
65
77
  1. **Publish** (when `settings.publish` is `auto`, or the user said yes), once for the whole run, following brain-ingest references/notion.md "Publish" for each write, in this order. Run `brain views` first, so the project and area Briefs are current:
66
- 1. **Pages:** `sync render --changed --plan plan.json`, write every item (pending relations: publish and record those first, then render again, until no item is pending), `sync record`. This publishes the new notes, the proposals, the meetings' relations, every source's Inbox row with its digest and full text, the report rows (then each Ask row's Brain Status to Processed), the cleared Full text boxes, the project and area Briefs, a question's Status = Open, and the Review rows decided more than 30 days ago (`action: trash`, moved to Notion's trash; decision 0045). Write in parallel, up to 10 at a time, and never read a page back after writing it.
67
- 2. **Tasks,** now that their projects and Inbox rows exist: `sync tasks --meeting` for each ingested meeting and `sync tasks --source` for each ingested source with owner tasks; create each returned item once; `sync record` its page ids. An item still listing `pending_relations` (a project that isn't in Notion) is not created: list it under Check.
68
- 3. Set Brain Status = Skipped on the Inbox rows the user skipped.
69
- 4. Log `brain log publish - pages=<n>` and commit `publish: catch up`.
78
+ 1. **Pages:** `sync render --changed --plan plan.json`, write every item (pending relations: publish and record those first, then render again, until no item is pending), `sync record`. This publishes the new notes and Documents, the proposals, the meetings' relations, every source's Inbox row with its digest, the report rows (then each Ask row's Brain Status to Done), the cleared Refresh asked boxes, the project and area Briefs, a question's Status = Open, and the Review rows decided more than 30 days ago (`action: trash`, moved to Notion's trash; decision 0045). Write in parallel, up to 10 at a time, and never read a page back after writing it. **Every write carries its final content:** never create a page or write a body with placeholder text to fill in later (brain-ingest references/notion.md, "One write, final content").
79
+ 2. *(Tasks)* **Tasks,** now that their projects and Inbox rows exist: `sync tasks --meeting` for each ingested meeting and `sync tasks --source` for each ingested source with owner tasks; create each returned item once; `sync record` its page ids. An item still listing `pending_relations` (a project that isn't in Notion) is not created: list it under Check.
80
+ 3. **Skipped rows:** set Brain Status = **Done** on each Inbox row the user said to skip, and its Summary to why ("Skipped: same as Acme requirements"), through the MCP; change nothing else on it (decision 0048).
81
+ 4. *(Documents)* **Clear the boxes:** untick Document asked on each Inbox row of step 3.5 (and of the Ready rows that asked for one) and set its Brain Status to Done; untick Promote asked on each decision or concept row. Only for requests this run carried out or found done (decision 0048).
82
+ 5. Log `brain log publish - pages=<n>` and commit `publish: catch up`.
83
+ 6. A meeting read again keeps Brain Status Reviewed until you set it back to **Ingested** through the MCP (brain-ingest step 11): do it for each re-read meeting.
70
84
  2. **Move the drop-folder files** (sources.md, "The drop folder", step 4): after the publish commit, or right after each file's ingest commit when the run doesn't publish.
71
- 3. **Push** per `settings.push` (AGENTS.md, "Write path").
72
- 4. **Report** once, in the shape of brain-ingest step 12, for the whole run, the decisions included:
85
+ 3. **Log the run:** `brain log catch-up - notes_read=<n> seconds=<s>`, the notes whose full text the run and its sub-agents read and the seconds from "catch up" to here (decision 0045). Commit it: `log: catch up`.
86
+ 4. **Push** per `settings.push` (AGENTS.md, "Write path").
87
+ 5. **Report** once, in the shape of brain-ingest step 12, for the whole run, the decisions included:
73
88
  ```
74
- Done: 9 applied · 3 captures and 2 files ingested · 12 new notes · 1 task for you · 5 old Review rows trashed
75
- Needs you: 3 Review rows (2 Review notes rows, 1 answer) · 2 files skipped (too long, say which parts)
89
+ Done: 9 applied · 3 captures and 2 files ingested · 12 new notes · 2 documents kept · 1 task for you · 5 old Review rows trashed
90
+ Needs you: 3 Review rows (2 from inputs, 1 answer) · 2 files skipped (too long, say which parts)
76
91
  Next: decide in Notion, then "catch up"
77
92
  ```
78
93
  Without Notion, the Next line is deciding in chat ("what needs my decision"), and "connect the brain to Notion" goes on the Needs you line.
79
- Below the three lines: **What came in** (with each input's Notion choice: "digest" or "full text") and **What changed**, then the **reports written**, each with its row, then **Check** (each skipped input with its reason, each attachment that couldn't be read, the notes kept as drafts or left unchanged by a Review notes row, stale proposals, assumptions), as brain-ingest step 12 and brain-apply "Finish" step 5 define them, uncapped. Offer the `settings.publish` switch here when AGENTS.md says to.
94
+ Below the three lines: **What came in** (each re-read with what changed; each Document with what it keeps) and **What changed**, then the **Fixes** you read, repeated back (brain-apply "Finish" step 5), then the **reports written or refreshed**, each with its row, then **Check** (each skipped input with its reason, each attachment that couldn't be read, the notes kept as drafts or left unchanged by a Review notes row, stale proposals, assumptions), as brain-ingest step 12 and brain-apply "Finish" step 5 define them, uncapped. Offer the `settings.publish` switch here when AGENTS.md says to.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: brain-connect-notion
3
- description: Connect the brain to the user's Notion space after it was built from the notion/ prompts. Gives the agent access to Notion, finds the Brain Data page and its databases, checks each has the properties the brain reads and writes, stores their ids in brain.json, maps the Tasks database and records the owner's identities. Changes nothing in Notion. Use when the user says "connect the brain to Notion", after building the Notion space, when Notion is unreachable, or when a skill reports a Notion database is not configured.
3
+ description: Connect the brain to the user's Notion space after it was built from the notion/ prompts. Gives the agent access to Notion, finds the Brain Data page and its databases, checks each has the properties the brain reads and writes, stores their ids in brain.json, maps the Tasks database and records the owner's identities. Also lists and switches the optional modules (Knowledge, Orgs, Documents, Reports, Tasks, Planning), walking the user through a module's Notion steps when it is turned on. Changes nothing in Notion itself. Use when the user says "connect the brain to Notion", "which modules do I have?", "turn on documents", "turn planning off", after building the Notion space, when Notion is unreachable, or when a skill reports a Notion database is not configured or a module is off.
4
4
  ---
5
5
 
6
6
  # Connect the brain to Notion
@@ -11,6 +11,19 @@ Run CLI commands as `brain <command> --brain <brain> --json`. If `brain` is not
11
11
 
12
12
  ## Procedure
13
13
 
14
+ 0. **Modules** (decision 0048), at the first connection, when the user hasn't chosen yet. Run `brain modules` and show the checklist, with what each module adds and its default:
15
+
16
+ ```
17
+ Core (always on): Inbox, Meetings, Projects, Areas, People, Review
18
+ [x] Knowledge: Decisions, Questions, Concepts
19
+ [x] Orgs: client and partner organizations
20
+ [ ] Documents: keep a document, or part of one, as a page
21
+ [ ] Reports: ask the brain in the Inbox, get a report you can refresh
22
+ [ ] Tasks: action items as Notion tasks
23
+ [ ] Planning: Goals and Key Results
24
+ ```
25
+
26
+ Ask once: "Keep these, or change some? (e.g. "add documents")". Write each change with `brain modules on|off <module>`. The steps below look only for the databases of modules that are on; a database that exists for a module that is off is reported ("Goals found; Planning is off: say "turn on planning" to use it"), and its id is still stored.
14
27
  1. **Check access.** The Notion connection (MCP) must reach the user's workspace. Search for the page **"Brain Data"**:
15
28
  - **No Notion tools in this session:** the agent isn't connected to Notion. Give the user the steps in "Connect your agent to Notion" below for the agent they are using, and stop.
16
29
  - **Not found:** the connection can't see the page. With the hosted Notion MCP, the user's own Notion account must have access to Brain Data; with an integration token, open Brain Data in Notion → `•••` → **Connections** → add the integration. Then stop.
@@ -31,9 +44,10 @@ Run CLI commands as `brain <command> --brain <brain> --json`. If `brain` is not
31
44
  | Review | `review` |
32
45
  | Inbox (called Capture Inbox before 0.3.0) | `inbox` |
33
46
  | Concepts | `concepts` |
47
+ | Documents (called References before migration 0010) | `documents` |
34
48
  | Tasks | `notion.tasks.database` (below) |
35
49
 
36
- A missing database is reported, not invented. The brain works without it, and the skills that need it say so.
50
+ A missing database is reported, not invented. A missing database of a module that is on is the module's Notion steps still to do ("Turning a module on" below); the brain works without it, and the skills that need it say so.
37
51
  3. **Check each database** (read-only). Retrieve the database, then its data source (current Notion API: a database has `data_sources`, and its properties live on the data source). Check that every property in docs/notion-space-design.md §3 for that database exists with the right type: relations point to the right database, and selects have the listed options.
38
52
  - Report each difference as `Database · Property: expected …, found …`.
39
53
  - Report two select options that share an id (it has happened after adding an option through Notion AI), and suggest deleting and re-adding the option by hand.
@@ -54,8 +68,21 @@ Run CLI commands as `brain <command> --brain <brain> --json`. If `brain` is not
54
68
  9. **Report:**
55
69
  - the databases connected;
56
70
  - anything missing or different from the design (step 3);
71
+ - the modules on, and those with a database still missing;
57
72
  - what to do next: build the Notion space's missing parts, or run `brain-sync` to import the rows you already created in Notion (0021), then ingest reviewed meetings.
58
73
 
74
+ ## Turning a module on or off
75
+
76
+ When the user asks ("turn on documents", "turn planning off", "which modules do I have?"), outside the procedure above:
77
+
78
+ 1. **List:** `brain modules`. Report each module as on or off; for one that is on, its `missing` databases.
79
+ 2. **Off:** `brain modules off <module>`, commit `modules: <module> off`. Say what stops: "Planning off: catch-up no longer reads Goals or Key Results. Nothing is deleted; turn it on again any time." Nothing changes in Notion; the user may hide the databases themselves.
80
+ 3. **On:** `brain modules on <module>`. Then check what Notion still needs. `missing` lists only the module's empty database ids, so it can't tell whether the module's properties, relations and buttons exist (and Reports has no database at all): read the databases `notion/modules/<module>.md` touches (step 3 above) and compare them with the file's steps, through each step's Verify item.
81
+ - **Everything there:** commit `modules: <module> on`, and say what the next catch-up does with it.
82
+ - **Something missing** (a database, a property, a relation, a button): walk the user through `notion/modules/<module>.md` in the product repo, from its first step that isn't done, step by step: the Notion AI prompts they paste, the buttons and layouts they set by hand, then find the new database under Brain Data (step 2 above), check it (step 3) and store its id with `brain config set notion.databases.<key> '"<id>"'` (Tasks: step 5). This skill doesn't build anything in Notion itself (decision 0022). Run `brain modules` again (`missing` is empty) and the file's Verify list. Commit `modules: <module> on`.
83
+ - **The user stops halfway:** the module stays on with a part missing; with a database id missing, its notes are skipped with `DATABASE_NOT_CONFIGURED` until the id is set, and a missing property or button means the requests it carries never arrive. Say so, and that "turn on <module>" picks up where they left off.
84
+ 4. **Report** in three lines: what changed, what still needs them in Notion, and the next step.
85
+
59
86
  ## Connect your agent to Notion
60
87
 
61
88
  The agent reads and writes Notion through a Notion MCP server (decision 0015). Give the user the steps for their agent; they run them in their own terminal, then restart the agent in the brain folder.
@@ -9,7 +9,7 @@ Answer how-to questions about the system from [references/guide.md](references/g
9
9
 
10
10
  ## Procedure
11
11
 
12
- 1. **Read the guide section** that matches the question. Its headings: The Spaces · The meeting flow · Deciding in Review · What you can edit · Adding things · What to say to your agent · When something looks wrong.
12
+ 1. **Read the guide section** that matches the question. Its headings: The Spaces · The meeting flow · Deciding in Review · Correcting what came in (a meeting, a capture, a report; refreshing a report) · What you can edit · Adding things · What to say to your agent · When something looks wrong.
13
13
 
14
14
  2. **If the question is about something that happened** ("why didn't…", "where did … go", "is my … set up"), check the live state before answering:
15
15
  - `brain status --brain . --json` (or without `--brain` in a linked repo). It reports pending proposals, Notion databases configured or missing, stale views, and the last log line.