@rubytech/create-maxy-code 0.1.61 → 0.1.63
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/dist/__tests__/installer-specialist-registration.test.js +112 -0
- package/dist/index.js +22 -0
- package/dist/specialist-registration.js +78 -0
- package/package.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +22 -0
- package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +50 -13
- package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +22 -21
- package/payload/platform/plugins/contacts/PLUGIN.md +9 -0
- package/payload/platform/plugins/docs/references/admin-session.md +55 -7
- package/payload/platform/plugins/email/PLUGIN.md +9 -0
- package/payload/platform/plugins/epc/PLUGIN.md +5 -0
- package/payload/platform/plugins/loop/PLUGIN.md +27 -0
- package/payload/platform/plugins/memory/PLUGIN.md +37 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/live-schema-source.test.js +137 -75
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/live-schema-source.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.d.ts +0 -17
- package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.js +32 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.d.ts +65 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +182 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js +8 -8
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js +241 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +9 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.js +9 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js +10 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.js +5 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.js +5 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-edit-attachment.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-edit-attachment.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-edit-attachment.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-web.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-web.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-web.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-rename-attachment.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-rename-attachment.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-rename-attachment.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +6 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +4 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +10 -3
- package/payload/platform/plugins/outlook/PLUGIN.md +7 -0
- package/payload/platform/plugins/preval/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/preval/PLUGIN.md +22 -12
- package/payload/platform/plugins/preval/hooks/preval-prompt-required.sh +140 -0
- package/payload/platform/plugins/preval/skills/property-preval/SKILL.md +77 -19
- package/payload/platform/plugins/preval/skills/property-preval/references/__tests__/adherence.test.py +373 -0
- package/payload/platform/plugins/preval/skills/property-preval/references/render.py +390 -47
- package/payload/platform/plugins/preval/skills/property-preval/references/template-inputs.schema.json +32 -21
- package/payload/platform/plugins/preval/skills/property-preval/references/template.html +0 -1
- package/payload/platform/plugins/property-data/PLUGIN.md +22 -0
- package/payload/platform/plugins/replicate/PLUGIN.md +3 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +8 -0
- package/payload/platform/plugins/tasks/PLUGIN.md +14 -0
- package/payload/platform/plugins/telegram/PLUGIN.md +3 -0
- package/payload/platform/plugins/waitlist/PLUGIN.md +7 -0
- package/payload/platform/plugins/whatsapp/PLUGIN.md +12 -0
- package/payload/platform/plugins/workflows/PLUGIN.md +8 -0
- package/payload/platform/services/claude-session-manager/dist/index.js +39 -1
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +21 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +148 -41
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts +23 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-drift.js +141 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-drift.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +13 -2
- package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js +135 -37
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -1
- package/payload/premium-plugins/real-agent/agents/compliance.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/epc/PLUGIN.md +5 -0
- package/payload/premium-plugins/real-agent/plugins/loop/PLUGIN.md +27 -0
- package/payload/premium-plugins/real-agent/plugins/preval/.claude-plugin/plugin.json +1 -1
- package/payload/premium-plugins/real-agent/plugins/preval/PLUGIN.md +22 -12
- package/payload/premium-plugins/real-agent/plugins/preval/hooks/preval-prompt-required.sh +140 -0
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/SKILL.md +77 -19
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/references/__tests__/adherence.test.py +373 -0
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/references/render.py +390 -47
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/references/template-inputs.schema.json +32 -21
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/references/template.html +0 -1
- package/payload/premium-plugins/real-agent/plugins/property-data/PLUGIN.md +22 -0
- package/payload/server/public/assets/{admin-DhN3G8W7.js → admin-ymReS1mN.js} +1 -1
- package/payload/server/public/assets/{data-B2ZVXOcE.js → data-D6U2e85B.js} +1 -1
- package/payload/server/public/assets/{graph-BAMGPHrK.js → graph-C274PN27.js} +1 -1
- package/payload/server/public/assets/{graph-labels-D9eBbvxo.js → graph-labels-DQFzd1FY.js} +1 -1
- package/payload/server/public/assets/{page-DjdVMWCz.js → page-D-OLjort.js} +1 -1
- package/payload/server/public/assets/{page-CV27Al6Z.js → page-DFFt9_Q0.js} +1 -1
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/graph.html +3 -3
- package/payload/server/public/index.html +4 -4
- package/payload/server/server.js +1 -1
|
@@ -85,25 +85,41 @@ The Hono route `POST /api/admin/claude-sessions` at [`platform/ui/server/routes/
|
|
|
85
85
|
|
|
86
86
|
**Callers.** `Sidebar.tsx`'s "+ New session" click handler (sends no `initialMessage` — Task 146 made Claude Code's own label canonical, so no UI-side stimulus is injected); the turn-recorder hook (loopback path — see "Turn-recorder" below); future programmatic spawns. Every caller routes through this wrapper. The on-the-wire signal that the contract held is the `[claude-session-manager:wrapper] spawn-request-in surface=<cookie|loopback>` log line followed by `forward-spawn-done`.
|
|
87
87
|
|
|
88
|
-
## Turn-recorder: a
|
|
88
|
+
## Turn-recorder: a first-class specialist spawn with three body overrides
|
|
89
89
|
|
|
90
|
-
After every completed operator admin turn, the Stop hook `platform/plugins/admin/hooks/turn-completed-graph-write.sh` dispatches one headless `database-operator` session that writes any new or missing information from the turn into the Neo4j graph.
|
|
90
|
+
After every completed operator admin turn, the Stop hook `platform/plugins/admin/hooks/turn-completed-graph-write.sh` dispatches one headless `database-operator` session that writes any new or missing information from the turn into the Neo4j graph. The recorder spawn is structurally a Sidebar "New session" body with three overrides — and the manager treats it as a first-class specialist spawn: the agent file is the prompt, the agent frontmatter is the tool surface, the per-spawn mcp.json is narrowed to the plugins the agent names.
|
|
91
91
|
|
|
92
|
+
Body overrides relative to a plain Sidebar click:
|
|
92
93
|
- `specialist: 'database-operator'`
|
|
93
94
|
- `model: 'haiku'`
|
|
94
|
-
- `initialMessage: "update the graph with any new or missing information or intent\n\n<
|
|
95
|
-
|
|
96
|
-
There is no recorder-only carving on the manager side: no preflight, no tool-surface gate, no `originatingSessionId` discriminator, no `MAXY_IS_RECORDER` env stamp, no recorder-only log surfaces. The PTY's own first-use error is the contract for tool absence.
|
|
95
|
+
- `initialMessage: "update the graph with any new or missing information or intent\n\n<conversation-text>"`
|
|
97
96
|
|
|
98
97
|
**Spawn body.** The hook POSTs `{adminSessionId, channel: 'browser', specialist: 'database-operator', model: 'haiku', initialMessage}` to `POST /api/admin/claude-sessions`. `adminSessionId` is the loopback-bypass key — the wrapper resolves the operator's real `senderId` from `GET <managerBase>/<adminSessionId>/meta` and forwards a Sidebar-shape body to the manager.
|
|
99
98
|
|
|
100
|
-
**`<
|
|
99
|
+
**`<conversation-text>`** is the operator JSONL walked in transcript order: every `user`/`assistant` record with non-empty text emitted as `"<type>: <text>"`, joined by `\n`. The full exchange is preserved so the recorder can infer operator-asserted facts that span multiple turns (e.g. "hello / what's your business? / Smalleys"). The earlier "last-turn-only" extractor stripped the framing the recorder needed. If no qualifying record exists, the hook emits `trigger-skipped reason=conversation-empty` and no recorder is spawned.
|
|
100
|
+
|
|
101
|
+
**Manager-side specialist branches.** The recorder is the first specialist subagent that exercises the full specialist flag matrix:
|
|
102
|
+
- The bundled `platform/templates/specialists/agents/database-operator.md` template is symlinked into `$CLAUDE_CONFIG_DIR/agents/database-operator.md` by the installer; without that link `claude --agent database-operator` silently falls back to the admin agent.
|
|
103
|
+
- `--append-system-prompt` is omitted entirely — the agent file IS the prompt; admin IDENTITY / SOUL / aboutOwner do NOT layer on top.
|
|
104
|
+
- `--allowed-tools` is sourced from the agent's frontmatter `tools:` list (11 entries for the recorder), not the admin surface.
|
|
105
|
+
- The per-spawn `mcp.json` is narrowed to only `memory`, `contacts`, `tasks` — the plugins whose tools the agent's frontmatter names.
|
|
101
106
|
|
|
102
107
|
**End-of-turn auto-archive.** When any session whose specialist is `database-operator` gains an assistant message with `stop_reason: "end_turn"` in its JSONL, the manager posts `/<sid>/stop` against itself, claude exits, the fs-watcher observes the PID-file removal and drops the row from the index. The auto-archive log line is `auto-archive sessionId=<sid> specialist=database-operator reason=end-turn …`.
|
|
103
108
|
|
|
104
109
|
**Hook recursion gate.** `pty-spawner` stamps `MAXY_SPECIALIST=<specialist>` on every PTY env. The Stop hook short-circuits when `MAXY_SPECIALIST=database-operator` so the recorder's own end-of-turn does not re-fire the hook.
|
|
105
110
|
|
|
106
|
-
**Observability.** The hook emits exactly two lines per operator turn via `/api/admin/log-ingest`: `[turn-recorder] trigger sessionId=<op> turnIndex=0 transcriptBytes=<n>
|
|
111
|
+
**Observability.** The hook emits exactly two lines per operator turn via `/api/admin/log-ingest`: `[turn-recorder] trigger sessionId=<op> turnIndex=0 transcriptBytes=<n> conversationBytes=<n>` and `[turn-recorder] spawn-request sessionId=<op> specialist=database-operator initialMessageBytes=<n>`. The manager adds `pty-spawn-allowlist specialist=database-operator count=11 sourced-from=agent-frontmatter` and `pty-spawn-start … specialist=database-operator append-system-prompt-bytes=0` before the PTY launches. The remainder of the recorder lifecycle is covered by the Sidebar's existing lines (`pty-spawned`, JSONL events, `auto-archive`). Failure-mode names: `trigger-skipped reason=…` enumerates `role-not-admin | is-recorder | empty-stdin | missing-transcript | conversation-empty`. Hook-side spawn errors emit `[turn-recorder] spawn-failed reason=loopback-http http=<code>`.
|
|
112
|
+
|
|
113
|
+
### Recorder lifecycle diagnostic
|
|
114
|
+
|
|
115
|
+
When the operator reports "the recorder did nothing this turn", run these six greps in order. The first absent line names the phase that failed. `<op>` is the admin operator's session id from the original Stop hook; `<rec>` is the recorder session id returned in phase 2's response and reused across phases 3–6.
|
|
116
|
+
|
|
117
|
+
1. **Stop hook fired.** `grep '\[turn-recorder\] trigger sessionId=<op>' ~/.<brand>/logs/server.log` — expects one line of shape `[turn-recorder] trigger sessionId=<op> turnIndex=0 transcriptBytes=<n> conversationBytes=<n>`. Absent: the Stop hook didn't run; check that `MAXY_SESSION_ROLE=admin` was set on the operator PTY and that `MAXY_SPECIALIST!=database-operator` (recursion gate).
|
|
118
|
+
2. **/spawn accepted.** `grep '\[turn-recorder\] spawn-request sessionId=<op>' ~/.<brand>/logs/server.log` — expects `[turn-recorder] spawn-request sessionId=<op> specialist=database-operator initialMessageBytes=<n>`. The response body of this POST carries `<rec>`. Absent: the hook fired but `/api/admin/claude-sessions` rejected; look for `[turn-recorder] spawn-failed reason=loopback-http http=<code>` on the next line.
|
|
119
|
+
3. **PTY started.** `grep 'pty-spawn-start .* specialist=database-operator' ~/.<brand>/logs/server.log` — expects `pty-spawn-start claudeBin=<…> argv-count=<n> append-system-prompt-bytes=0 … specialist=database-operator prompt-positional=yes prompt-bytes=<n>`. Absent: the wrapper accepted but the manager rejected before exec; check the spawn-failure surfaces (`which-claude-not-found | pty-spawn-failed | pid-file-timeout | host-context-unresolved | identity-unresolved | mcp-config-write-failed`).
|
|
120
|
+
4. **Agent file resolved.** `grep 'pty-spawn-allowlist specialist=database-operator count=11 sourced-from=agent-frontmatter' ~/.<brand>/logs/server.log` — expects exactly one line per recorder spawn. Absent (or `count` not equal to the frontmatter's tool count): the agent file at `$CLAUDE_CONFIG_DIR/agents/database-operator.md` is missing the `tools:` line, or the symlink the installer creates never landed. Re-run the installer.
|
|
121
|
+
5. **Graph write outcome.** `grep '\[mcp:memory\] memory-write .* session=<rec>' ~/.<brand>/logs/server.log` — expects one line ending `result=ok elementId=<id>` or `result=error reason=<slug>` (slug enumerated by the memory MCP write-path observability work). Absent: the recorder loaded but produced no tool calls — model-side decision, not infra. Read the recorder JSONL at `<accountDir>/.claude/projects/<slug>/<rec>.jsonl` to see what the LLM did.
|
|
122
|
+
6. **Auto-archive.** `grep 'auto-archive .* sessionId=<rec> .* specialist=database-operator reason=end-turn' ~/.<brand>/logs/server.log` — expects one line. Absent: the recorder finished but the manager's end-turn watcher didn't fire; the fs-watcher row will get reaped on its TTL but the recorder hung longer than expected. Investigate `pty-spawn-stop` and `pid-file-removed` lines on the same `<rec>`.
|
|
107
123
|
|
|
108
124
|
## Session identifiers (Task 135)
|
|
109
125
|
|
|
@@ -114,6 +130,38 @@ The metadata pane surfaces two distinct identifier values. Task 141 collapsed th
|
|
|
114
130
|
| `sessionId` | Claude's session. Two phases: bridge suffix (`session_xxx`, the URL segment in `claude.ai/code/<session_xxx>`, set when claude prints the `/remote-control` URL) and JSONL basename UUID (claude's intrinsic id on disk, bound when the first turn flushes the JSONL). Both phases coexist on a live row after URL capture; the manager wire emits the bridge form when set, falling back to the JSONL basename in the pre-URL-capture window. The resolver routes either phase to the same row, so callers never need to choose. | `sessionId` (collapsed from the earlier three-field surface (see Task 141) `sessionId` + `claudeSessionId` + `bridgeSessionId`) | `sessionId=` |
|
|
115
131
|
| `accountId` | Account / workspace UUID. For the admin channel, the value the manager carries as `senderId` IS the accountId; for non-admin channels the same wire field carries a phone / email / chat-id (the channel-level sender), so its log key on those paths is still `senderId=`. | `senderId` (channel-agnostic) | `accountId=` in admin-flow emit sites; `senderId=` in channel-bridge sites |
|
|
116
132
|
|
|
133
|
+
## Memory MCP write-path outcome lines (Task 166)
|
|
134
|
+
|
|
135
|
+
Every write-path tool in the memory plugin MCP emits one structured line per invocation to `server.log` via the loopback `/api/admin/log-ingest` route. The operator can answer "did this write succeed?" from a single greppable surface — no need to cross-reference the per-process `mcp-memory-stderr-<date>.log`.
|
|
136
|
+
|
|
137
|
+
Line shapes:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
[mcp:memory] <tool-name> account=<id|—> session=<convId|—> labels=<csv|—> name=<value|—> result=ok elementId=<id|—> ms=<n>
|
|
141
|
+
[mcp:memory] <tool-name> account=<id|—> session=<convId|—> labels=<csv|—> name=<value|—> result=error reason=<slug> detail=<≤120 chars> ms=<n>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Enumerated `reason` slugs (failure path): `invalid-input | schema-unknown-label | schema-property-naming | account-isolation | producedby-task-not-found | constraint-violation | conflicting-element-id | invalid-target-node-id | gate-blocked | neo4j-driver-error`. Free-form error text remains in the `detail` field. New slugs are added only by amending the helper's union type; nothing silently falls through to a generic `unknown`.
|
|
145
|
+
|
|
146
|
+
Wired tools: `memory-write`, `memory-update`, `memory-delete`, `memory-restore`, `memory-empty-trash`, `memory-archive-write`, `memory-ingest`, `memory-ingest-extract`, `memory-ingest-web`, `memory-classify`, `memory-reindex`, `memory-edit-attachment`, `memory-rename-attachment`, `profile-update`, `profile-delete`, `graph-prune-denylist-add`, `graph-prune-denylist-remove`, `conversation-archive-derive-insights`, `conversation-archive-enrich-rejection`, `conversation-memory-expunge`. Read-path tools (`memory-search`, `memory-rank`, etc.) are intentionally out of scope — reads do not change state and their failures already reach the caller.
|
|
147
|
+
|
|
148
|
+
Diagnostic grep:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Did the most recent memory-write attempt land, and what was it?
|
|
152
|
+
grep '\[mcp:memory\] memory-write .* result=' ~/.${brand}/logs/server.log | tail
|
|
153
|
+
|
|
154
|
+
# All failed writes across every memory MCP tool, grouped by reason:
|
|
155
|
+
grep '\[mcp:memory\] .* result=error' ~/.${brand}/logs/server.log | awk -F'reason=' '{print $2}' | awk '{print $1}' | sort | uniq -c | sort -rn
|
|
156
|
+
|
|
157
|
+
# Did the loopback POST itself fail? (Helper falls back to stderr and re-writes
|
|
158
|
+
# the structured line, so the event is never lost — this just flags that the
|
|
159
|
+
# session-manager's /api/admin/log-ingest was unreachable for some window.)
|
|
160
|
+
grep '\[mcp:memory\] log-ingest-failed' ~/.${brand}/logs/mcp-memory-stderr-*.log
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The existing `mcp-memory-stderr-<date>.log` capture is unchanged on error paths — the new structured line is additive, not a relocation. Crash-mode debugging continues to read the stderr log; routine "did it land?" questions read `server.log`.
|
|
164
|
+
|
|
117
165
|
## Out of scope
|
|
118
166
|
|
|
119
167
|
- Public/WhatsApp/Telegram sessions — out of scope. Their sessionKeys remain `crypto.randomUUID()` and follow the existing rejection-on-restart contract.
|
|
@@ -4,22 +4,31 @@ description: "Email — dedicated email account. Retrieval: email-graph-query fo
|
|
|
4
4
|
tools:
|
|
5
5
|
- name: email-setup
|
|
6
6
|
publicAllowlist: false
|
|
7
|
+
adminAllowlist: false
|
|
7
8
|
- name: email-read
|
|
8
9
|
publicAllowlist: false
|
|
10
|
+
adminAllowlist: false
|
|
9
11
|
- name: email-send
|
|
10
12
|
publicAllowlist: false
|
|
13
|
+
adminAllowlist: false
|
|
11
14
|
- name: email-reply
|
|
12
15
|
publicAllowlist: false
|
|
16
|
+
adminAllowlist: false
|
|
13
17
|
- name: email-search
|
|
14
18
|
publicAllowlist: false
|
|
19
|
+
adminAllowlist: false
|
|
15
20
|
- name: email-graph-query
|
|
16
21
|
publicAllowlist: false
|
|
22
|
+
adminAllowlist: false
|
|
17
23
|
- name: email-otp-extract
|
|
18
24
|
publicAllowlist: false
|
|
25
|
+
adminAllowlist: false
|
|
19
26
|
- name: email-status
|
|
20
27
|
publicAllowlist: false
|
|
28
|
+
adminAllowlist: false
|
|
21
29
|
- name: email-auto-respond-config
|
|
22
30
|
publicAllowlist: false
|
|
31
|
+
adminAllowlist: false
|
|
23
32
|
always: false
|
|
24
33
|
embed: ["admin"]
|
|
25
34
|
metadata: {"platform":{}}
|
|
@@ -4,14 +4,19 @@ description: "gov.uk EPC register — by-address and by-UPRN lookup of the most
|
|
|
4
4
|
tools:
|
|
5
5
|
- name: epc-key-register
|
|
6
6
|
publicAllowlist: false
|
|
7
|
+
adminAllowlist: false
|
|
7
8
|
- name: epc-key-deregister
|
|
8
9
|
publicAllowlist: false
|
|
10
|
+
adminAllowlist: false
|
|
9
11
|
- name: epc-key-list
|
|
10
12
|
publicAllowlist: false
|
|
13
|
+
adminAllowlist: false
|
|
11
14
|
- name: epc-lookup-by-address
|
|
12
15
|
publicAllowlist: false
|
|
16
|
+
adminAllowlist: false
|
|
13
17
|
- name: epc-lookup-by-uprn
|
|
14
18
|
publicAllowlist: false
|
|
19
|
+
adminAllowlist: false
|
|
15
20
|
always: false
|
|
16
21
|
metadata: {"platform":{"optional":true,"embed":["admin"]}}
|
|
17
22
|
mcp:
|
|
@@ -4,58 +4,85 @@ description: "Loop CRM integration — full read/write access to all 8 resource
|
|
|
4
4
|
tools:
|
|
5
5
|
- name: loop-key-register
|
|
6
6
|
publicAllowlist: false
|
|
7
|
+
adminAllowlist: false
|
|
7
8
|
- name: loop-key-deregister
|
|
8
9
|
publicAllowlist: false
|
|
10
|
+
adminAllowlist: false
|
|
9
11
|
- name: loop-key-list
|
|
10
12
|
publicAllowlist: false
|
|
13
|
+
adminAllowlist: false
|
|
11
14
|
- name: loop-people-search
|
|
12
15
|
publicAllowlist: false
|
|
16
|
+
adminAllowlist: false
|
|
13
17
|
- name: loop-people-detail
|
|
14
18
|
publicAllowlist: false
|
|
19
|
+
adminAllowlist: false
|
|
15
20
|
- name: loop-property-search
|
|
16
21
|
publicAllowlist: false
|
|
22
|
+
adminAllowlist: false
|
|
17
23
|
- name: loop-property-detail
|
|
18
24
|
publicAllowlist: false
|
|
25
|
+
adminAllowlist: false
|
|
19
26
|
- name: loop-property-listed
|
|
20
27
|
publicAllowlist: false
|
|
28
|
+
adminAllowlist: false
|
|
21
29
|
- name: loop-property-sold
|
|
22
30
|
publicAllowlist: false
|
|
31
|
+
adminAllowlist: false
|
|
23
32
|
- name: loop-property-viewing
|
|
24
33
|
publicAllowlist: false
|
|
34
|
+
adminAllowlist: false
|
|
25
35
|
- name: loop-property-callback
|
|
26
36
|
publicAllowlist: false
|
|
37
|
+
adminAllowlist: false
|
|
27
38
|
- name: loop-property-information
|
|
28
39
|
publicAllowlist: false
|
|
40
|
+
adminAllowlist: false
|
|
29
41
|
- name: loop-viewing-search
|
|
30
42
|
publicAllowlist: false
|
|
43
|
+
adminAllowlist: false
|
|
31
44
|
- name: loop-viewing-detail
|
|
32
45
|
publicAllowlist: false
|
|
46
|
+
adminAllowlist: false
|
|
33
47
|
- name: loop-viewing-create
|
|
34
48
|
publicAllowlist: false
|
|
49
|
+
adminAllowlist: false
|
|
35
50
|
- name: loop-viewing-update
|
|
36
51
|
publicAllowlist: false
|
|
52
|
+
adminAllowlist: false
|
|
37
53
|
- name: loop-feedback-get
|
|
38
54
|
publicAllowlist: false
|
|
55
|
+
adminAllowlist: false
|
|
39
56
|
- name: loop-feedback-submit
|
|
40
57
|
publicAllowlist: false
|
|
58
|
+
adminAllowlist: false
|
|
41
59
|
- name: loop-team-info
|
|
42
60
|
publicAllowlist: false
|
|
61
|
+
adminAllowlist: false
|
|
43
62
|
- name: loop-team-availability
|
|
44
63
|
publicAllowlist: false
|
|
64
|
+
adminAllowlist: false
|
|
45
65
|
- name: loop-marketing-match
|
|
46
66
|
publicAllowlist: false
|
|
67
|
+
adminAllowlist: false
|
|
47
68
|
- name: loop-marketing-match-batch
|
|
48
69
|
publicAllowlist: false
|
|
70
|
+
adminAllowlist: false
|
|
49
71
|
- name: loop-marketing-match-request
|
|
50
72
|
publicAllowlist: false
|
|
73
|
+
adminAllowlist: false
|
|
51
74
|
- name: loop-marketing-enquiry
|
|
52
75
|
publicAllowlist: false
|
|
76
|
+
adminAllowlist: false
|
|
53
77
|
- name: loop-auto-responder
|
|
54
78
|
publicAllowlist: false
|
|
79
|
+
adminAllowlist: false
|
|
55
80
|
- name: loop-customer-preferences
|
|
56
81
|
publicAllowlist: false
|
|
82
|
+
adminAllowlist: false
|
|
57
83
|
- name: loop-supplier
|
|
58
84
|
publicAllowlist: false
|
|
85
|
+
adminAllowlist: false
|
|
59
86
|
skills:
|
|
60
87
|
- skills/tone-matched-drafter/SKILL.md
|
|
61
88
|
- skills/priority-ranker/SKILL.md
|
|
@@ -4,62 +4,91 @@ description: "Graph memory plugin. Provides memory-search (with optional `fields
|
|
|
4
4
|
tools:
|
|
5
5
|
- name: memory-search
|
|
6
6
|
publicAllowlist: false
|
|
7
|
+
adminAllowlist: true
|
|
7
8
|
- name: memory-rank
|
|
8
9
|
publicAllowlist: false
|
|
10
|
+
adminAllowlist: false
|
|
9
11
|
- name: memory-write
|
|
10
12
|
publicAllowlist: false
|
|
13
|
+
adminAllowlist: false
|
|
11
14
|
- name: memory-update
|
|
12
15
|
publicAllowlist: false
|
|
16
|
+
adminAllowlist: false
|
|
13
17
|
- name: memory-reindex
|
|
14
18
|
publicAllowlist: false
|
|
19
|
+
adminAllowlist: false
|
|
15
20
|
- name: memory-ingest
|
|
16
21
|
publicAllowlist: false
|
|
22
|
+
adminAllowlist: false
|
|
17
23
|
- name: memory-ingest-extract
|
|
18
24
|
publicAllowlist: false
|
|
25
|
+
adminAllowlist: false
|
|
19
26
|
- name: memory-ingest-web
|
|
20
27
|
publicAllowlist: false
|
|
28
|
+
adminAllowlist: false
|
|
21
29
|
- name: memory-classify
|
|
22
30
|
publicAllowlist: false
|
|
31
|
+
adminAllowlist: false
|
|
23
32
|
- name: memory-find-candidates
|
|
24
33
|
publicAllowlist: false
|
|
34
|
+
adminAllowlist: true
|
|
25
35
|
- name: memory-delete
|
|
26
36
|
publicAllowlist: false
|
|
37
|
+
adminAllowlist: true
|
|
27
38
|
- name: memory-restore
|
|
28
39
|
publicAllowlist: false
|
|
40
|
+
adminAllowlist: true
|
|
29
41
|
- name: memory-empty-trash
|
|
30
42
|
publicAllowlist: false
|
|
43
|
+
adminAllowlist: true
|
|
31
44
|
- name: memory-list-attachments
|
|
32
45
|
publicAllowlist: false
|
|
46
|
+
adminAllowlist: true
|
|
33
47
|
- name: memory-read-attachment
|
|
34
48
|
publicAllowlist: false
|
|
49
|
+
adminAllowlist: true
|
|
35
50
|
- name: memory-edit-attachment
|
|
36
51
|
publicAllowlist: false
|
|
52
|
+
adminAllowlist: true
|
|
37
53
|
- name: memory-rename-attachment
|
|
38
54
|
publicAllowlist: false
|
|
55
|
+
adminAllowlist: true
|
|
39
56
|
- name: memory-archive-write
|
|
40
57
|
publicAllowlist: false
|
|
58
|
+
adminAllowlist: false
|
|
41
59
|
- name: conversation-archive-derive-insights
|
|
42
60
|
publicAllowlist: false
|
|
61
|
+
adminAllowlist: false
|
|
43
62
|
- name: conversation-archive-enrich-rejection
|
|
44
63
|
publicAllowlist: false
|
|
64
|
+
adminAllowlist: false
|
|
45
65
|
- name: conversation-list
|
|
46
66
|
publicAllowlist: false
|
|
67
|
+
adminAllowlist: true
|
|
47
68
|
- name: conversation-search
|
|
48
69
|
publicAllowlist: false
|
|
70
|
+
adminAllowlist: true
|
|
49
71
|
- name: profile-read
|
|
50
72
|
publicAllowlist: false
|
|
73
|
+
adminAllowlist: false
|
|
51
74
|
- name: profile-update
|
|
52
75
|
publicAllowlist: false
|
|
76
|
+
adminAllowlist: false
|
|
53
77
|
- name: profile-delete
|
|
54
78
|
publicAllowlist: false
|
|
79
|
+
adminAllowlist: true
|
|
55
80
|
- name: graph-prune-denylist-add
|
|
56
81
|
publicAllowlist: false
|
|
82
|
+
adminAllowlist: true
|
|
57
83
|
- name: graph-prune-denylist-list
|
|
58
84
|
publicAllowlist: false
|
|
85
|
+
adminAllowlist: true
|
|
59
86
|
- name: graph-prune-denylist-remove
|
|
60
87
|
publicAllowlist: false
|
|
88
|
+
adminAllowlist: true
|
|
61
89
|
- name: conversation-memory-expunge
|
|
62
90
|
publicAllowlist: false
|
|
91
|
+
adminAllowlist: true
|
|
63
92
|
hidden:
|
|
64
93
|
- session-compact
|
|
65
94
|
- session-compact-status
|
|
@@ -158,6 +187,14 @@ Before any structured write, load `references/schema-base.md` via `plugin-read`.
|
|
|
158
187
|
|
|
159
188
|
**Forbidden properties.** A "Forbidden Properties" table in any schema markdown file declares per-label deny-listed property keys. The validator rejects writes that include a forbidden key for the matching primary label and emits `[schema-validator] outcome=rejected label=<X> property=<Y> reason=forbidden writer=<agentName>`. The first row is `Person | name` — use `givenName` + `familyName` (rendered display name composed at read time). The check fires after the synonym pass, so `firstName → givenName` rewrites still happen first.
|
|
160
189
|
|
|
190
|
+
**Drift log shape.** On every schema-cache refresh the validator compares `db.labels()` (live) against `schema.cypher` declarations and the schema markdown's documented labels, and emits one summary line per non-empty drift kind:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
[schema-validator] drift kind=<kind> count=<n> tokens=<csv up to 10>[+<remainder>]
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`<kind>` is one of `declared-not-live`, `live-not-declared`, `markdown-orphan`. Tokens are alphabetically sorted; if more than 10 drift in a kind the line names the first 10 and appends `+<remainder>` (e.g. `count=38 tokens=Applicant,…,Engagement+28`). Empty kinds emit nothing — a clean schema produces no drift lines per refresh. Set `MEMORY_MCP_VERBOSE_DRIFT=1` on the manager unit to keep the historical per-token lines underneath each summary; default off because drift sets of 50+ tokens otherwise bury real signals (write errors, validator rejections) in `mcp-memory-stderr-<date>.log`.
|
|
197
|
+
|
|
161
198
|
## Document Ingestion
|
|
162
199
|
|
|
163
200
|
Document ingestion of any kind — PDFs, text, transcripts, web pages, single files — routes to the `specialists:database-operator` specialist, which loads the universal `document-ingest` skill at `skills/document-ingest/SKILL.md`. The admin agent never calls `memory-ingest` directly; it dispatches with the document path, the document subject (the anchor node), and the visibility scope.
|
|
@@ -524,7 +524,7 @@ server.tool("conversation-archive-enrich-rejection", "Record or undo a per-row r
|
|
|
524
524
|
.describe("record = append rejection; undo = remove rejection (called after `wire`)."),
|
|
525
525
|
}, async ({ archiveElementId, chunkElementId, kind, contentHash, mode }) => {
|
|
526
526
|
try {
|
|
527
|
-
const result = conversationArchiveEnrichRejection({
|
|
527
|
+
const result = await conversationArchiveEnrichRejection({
|
|
528
528
|
accountId,
|
|
529
529
|
archiveElementId,
|
|
530
530
|
chunkElementId,
|
|
@@ -1631,7 +1631,7 @@ if (!readOnly) {
|
|
|
1631
1631
|
values: z.array(z.string().min(1)).min(1).describe("Substring values to add. Match is exact substring (case-sensitive) against string-typed properties only."),
|
|
1632
1632
|
}, async ({ values }) => {
|
|
1633
1633
|
try {
|
|
1634
|
-
const result = graphPruneDenylistAdd(values);
|
|
1634
|
+
const result = await graphPruneDenylistAdd(values);
|
|
1635
1635
|
const lines = [
|
|
1636
1636
|
`Added ${result.added.length} entries to deny-list (total ${result.totalAfter}).`,
|
|
1637
1637
|
];
|
|
@@ -1655,7 +1655,7 @@ if (!readOnly) {
|
|
|
1655
1655
|
values: z.array(z.string().min(1)).min(1).describe("Substring values to remove (must match exactly as previously added)."),
|
|
1656
1656
|
}, async ({ values }) => {
|
|
1657
1657
|
try {
|
|
1658
|
-
const result = graphPruneDenylistRemove(values);
|
|
1658
|
+
const result = await graphPruneDenylistRemove(values);
|
|
1659
1659
|
const lines = [
|
|
1660
1660
|
`Removed ${result.removed.length} entries from deny-list (total ${result.totalAfter}).`,
|
|
1661
1661
|
];
|