@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
package/.env.example
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# EMET configuration.
|
|
2
|
+
# Copy this file to .env and fill it in. .env is gitignored - never commit it.
|
|
3
|
+
# Real environment variables always take precedence over this file.
|
|
4
|
+
|
|
5
|
+
# ---- storage (required) ----
|
|
6
|
+
# Atlas: the mongodb+srv:// string from Connect -> Drivers.
|
|
7
|
+
# A local MongoDB (6 or later) also works: MONGODB_URI=mongodb://127.0.0.1:27017/
|
|
8
|
+
# Only semantic_recall needs Atlas (its vector index); everything else runs on either.
|
|
9
|
+
MONGODB_URI=mongodb+srv://USERNAME:PASSWORD@cluster.example.mongodb.net/?retryWrites=true&w=majority
|
|
10
|
+
MONGODB_DB=emet
|
|
11
|
+
|
|
12
|
+
# ---- provenance ----
|
|
13
|
+
# Every write records the host that made it (its source tag). Register the tags
|
|
14
|
+
# your hosts and bots will use, so a typo is marked, not invented. List every tag
|
|
15
|
+
# you will give the setup interview or pass as `source` - while this is set, a
|
|
16
|
+
# transcript append under a tag not listed here is refused.
|
|
17
|
+
# Unset = any tag is accepted, and the bot guards (bots/ folders, main records)
|
|
18
|
+
# are OFF. See docs/BOTS.md before adding a bot's tag.
|
|
19
|
+
EMET_SOURCE_TAGS=laptop,phone,cli
|
|
20
|
+
# A remote server shared by several hosts: do not set EMET_SOURCE_TAG - a default
|
|
21
|
+
# makes every host look the same; each host passes its own tag on the write.
|
|
22
|
+
# A server used by one host only may set its default tag:
|
|
23
|
+
# EMET_SOURCE_TAG=laptop
|
|
24
|
+
|
|
25
|
+
# HMAC key for signed digests. Generate once, keep only here / on your host.
|
|
26
|
+
# Never commit a real value. Never store it in Mongo. Unset = entries are saved
|
|
27
|
+
# "unsigned" (everything else works). To make one:
|
|
28
|
+
# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
29
|
+
# EMET_SIGNING_KEY=
|
|
30
|
+
|
|
31
|
+
# Two doors for a second person into THIS store, each off unless set to 1.
|
|
32
|
+
# Leave both unset on a single-person assistant.
|
|
33
|
+
# EMET Guest Access: one-time codes for read access. Set to 1 only on a
|
|
34
|
+
# household or project EMET meant to be shared.
|
|
35
|
+
# EMET_INVITES=1
|
|
36
|
+
# EMET Member Access: one-time codes for a new person with read and write
|
|
37
|
+
# access (never the owner). Separate from guest access.
|
|
38
|
+
# EMET_MEMBER_ACCESS=1
|
|
39
|
+
|
|
40
|
+
# The monorail, the server-side check on the order of a session's writes
|
|
41
|
+
# (docs/GUARDRAILS-AND-MONORAILS.md), runs in enforce only and has no setting:
|
|
42
|
+
# EMET_SESSION_GRAPH is no longer read. Every check is stored in <prefix>graph_lab;
|
|
43
|
+
# emet_gaps summarizes it.
|
|
44
|
+
|
|
45
|
+
# Optional. The time zone session ids are dated in (IANA name). Set it to your
|
|
46
|
+
# own zone, so an evening session carries your day, not UTC's. If unset, the
|
|
47
|
+
# default is America/New_York.
|
|
48
|
+
# EMET_TIMEZONE=America/New_York
|
|
49
|
+
|
|
50
|
+
# Optional. Minutes after a complete close in which the session still takes its
|
|
51
|
+
# ONE closing exchange (the reply sent after emet_session_close). After that one
|
|
52
|
+
# append, or once the window passes, the session is locked. Default 5; 0 = off;
|
|
53
|
+
# at most 60 (a larger value is capped at 60). A negative or non-numeric value
|
|
54
|
+
# is not used: the server logs a warning and uses 5. The legacy name
|
|
55
|
+
# CASCADE_CLOSE_GRACE_MINUTES is still read as a deprecated fallback; EMET_ wins.
|
|
56
|
+
# EMET_CLOSE_GRACE_MINUTES=5
|
|
57
|
+
|
|
58
|
+
# Optional. The date from which this record is held to the current rules.
|
|
59
|
+
# Set it and the startup line reports gaps SINCE this date beside the lifetime
|
|
60
|
+
# figure - the lifetime figure never falls once history is in the store; the
|
|
61
|
+
# since-baseline figure is the one that should trend to zero.
|
|
62
|
+
# EMET_GAP_BASELINE=2026-09-07
|
|
63
|
+
|
|
64
|
+
# Optional. Startup page size in bytes: emet_initialize is served in pages that
|
|
65
|
+
# each fit this budget (default 18000; clamped to 12000-19000). Lower it only for
|
|
66
|
+
# a host that cuts results shorter than the usual 20,000-byte limit.
|
|
67
|
+
# EMET_INIT_PAGE_BYTES=18000
|
|
68
|
+
|
|
69
|
+
# Optional. read_doc page limit in bytes as the host receives it (default 18000):
|
|
70
|
+
# a page ends before its JSON-escaped text plus 1,500 bytes for the rest of the
|
|
71
|
+
# result would pass it, on a whole character. Offsets are UTF-8 bytes.
|
|
72
|
+
# EMET_READ_DOC_PAGE=18000
|
|
73
|
+
|
|
74
|
+
# ---- document names (optional; defaults shown) ----
|
|
75
|
+
# The session handoff and the board.
|
|
76
|
+
# EMET_HANDOFF_DOC=HANDOFF.md
|
|
77
|
+
# EMET_STATE_DOC=STATE.md
|
|
78
|
+
# The user's host-and-machine notes.
|
|
79
|
+
# EMET_INSTALL_DOC=bootstrap/INSTALL.md
|
|
80
|
+
# The character document (character and voice). When unset, the usual
|
|
81
|
+
# bootstrap names are tried in order (bootstrap/CHARACTER.md first).
|
|
82
|
+
# EMET_CHARACTER_DOC=bootstrap/CHARACTER.md
|
|
83
|
+
# More record documents, beside the handoff (comma-separated ids): kept as
|
|
84
|
+
# superseded records, never amended. Bot handoffs are listed here, e.g.
|
|
85
|
+
# bots/<tag>/HANDOFF.md.
|
|
86
|
+
# EMET_RECORD_DOCS=
|
|
87
|
+
# More document-to-template mappings for validate_doc, as id=template pairs
|
|
88
|
+
# (comma-separated). Additive only: an entry that would change a built-in
|
|
89
|
+
# mapping is ignored and reported.
|
|
90
|
+
# EMET_TEMPLATE_MAP=
|
|
91
|
+
|
|
92
|
+
# ---- http transport only (src/http-remote.js) ----
|
|
93
|
+
PORT=8849
|
|
94
|
+
# Local use: keep the server on this machine only.
|
|
95
|
+
HOST=127.0.0.1
|
|
96
|
+
# Deploy-only (container/host behind a proxy): listen on all interfaces.
|
|
97
|
+
# HOST=0.0.0.0
|
|
98
|
+
# When deployed: must exactly match the deployed https URL - it is the OAuth issuer.
|
|
99
|
+
# Leave it unset to run the HTTP server on this machine; it then defaults to
|
|
100
|
+
# http://127.0.0.1:PORT.
|
|
101
|
+
# PUBLIC_URL=https://your-deployment.example.com
|
|
102
|
+
# Typed once per device to authorize it. This is the whole perimeter. Make it strong.
|
|
103
|
+
# While it is unset, the HTTP server refuses every authorization.
|
|
104
|
+
# EMET_OAUTH_PASSPHRASE=
|
|
105
|
+
# The server trusts exactly one proxy hop (Railway's edge). TRUST_PROXY is not read.
|
|
106
|
+
# Client ID Metadata Documents are advertised by default; 0 falls back to
|
|
107
|
+
# Dynamic Client Registration only (a rollback with no redeploy).
|
|
108
|
+
# EMET_CIMD=1
|
|
109
|
+
# One redacted log line per OAuth/MCP request and per error response; 0 silences it.
|
|
110
|
+
# EMET_REQUEST_LOG=1
|
|
111
|
+
|
|
112
|
+
# ---- optional ----
|
|
113
|
+
# Collection name prefix. Governs layer collections, the counters collection and the
|
|
114
|
+
# OAuth collections. Change only before first use - or set it to cascade_ to adopt an
|
|
115
|
+
# existing upstream CASCADE store in place. See docs/SETUP.md, "Migrating an existing
|
|
116
|
+
# CASCADE deployment".
|
|
117
|
+
# EMET_COLLECTION_PREFIX=emet_
|
|
118
|
+
|
|
119
|
+
# Atlas Vector Search index used by semantic_recall. Migrating installs set this to
|
|
120
|
+
# cascade_content_auto.
|
|
121
|
+
# EMET_VECTOR_INDEX=emet_content_auto
|
|
122
|
+
|
|
123
|
+
# Optional supplementary corpus searched by corpus_recall.
|
|
124
|
+
# EMET_CORPUS_COLLECTION=corpus_chunks
|
|
125
|
+
# EMET_CORPUS_INDEX=corpus_content_auto
|
|
126
|
+
|
|
127
|
+
# Comma-separated names for the optional supplementary corpus searched by
|
|
128
|
+
# corpus_recall. Leave unset unless you have populated a corpus yourself.
|
|
129
|
+
# EMET_CORPORA=
|
|
130
|
+
|
|
131
|
+
# Diagnostics.
|
|
132
|
+
LOG_LEVEL=info
|
|
133
|
+
LOG_FORMAT=text
|
|
134
|
+
# DEBUG=true
|
|
135
|
+
# EMET_AUDIT_LOG=
|
|
136
|
+
# EMET_CRASH_LOG=
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to EMET are listed here, newest first. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and version numbers follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/). EMET is still 0.x: the stored data shapes may
|
|
6
|
+
change before 1.0.
|
|
7
|
+
|
|
8
|
+
## 0.2.4 - 2026-10-08
|
|
9
|
+
|
|
10
|
+
A board fix, a public website, and the first npm package, `@dreamforgestudiollc/emet`. A session that boots with no unhandled drops can edit the board again. No data shapes or settings change; deploy over 0.2.3 as is.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- A static website in `site/`, for search, and a GitHub Actions workflow that publishes that folder to GitHub Pages on pushes to `main`.
|
|
15
|
+
- `glama.json` at the repo root names `dreamforgestudiollc` as maintainer for the Glama directory listing.
|
|
16
|
+
- The README records the origin in the same words as the site: EMET was built by Dreamforge Studio LLC from a neurodivergent user’s own need for an AI assistant that remembers. The word coined for that is neurendipity: neurodivergent and serendipity.
|
|
17
|
+
- The public-scrub suite reads the Pages workflow's deploy job `if` and requires it to be exactly `github.repository == 'dreamforgestudiollc/EMET' && github.ref == 'refs/heads/main'`. A repository name that only contains that text, such as `dreamforgestudiollc/EMET-private`, does not pass.
|
|
18
|
+
- The same suite requires `site/sitemap.xml`, `site/robots.txt`, `site/.nojekyll`, and every image the site HTML references to be present on the scrub and publish walk. Removing one of those files fails the suite.
|
|
19
|
+
- `server.json` for the Official MCP Registry. Its name is `io.github.dreamforgestudiollc/emet`, the same value as `mcpName` in package.json. The npm package it names is the stdio server at version 0.2.4.
|
|
20
|
+
- The pack test reads the text inside the tarball. On a scrubbed tree, an install-specific name in any packed file fails it. On this private tree that check waits, because the publish scrub has not rewritten those files yet.
|
|
21
|
+
- The site image check fails a root-relative `/EMET/` image URL, a protocol-relative URL, a JSON-LD image in one of those forms, and a path that climbs out of the repository. A second Pages job with no `if` fails the deploy gate.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- The README now opens with the search line and a short account of what EMET does, in the same words as the website: an MCP (Model Context Protocol) memory server, persistent shared memory for AI agents, bot teams and chats. The previous opening paragraph, including how to connect a single-session chat, is kept below that.
|
|
26
|
+
- package.json is prepared for a public npm release at version 0.2.4. The package name is now `@dreamforgestudiollc/emet`. It was `emet-mcp-server`. npm refused the unscoped name `emet` at publish as too similar to existing package names, so the package uses the documented scoped fallback with `"publishConfig": { "access": "public" }`. `server.json` names the same package. The command it installs is still `emet`. `@black-knight.dev/emet` is a different server that also installs a command named `emet`. Keywords match the public GitHub topics. `repository`, `homepage` (`https://dreamforgestudiollc.github.io/EMET/`), and `bugs` point at the public project. `bin` and `main` stay `src/index.js`. `engines` stays Node 20 or newer. The `files` list ships the server, the charter, templates, guides, top-level docs, the changelog, the registry manifest, and `.env.example`. It does not ship tests, scripts, `docs/status/`, backups, or `.env`.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- A session that boots with no unhandled drops can edit or restore the board. The empty list was not saved, so the board guard treated it as a list that had failed to load. A list that really failed to load is still refused. Retired drops stay off that list.
|
|
31
|
+
- A module file is opened from `fileURLToPath` and `path.resolve`. On Windows, `new URL(...).pathname` is `/C:/...`, and resolving that against a `C:` working directory produced `C:\C:\...` and the open failed.
|
|
32
|
+
- `.env.example` no longer assigns `TRUST_PROXY`. The server trusts exactly one proxy hop (Railway's edge) and does not read that variable.
|
|
33
|
+
- The example environment that ships is the public one. It listens on `127.0.0.1`, registers the generic tags `laptop,phone,cli`, and leaves `EMET_OAUTH_PASSPHRASE` commented out, so HTTP authorization stays refused until someone sets a passphrase. The pack test fails if the packed example assigns a passphrase, binds `0.0.0.0`, or names this install's source tags.
|
|
34
|
+
|
|
35
|
+
## 0.2.3 - 2026-10-07
|
|
36
|
+
|
|
37
|
+
The security fixes from the October audit, recall that ranks by how well an entry matches and keeps ended entries visible, and public wording that matches the code. Read the 0.2.3 checklist in docs/DEPLOY.md before upgrading: every host tag must be listed in `EMET_SOURCE_TAGS`, a `cloud-scheduled-` tag is refused, and an HTTP client whose token has no source tag signs in again once.
|
|
38
|
+
|
|
39
|
+
### Security
|
|
40
|
+
|
|
41
|
+
- The client-metadata fetch connects to the public address it already checked. A second DNS answer cannot move that connection onto a private, loopback, link-local, or metadata address. A redirect is still refused.
|
|
42
|
+
- That address check uses the parsed bits of the address. The whole link-local range `fe80::/10` is refused, including `fe90::` and `febf::`. The same check refuses loopback, private, unique-local, unspecified, multicast, IPv4-mapped and IPv4-compatible addresses, NAT64 `64:ff9b::/96`, and carrier-grade NAT. An unreachable pinned address rejects the fetch and does not crash the process.
|
|
43
|
+
- Every HTTP response sends `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Referrer-Policy: no-referrer`, and HSTS. The consent page keeps its own content security policy.
|
|
44
|
+
- `save_transcript` no longer reads a file path. The caller passes the exchanges, each field is capped, and the whole request is capped. The server does not read the disk for a transcript.
|
|
45
|
+
- An invite code, an authorization code, and a refresh token can be spent once. A second redeem does not create a second person. Inside a short grace window a repeated refresh returns the replacement already issued; any other reuse revokes that whole sign-in.
|
|
46
|
+
- A board edit or restore runs only when the session has a verified drop list from `emet_session_open`. An append does not open that session. No write may shrink a document below half of its largest size in the last 24 hours. That window is a floor on cuts, not a fading of memory.
|
|
47
|
+
- A refusal does not publish the list of source tags, and a `cloud-scheduled-` prefix is not a registered tag. Over HTTP the source tag is the one bound at approval. Stdio stamps one local subject, and the 20-drop cap is one bucket for the whole local process.
|
|
48
|
+
- Setup, guest invites, and member codes are the owner's. A guest invite is read-only. Opening a session, and a status check that probes the write path, need write access. The probe removes its own document and leaves the collection. An HTTP token with no scopes is not the owner. The consent page shows the scopes it is granting.
|
|
49
|
+
- A governed write that names a session stops when the session record cannot be read. Nothing is written.
|
|
50
|
+
- The client-metadata fetch refuses loopback, private, link-local, and metadata addresses, and it is rate limited. Tool rate limits are per person and client. The HTTP body limit is 256kb, and the server trusts one proxy hop.
|
|
51
|
+
- The consent page sends a content security policy, denies framing, and sends HSTS. Error details are not attached on HTTP, including a rate-limit response. The audit log is redacted the same way as the console.
|
|
52
|
+
- A token issued before source tags were stored may still write when the caller names a tag that is an exact member of `EMET_SOURCE_TAGS`. Refreshing that token is refused (`invalid_grant`): the client signs in again, and the new consent binds a registered tag. Those logins age out on their own. An empty registry has no members, so that fallback does not accept an arbitrary tag.
|
|
53
|
+
- The local stdio client is the owner and can create guest and member codes. Over HTTP those codes still require an owner person. A member code can carry a registered source tag, set by the owner when the code is created and bound when the code is redeemed.
|
|
54
|
+
- A later verified `emet_session_open` clears `drops_unverified` when the drop load succeeds, including when open drops remain. Only a failed drop load sets the flag. An open drop still has to be retired before the board is edited.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- Session start lists the half-finished, dated, open, undecided, and parked rows it can read (`named_items`). A section that is not a table is marked unread, including prose such as "None". Unread is not an empty list: the session still reads the document. An empty list is not a reason to skip the document. Nothing is hidden, and nothing is dropped because it is old.
|
|
59
|
+
- The handoff refusal names `patch_doc` for the board. Restoring the board counts as the board step.
|
|
60
|
+
- Recall orders matches by how many of your words appear, then by importance. Current entries come first in every order, including time order. Pass `order: 'latest'` for time order. A standalone "latest", "newest", or "most recent", together with other words, reorders those matches and does not change which rows match. "latest-budget", "not the latest", and a bare "latest" are ordinary keywords.
|
|
61
|
+
- An entry that has expired or been superseded stays in recall and in layer queries. It is marked with the date it ended and, when a newer entry replaced it, which one. The current entry is listed first, including when you ask for the latest or sort by time. Pass `history: true` when you need the ended entries and the current ones already fill the limit.
|
|
62
|
+
- Revising an entry records the end date and the new entry's id on the old one. The old entry stays readable.
|
|
63
|
+
- Retired documents stay in the document list and in the startup scan, after the current ones, marked with the date they were retired and what replaced them. A retired drop is listed apart from the drops that still need a decision.
|
|
64
|
+
- A recall or a layer query ranks matching rows in the store before it keeps a bounded window (at least 200 rows, or 20 times the page). The rank is the same as the page: current entries first, then how many words match and importance, or time when you asked for the latest. A better match is not dropped for a lower importance or an older time. A blank sort value comes first when the order is ascending and last when it is descending. A word is matched as itself, so `$gt` is that text. Capital and lower case count as the same match, including `École` and `école`. `İ` matches only itself. Full-width letters fold only with their full-width counterparts. `ẞ` and `ß` fold together. The page keeps the store's hit count, so the two do not disagree. The sort may use disk so a layer of large entries can finish.
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
|
|
68
|
+
- The public wording now matches the code on who can join (one owner; Guest is read-only and Member is read and write; both stay off until turned on), on the drop-cap buckets, and on working documents (`retire_doc` refuses them; a rename marks the old id retired and the text stays). The charter states the monorail is enforce only, and that a templated write is checked, marked, and kept as the current revision.
|
|
69
|
+
|
|
70
|
+
### Internal
|
|
71
|
+
|
|
72
|
+
- Tests now pin the guards a mutation check left unasserted, and the MCP SDK and proxy-addr dependencies are updated.
|
|
73
|
+
- Session close prunes size baselines only for sessions closed or idle more than 7 days, and only those keys. A live session's baseline on a document is not touched.
|
|
74
|
+
- An HTTP caller with no OAuth client id is stored as http:visitor, never in a stdio bucket.
|
|
75
|
+
- The test suite sets the boot-list store timeout short so a missing store does not stall the run.
|
|
76
|
+
- The HTTP visitor check calls the HTTP tool path with no OAuth client id, and the baseline prune check leaves a document with only live or fresh baselines unwritten.
|
|
77
|
+
## 0.2.2 - 2026-10-04
|
|
78
|
+
|
|
79
|
+
The board is guarded, and the test store is shared.
|
|
80
|
+
|
|
81
|
+
- A session cannot wipe or overwrite the board. The server sets up a blank board, and a session can only edit it, with a reason. An added item says where it came from. A removed or closed item says why.
|
|
82
|
+
- No change may leave a document under half the size it had when this session first touched it. Overlapping edits and a walk-down across edits are refused. Working documents are edited, not retired.
|
|
83
|
+
- A board edit or restore is refused while a drop listed at that session's boot is still open. Drops are capped at 20 per caller per New York day. A drop with no source is stored as visitor.
|
|
84
|
+
- An owner-listed host can restore an earlier version of the board or a working document, with a reason, when the copy matches its stored hash. A record is not restored. A shipped copy is never restored.
|
|
85
|
+
- Every write records the person and the connected app, stamped by the server from the login, never taken from the caller.
|
|
86
|
+
- A read-only token can initialize and open a session. A missing board is provisioned only for a write-scoped caller, or at setup.
|
|
87
|
+
- The test suites share one in-memory store. No behavior change.
|
|
88
|
+
|
|
89
|
+
## 0.2.1 - 2026-10-03
|
|
90
|
+
|
|
91
|
+
Startup comes in pages that fit every host, every startup carries a `load_id`, long documents
|
|
92
|
+
are read in byte-sized pages, and the session-order check now refuses every skipped step, with
|
|
93
|
+
the way to pass in the same reply. After upgrading, each host reconnects once to see the new
|
|
94
|
+
arguments, then reads its startup again before opening a session.
|
|
95
|
+
|
|
96
|
+
There is no 0.2.0 release: 0.2.1 follows 0.1.0 directly, so this entry lists every change
|
|
97
|
+
since 0.1.0.
|
|
98
|
+
|
|
99
|
+
### Added
|
|
100
|
+
|
|
101
|
+
- **Startup in pages.** `emet_initialize` now sends the startup in pages of about 18 KB
|
|
102
|
+
each, so it fits hosts that cut long tool results short. The rules and instructions that
|
|
103
|
+
must always be followed come first. Page 1 lists what every page carries, and each page
|
|
104
|
+
names the exact call for the next one. Every page of one startup comes from the same
|
|
105
|
+
snapshot, even if new memories are written in between. If the startup changes partway
|
|
106
|
+
through, the server says so and you start again from page 1. `page: "all"` still returns
|
|
107
|
+
the whole startup in one result for hosts with no size limit, led by its `load_id`. The page size can be set
|
|
108
|
+
with `EMET_INIT_PAGE_BYTES` (12,000–19,000 bytes, default 18,000). Hosts may need to
|
|
109
|
+
reconnect once to see the new `page` and `load_id` arguments. A `page` that isn't a whole
|
|
110
|
+
number from 1, or `"all"`, is refused with a clear message.
|
|
111
|
+
- **Missing-page check when a session opens.** `emet_session_open` checks that every page
|
|
112
|
+
of your startup was fetched, named by the `load_id` from your startup pages. An open with
|
|
113
|
+
a page missing is refused (see Changed).
|
|
114
|
+
- `.env.example` now lists every setting the server reads. New entries include
|
|
115
|
+
`EMET_MEMBER_ACCESS`, the page-size settings, the document-name overrides,
|
|
116
|
+
`EMET_RECORD_DOCS`, `EMET_TEMPLATE_MAP`, `EMET_CIMD` and `EMET_REQUEST_LOG`.
|
|
117
|
+
- `CHANGELOG.md` (this file).
|
|
118
|
+
- **`read_doc` version pin.** Pass the `version` (or `sha256`) your first page returned as
|
|
119
|
+
`expected_version` (or `expected_sha256`) with each later page. If the document changed
|
|
120
|
+
in between, the read is refused with "document changed - restart from offset 0" and no
|
|
121
|
+
content, so pages of two versions are never joined. The pin is optional; without it a read
|
|
122
|
+
works as before. A shipped guide has no version, so pin it by `sha256`.
|
|
123
|
+
|
|
124
|
+
### Changed
|
|
125
|
+
|
|
126
|
+
- **The session-order check now refuses every skipped step.** It runs in enforce only: there
|
|
127
|
+
is no report mode and no off switch, and `EMET_SESSION_GRAPH` is no longer read (remove it
|
|
128
|
+
from the service's variables). A skipped step is refused before anything is written, and
|
|
129
|
+
the refusal is recorded in `emet_gaps`. Every refusal says how to pass in the same reply:
|
|
130
|
+
an open with no `load_id` is told to pass it from the startup pages; a missing startup page
|
|
131
|
+
is named with the exact `emet_initialize` call; a skipped exchange is named with the
|
|
132
|
+
`emet_transcript_append` call; a write with no session is told to open one with
|
|
133
|
+
`emet_session_open` and its `load_id`; a write to a closed session is told the work belongs
|
|
134
|
+
in the next session; an early handoff names each step and its tool. A session id the caller
|
|
135
|
+
sent is echoed at most 64 characters, so the instruction always fits. A transcript write
|
|
136
|
+
with a missing or unregistered `source` is told first to pass one, then which tags are
|
|
137
|
+
accepted: the first 8 registered tags, then "+N more", and the caller's tag capped at 64
|
|
138
|
+
characters, so the refusal stays under the cap with any number of registered tags. One exception stays: if
|
|
139
|
+
the check cannot read the records of the session a write names, the write goes ahead and is
|
|
140
|
+
recorded as `unknown`.
|
|
141
|
+
Writes that name no session (for example the scheduled weekly intake) are now refused
|
|
142
|
+
(gate `no_session`) until they open a session.
|
|
143
|
+
- The startup sends each memory layer's importance band once instead of twice, which saves
|
|
144
|
+
a little space at the start of every session.
|
|
145
|
+
- **`read_doc` pages are now measured in bytes, as the host receives them.** A long
|
|
146
|
+
document comes back in pages (was 40,000 characters). A page ends before its text, written
|
|
147
|
+
as JSON (where every newline, quote and backslash costs an extra byte), plus 1,500 bytes
|
|
148
|
+
kept for the rest of the result would pass the limit (default 18,000). So a page of
|
|
149
|
+
quote-heavy, code-like or short-line text holds less document text than a page of prose.
|
|
150
|
+
The 1,500 bytes is an allowance, not a measurement: a result whose other fields run longer
|
|
151
|
+
(for example a long list of conformance failures) can still pass 18,000 bytes, and a host
|
|
152
|
+
that cuts at about 20,000 bytes is not guaranteed the whole result in every case. A page
|
|
153
|
+
never splits a character. `offset`, `next_offset`, `returned` and `size` in the `page`
|
|
154
|
+
block are UTF-8 bytes; `returned_escaped` is the page's size as JSON, and `envelope_spare`
|
|
155
|
+
is the 1,500. Following `next_offset` still gives back the whole document exactly. The
|
|
156
|
+
result's whole-document `size` stays in characters; `size_unit` says so and `size_bytes`
|
|
157
|
+
gives the UTF-8 bytes. `EMET_READ_DOC_PAGE` sets the limit (default 18000).
|
|
158
|
+
- **Startup pages say to fetch them all before opening a session.** Page 1 and every page
|
|
159
|
+
that names a next call now say "Fetch all N pages before emet_session_open; an open with
|
|
160
|
+
any page not fetched is refused." The line replaces the older "keep calling until a page
|
|
161
|
+
says it is the last", and binding text stays where it was.
|
|
162
|
+
- **Missing startup pages go through the session-order check.** `emet_session_open` passes
|
|
163
|
+
a `startup_pages` gate: an open with a page of its startup never fetched is refused,
|
|
164
|
+
nothing is written, and the reply leads with the exact call for the first missing page and
|
|
165
|
+
names the missing pages once, as ranges (`2-40`), so it fits the 500-character error cap
|
|
166
|
+
however many pages are missing. A `load_id` the server has no record of (made up, expired
|
|
167
|
+
60 minutes after its last page, or from before a restart) is refused too, since its pages
|
|
168
|
+
cannot be checked: the reply says to call `emet_initialize {}`, fetch every page and open
|
|
169
|
+
with the `load_id` it returns. After a server restart each host does that once.
|
|
170
|
+
The record of fetched pages now keeps up to 2,000 loads for 60 minutes after each load's
|
|
171
|
+
last page (the page cache still keeps 32 payloads for 10 minutes), so many hosts starting at
|
|
172
|
+
once, or a host that opens a while after reading its startup, still open.
|
|
173
|
+
- **A session open must name its startup.** Pass the `load_id` from your startup pages
|
|
174
|
+
(`startup_page.load_id`; every page carries it and the last page names it) to
|
|
175
|
+
`emet_session_open`, so the page check runs on your own startup, never on another host's.
|
|
176
|
+
It stays optional in the tool schema, but an open without it is refused before anything is
|
|
177
|
+
written and told to pass it. The server no longer falls back to the latest startup it built.
|
|
178
|
+
- **Every startup carries a load_id, so every host can open a session.** A startup served
|
|
179
|
+
whole - `page: "all"`, a startup that fits one result, and a store that is not set up yet
|
|
180
|
+
(or cannot be reached, or is misconfigured) - now leads with `startup_page` (`index`, `of: 1`,
|
|
181
|
+
`load_id`, `next: null`) and a `page_notice` that says to pass that `load_id` to
|
|
182
|
+
`emet_session_open`. The load is recorded with every page fetched, so the open passes the
|
|
183
|
+
page check. The payload after those two fields is unchanged, byte for byte, and its `load_id`
|
|
184
|
+
is the same one its pages carry. The startup tests' byte-for-byte pins now compare the payload
|
|
185
|
+
after pinning the two leading fields exactly. On a new store the setup flow opens a session
|
|
186
|
+
with that `load_id`, appends, records the interview with `emet_setup_complete` (which never
|
|
187
|
+
needs a session) and closes as usual.
|
|
188
|
+
- When EMET Guest Access and EMET Member Access are both off, the refusal message now
|
|
189
|
+
names both and the setting that turns each one on.
|
|
190
|
+
- The README explains that Grok Bot teams and single-session Grok chats on the same server
|
|
191
|
+
share one memory: what the bots save is there for a fresh chat to find once it
|
|
192
|
+
initializes, and the reverse. A single-session chat uses that memory most reliably when the
|
|
193
|
+
instruction block from `docs/BOOTSTRAP.md` is in its project instructions, or, where there is
|
|
194
|
+
no such field, pasted as its first message.
|
|
195
|
+
- The server reports version 0.2.1.
|
|
196
|
+
- The README has a short "Best practices" section: split the work by what each host does
|
|
197
|
+
best, with a single-session chat for long one-sitting drafting and review and bots for the
|
|
198
|
+
rest. The one line you send the chat names the document that holds the task.
|
|
199
|
+
- The README says how to connect a single-session chat: add the server's `/mcp` URL as a
|
|
200
|
+
remote MCP connector on a host that supports its OAuth sign-in, sign in with the passphrase,
|
|
201
|
+
then put the `docs/BOOTSTRAP.md` block in the project instructions.
|
|
202
|
+
- The README's Best practices section adds eight short entries: fetch every startup page and
|
|
203
|
+
open with its `load_id`; set `EMET_SOURCE_TAGS` before a second writer; put the instruction
|
|
204
|
+
block in the project's instructions; standing approval for reads; reconnect after a tool-list
|
|
205
|
+
change; register a bot in one change; prove the write path with `probe: true`; keep house
|
|
206
|
+
style in the store.
|
|
207
|
+
- In the public release, the shipped `CHARTER.md` and nine base templates carry no internal
|
|
208
|
+
ids; the meaning is unchanged. An install whose stored charter is the public 0.1.0 text is
|
|
209
|
+
reported as differing from the shipped copy until it is rewritten with `write_doc`.
|
|
210
|
+
- **The startup and the docs say to open a session with the startup's `load_id`.** The
|
|
211
|
+
startup's short instructions read "After every startup page, call emet_session_open with
|
|
212
|
+
its load_id", and `tools_in_force` reads "emet_session_open with the startup's load_id, after
|
|
213
|
+
every startup page". On a live-sized store the five pages, as received, are 17,301, 17,864,
|
|
214
|
+
13,778, 14,033 and 5,560 bytes; every page stays within the 18,000-byte page budget, and a
|
|
215
|
+
test checks it. The bot session loop in `docs/BOTS.md` starts with `emet_initialize {}` and
|
|
216
|
+
every page it names (`{"page": "all"}` only on a host known to read long results whole) and
|
|
217
|
+
opens with that `load_id`; the README, the paste-in block in `docs/BOOTSTRAP.md` and the bot
|
|
218
|
+
handoff template say the same.
|
|
219
|
+
- `docs/DEPLOY.md`'s rollback note says what each `EMET_SESSION_GRAPH` value does on the
|
|
220
|
+
older build, and `docs/ROADMAP.md` records the enforce-only monorail and paged startup as
|
|
221
|
+
deployed.
|
|
222
|
+
|
|
223
|
+
### Fixed
|
|
224
|
+
|
|
225
|
+
- In `emet_gaps`, session-order results now show the source tag of memory saves and
|
|
226
|
+
revisions (they showed none before), and flagged document writes now name the document.
|
|
227
|
+
- The README and the permissions guide now give the correct tool count: 28 tools, 12 of
|
|
228
|
+
them read-only.
|
|
229
|
+
- The "Known gaps" entry about the scheduled weekly intake is rewritten in plain words and
|
|
230
|
+
matches how such writes are handled now.
|
|
231
|
+
- The upstream project EMET is built from can no longer be reached at its old address.
|
|
232
|
+
The credit is kept as it was, with a note that the link is unavailable.
|
|
233
|
+
- The README, the setup and guided-setup guides, the deploy guide and the message at the end
|
|
234
|
+
of setup no longer say to set a distinct `EMET_SOURCE_TAG` per host. On a server several
|
|
235
|
+
hosts share it stays unset: each host passes its own `source`, and `EMET_SOURCE_TAGS`
|
|
236
|
+
registers the tags, as `.env.example` already said. A default tag is only for a server one
|
|
237
|
+
host uses.
|
|
238
|
+
- `emet_session_close` takes `source`, and the close is never refused for it. The close is
|
|
239
|
+
attributed only to a registered tag that wrote the session (the `source` passed, else the
|
|
240
|
+
server's default tag); otherwise it warns and says why: no tag, a tag not registered in
|
|
241
|
+
`EMET_SOURCE_TAGS`, or a tag that did not write the session. The tag is echoed capped at
|
|
242
|
+
whole characters. It used to warn on every close on a server with no default tag, even when
|
|
243
|
+
the host passed a registered tag of its own.
|
|
244
|
+
- The bot handoff template's session loop now says to fetch every startup page, with
|
|
245
|
+
`{"page": "all"}` only on a host known to read long results whole, as `docs/BOTS.md` does.
|
|
246
|
+
- The setup interview's note for a store that is already initialized now says a second
|
|
247
|
+
`emet_setup_complete` is refused unless `reissue: true` is passed. It said a re-run would
|
|
248
|
+
create a new version.
|
|
249
|
+
|
|
250
|
+
### Security
|
|
251
|
+
|
|
252
|
+
- Updated three dependencies to patch releases that fix moderate advisories: `fast-uri`
|
|
253
|
+
3.1.8, `hono` 4.13.12 and `ip-address` 10.7.3. No direct dependency changed.
|
|
254
|
+
- New tests confirm that a code is refused before any lookup when both access doors are
|
|
255
|
+
off, that the owner's sign-in still refreshes, and that a database outage is reported
|
|
256
|
+
as a server error (500), not as a bad sign-in.
|
|
257
|
+
|
|
258
|
+
## 0.1.0 - 2026-10-02
|
|
259
|
+
|
|
260
|
+
The first public release.
|
|
261
|
+
|
|
262
|
+
### Added
|
|
263
|
+
|
|
264
|
+
- **A shared memory server for MCP.** One store in MongoDB (Atlas or self-hosted) that
|
|
265
|
+
several hosts can read and write: desktop and command-line apps, browser and phone
|
|
266
|
+
clients, and assistants from other vendors.
|
|
267
|
+
- **Six memory layers and a word-for-word transcript tier.** Curated memories and the
|
|
268
|
+
conversations behind them are kept apart, so neither can quietly overwrite the other.
|
|
269
|
+
- **Every write is checked.** Each write is read back and compared before it is reported
|
|
270
|
+
as saved. Each memory carries a content digest (and a signature, when a signing key is
|
|
271
|
+
set), and each layer forms a hash chain that `emet_gaps` can walk end to end.
|
|
272
|
+
- **Corrections without deletion.** Memories and transcripts are corrected by superseding
|
|
273
|
+
them, never by editing or deleting them. Documents can be changed, but every earlier
|
|
274
|
+
version is kept in their history, and they are retired rather than deleted.
|
|
275
|
+
- **A versioned document store** with templates, a conformance check and a full revision
|
|
276
|
+
history.
|
|
277
|
+
- **Session start and close.** One call to `emet_initialize` gives the assistant everything
|
|
278
|
+
it needs at the start; `emet_session_open` starts the transcript. Closing a session
|
|
279
|
+
requires receipts for each record it was supposed to update.
|
|
280
|
+
- **A session-order check** that watches the order of a session's writes. It ships in
|
|
281
|
+
report mode: it flags what it would refuse and blocks nothing.
|
|
282
|
+
- **Local or remote.** The same code runs as a local stdio server or as a remote HTTP
|
|
283
|
+
server with OAuth sign-in, protected by a passphrase you choose.
|
|
284
|
+
- **Two optional access doors, both off by default.** EMET Guest Access gives a second
|
|
285
|
+
person read access; EMET Member Access gives a new person read and write access, never
|
|
286
|
+
the owner's identity. Each person's sign-in only refreshes while its own door is on.
|
|
287
|
+
- **Source tags.** Every write records which host made it. Registering the allowed tags
|
|
288
|
+
with `EMET_SOURCE_TAGS` turns on the guards against unknown or mistyped tags.
|
|
289
|
+
- **Least-privilege database access.** A script and guide for a database role that can add
|
|
290
|
+
and update records but never delete them.
|
|
291
|
+
- **Secrets masked before storage.** Common secrets such as API keys, tokens and
|
|
292
|
+
passwords in connection strings are masked in content before it is saved.
|
|
293
|
+
- **Clear sign-in errors.** An expired, revoked, replaced or unknown sign-in is answered as
|
|
294
|
+
a sign-in problem (401 or 400) that tells the app to sign in again, not as a server error.
|
|
295
|
+
- 28 tools, 12 of them read-only, each labelled with standard MCP hints so a host can tell
|
|
296
|
+
reads from writes (and, if it chooses, skip approval for reads).
|
package/CHARTER.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# EMET ARCHITECTURE CHARTER
|
|
2
|
+
|
|
3
|
+
**Record control:** id `CHARTER.md` · revision: the store's version governs · status: IN FORCE · approved: user · 2026-09-11 · a decision record · revised with the user's approval 2026-09-15 (the consolidated revision, a decision record) · revised at the user's word 2026-09-23 (parked items named at startup; §3 commitment 8, §6 item 3; a decision record) · revised with the user's approval 2026-09-27 (pending lessons named at startup; blocked-close cap and scope at close; §6 items 3 and close; a recorded lesson) · revised with the user's approval 2026-09-29 (the aleph named as the integrity verifier; Guardrails & Monorails, with switches; the database boundary; the per-exchange transcript; the user as final authority; §1, §3 commitments 1, 2 and 9, §4, §6, §8, §10; a decision record) · revised with the user's approval 2026-09-30 (the admission test: four questions before anything is built, DMADV while in design, DMAIC once stable; §3 commitment 6; a decision record) · Tier 1 · owner: the user · decision record: the owner's
|
|
4
|
+
**Written:** 2026-09-10, session `2026-09-10_morning-mobile-init`, source `mobile`
|
|
5
|
+
⚠ **Public document once the repository is public.** The disclosure line (a decision record) must be drawn before publication. This document states structure and intent only — no implementation specifics.
|
|
6
|
+
⚠ **§1 is in the user's words (2026-09-11); attorney review pending** (claim language is on that agenda).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## §1 PURPOSE AND INTENDED USE — the user's words, 2026-09-11 (procedural entry of that date) · attorney review pending
|
|
11
|
+
|
|
12
|
+
**EMET is a persistent contextual memory MCP server that gives an AI assistant a consistent, user-tailored identity, with the option of plug-in customization of interaction style and function.** It gives the assistant a durable, verifiable record that survives across sessions, devices and host applications — who the assistant is, who it serves, what has happened, what has been decided, and where the work stands — so each session continues from the last instead of starting over.
|
|
13
|
+
|
|
14
|
+
**It is designed with the understanding that it may be used in support of processes and environments operating under ISO quality-management standards such as ISO 9001 and ISO 13485.** Its records are attributable, versioned, never deleted and integrity-checked, and its documents are controlled: every templated write is checked against the template in force, a write that fails that check is marked and kept as the current revision, and a later revision or an acceptance clears the mark. EMET itself holds no certification and claims no conformity. An organization that uses it within its quality management system remains responsible for that system, including validating EMET for its intended use there (ISO 13485 §4.1.6).
|
|
15
|
+
|
|
16
|
+
**A record that is never deleted or edited must also be accurate** (the user, 2026-09-29: *"It is integral for the ISO data that is never deleted or edited to be accurate"*). Permanence without accuracy only preserves an error. So every write is verified as recorded accurately before it is confirmed, and every later read is checked against what was recorded — the aleph (§4).
|
|
17
|
+
|
|
18
|
+
**The same expectation governs how EMET is built.** Its code — JavaScript on Node.js today, and any language it is implemented in later — and its development processes are held to it: every change is version-controlled, tested by an automated suite, released deliberately, and verified live with a real call before it is called done, and the history of what changed is kept. That evidence is what an organization's own validation can draw on.
|
|
19
|
+
|
|
20
|
+
**It is designed first for neurodivergent users** (ADHD, autism, AuDHD), for whom lost context and re-explaining carry a higher cost. It works for anyone.
|
|
21
|
+
|
|
22
|
+
**Intended user:** one user working with an AI assistant through hosts that support the Model Context Protocol.
|
|
23
|
+
|
|
24
|
+
**Not intended:** EMET is not a medical device. It does not diagnose, treat or monitor any condition and is not a substitute for clinical care. It does not control what an assistant says; it records what is written to it.
|
|
25
|
+
|
|
26
|
+
## §2 SCOPE
|
|
27
|
+
|
|
28
|
+
**In scope:** the record — memory layers, verbatim transcripts, controlled documents, the rules for writing, reading and correcting them, and the standing definition of the assistant.
|
|
29
|
+
**Out of scope:** the model's behaviour, the host application, and the conversation itself. **EMET sees what is written to it, not what is said.** No control in EMET can stop an assistant telling a user something false; what EMET can do is make the record honest, attributable and checkable.
|
|
30
|
+
|
|
31
|
+
## §3 DESIGN COMMITMENTS
|
|
32
|
+
|
|
33
|
+
1. **Verification over assertion.** Every write is read back by the aleph and verified before a receipt is returned, and every later read is checked against what was recorded. A claim of completion needs evidence.
|
|
34
|
+
2. **Nothing is deleted.** Entries are superseded, documents are revised or retired, events are never rewritten. Prior versions are retained. **This holds below the server too:** the database login EMET runs under has no permission to remove the record, so a fault in the server cannot delete it either.
|
|
35
|
+
3. **Provenance is part of the memory.** Every write names the host that produced it, and assertions point to their source.
|
|
36
|
+
4. **State a rule once.** Rules held in code are pointed to, never copied into documents.
|
|
37
|
+
5. **Controls, not reminders.** Where a rule matters, a mechanism enforces it; an instruction to be careful is not a control.
|
|
38
|
+
6. **Over-engineering is a defect — the check comes before the build.** Anything may be considered; nothing is built until it answers four questions. **What failure does it fix, and where is it in the record?** An observed failure, not an anticipated one. **What does it replace or retire?** An addition that replaces nothing clears a higher bar. **How will we know it worked?** One measure, checked in a pilot. **What holds it once it works?** A control, not a reminder (commitment 5). What cannot answer all four stays a seed. Additions are gated before they ship, not trimmed after (the user, 2026-09-30: *"I dont want us to become an oreborous eating its tail with proposed additions to then reduce afterwards"*). **The method follows the product's stage** (the user, 2026-09-30: *"The variant works for now, dmaic for once stable"*): while EMET is still being designed, work runs DMADV — Define, Measure, Analyze, Design, Verify. Once it is stable, work runs DMAIC — Define, Measure, Analyze, Improve, Control.
|
|
39
|
+
7. **No implied conformity.** EMET puts recognised quality-management practice into operation. It claims no certification.
|
|
40
|
+
8. **Out of sight is out of mind.** For users with time blindness or object impermanence, an item not named does not exist. At every session start the server lists the half-finished, dated, open, undecided, and parked rows it can read (`named_items` on `emet_initialize`), and the session says those names. A section that is not a table is marked unread, and an empty list is not a reason to skip the document. A count is the assistant's check, never a substitute for the names. **Parked items are named too, in a list of their own** — what the user deliberately set aside drops out of mind as fast as what they forgot, so parked means out of the way, never out of sight; each is named with what brings it back, and nothing is asked of it (the user, 2026-09-23: *"for ND it's out of sight out of mind"*). Naming the user's own items is external working memory, not unrequested instruction. This commitment is part of the floor.
|
|
41
|
+
9. **Guardrails & Monorails.** Judgment and process are kept apart (the user, 2026-09-29). **Guardrails** — the floor, the character, the served instructions — bound a field in which the assistant uses its judgment freely. **The monorail** — the session's order of work — carries it from one field to the next on a track the server checks, which it cannot leave. Where the flow must fork, a **switch** at the junction routes it to the guardrail space that fits: a small logic unit in EMET, tripped only by its condition, like a transistor, with no hosted model and no outside service (the user, 2026-09-29). The track throws the switch; the assistant does not choose whether to follow the protocol or which branch to take. Each switch is designed for its junction, from the function it serves and the flow of information and tasking through it. This is commitment 5 applied to the order of a session.
|
|
42
|
+
|
|
43
|
+
## §4 ARCHITECTURE — components and their roles
|
|
44
|
+
|
|
45
|
+
| Component | Role | Where its rules live |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| **The floor** | How the assistant engages the user, regardless of configuration. Cannot be edited by setup or by the user. The guardrails' base. | Server code |
|
|
48
|
+
| **Bootstrap documents** | The assistant's standing definition: identity, character, the user, available tools. Without them the assistant is a hollow golem — it functions, but only as a transcriber. | Document store, built at the first-run interview |
|
|
49
|
+
| **SHEM** | The name the user inscribes — who the assistant is, held in the identity document. In the golem lore the inscription and the Name are separate: EMET is the truth written on the substance; the SHEM is what animates it. EMET supplies the substance and the record; the user supplies the SHEM. Its spoken form is the user's identity phrase (§6). | Identity document, written at the first-run interview |
|
|
50
|
+
| **Tier 1 — memory layers** | Curated meaning, in six layers: identity, semantic, episodic, procedural, meta, working. Queried first. | Layer charter, server code |
|
|
51
|
+
| **Tier 2 — verbatim transcripts** | The word-for-word record of each session, appended one exchange at a time as the session runs. **Independent of Tier 1 by design** — the independence is what makes it a second line of inquiry. Tier 1 entries point into it by session and span; timestamp is the fallback bridge. | Server code |
|
|
52
|
+
| **Document store** | Controlled documents: the board, handoffs, threads, seeds, working papers, bootstrap, this charter. Versioned; every prior revision archived. | Template standard (`templates/STANDARD.md`) |
|
|
53
|
+
| **The write path** | The single entry for every write. Masks secrets, attributes the source, marks what the writer left out, digests content and metadata, and hands the write to the aleph before returning a receipt. Refuses a semantic or procedural entry with no source (2026-09-29): a durable claim must point to where it was said. Validates every templated document against the template in force and marks nonconformance for audit and review (live 2026-09-11). | Server code |
|
|
54
|
+
| **The aleph** | **Verifies memory integrity.** At the write: that it was recorded accurately — every write is read back and compared before any receipt, and a store that does not hold what was sent is reported as that, never as an ordinary failure. At every later read: that it is still what was recorded — each entry's digests, signature and place in its layer's hash chain are checked, and the whole chain can be walked by any host. Named for the first letter of *emet*: erase it and *met*, dead, remains — a memory that answers without verification. | Server code |
|
|
55
|
+
| **The monorail (session graph)** | Checks the order of each session's writes on every host, with no host hook: a session is opened before it is written to, no exchange is skipped, the handoff comes last, nothing is written after a complete close. Each write is told the next stop. Where a flow forks, a switch owned by the track, never the assistant, picks the branch to a guardrail space (designed 2026-09-29; not yet built). Every check is stored with its time as a lab result. Enforce only since 2026-10-03: a skipped step is refused, and there is no report mode or off switch. | Server code |
|
|
56
|
+
| **The database boundary** | The login EMET runs under may add and update, never remove the record (2026-09-29). Commitment 2 is enforced by the database as well as by the server. | Database role, defined once in server code |
|
|
57
|
+
| **The read path** | Returns entries with their integrity status, verified by the aleph. A superseded entry surfaces marked, naming what replaced it and the date it ended (decided 2026-09-13); a lookup by any id in a supersession chain also returns the live end of the chain, so a cross-reference keeps resolving after every later revision (2026-09-15). An expired entry surfaces the same way, marked with its end date. Current entries come first in every order, including time order. Retired documents stay in the document list and the startup scan, after the current documents, marked with the date and what replaced them. Recall ranks by relevance and importance. Time order is `order: 'latest'`, or a standalone latest, newest, or most recent together with other words. Retained document revisions are readable in full. | Server code |
|
|
58
|
+
| **Supplementary corpus** | Optional reference material loaded by the user, separate from memory. | Server code |
|
|
59
|
+
| **Extension socket** | **Planned, not built.** Where a GEM (Guided Engagement Module) seats; a RUNE (Registered Utility Node Extension) is a tool etched into a GEM. All GEMs are built to a standard. **Precedence (decided 2026-09-11):** a GEM the user adds takes precedence over the floor's modifiable defaults — voice, pace, how much is explained — and any conflict is resolved with the user when the GEM is added. **No GEM reaches the floor's protections:** it may add depth that complements them, never remove or weaken them. No GEM, whatever its authorship or intent, may compromise the user — and that is enforced by the socket, not left to a GEM author's good faith (commitment 5). | To be written |
|
|
60
|
+
|
|
61
|
+
## §5 HIERARCHY
|
|
62
|
+
|
|
63
|
+
**Document hierarchy — four tiers.** Register: `templates/INDEX.md`.
|
|
64
|
+
1. **Charter** — this document.
|
|
65
|
+
2. **Procedures** — how a session runs; the floor and layer charter in code.
|
|
66
|
+
3. **Work instructions and reference** — how to do a specific thing.
|
|
67
|
+
4. **Forms and records** — templates, and the documents filled from them.
|
|
68
|
+
|
|
69
|
+
**Order of authority when sources disagree:**
|
|
70
|
+
1. **The user's current word** — on everything the floor leaves to the user.
|
|
71
|
+
2. **The floor** — on what is owed to the user regardless of configuration.
|
|
72
|
+
3. **The current controlled document** (board, thread) — on where things stand.
|
|
73
|
+
4. **Tier 1 entries** — on what happened and what it meant.
|
|
74
|
+
5. **Tier 2 transcripts** — on exactly what was said.
|
|
75
|
+
A disagreement between sources is recorded, not silently resolved.
|
|
76
|
+
|
|
77
|
+
## §6 FLOW
|
|
78
|
+
|
|
79
|
+
**Session start — reads:** initialize → open the session → read the board and the handoff → scan seed triggers.
|
|
80
|
+
**Session start — what the user sees, in this order:**
|
|
81
|
+
1. **EMET's line:** *"Truth stands. Memory connected."* — or, if the server did not answer, *"MET — the aleph is missing. Memory not connected."* (EMET's line claims truth and connection, never life; the user's name does the animating.)
|
|
82
|
+
2. **The user's identity phrase**, if one is set — the SHEM spoken, confirming the assistant's identity loaded.
|
|
83
|
+
3. **The named items** — every half-state row, every dated item in the next seven days, every open item the user owns with its next action, and anything left undecided last session; drawn from the board, the user's calendar and any active schedule. **Then, under its own heading, every parked item** — one line each with what brings it back; named, never pressed (commitment 8). **Then, under its own heading, every pending lesson** — a correction the record holds three or more times with no disposition; one line each, named, never pressed. A lesson is settled by a check in code, a rule landed in a controlled document, or a written ruling that it cannot be checked; the server computes the list (`lessons_pending`, 2026-09-27) so the next conversion of advice into a control (commitment 5) is a standing decision, not a count.
|
|
84
|
+
4. **The board's counts as the check, never in place of the names.**
|
|
85
|
+
5. **What is actually available in this session**, confirmed before any capability is claimed.
|
|
86
|
+
6. Then any question. **Never open with a question alone.**
|
|
87
|
+
**During work:** append each exchange to the transcript after every reply, as it happens · every write names its session and exchange, and is told the next stop · search the record before answering anything with prior context · write decisions when they are made, with the user's words · write with provenance · verify each write by its receipt.
|
|
88
|
+
**Session close — this is the one place the order is stated:** update working documents → session record in memory → board → verbatim transcript, confirmed complete (it was appended as the session ran) → **handoff last, in one write** → confirm every artifact landed. The handoff is last because its close verification attests to the other artifacts; written earlier, it attests to things that do not yet exist and needs a patch afterwards. If a session ends mid-close, the prior handoff stands and the board and session record already carry the session. **A close that fails its check is returned with a scope per missing item — what may be touched to clear it and nothing else — and the third blocked close on one session escalates: the assistant stops, hands the user the list, and waits for their word. The counter resets only with a new session (rule in code, 2026-09-27).** **The server checks this order on every write (the monorail, §4):** a skipped step is refused. Enforce only since 2026-10-03; there is no report mode.
|
|
89
|
+
**Correction:** a layer entry is superseded by a revision that stands alone · a document is revised or retired · an event is never rewritten; a later entry corrects the reading of it.
|
|
90
|
+
|
|
91
|
+
## §7 DOCUMENT CONTROL
|
|
92
|
+
|
|
93
|
+
Governed by `templates/STANDARD.md`. Base templates must be followed and may be expanded, never loosened. Every templated write is validated; a nonconforming write is **marked for audit and review**, never silently accepted and never discarded.
|
|
94
|
+
|
|
95
|
+
## §8 ROLES
|
|
96
|
+
|
|
97
|
+
- **User** — owns the intended use, makes decisions, sets standards for how the assistant works. **The final authority** (the user, 2026-09-29: *"AI assistants are subordinate to the user. While it is a collaborative relationship without a sycophantic role by the AI, the user is the final authority"*).
|
|
98
|
+
- **Assistant** — executes, verifies, records. Recommends and disagrees plainly; never records its recommendation as the user's decision.
|
|
99
|
+
- **Host** — the application running the assistant. Every host writes under its own source tag.
|
|
100
|
+
- **EMET** — the record, and the enforcement of whatever code can enforce.
|
|
101
|
+
|
|
102
|
+
## §9 CHANGE CONTROL
|
|
103
|
+
|
|
104
|
+
This charter changes by revision, with the user's approval. Rules held in code change by release: committed, deployed, and verified live with a real call — **a pushed fix is not a live fix.**
|
|
105
|
+
|
|
106
|
+
**This charter is locked the same way as the base templates** (`templates/STANDARD.md` §9a, L1 — decided 2026-09-11). It ships with the release and the server reads it from there; any copy in an install's store is for reading, not authority, and a store copy that differs from the shipped copy is marked nonconforming. `emet_initialize` points to it in every state, **including a new store before the first-run interview**, so the floor, this charter and the startup instructions are present before any SHEM is placed.
|
|
107
|
+
|
|
108
|
+
## §10 LIMITS, STATED PLAINLY
|
|
109
|
+
|
|
110
|
+
- Retrieval is not guaranteed complete, and an assistant's behaviour is not reproducible run to run. **EMET's record is deterministic and verifiable even where the assistant is not** — that is the claim, and its limit.
|
|
111
|
+
- EMET is derived from the CASCADE memory server (MIT licence); attribution is maintained in the repository.
|
|
112
|
+
|
|
113
|
+
**Where an AI assistant can be controlled at all, and which of those places EMET is** (the user's assessment, 2026-09-14; placed here at his direction 2026-09-15 so the charter is one complete record). Three places:
|
|
114
|
+
|
|
115
|
+
1. *Training.* The model's maker sets what the model tends to do. Out of reach of any user, host or server.
|
|
116
|
+
2. *The host.* The application running the assistant. Some hosts expose deterministic hooks — before a tool call, after an output — that can block an action regardless of what the model intended. Where a host offers them, that is real enforcement, and it belongs to the host. Many chat hosts expose none. **EMET depends on none of them** (the user, 2026-09-29): it must run the same for any assistant, on any device, with no model- or host-specific tool.
|
|
117
|
+
3. *EMET — the write boundary.* EMET sees exactly one thing: the calls the assistant makes to EMET's own tools. It never sees the user's message and never sees the assistant's reply (§2). **Within that boundary it checks each call and, since 2026-09-29, the order of the calls** (the monorail) — so a skipped exchange or an early handoff is caught on every host, without a hook. This does not widen what EMET sees.
|
|
118
|
+
|
|
119
|
+
**Why "delivered at session start" is not "enforced".** The floor and the character document reach the assistant through `emet_initialize` and are then context — text the model reads before generating. Instructions in context shape a probabilistic generation; there is no point in the process where a rule is checked and passed or failed. An assistant that drifts from the floor has not weighed it and decided to step over it; it has generated a reply in which the floor did not carry enough weight. This decides which fixes work: restating a rule more forcefully adds no check, and a reminder is not a control (commitment 5). **Drift is not a decision to violate.**
|
|
120
|
+
|
|
121
|
+
**What EMET enforces** is everything that passes through the write path, deterministically (§4): the receipt, and the aleph's verification behind it that the record holds exactly what was written; the source tag, the provenance pointer and origin on assertions; template validation on documents; supersession in place of deletion, held by the database as well as the server; masking of secrets; and the order of a session's writes. The forms of drift that reach the record are therefore caught at the door — a task row opened without the user's words behind it, an assistant's reading written into the field that holds the user's quote, an assertion with no origin, a turn left out of the transcript.
|
|
122
|
+
|
|
123
|
+
**What EMET does not enforce.** It cannot stop an assistant saying something unfounded to the user; nothing at the memory layer can. It cannot stop an assistant proposing work the user did not ask for, unless the proposal is written to the record, where it can be marked. It cannot verify that a stored assertion is true, only that it is attributed and sourced, and that the record holds it exactly as it was written. It filters writes, not responses.
|
|
124
|
+
|
|
125
|
+
**What this means for a user.** The controls that catch conversational drift are the user's own questions, a host's hooks where they exist, and — for a high-stakes session — a second assistant asked to check the first. EMET's contribution is that when drift happens, the next session can see it, attribute it and correct the record without erasing the evidence. That is the whole of its jurisdiction, and it is the part that survives a change of model, host or vendor.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 C.I.P.S. LLC
|
|
4
|
+
Copyright (c) 2026 Dreamforge Studio LLC
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|