@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.
- package/.env.example +136 -0
- package/CHANGELOG.md +296 -0
- package/CHARTER.md +125 -0
- package/LICENSE +22 -0
- package/README.md +783 -2
- package/docs/AUTHORSHIP.md +26 -0
- package/docs/BENCHMARKS.md +261 -0
- package/docs/BOOTSTRAP.md +127 -0
- package/docs/BOTS.md +79 -0
- package/docs/COVERAGE.md +64 -0
- package/docs/DEPLOY.md +246 -0
- package/docs/DISCIPLINES.md +29 -0
- package/docs/GUARDRAILS-AND-MONORAILS.md +107 -0
- package/docs/GUIDED-SETUP.md +296 -0
- package/docs/PERMISSIONS.md +118 -0
- package/docs/ROADMAP.md +59 -0
- package/docs/SETUP.md +259 -0
- package/guides/NEURODIVERGENT_SUPPORT.md +278 -0
- package/package.json +70 -4
- package/server.json +39 -0
- package/src/aleph.js +395 -0
- package/src/annotations.js +135 -0
- package/src/approve-throttle.js +54 -0
- package/src/atlas-role.js +58 -0
- package/src/conformance.js +688 -0
- package/src/content_analyzer.js +450 -0
- package/src/database.js +811 -0
- package/src/disciplines.js +26 -0
- package/src/dispatch.js +279 -0
- package/src/env.js +52 -0
- package/src/floor.js +187 -0
- package/src/gaps.js +476 -0
- package/src/guides.js +48 -0
- package/src/http-remote.js +269 -0
- package/src/index.js +390 -0
- package/src/invites.js +167 -0
- package/src/layers.js +449 -0
- package/src/lessons-to-checks.js +366 -0
- package/src/logger.js +299 -0
- package/src/metadata.js +61 -0
- package/src/module-path.js +32 -0
- package/src/mongo-connect.js +48 -0
- package/src/named-items.js +208 -0
- package/src/oauth-provider.js +838 -0
- package/src/persons.js +116 -0
- package/src/provenance.js +257 -0
- package/src/redact.js +231 -0
- package/src/request-log.js +124 -0
- package/src/scopes.js +97 -0
- package/src/security-headers.js +26 -0
- package/src/session-graph.js +945 -0
- package/src/session.js +1097 -0
- package/src/setup.js +1313 -0
- package/src/startup-pages.js +354 -0
- package/src/startup-payload.js +126 -0
- package/src/tools.js +4271 -0
- package/src/transcript-session.js +106 -0
- package/src/validation.js +1163 -0
- package/src/version.js +2 -0
- package/templates/BOARD.md +72 -0
- package/templates/BOTHANDOFF.md +57 -0
- package/templates/CHARACTER.md +30 -0
- package/templates/HANDOFF.md +63 -0
- package/templates/IDENTITY.md +29 -0
- package/templates/INDEX.md +82 -0
- package/templates/INSTALL.md +29 -0
- package/templates/PROCEDURE.md +39 -0
- package/templates/ROSTER.md +43 -0
- package/templates/SEED.md +65 -0
- package/templates/STAGING.md +37 -0
- package/templates/STANDARD.md +99 -0
- package/templates/THREAD.md +43 -0
- 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.
|
package/docs/ROADMAP.md
ADDED
|
@@ -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.
|