@dreamforgestudiollc/emet 0.0.0-stage → 0.2.4

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 (73) hide show
  1. package/.env.example +136 -0
  2. package/CHANGELOG.md +296 -0
  3. package/CHARTER.md +125 -0
  4. package/LICENSE +22 -0
  5. package/README.md +783 -2
  6. package/docs/AUTHORSHIP.md +26 -0
  7. package/docs/BENCHMARKS.md +261 -0
  8. package/docs/BOOTSTRAP.md +127 -0
  9. package/docs/BOTS.md +79 -0
  10. package/docs/COVERAGE.md +64 -0
  11. package/docs/DEPLOY.md +246 -0
  12. package/docs/DISCIPLINES.md +29 -0
  13. package/docs/GUARDRAILS-AND-MONORAILS.md +107 -0
  14. package/docs/GUIDED-SETUP.md +296 -0
  15. package/docs/PERMISSIONS.md +118 -0
  16. package/docs/ROADMAP.md +59 -0
  17. package/docs/SETUP.md +259 -0
  18. package/guides/NEURODIVERGENT_SUPPORT.md +278 -0
  19. package/package.json +70 -4
  20. package/server.json +39 -0
  21. package/src/aleph.js +395 -0
  22. package/src/annotations.js +135 -0
  23. package/src/approve-throttle.js +54 -0
  24. package/src/atlas-role.js +58 -0
  25. package/src/conformance.js +688 -0
  26. package/src/content_analyzer.js +450 -0
  27. package/src/database.js +811 -0
  28. package/src/disciplines.js +26 -0
  29. package/src/dispatch.js +279 -0
  30. package/src/env.js +52 -0
  31. package/src/floor.js +187 -0
  32. package/src/gaps.js +476 -0
  33. package/src/guides.js +48 -0
  34. package/src/http-remote.js +269 -0
  35. package/src/index.js +390 -0
  36. package/src/invites.js +167 -0
  37. package/src/layers.js +449 -0
  38. package/src/lessons-to-checks.js +366 -0
  39. package/src/logger.js +299 -0
  40. package/src/metadata.js +61 -0
  41. package/src/module-path.js +32 -0
  42. package/src/mongo-connect.js +48 -0
  43. package/src/named-items.js +208 -0
  44. package/src/oauth-provider.js +838 -0
  45. package/src/persons.js +116 -0
  46. package/src/provenance.js +257 -0
  47. package/src/redact.js +231 -0
  48. package/src/request-log.js +124 -0
  49. package/src/scopes.js +97 -0
  50. package/src/security-headers.js +26 -0
  51. package/src/session-graph.js +945 -0
  52. package/src/session.js +1097 -0
  53. package/src/setup.js +1313 -0
  54. package/src/startup-pages.js +354 -0
  55. package/src/startup-payload.js +126 -0
  56. package/src/tools.js +4271 -0
  57. package/src/transcript-session.js +106 -0
  58. package/src/validation.js +1163 -0
  59. package/src/version.js +2 -0
  60. package/templates/BOARD.md +72 -0
  61. package/templates/BOTHANDOFF.md +57 -0
  62. package/templates/CHARACTER.md +30 -0
  63. package/templates/HANDOFF.md +63 -0
  64. package/templates/IDENTITY.md +29 -0
  65. package/templates/INDEX.md +82 -0
  66. package/templates/INSTALL.md +29 -0
  67. package/templates/PROCEDURE.md +39 -0
  68. package/templates/ROSTER.md +43 -0
  69. package/templates/SEED.md +65 -0
  70. package/templates/STAGING.md +37 -0
  71. package/templates/STANDARD.md +99 -0
  72. package/templates/THREAD.md +43 -0
  73. package/templates/USER.md +29 -0
@@ -0,0 +1,296 @@
1
+ # Guided setup — let your AI set EMET up for you
2
+
3
+ This is the path for someone who has never deployed anything. You do three things in a
4
+ browser when asked. Your AI does everything else — installs, configures, deploys, verifies —
5
+ and tells you what it did at each stage.
6
+
7
+ **Part A** is for you. It is short. **Part B** is for your AI; you do not need to read it.
8
+
9
+ ---
10
+
11
+ ## Part A — for the person
12
+
13
+ ### What you are setting up
14
+
15
+ A memory your AI keeps between conversations, on every device you use — it is a small server
16
+ plus a database, and your AI will hold the whole thing together from here. When it is done,
17
+ you say **"initialize"** at the start of a conversation and your AI picks up where it left
18
+ off.
19
+
20
+ ### What you need before you start
21
+
22
+ - **Claude** (or another MCP-capable assistant) — and a way for it to run commands on your
23
+ computer. See *Giving your AI a shell* below. This is the one step you do yourself.
24
+ - **About 30–45 minutes**, mostly waiting.
25
+ - **An email address** for two free accounts: MongoDB Atlas (the database) and Railway (the
26
+ host). Atlas's free tier needs no card. Railway may ask for a card or a small plan for an
27
+ always-on server — check what it shows you at sign-up; your AI will tell you the moment it
28
+ needs you there.
29
+
30
+ ### Giving your AI a shell
31
+
32
+ Your AI can only set things up if it can run commands. Pick whichever of these matches what
33
+ you have:
34
+
35
+ | You use | What to do |
36
+ |---|---|
37
+ | **Claude Desktop (the app)** | Install **Desktop Commander**, an MCP server that gives Claude a terminal and file access. Run this in a terminal: `npx @wonderwhy-er/desktop-commander@latest setup` (needs Node.js — <https://nodejs.org>, LTS). Then **fully quit and restart Claude Desktop.** Other installers: <https://github.com/wonderwhy-er/DesktopCommanderMCP>. |
38
+ | **Claude Code (the terminal tool)** | Nothing. It already has a shell. |
39
+ | **Claude Cowork** | Nothing. It has its own shell. |
40
+
41
+ One honest note about Desktop Commander: it can run any command you could run. That is what
42
+ makes guided setup possible, and it is also why you should read what your AI says it is about
43
+ to do. Per-step approval in Claude Desktop is the safety net — keep it on.
44
+
45
+ ### Starting
46
+
47
+ Paste this into a new conversation:
48
+
49
+ > Set up EMET for me. Fetch `https://raw.githubusercontent.com/dreamforgestudiollc/EMET/main/docs/GUIDED-SETUP.md`, read Part B, and follow it stage by stage. Ask me only when a step needs me — I will sign in to things when you tell me to. I want the remote (phone-reachable) server too.
50
+
51
+ (Drop the last sentence if you only want it on this one computer. If the link does not open
52
+ for your AI — the repository may be private — download this file and paste Part B into the
53
+ conversation instead.)
54
+
55
+ ### The three moments you will be asked to act
56
+
57
+ 1. **Sign in to MongoDB Atlas** — a browser window opens; create an account or sign in. Your AI waits.
58
+ 2. **Sign in to Railway** — same shape. If Railway asks for a card or a plan, that is between you and Railway; your AI will pause until you are through.
59
+ 3. **Add the connector in Claude** — Settings → Connectors → *Add custom connector* → paste the URL your AI gives you → enter the passphrase it gives you. Enable it in your conversation from the **+** menu.
60
+
61
+ Then say **"initialize"**. Your AI will ask you a few questions about who it should be and who you are. That is the setup interview, and it is the part that turns a database into a memory.
62
+
63
+ ### Keep two things
64
+
65
+ Your AI will hand you a **passphrase** and a **URL** at the end. Keep both somewhere safe. The passphrase is the whole perimeter of your memory — there is no second factor.
66
+
67
+ ### Every conversation from now on: two words
68
+
69
+ **"initialize"** as your first message — your AI loads who it is, who you are, and where you
70
+ left off. **"wrap up"** as your last — it writes the handoff, the state, a session entry and
71
+ the word-for-word transcript, then confirms with `emet_session_close` that everything landed.
72
+ Wait for it to say **complete** before you close the window. Skip the first and it answers from
73
+ guesswork; skip the second and the next session inherits a hole. The README's *Every session
74
+ after that* section says why.
75
+
76
+ ---
77
+
78
+ ## Part B — for the AI
79
+
80
+ You are setting up EMET for a person who may never have done anything like this. Your job is to
81
+ do every step you can, ask for exactly the steps you cannot, verify each stage before the next,
82
+ and report plainly. Read all of Part B before running anything.
83
+
84
+ ### Rules that hold for the whole procedure
85
+
86
+ 1. **Never put a secret in the conversation.** Not the connection string, not the passphrase,
87
+ not a token. Write them to files and environment variables with your tools. When you must
88
+ hand the person a value (the passphrase, once), say what it is for and where to keep it.
89
+ EMET masks secrets in anything written to its own store; the chat you are in is not that store.
90
+ 2. **Generate the passphrase yourself.** 24+ characters, letters and digits, no ambiguous
91
+ glyphs — `node -e "console.log(require('crypto').randomBytes(18).toString('base64url'))"`.
92
+ Do not ask the person to invent one.
93
+ 3. **Verify before proceeding.** Every stage ends with a check. If the check fails, stop, show
94
+ the person the actual output, and say what you think it means — marked as your reading, not
95
+ as fact. Do not retry blindly and do not invent a cause.
96
+ 4. **Ask only at the three human moments** (Atlas sign-in, Railway sign-in, connector add) and
97
+ when a command genuinely needs something only they have. Everything else is yours.
98
+ 5. **One machine at a time.** If you are running in a cloud sandbox rather than on the person's
99
+ computer, say so, and know that local-server config (stage 2) must be written on *their*
100
+ machine, not yours.
101
+ 6. **Report each stage in two or three sentences.** What you did, what you verified, what is next.
102
+
103
+ ### Stage 0 — check the ground
104
+
105
+ ```
106
+ node --version # need 20+ (package.json engines); 22 preferred
107
+ npm --version
108
+ git --version
109
+ ```
110
+
111
+ If `node` is missing: on Windows `winget install OpenJS.NodeJS.LTS`; macOS `brew install node`;
112
+ Linux via the distribution package or <https://nodejs.org>. If `git` is missing, download the
113
+ repository as a zip instead of cloning.
114
+
115
+ Then get the code:
116
+
117
+ ```
118
+ git clone https://github.com/dreamforgestudiollc/EMET.git
119
+ cd EMET
120
+ npm install
121
+ ```
122
+
123
+ **Verify:** `node -e "import('./src/layers.js').then(m => console.log(Object.keys(m.LAYER_CHARTER).length + ' layers'))"` prints `6 layers`.
124
+
125
+ ### Stage 1 — the database (MongoDB Atlas)
126
+
127
+ **Install the Atlas CLI.** Windows: download and run the `.msi` from
128
+ <https://www.mongodb.com/docs/atlas/cli/current/install-atlas-cli/> (you can open the download
129
+ for the person and ask them to click through; then open a fresh shell so PATH updates). macOS:
130
+ `brew install mongodb-atlas-cli`. Linux: the apt/yum instructions on that same page. Verify with
131
+ `atlas --version`.
132
+
133
+ **Human moment 1.** Run:
134
+
135
+ ```
136
+ atlas auth login
137
+ ```
138
+
139
+ A browser opens. Tell the person: *"A MongoDB window has opened. Create an account or sign in — the free tier needs no card. Tell me when you are back."* Wait. Then `atlas auth whoami` must print their account.
140
+
141
+ **Create everything in one command.** Generate a database password first (same method as the
142
+ passphrase; keep it out of the chat). Then:
143
+
144
+ ```
145
+ atlas setup --clusterName emet --tier M0 --username emet_app --password <generated> \
146
+ --accessListIp 0.0.0.0/0 --skipSampleData --skipMongosh --force
147
+ ```
148
+
149
+ `--accessListIp 0.0.0.0/0` is deliberate: a hosted server's egress IP is dynamic, so it cannot
150
+ be allowlisted, and security rests on the scoped user plus the OAuth passphrase. If the person
151
+ wants a **local-only** setup, use `--currentIp` instead. `--force` accepts defaults for
152
+ anything unspecified (provider and region — fine). If `atlas setup` reports it needs a project
153
+ or organization, follow its prompt; it creates them.
154
+
155
+ Cluster creation takes a few minutes. Poll:
156
+
157
+ ```
158
+ atlas clusters describe emet --output json
159
+ ```
160
+
161
+ until `"stateName": "IDLE"`.
162
+
163
+ **Get the connection string and write `.env`:**
164
+
165
+ ```
166
+ atlas clusters connectionStrings describe emet --output json
167
+ ```
168
+
169
+ Take the `standardSrv` value (`mongodb+srv://emet.xxxxx.mongodb.net`) and insert the user and
170
+ password: `mongodb+srv://emet_app:<password>@emet.xxxxx.mongodb.net/?retryWrites=true&w=majority`.
171
+ **Percent-encode the password if it contains `@ : / ? # [ ] %`** — a generated base64url
172
+ password will not. Copy `.env.example` to `.env` and set:
173
+
174
+ ```
175
+ MONGODB_URI=<the string above>
176
+ MONGODB_DB=emet
177
+ EMET_SOURCE_TAG=<this computer's name, e.g. laptop>
178
+ ```
179
+
180
+ **Verify:** `node -e "import('mongodb').then(async ({MongoClient}) => { const c = new MongoClient(process.env.MONGODB_URI); await c.connect(); console.log('ok', (await c.db('emet').command({ping:1})).ok); await c.close(); })"` — run with the `.env` loaded (`node --env-file=.env -e "..."` on Node 20.6+). Expect `ok 1`. If it times out, the access list has not propagated yet; wait a minute and retry once.
181
+
182
+ **Skip the vector index for now.** `semantic_recall` is optional; keyword recall works without
183
+ it, and Atlas Automated Embedding is not available on every tier. It is a later step, in
184
+ [SETUP.md](SETUP.md) stage 1, item 7, once everything else works.
185
+
186
+ ### Stage 2 — the local server (this computer)
187
+
188
+ This is what the person's desktop assistant talks to. It runs from the repo folder.
189
+
190
+ Write the MCP client entry. For Claude Desktop, merge into `claude_desktop_config.json`
191
+ (Windows `%APPDATA%\Claude\claude_desktop_config.json`; macOS
192
+ `~/Library/Application Support/Claude/claude_desktop_config.json`; Linux `~/.config/Claude/claude_desktop_config.json`).
193
+ **Read the file first and merge — do not overwrite other servers** (Desktop Commander's own
194
+ entry is in there):
195
+
196
+ ```json
197
+ "emet": {
198
+ "command": "node",
199
+ "args": ["<absolute path to repo>/src/index.js"],
200
+ "env": { "MONGODB_URI": "<from .env>", "MONGODB_DB": "emet", "EMET_SOURCE_TAG": "<same tag>" }
201
+ }
202
+ ```
203
+
204
+ Absolute path, forward slashes are fine on Windows. For Claude Code: `claude mcp add emet -e MONGODB_URI=<...> -e MONGODB_DB=emet -e EMET_SOURCE_TAG=<tag> -- node <absolute path>/src/index.js`, or the `.mcp.json` equivalent.
205
+
206
+ **Human moment (small):** *"Fully quit Claude Desktop — from the system tray, not just the window — and open it again. Tell me when it is back."* Then, in the new conversation, the `emet` tools appear. Call `emet_status`: expect `initialized: false` and a live database. Call it again with `probe: true`: it writes a probe and reads it back — expect every check passed.
207
+
208
+ If the person only wanted this computer, skip to stage 4.
209
+
210
+ ### Stage 3 — the remote server (phone and everything else)
211
+
212
+ ```
213
+ npm i -g @railway/cli
214
+ railway --version
215
+ ```
216
+
217
+ On Windows, if the shim fails with `'"node"' is not recognized`, call the binary directly:
218
+ `%APPDATA%\npm\node_modules\@railway\cli\bin\railway.exe`.
219
+
220
+ **Human moment 2.** Run `railway login` (plain — not `--browserless`, which only works when
221
+ approved on the same machine). Tell the person: *"A Railway window has opened. Create an account
222
+ or sign in. If it asks for a card or a plan, that is Railway's requirement for an always-on
223
+ server — decide there and tell me when you are through."* Wait. `railway whoami` must print them.
224
+
225
+ **Create the project and set variables BEFORE the first deploy** — a server that boots once
226
+ misconfigured leaves residue:
227
+
228
+ ```
229
+ railway init # from the repo root; name it emet
230
+ railway variables --set MONGODB_URI=<from .env> --set MONGODB_DB=emet \
231
+ --set EMET_OAUTH_PASSPHRASE=<generated passphrase> --set EMET_SOURCE_TAGS=<every host's tag, e.g. laptop,phone>
232
+ railway up --detach
233
+ railway domain # prints https://<something>.up.railway.app
234
+ railway variables --set PUBLIC_URL=https://<that host>
235
+ railway up --detach # second pass: PUBLIC_URL is the OAuth issuer and must match
236
+ ```
237
+
238
+ Leave `EMET_SOURCE_TAG` unset on this server: several hosts share it, each host passes its own
239
+ tag as `source` on its writes, and `EMET_SOURCE_TAGS` registers the tags. A default tag would
240
+ make every host look the same; set one only on a server a single host uses.
241
+
242
+ The repository's `Dockerfile` already starts the HTTP transport; no start command to set. The
243
+ two-pass deploy is not optional. **Never run `railway variables` without `--kv` and never paste
244
+ its output anywhere** — it prints secrets in plaintext.
245
+
246
+ **Verify** (build takes about two minutes; poll):
247
+
248
+ ```
249
+ curl https://<host>/health → {"ok":true,"service":"emet","tools":N,...}
250
+ curl https://<host>/.well-known/oauth-authorization-server → OAuth metadata, not a 404
251
+ ```
252
+
253
+ A 404 on the second means `PUBLIC_URL` is wrong. The connector URL is `https://<host>/mcp` —
254
+ **the `/mcp` suffix is required**; the root path is 404 by design.
255
+
256
+ **Human moment 3.** Tell the person, exactly: *"Open Claude → Settings → Connectors → Add custom
257
+ connector. Name: EMET. URL: `https://<host>/mcp`. Click connect — you will be sent to a
258
+ passphrase page. The passphrase is: `<passphrase>` — keep it; it is the only key to your memory.
259
+ Then enable EMET in this conversation from the + menu and tell me."*
260
+
261
+ **Verify from the remote route:** `emet_status` with `probe: true` through the connector. Then the real
262
+ test — `remember` something on one route and `recall` it on the other. If both see it, the
263
+ deployment is real.
264
+
265
+ ### Stage 4 — the interview
266
+
267
+ Say nothing about setup. Call `emet_initialize`. On a new store it returns `setup_required` and
268
+ the interview questions. Ask them **conversationally, one at a time** — what the assistant should
269
+ be called and how it should carry itself, the person's name in the form they want used, what the
270
+ memory is for, and optionally how they want to be worked with and this host's tag. Then
271
+ `emet_setup_complete`. It refuses partial answers rather than inventing an identity; that is
272
+ correct behaviour.
273
+
274
+ Then hand the person the short instruction block from [BOOTSTRAP.md](BOOTSTRAP.md) to paste
275
+ into their project instructions, so future sessions consult the memory without being told.
276
+
277
+ ### Stage 5 — close out
278
+
279
+ Tell the person, in plain words:
280
+
281
+ - what was set up (local server, remote server, or both) and where the code lives on disk;
282
+ - the connector URL and that the passphrase is the whole perimeter — rotate it by changing
283
+ `EMET_OAUTH_PASSPHRASE` on Railway and redeploying, which invalidates every device;
284
+ - that every host has its own source tag (a local entry's `EMET_SOURCE_TAG`; on the shared
285
+ remote server, the `source` each host passes, registered in `EMET_SOURCE_TAGS`), and what
286
+ this one's is;
287
+ - that `emet_status` (and `emet_status` with `probe: true`) is the thing to call when
288
+ something seems wrong, and [SETUP.md](SETUP.md) has the symptom table;
289
+ - that after any future deploy which changes the tool list, each device must reconnect the
290
+ connector to see the new tools — nothing breaks, the new ones just stay invisible until then.
291
+ - that if they later run other agents (bots) against the same memory, each needs its own tag,
292
+ its own handoff and a roster row before its first write — [BOTS.md](BOTS.md) is the procedure,
293
+ and their own assistant's tag (the hub) is never listed as a bot.
294
+
295
+ Do not summarise what the person told you in the interview back at them. It is stored; they
296
+ know what they said.
@@ -0,0 +1,118 @@
1
+ # Permissions and approvals
2
+
3
+ How to decide what EMET may do without being asked each time, and how to set it.
4
+
5
+ ---
6
+
7
+ ## Where the boundary can live
8
+
9
+ There are three places, and it is worth being clear about which is which:
10
+
11
+ - **The host** decides *what gets called* and *what data goes into the call*. Approval prompts,
12
+ allow-lists and "always allow" settings all live here.
13
+ - **The server** decides *what it will do when asked*. Refusing an operation, versioning a write,
14
+ archiving before replacing, checking the order of a session's writes (the monorail) - all here.
15
+ - **The database** decides *what the server's own login may do*. EMET's login runs under the
16
+ least-privilege role `emetRecordKeeper` ([SETUP.md](SETUP.md), `src/atlas-role.js`): it can
17
+ insert and update, and it has no permission to remove anything from the record. So "nothing is
18
+ deleted" holds even against a bug in the server, not only against a model's choice.
19
+
20
+ No layer can widen another. In particular, **a server cannot grant itself permission**. Nothing in
21
+ this repository can stop your host from asking you to approve every call, and nothing in it should
22
+ be able to.
23
+
24
+ What a server *can* do is describe itself accurately enough that a host has something to reason
25
+ with. That is what tool annotations are.
26
+
27
+ ---
28
+
29
+ ## What EMET declares
30
+
31
+ Every tool carries MCP annotations, declared in one table in `src/annotations.js`:
32
+
33
+ | Hint | Meaning |
34
+ |---|---|
35
+ | `readOnlyHint` | The tool does not modify anything. |
36
+ | `destructiveHint` | It may replace or remove existing data. |
37
+ | `idempotentHint` | Calling it again with the same arguments changes nothing further. |
38
+ | `openWorldHint` | It reaches systems outside this server's own store. |
39
+
40
+ Of the 29 tools:
41
+
42
+ - **11 are read-only.** `emet_gaps`, `emet_floor`, `recall`, `semantic_recall`,
43
+ `corpus_recall`, `query_layer`, `query_transcripts`, `read_doc`, `read_doc_history`, `list_docs`,
44
+ `validate_doc`. These cannot change the store under any arguments.
45
+ - **10 are additive writes.** `emet_initialize` (it provisions a missing board), `save_to_layer`, `revise_memory`, `save_transcript`,
46
+ `revise_transcript`, `emet_session_open`, `emet_transcript_append`, `emet_session_close` (it
47
+ records blocked attempts), `rename_doc`, `accept_nonconformance`. They add; they do not remove or replace.
48
+ `emet_session_open` still needs the `emet.write` scope, because it stamps the drop list a board edit trusts.
49
+ `emet_initialize` stays a read.
50
+ - **6 can replace what is already there, or hand out access.** `write_doc`, `patch_doc`, `restore_doc`, `emet_setup_complete`,
51
+ `emet_invite_create`, `emet_member_access_create`. Prior versions of a document are archived to the history
52
+ collection first, but the visible content a person may be relying on is replaced. A code that grants access
53
+ is marked the same way: it is not a harmless add.
54
+ - **1 marks a document obsolete.** `retire_doc`. Neither a removal nor a replacement: the
55
+ document keeps its id and its full content, `read_doc` still returns it, and `list_docs`
56
+ keeps it after the current documents, marked with the date it was retired and what replaced
57
+ it. Idempotent — retiring an already-retired document reports
58
+ the existing mark rather than making a second one.
59
+ - **1 reads, and on request writes a probe and removes it.** `emet_status`. Deliberately not
60
+ declared read-only: with `probe: true` it writes, and a health check that only reads cannot
61
+ detect a broken write path. A read-scoped token may call it without `probe`. With `probe: true` it needs
62
+ `emet.write`. The probe deletes only that document. It does not drop the collection.
63
+
64
+ **`openWorldHint` is false on every tool.** The tools talk to this server's configured database
65
+ and nothing else: no filesystem and no shell. The sign-in server fetches a client's metadata
66
+ document, and only from a public address it has already checked. That is the main reason a memory
67
+ server can reasonably be given standing permission when other servers should not.
68
+
69
+ `src/annotations.js` is the complete statement of what EMET does to a store. It is short on
70
+ purpose: anyone deciding how much to approve should be able to read it in one screen and check it
71
+ against the code.
72
+
73
+ ---
74
+
75
+ ## Choosing a posture
76
+
77
+ The question worth asking is not "how much do I trust this server" but **"what does a wrong call
78
+ actually cost, and can I get back what it took?"**
79
+
80
+ - **Reads cost nothing and cannot be wrong destructively.** Approving them individually spends
81
+ attention on the calls that carry no risk, and a session is mostly reads. Standing approval for
82
+ the read-only group is the change that removes most of the friction.
83
+ - **Additive writes are recoverable by construction.** Layer entries are superseded rather than
84
+ edited, so a bad entry is visible and correctable but never overwrites what it corrects.
85
+ - **Replacing writes are recoverable but not free.** The prior version is archived, so nothing is
86
+ destroyed; you may still want to see these, particularly early on, because a wrong `write_doc`
87
+ is silently a *different document* rather than an error.
88
+
89
+ A reasonable default for most users: **standing approval for reads, per-call or standing for
90
+ additive writes according to taste, and eyes on the replacing writes, including setup and the two access doors.**
91
+
92
+ **Do not carry this posture across to other servers.** It rests on `openWorldHint` being false and
93
+ on every write being versioned. A filesystem or shell server has neither property: there, a single
94
+ wrong call can do something no archive brings back, and per-call approval is the actual safety
95
+ mechanism rather than an inconvenience.
96
+
97
+ ---
98
+
99
+ ## Setting it
100
+
101
+ Approval settings are host-side. The exact wording differs between hosts and changes over time,
102
+ so look for the per-tool or per-connector permission settings in whichever host you have connected
103
+ EMET to, and grant standing approval to the tools you have decided on.
104
+
105
+ ---
106
+
107
+ ## When the prompting suddenly increases
108
+
109
+ **A host's remembered approvals are tied to the tool list it has cached.** When a server adds or
110
+ renames tools, the host is looking at a list it has not seen before, and previously granted
111
+ approvals may no longer match. Reconnecting the server to refresh its tool list is normal after an
112
+ upgrade; being asked to approve things you had already approved is the usual symptom, and it
113
+ settles once the new list is approved.
114
+
115
+ If prompting stays heavy after that, the thing to check is whether the annotations are actually
116
+ reaching the host: `emet_initialize` and any tool listing should show them. A host that receives no
117
+ annotations has no way to distinguish `read_doc` from `write_doc`, and the correct behaviour for
118
+ such a host is to ask about both.
@@ -0,0 +1,59 @@
1
+ # EMET — Next Steps and Proposed Features
2
+
3
+ Status as of 2026-10-07. This is a working roadmap, not a commitment: items move when the owner rules on them. Nothing here is built unless it says so.
4
+
5
+ ## Where things stand
6
+
7
+ - **Live:** 29 tools (11 read-only); layer writes and reads native to MongoDB; server-side checks on session start and close (machine line on the first transcript append, blocked-close cap with scope, pending lessons at startup); receipts required at close; the handoff is a record, superseded and never amended.
8
+ - **The aleph** verifies every write by reading it back before any receipt, and every later read by its digests, signature and place in its layer's hash chain. `emet_gaps` walks the whole chain for any host.
9
+ - **Guardrails & Monorails** ([docs/GUARDRAILS-AND-MONORAILS.md](GUARDRAILS-AND-MONORAILS.md)): the server checks the order of a session's writes. Enforce only since 0.2.1 (deployed 2026-10-03; report mode 2026-09-29 to 2026-10-03): every skipped step is refused with the way to pass, and every check is stored as a timestamped lab result.
10
+ - **The database** login runs under the least-privilege role `emetRecordKeeper`: it can insert and update, never remove the record.
11
+ - **Startup load:** since 0.2.1, `emet_initialize` is served in pages of at most 18,000 bytes as received (on a live-sized store, five pages totalling about 68 KB as received, or about 64 KB whole), so a host that cuts long results short still reads all of it; `page: "all"` returns it whole on a host with no size limit.
12
+
13
+ ## Next steps, in order
14
+
15
+ 1. **Monorail: enforce only** (decided and deployed 2026-10-03, release 0.2.1). Every skipped step is refused and the refusal says how to pass; there is no report mode or off switch. Every host and scheduled routine must now read its startup, open a session with its `load_id`, and pass the `session_id` on its writes.
16
+ 2. **Admission test on the proposed items.** Every proposed feature below answers the four questions of charter commitment 6 before it is built (2026-09-30 read: the compiled-pages pilot passes; the lint pass needs a named measure; hybrid search, graph links and confidence scores do not pass yet).
17
+ 3. **Initialize payload trim.** Character document trim; measure the payload again.
18
+ 4. ~~**Register or retire the `cloud-scheduled-intake` source tag.**~~ Retired 2026-10-02 (the owner, a decision record, item 7): it is a legacy tag; the weekly intake now runs under `intake-bot`, with no `session_id` on its writes; under enforce-only those writes are refused (`no_session`) until it opens a session with its startup's `load_id` (item 1). The existing rows keep counting as ambiguous in `emet_gaps` rather than being re-attributed, and the count stops growing as long as nothing new is written under the old tag. The prefix `cloud-scheduled-<task>` does not count as registered. Only an exact tag in `EMET_SOURCE_TAGS` is accepted, and a refusal does not publish the list.
19
+ 5. **Monorail switches.** Small logic at each junction where a session's flow must fork, routing it to the right guardrail space: tripped only by its condition, like a transistor; no hosted model, no API; each designed from the function it serves and the flow of information and tasking through it ([GUARDRAILS-AND-MONORAILS.md](GUARDRAILS-AND-MONORAILS.md), decided 2026-09-29). First candidate junctions come with the socket, where a switch picks the GEM.
20
+ 6. **The socket** — see below.
21
+
22
+ ## Done since the last revision (2026-09-28)
23
+
24
+ - SQL translator stage 2: read path native to MongoDB; the translator and the `event` mirror column removed.
25
+ - Test-tree pass: one shared harness; dated suites named by subject.
26
+ - Open questions answered 2026-09-29: the lessons `shadow` block dropped, the lesson key checked at the door; a coverage number published as an input to review; the character document consolidated quarterly (first pass done, SOUL.md v7).
27
+ - Chain verification: one MongoDB connection path with a DNS fallback, then the chain walk moved into `emet_gaps` so no host needs the repo or a shell.
28
+ - Security audit, first pass: two findings fixed; nothing open.
29
+ - Least-privilege Atlas role, scripted and documented for new users.
30
+ - Provenance stamped from the transcript; semantic and procedural writes with no source refused.
31
+ - Guardrails & Monorails and lab results.
32
+ - Charter revised 2026-09-29 (the aleph, the monorail, the database boundary, the per-exchange transcript) and again 2026-09-30 (the admission test in commitment 6).
33
+
34
+ ## Proposed features and functions
35
+
36
+ - **GEM socket (plug-in standard).** A GEM is a nested module inside EMET that modifies engagement; a RUNED GEM also carries tools (RUNEs). The socket must mount several GEMs, switch each on or off, and prioritise the active ones in a running schema that prevents conflicts — with a cap on sockets, a cap on active GEMs, and a priority order, because every active GEM costs the model context. Includes a developer guide for building one.
37
+ - **Claim-status grading.** Extend provenance so every recorded claim carries a status: established, deduced, proposed, still owed, or rejected — and rejected routes stay on the record with the reason they failed. (Idea taken from a physics research corpus that grades its own claims this way.)
38
+ - **Index-first retrieval.** Score candidates against a one-line-per-item index before opening anything, open only the best match, follow one link at most — finding is logic, not a model call. EMET already has the shape (handoff and board as router, document list as index); the work is keeping the startup router small.
39
+ - **Composite retrieval scoring.** Live as of this revision: recall ranks by how many query words match, then by importance. Current entries come first in every order, including time order. Time order is `order: 'latest'`, or a standalone latest, newest, or most recent together with other words. That phrase only reorders rows that already match. Nothing fades or is down-weighted for age. A superseded or expired entry stays in the result, marked with its end date and what replaced it. `history: true` reads the ended entries when current ones fill the limit. A recall or layer query ranks matching rows in the store (current before ended, then keyword hits and importance, or time when you asked for the latest) and then keeps a bounded window (at least 200 rows, or 20 times the page), not the whole layer. A blank sort value comes first when ascending and last when descending.
40
+ - **Export, import, restore-and-compare.** Not built; listed in the README's known gaps.
41
+ - **Organizational use.** Many private EMETs and a document gateway between them. Nothing built before a named customer.
42
+ - **Shared hive memory for AI bots (proposed 2026-09-30).** One EMET as a common memory that several agent bots read and write as users, each keeping its own memories — candidates are Grok Bot, OpenAI dots and Meta Muse, all of which can reach a remote MCP server. A GEM per bot, seated in the socket, if needed. Taken up with the socket; the first design question is each bot's source tag and scope.
43
+ - **Compiled topic pages, pilot (proposed 2026-09-30).** After the LLM-wiki pattern: a document prefix of topic pages compiled from semantic entries. Every claim cites its entry or transcript span; a compiled page never cites another compiled page as evidence; pages are derived, never the source of truth; one compiler role builds pages, others write entries only. No database change — the document store already versions, hashes, signs and checks form. Pilot page: the hive-memory idea. Nothing added beyond what the pilot needs.
44
+ - **Lint pass over the semantic layer (proposed 2026-09-30).** A scheduled sweep for contradictions between entries, outdated claims a newer entry supersedes, entries that should link and don't, and subjects mentioned often with no compiled page. Findings are reported, never applied automatically; corrections go through supersession. Built after the pilot page, and only once it names its measure. Design inputs from the LLM Wiki v2 review (typed links, multi-agent sync rules, drift invariants, confidence only on top of provenance) are each weighed against commitment 6 before adoption. Its idea of letting entries fade from what surfaces is not taken: nothing in EMET fades.
45
+ - **Advisory judge for team traffic (parked).** A fast external decision model (TypeSafe's Jev was evaluated) could sort traffic and interactions when many people and hosts share one EMET. Never in the write path — no model decides what EMET stores. Not for single-user installs.
46
+ - **Local open-weight model as a host.** A read-only trial of EMET under a locally run model, once the host machine's GPU and RAM are on record.
47
+ - **Stranger install.** A clean-machine install by someone who has never seen EMET, to find first-run friction.
48
+ - **Remove Dynamic Client Registration** by 2027-06-01, as MCP moves to client ID metadata documents.
49
+ - **Public landing page (parked)** until a public publish path exists.
50
+
51
+ ## Design commitments these must keep
52
+
53
+ - No model in the write path: EMET stores only what the assistant deliberately chose to write.
54
+ - Controls, not reminders: a rule that matters is checked by the server.
55
+ - Over-engineering is a defect, and the check comes before the build. Nothing is built until it
56
+ names the failure it fixes, what it replaces, how we will know it worked, and what keeps it
57
+ working (charter commitment 6). While EMET is in design it follows DMADV (define, measure,
58
+ analyze, design, verify); once stable, DMAIC (define, measure, analyze, improve, control).
59
+ - Correct the record by superseding, never by editing.