@rubytech/create-maxy-code 0.1.151 → 0.1.152

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
  3. package/payload/platform/lib/graph-search/dist/index.js +10 -9
  4. package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
  5. package/payload/platform/lib/graph-search/src/index.ts +10 -9
  6. package/payload/platform/package.json +2 -2
  7. package/payload/platform/plugins/admin/PLUGIN.md +1 -1
  8. package/payload/platform/plugins/admin/hooks/__tests__/pre-turn-graph-pass.test.sh +26 -129
  9. package/payload/platform/plugins/admin/hooks/pre-turn-graph-pass.sh +64 -131
  10. package/payload/platform/plugins/docs/PLUGIN.md +1 -1
  11. package/payload/platform/plugins/docs/references/admin-session.md +2 -2
  12. package/payload/platform/plugins/docs/references/internals.md +1 -64
  13. package/payload/platform/plugins/docs/references/platform.md +1 -1
  14. package/payload/platform/plugins/docs/references/plugins-guide.md +2 -2
  15. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts +1 -1
  16. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts.map +1 -1
  17. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +25 -45
  18. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -1
  19. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  20. package/payload/platform/plugins/memory/PLUGIN.md +8 -16
  21. package/payload/platform/plugins/memory/bin/conversation-archive-ingest.mjs +14 -11
  22. package/payload/platform/plugins/memory/mcp/dist/index.js +13 -269
  23. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  24. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.d.ts +1 -24
  25. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.d.ts.map +1 -1
  26. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.js +8 -211
  27. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.js.map +1 -1
  28. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts +99 -0
  29. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts.map +1 -0
  30. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.js +56 -0
  31. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.js.map +1 -0
  32. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +12 -32
  33. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -1
  34. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js +19 -281
  35. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js.map +1 -1
  36. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +0 -3
  37. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
  39. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +15 -14
  40. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
  41. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +1 -1
  42. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  43. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +1 -1
  44. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  45. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +1 -76
  46. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
  47. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +73 -329
  48. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
  49. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  50. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +10 -12
  51. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  52. package/payload/platform/plugins/memory/mcp/vitest.config.ts +4 -3
  53. package/payload/platform/plugins/memory/references/graph-primitives.md +2 -2
  54. package/payload/platform/plugins/memory/references/schema-base.md +2 -7
  55. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +71 -46
  56. package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +2 -2
  57. package/payload/platform/scripts/seed-neo4j.sh +0 -49
  58. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  59. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +3 -2
  60. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  61. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
  62. package/payload/platform/templates/specialists/agents/citation-auditor.md +37 -0
  63. package/payload/platform/templates/specialists/agents/compiled-truth-rewriter.md +42 -0
  64. package/payload/platform/templates/specialists/agents/database-operator.md +2 -30
  65. package/payload/platform/templates/specialists/agents/research-assistant.md +2 -2
  66. package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +37 -0
  67. package/payload/server/{adminuser-self-heal-YC47O34W.js → adminuser-self-heal-WSFCOEII.js} +1 -1
  68. package/payload/server/{chunk-T3DJD5QR.js → chunk-AXOL2PPG.js} +1 -1
  69. package/payload/server/{chunk-HYQNUVGO.js → chunk-PFF6I7KP.js} +1 -8
  70. package/payload/server/maxy-edge.js +2 -2
  71. package/payload/server/public/assets/{admin-CnLGltuE.js → admin-kh_oCHeS.js} +54 -54
  72. package/payload/server/public/assets/{data-MB2EWZUP.js → data-BHASh0_Y.js} +1 -1
  73. package/payload/server/public/assets/{graph-B2FnDRz-.js → graph-BhEI09tF.js} +1 -1
  74. package/payload/server/public/assets/graph-labels-DXlmm1og.js +1 -0
  75. package/payload/server/public/assets/{page-BJKRa6Db.js → page-CDWu1Aft.js} +3 -3
  76. package/payload/server/public/assets/{page-Bx2p3W1k.js → page-cyvshX4Z.js} +1 -1
  77. package/payload/server/public/data.html +3 -3
  78. package/payload/server/public/graph.html +3 -3
  79. package/payload/server/public/index.html +4 -4
  80. package/payload/server/server.js +319 -1286
  81. package/payload/platform/lib/graph-search/src/__tests__/query-expansion.test.ts +0 -96
  82. package/payload/platform/lib/graph-search/src/query-expansion.ts +0 -129
  83. package/payload/platform/lib/oauth-llm/src/index.ts +0 -583
  84. package/payload/platform/lib/oauth-llm/tsconfig.json +0 -8
  85. package/payload/platform/lib/screening-patterns/src/index.ts +0 -51
  86. package/payload/platform/lib/screening-patterns/tsconfig.json +0 -8
  87. package/payload/server/public/assets/graph-labels-DDYqDlu3.js +0 -1
@@ -1,11 +1,24 @@
1
1
  #!/usr/bin/env bash
2
- # UserPromptSubmit hook — pre-turn graph pass. Task 425.
2
+ # UserPromptSubmit hook — pre-turn graph pass. Tasks 425, 430.
3
3
  #
4
- # Fires once per operator prompt submission. Dispatches the
5
- # `database-operator` specialist with the full conversation (as
6
- # `[role: text]` pairs) plus the actual content of every node already
7
- # written under this `conversationId`. The specialist decides what new
8
- # graph rows the conversation supports and writes them.
4
+ # Fires once per admin-agent operator prompt submission. Emits a
5
+ # directive into the admin agent's `additionalContext` that instructs
6
+ # **admin** to scan the just-submitted operator turn for new candidate
7
+ # graph rows (mentions, ideas, commitments, contacts, learnings any
8
+ # label the schema admits), then dispatch one `database-operator` Task
9
+ # per candidate write. Admin is the session-walker; the specialist only
10
+ # sees a narrowly-scoped per-write brief, never the conversation.
11
+ #
12
+ # Task 430 corrects the Task 425 orchestration shape. The Task 425 hook
13
+ # packaged the full conversation blob into the specialist's prompt; that
14
+ # collapsed the data channel and the instruction channel into one
15
+ # context, so operator prose pattern-matching as a writer-binding
16
+ # instruction ("memory-update is denied this session") was treated as
17
+ # binding and the pass self-denied. Same failure class as the writer-POV
18
+ # schema doctrine read as binding the agent (Task 199 / 995). The
19
+ # session-end retrospective never had this defect because admin walked
20
+ # the transcript itself and dispatched per-item briefs to the
21
+ # specialist — Task 430 brings the per-turn pass to the same shape.
9
22
  #
10
23
  # Supersedes Task 412's Stop-hook registration. The Stop hook fired on
11
24
  # every assistant `end_turn`, including the agent's own ack after the
@@ -16,19 +29,19 @@
16
29
  # `session-end-retrospective.sh` Stop hook walks the full transcript at
17
30
  # `/end` and picks up the final assistant reply.
18
31
  #
19
- # The two doctrinal early exits remain:
32
+ # The doctrinal early exits remain:
20
33
  # - MAXY_SESSION_ROLE must equal "admin" → reason=role-not-admin
21
34
  # - MAXY_SPECIALIST must be empty → reason=is-specialist
22
- # `missing-transcript` is retained as a safety exit. `empty-stdin` is
23
- # dropped UserPromptSubmit always carries a JSON envelope.
35
+ # `missing-transcript` is retained as a safety exit (the prior-writes
36
+ # context fetch still needs a real session). `wrong-hook-event` rejects
37
+ # stale Stop-shaped fires.
24
38
  #
25
39
  # Input: Claude Code's UserPromptSubmit hook stdin shape
26
40
  # { "session_id": "<intrinsic>", "transcript_path": "<jsonl path>",
27
41
  # "cwd": "<…>", "hook_event_name": "UserPromptSubmit",
28
42
  # "prompt": "<operator text>" }
29
- # `prompt` is ignored — the conversation walk reads the JSONL, which
30
- # already contains the just-submitted user message because
31
- # UserPromptSubmit fires after the prompt is written.
43
+ # `prompt` is ignored — the directive instructs admin to read the turn
44
+ # it already has in context.
32
45
  #
33
46
  # Output: stdout JSON of the documented UserPromptSubmit shape:
34
47
  # { "hookSpecificOutput": { "hookEventName": "UserPromptSubmit",
@@ -36,8 +49,8 @@
36
49
  # exit 0. The directive carries the literal token
37
50
  # `[system: pre-turn-graph-pass-hook]` so the agent's IDENTITY.md
38
51
  # UserPromptSubmit-directive section can distinguish it from operator
39
- # text. The agent performs the named Task dispatch as a background pass
40
- # and then continues with its normal response to the operator.
52
+ # text. The agent performs the per-write dispatches as a background
53
+ # pass and then continues with its normal response to the operator.
41
54
 
42
55
  set -uo pipefail
43
56
 
@@ -103,96 +116,12 @@ fi
103
116
 
104
117
  CONVERSATION_ID="${CONVERSATION_NODE_ID:-}"
105
118
 
106
- # Walk the transcript and emit the conversation as `[role: text]` pairs,
107
- # oldest first. User turns whose only content is `tool_result` blocks are
108
- # skipped (they carry tool plumbing, not operator intent). Multi-block
109
- # assistant turns concatenate their `text` blocks; `tool_use` blocks are
110
- # dropped. The just-submitted operator prompt is already present in the
111
- # JSONL by the time UserPromptSubmit fires.
112
- CONVERSATION=$(TRANSCRIPT_PATH="$TRANSCRIPT_PATH" python3 - <<'PY'
113
- import os, json, sys
114
-
115
- def assistant_text(rec):
116
- msg = rec.get("message", {}) or {}
117
- if msg.get("role") != "assistant":
118
- return ""
119
- content = msg.get("content")
120
- if isinstance(content, str):
121
- return content
122
- if isinstance(content, list):
123
- parts = []
124
- for b in content:
125
- if isinstance(b, dict) and b.get("type") == "text":
126
- t = b.get("text")
127
- if isinstance(t, str):
128
- parts.append(t)
129
- return "".join(parts)
130
- return ""
131
-
132
- def user_text(rec):
133
- msg = rec.get("message", {}) or {}
134
- if msg.get("role") != "user":
135
- return None
136
- content = msg.get("content")
137
- if isinstance(content, str):
138
- return content
139
- if isinstance(content, list):
140
- parts = []
141
- saw_non_tool_result = False
142
- for b in content:
143
- if not isinstance(b, dict):
144
- continue
145
- btype = b.get("type")
146
- if btype == "tool_result":
147
- continue
148
- saw_non_tool_result = True
149
- if btype == "text":
150
- t = b.get("text")
151
- if isinstance(t, str):
152
- parts.append(t)
153
- if not saw_non_tool_result:
154
- return None
155
- return "".join(parts)
156
- return None
157
-
158
- path = os.environ["TRANSCRIPT_PATH"]
159
- out_lines = []
160
- try:
161
- with open(path, "r", encoding="utf-8") as f:
162
- for raw in f:
163
- raw = raw.strip()
164
- if not raw:
165
- continue
166
- try:
167
- rec = json.loads(raw)
168
- except Exception:
169
- continue
170
- if not isinstance(rec, dict):
171
- continue
172
- rtype = rec.get("type")
173
- if rtype == "user":
174
- t = user_text(rec)
175
- if t is None:
176
- continue
177
- out_lines.append(f"[user: {t.strip()}]")
178
- elif rtype == "assistant":
179
- t = assistant_text(rec)
180
- if not t.strip():
181
- continue
182
- out_lines.append(f"[assistant: {t.strip()}]")
183
- except Exception as e:
184
- sys.stderr.write(f"transcript-walk-failed: {e}\n")
185
- sys.exit(0)
186
-
187
- print("\n\n".join(out_lines))
188
- PY
189
- )
190
- CONVERSATION_TURNS=$(printf '%s\n' "$CONVERSATION" | grep -c '^\[' || true)
191
- CONTEXT_BYTES=${#CONVERSATION}
192
-
193
119
  # Fetch the actual content of every node already written under this
194
120
  # conversation, account-scoped. The route runs loopback-only — the hook
195
121
  # is in-process on the device, same trust boundary as `/log-ingest`.
122
+ # Admin reads this skip-list before deciding what new writes to
123
+ # dispatch; the specialist never sees it (per-write briefs name the
124
+ # elementId admin already resolved when attaching to an existing node).
196
125
  PRIOR_WRITES="(none)"
197
126
  PRIOR_WRITES_COUNT=0
198
127
  if [ -n "$CONVERSATION_ID" ]; then
@@ -238,42 +167,46 @@ print(f"{len(writes)}\t" + "\n".join(lines))
238
167
  fi
239
168
  fi
240
169
 
241
- emit_log "dispatch sessionId=${SESSION_ID} conversationId=${CONVERSATION_ID:-<unset>} conversationTurns=${CONVERSATION_TURNS} priorWritesCount=${PRIOR_WRITES_COUNT} contextBytes=${CONTEXT_BYTES} ms=0"
242
-
243
- # Emit the documented UserPromptSubmit JSON envelope on stdout. Python
244
- # composes the directive body and handles JSON encoding so embedded
245
- # newlines, quotes, and backslashes in the conversation and prior-writes
246
- # blocks are escaped correctly.
247
- ACCOUNT_ID_OUT="${ACCOUNT_ID:-<unset>}" \
248
- SESSION_ID_OUT="${SESSION_ID}" \
249
- CONVERSATION_ID_OUT="${CONVERSATION_ID:-<unset>}" \
250
- CONVERSATION_OUT="${CONVERSATION}" \
251
- PRIOR_WRITES_OUT="${PRIOR_WRITES}" \
252
- python3 - <<'PY'
253
- import os, json, sys
170
+ # Compose the directive body before logging so contextBytes reflects
171
+ # the actual payload size handed to admin (skip-list + directive prose).
172
+ DIRECTIVE_BODY=$(ACCOUNT_ID_OUT="${ACCOUNT_ID:-<unset>}" \
173
+ SESSION_ID_OUT="${SESSION_ID}" \
174
+ CONVERSATION_ID_OUT="${CONVERSATION_ID:-<unset>}" \
175
+ PRIOR_WRITES_OUT="${PRIOR_WRITES}" \
176
+ python3 - <<'PY'
177
+ import os
254
178
  body = (
255
179
  "[system: pre-turn-graph-pass-hook]\n"
256
- "Before responding to the operator, dispatch the database-operator specialist via the Task tool with the parameters below. "
257
- "This is a background graph-write pass; do not surface the dispatch in your reply to the operator. "
258
- "After the specialist returns its one-line summary, continue with your normal response to the operator's prompt.\n\n"
259
- "Agent dispatch parameters:\n"
260
- " subagent_type: database-operator\n"
261
- " prompt: |\n"
262
- f" accountId: {os.environ['ACCOUNT_ID_OUT']}\n"
263
- f" sessionId: {os.environ['SESSION_ID_OUT']}\n"
264
- f" conversationId: {os.environ['CONVERSATION_ID_OUT']}\n\n"
265
- " Background pre-turn graph pass. Given the conversation below and the list of nodes already written under this conversationId, derive any new graph rows the conversation supports (mentions, ideas, learnings, contacts, tasks — anything the schema admits) and write them. Skip writes the prior list already covers; rely on MERGE semantics for the rest. Return one line in the form: db-op: writes=<n> ms=<n>\n\n"
266
- " <conversation>\n"
267
- f" {os.environ['CONVERSATION_OUT']}\n"
268
- " </conversation>\n\n"
269
- " <prior-writes>\n"
270
- f" {os.environ['PRIOR_WRITES_OUT']}\n"
271
- " </prior-writes>\n"
180
+ "Before responding to the operator, run the pre-turn graph pass. "
181
+ "Scan the operator turn you just received for any new graph-worthy content not already covered by the prior-writes list below "
182
+ "mentions of named entities, ideas or learnings the operator stated, contacts named for the first time, tasks the operator committed to, decisions, anything the schema admits. "
183
+ "For each candidate write, dispatch one Task to the `database-operator` specialist with a brief that names the label, the relevant properties, and (when attaching to an existing node) the elementId from the prior-writes list. "
184
+ "Skip writes the prior-writes list already covers — a `:MENTIONS` edge that is already there does not need re-emitting; an existing `:Person` is attached to by elementId, not re-created. "
185
+ "If the turn supports no new writes, dispatch nothing. "
186
+ "Do not surface these dispatches in your reply to the operator. After the dispatches return, continue with your normal response to the operator's prompt.\n\n"
187
+ f"accountId: {os.environ['ACCOUNT_ID_OUT']}\n"
188
+ f"sessionId: {os.environ['SESSION_ID_OUT']}\n"
189
+ f"conversationId: {os.environ['CONVERSATION_ID_OUT']}\n\n"
190
+ "<prior-writes>\n"
191
+ f"{os.environ['PRIOR_WRITES_OUT']}\n"
192
+ "</prior-writes>\n"
193
+ )
194
+ print(body, end="")
195
+ PY
272
196
  )
197
+ CONTEXT_BYTES=${#DIRECTIVE_BODY}
198
+
199
+ emit_log "dispatch sessionId=${SESSION_ID} conversationId=${CONVERSATION_ID:-<unset>} directive-shape=admin-walks priorWritesCount=${PRIOR_WRITES_COUNT} contextBytes=${CONTEXT_BYTES} ms=0"
200
+
201
+ # Emit the documented UserPromptSubmit JSON envelope on stdout. Python
202
+ # handles JSON encoding so embedded newlines, quotes, and backslashes
203
+ # in the prior-writes block are escaped correctly.
204
+ DIRECTIVE_BODY_OUT="$DIRECTIVE_BODY" python3 - <<'PY'
205
+ import os, json, sys
273
206
  sys.stdout.write(json.dumps({
274
207
  "hookSpecificOutput": {
275
208
  "hookEventName": "UserPromptSubmit",
276
- "additionalContext": body,
209
+ "additionalContext": os.environ["DIRECTIVE_BODY_OUT"],
277
210
  }
278
211
  }))
279
212
  PY
@@ -31,7 +31,7 @@ Load these when users ask about Maxy features or need guidance:
31
31
  Load these when performing admin tasks or diagnosing platform behaviour:
32
32
 
33
33
  - **Platform architecture** → `references/platform.md` — how the platform works, agent types, the plugin model
34
- - **Platform internals** → `references/internals.md` — retrieval pipeline, embedding infrastructure, guard layers, query classification, memory-rank, graph expansion, keyword subscriptions, context assembly, inbound message screening, tool call audit trail, programmatic spawn entry point and recorder auto-archive lifecycle. Load when answering architecture questions, assessing whether a capability exists, diagnosing retrieval behaviour, or reviewing security and privacy features.
34
+ - **Platform internals** → `references/internals.md` — retrieval pipeline, embedding infrastructure, guard layers, graph expansion, keyword subscriptions, context assembly, tool call audit trail, programmatic spawn entry point and recorder auto-archive lifecycle. Load when answering architecture questions, assessing whether a capability exists, diagnosing retrieval behaviour, or reviewing security and privacy features.
35
35
  - **Admin UI** → `references/admin-ui.md` — compact map of every `/api/admin/*` mount, every sidebar surface, the system-stats widget (CPU/RAM thresholds), the artefact pane, and the health-vs-version split. Load when diagnosing an admin route, explaining the CPU/RAM widget, or onboarding a new admin endpoint.
36
36
  - **Admin session** → `references/admin-session.md` — signed sessionKey + PIN-rebind survival contract, SDK-resume across `systemctl restart`, and the single-entry `POST /api/admin/claude-sessions` wrapper that owns every programmatic admin spawn-with-initialMessage. Load when diagnosing admin session continuity, designing a programmatic admin spawn, or reviewing the turn-recorder lifecycle.
37
37
  - **Cloudflare** → `references/cloudflare.md` — dashboard-first tunnel setup, the `cloudflared`-CLI-only tool surface, single-recovery-path (re-login) for every wrong-account failure.
@@ -129,7 +129,7 @@ The hook emits two summary lines per fire immediately before `spawn-request`:
129
129
  - `--allowed-tools` is **not** pushed to argv. `--agent <name>` resolves the agent file's `tools:` frontmatter natively against Claude Code's plugin-tool registry; the argv push (Task 165) was empirically redundant and namespace-broke after Task 203's `mcp__plugin_…` rename (Task 207).
130
130
  - The per-spawn `mcp.json` is **not** written and `--mcp-config` is **not** pushed. Plugin manifests register the MCPs at session start (Tasks 202+203). The per-account env that the JSON used to inject (`ACCOUNT_ID`, `USER_ID`, `NEO4J_URI`, `NEO4J_PASSWORD`, `PLATFORM_ROOT`, `CLAUDE_CONFIG_DIR`) now rides the PTY env block directly — see [`mcp-servers.md`](mcp-servers.md) §3 (Task 207).
131
131
  - `--permission-mode bypassPermissions` is auto-pushed when the caller has not set `permissionMode`. Headless specialists have no operator to consent to write tools; default mode blocks them (Task 207).
132
- - `--remote-control` is **not** attached and the URL-capture handler is not registered. Remote Control is channel-facing only; the recorder has no human in the loop, so no `claude.ai/code/session_<id>` URL is ever emitted and the per-byte URL regex consumes no PTY output. The spawn log line carries `remoteControl=false`. Channel-facing specialists (content-producer, librarian, personal-assistant, project-manager, research-assistant) keep `--remote-control`; only specialists named in `HEADLESS_ROLES` (`database-operator`, `memory-classify`, `commitment`, `classifier`) drop it.
132
+ - `--remote-control` is **not** attached and the URL-capture handler is not registered. Remote Control is channel-facing only; the recorder has no human in the loop, so no `claude.ai/code/session_<id>` URL is ever emitted and the per-byte URL regex consumes no PTY output. The spawn log line carries `remoteControl=false`. Channel-facing specialists (content-producer, librarian, personal-assistant, project-manager, research-assistant) keep `--remote-control`; only specialists named in `HEADLESS_ROLES` (`database-operator`, `citation-auditor`, `typed-edge-classifier`, `compiled-truth-rewriter`) drop it.
133
133
 
134
134
  **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 …`. Every operator-request stop (auto-archive included) now ends in `master-fd=closed` because `stopSession()` calls `pty.destroy()` explicitly before `store.remove` (Task 170 — see `platform.md` "stopSession fd contract" for the failure mode this closes).
135
135
 
@@ -171,7 +171,7 @@ Line shapes:
171
171
 
172
172
  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`.
173
173
 
174
- 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.
174
+ 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-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`, etc.) are intentionally out of scope — reads do not change state and their failures already reach the caller. (Task 424 removed `memory-rank` and `memory-classify`.)
175
175
 
176
176
  Diagnostic grep:
177
177
 
@@ -232,69 +232,6 @@ Admin: `[admin-query-classifier]` log line with `topicChange`, `topicChangeConfi
232
232
  Public: `[public-query-classifier]` log line with `search`, `effectiveQuery`, `reason`, `latencyMs`. The intentional absence of topic-change fields in the public log is the on-disk evidence that the public path does less work.
233
233
 
234
234
  ---
235
-
236
- ## Memory-Rank — LLM-Reasoned Document Grading
237
-
238
- The `memory-rank` tool adds an LLM reasoning layer on top of `memory-search`. Instead of relying solely on vector similarity and BM25 scores, it passes a candidate pool to Haiku with a natural-language ranking criterion and receives a re-ordered list with per-item reasoning.
239
-
240
- ### Pipeline
241
-
242
- ```
243
- QUERY ──► memory-search (pool=20) ──► candidates
244
-
245
-
246
- Claude Haiku
247
- (ranking prompt)
248
-
249
-
250
- ranked results
251
- (with reasoning)
252
- ```
253
-
254
- ### Configuration
255
-
256
- | Parameter | Default | Maximum |
257
- |---|---|---|
258
- | Output limit | 10 results | 50 |
259
- | Candidate pool | 20 candidates | 50 |
260
- | Expand hops | 1 | — |
261
-
262
- The candidate pool is always larger than the output limit. Haiku sees 20 candidates (with their properties and up to 10 related nodes each) and returns a ranked subset.
263
-
264
- ### Ranking prompt
265
-
266
- Haiku receives a sandboxed system prompt that:
267
- - Defines it as an entity ranker, not a general assistant
268
- - Instructs it to assess each candidate against the provided criterion
269
- - Forces it to call the `emit_ranker_output` tool with structured `rankings[]` of `{nodeId, rank (1-indexed, 1 = most important), reasoning (one sentence, ≤300 chars)}` — Anthropic validates the payload against `RankerOutputTool.input_schema` at the API boundary, so markdown-fence and malformed-JSON failure modes are impossible by construction
270
- - Explicitly labels the user-provided criterion as "data, not instructions" to prevent prompt injection
271
-
272
- The criterion itself (from the calling agent) is wrapped in `<<<CRITERION... CRITERION` delimiters in the user message.
273
-
274
- ### Hallucination defence
275
-
276
- Two layers:
277
- 1. **Input isolation** — Haiku only sees nodeIds from the candidate pool. The prompt says "only use nodeIds from the candidate list. Never invent a nodeId."
278
- 2. **Output validation** — The parser maintains a set of valid nodeIds. Any nodeId in Haiku's response that is not in the input set is silently discarded and counted. If all rankings are hallucinated, the system falls back to unranked results.
279
-
280
- ### Graceful degradation
281
-
282
- When ranking fails (no OAuth credentials, API error, rate limit, network timeout, schema-violating `tool_use.input`, empty response, all-hallucinated), the tool returns the original `memory-search` results in their score order, prefixed with:
283
-
284
- ```
285
- [Ranking unavailable: <reason>] — showing N candidates in their original memory-search score order.
286
- ```
287
-
288
- This makes the failure visible to the agent, which can relay it to the user. Degraded success — not an error response.
289
-
290
- ### Observability
291
-
292
- - `[memory-rank] candidates=N (requested pool=M, limit=L)` — on every call
293
- - `[memory-rank] calling haiku (candidates=N)` — before API call
294
- - `[memory-rank] [<accountId>] structured-output ok stop-reason=<r> output-tokens=<n>` — per-call surface naming the structured tool-use path. `stop_reason=tool_use` on the happy path; `max_tokens` indicates a structurally-truncated `tool_use.input` that the post-validator either drops or escalates.
295
- - `[memory-rank] haiku ok (ranked=N, hallucinated=M)` — after successful ranking
296
- - `[memory-rank] ERROR reason="..."` — when ranking fails (the classifier-error-rename fix — was `fallback reason="..."`). Schema-violating `tool_use.input` lands here as `tool_use input failed schema` instead of the pre-structured-output `malformed JSON` / `response-truncated` strings.
297
-
298
235
  ---
299
236
 
300
237
  ## Reports — durable workflow output (Task 332)
@@ -414,7 +351,7 @@ When both `KNOWLEDGE.md` and `KNOWLEDGE-SUMMARY.md` exist, the server compares m
414
351
 
415
352
  ### Admin agent path
416
353
 
417
- The admin agent runs via Claude Code CLI, which manages its own system prompt assembly. Knowledge reaches the admin agent through MCP tools — `memory-search` and `memory-rank` are available as tools the agent can call during a turn. The admin agent also receives session context via `loadSessionContext`, which injects:
354
+ The admin agent runs via Claude Code CLI, which manages its own system prompt assembly. Knowledge reaches the admin agent through MCP tools — `memory-search` is the read-path entry point (server-side LLM ranking was removed by Task 424; the agent ranks in-turn against any criterion). The admin agent also receives session context via `loadSessionContext`, which injects:
418
355
 
419
356
  - Recent review digest (last public chat or review digest `CreativeWork`)
420
357
  - Open tasks (priority-ordered, capped)
@@ -54,7 +54,7 @@ Roles are installed during setup and listed when {{productName}} introduces itse
54
54
 
55
55
  {{productName}} maintains a graph database (Neo4j) of everything you've told it. People, conversations, preferences, and context are stored as connected nodes. When you ask {{productName}} something, it searches this graph to retrieve relevant context before responding.
56
56
 
57
- **The recording loop.** When you submit a prompt, a UserPromptSubmit hook (`pre-turn-graph-pass.sh`) fires the `database-operator` specialist as a background dispatch before {{productName}} composes its reply. The dispatch carries the full conversation up to and including your just-submitted prompt as `[role: text]` pairs, plus the list of every node already written under this conversation, fetched via `GET /api/admin/post-turn-context`. The specialist decides what new graph rows the conversation supports — mentions of named entities, ideas, learnings, contacts, tasks, anything the schema admits — and writes them. Duplicate writes between this background pass and any inline write the admin agent dispatched mid-turn are accepted and cleaned up by the dream-cycle / hygiene sweeps. One dispatch per operator prompt; the dispatch fires before {{productName}}'s reply and runs in parallel with it. The admin agent can also dispatch `database-operator` inline at its own discretion when a write must complete before the assistant response ends. The final assistant reply of the session is not covered by the per-turn pass (no further operator prompt fires) and is picked up by the `session-end-retrospective.sh` Stop hook when you type `/end`. To disable the background pass for an account, remove the `pre-turn-graph-pass.sh` UserPromptSubmit-hook entry from that account's `~/.<brand>/.claude/settings.json`; there is no toggle.
57
+ **The recording loop.** When you submit a prompt, a UserPromptSubmit hook (`pre-turn-graph-pass.sh`) injects a system directive into {{productName}}'s next turn, before it composes its reply. The directive instructs {{productName}} to scan your just-submitted turn for new graph-worthy content — mentions of named entities, ideas, learnings, contacts, tasks, anything the schema admits — and dispatch one `database-operator` Task per candidate write. The directive carries a skip-list of every node already written under this conversation (fetched via `GET /api/admin/post-turn-context`) so {{productName}} attaches to existing nodes by elementId instead of duplicating them. The per-write dispatches run as background work; you do not see them in the reply. {{productName}} can also dispatch `database-operator` inline at its own discretion when a write must complete before the assistant response ends. The final assistant reply of the session is not covered by the per-turn pass (no further operator prompt fires) and is picked up by the `session-end-retrospective.sh` Stop hook when you type `/end`. To disable the per-turn pass for an account, remove the `pre-turn-graph-pass.sh` UserPromptSubmit-hook entry from that account's `~/.<brand>/.claude/settings.json`; there is no toggle.
58
58
 
59
59
  The memory graph is stored on your Pi. It never leaves your network.
60
60
 
@@ -41,8 +41,8 @@ These are enabled during onboarding and can be added or removed at any time. Som
41
41
  | `notion-import` | Import a Notion workspace export (markdown + CSV) — pages, databases, hierarchy, attachments, schema-bounded relations, `@person` mentions account-filtered | Database operator |
42
42
  | `obsidian-import` | Import an extracted Obsidian vault — pages map to `:KnowledgeDocument`, wikilinks resolve to intra-vault pages or existing entities, tags become `:DefinedTerm`, embedded images become `:DigitalDocument`. Two-phase tool (dry-run → operator disambiguation → commit). | Database operator |
43
43
  | `x-import` | Import an X (Twitter) Basic Data Export — tweet stream renders as one chronological transcript and ingests as a single `:KnowledgeDocument` (`source='x'`); each DM `conversationId` ingests as one `:ConversationArchive` (`source='x-dm'`, keyed on `conversationIdentity`) via `conversation-archive-ingest.sh`. Mentions, replies, and quote-tweet authors resolve to `:Person` on lowercased `xHandle`; every handle and DM senderId confirms against existing nodes (no auto-create). Per-thread KD granularity and `:Post` / `:DirectMessage` labels are explicitly rejected. | Database operator |
44
- | `memory/skills/conversation-archive` | Source-agnostic conversation transcript ingest. One skill for WhatsApp `_chat.txt`, Telegram, Signal, LinkedIn DMs, Zoom transcript, meeting minutes, iMessage, Slack, X DMs — `--source <enum>` selects the per-source normaliser. Single Bash entry — `bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source <enum> --owner-element-id <id> --participant-person-ids <csv> --scope <admin\|public>` — runs normalise → operator-confirms owner + every distinct sender → sessionize at gap-hours boundaries (default 12h) → classify each session via Haiku (`memory-classify` with `mode='chat'`) into topic-bounded `:Section` chunks → memory-ingest with `conversationIdentity` set (writes `:KnowledgeDocument`), `source=<enum>`. Re-imports are delta-append. Auto-creating participants is forbidden — any sender outside the operator-confirmed closed set LOUD-FAILs with `parser-miss`. Distinct from the live `whatsapp` plugin (Baileys). | Database operator |
45
- | `memory/skills/conversation-archive-enrich` | Phase 2 for any named `:ConversationArchive` — source-agnostic per-row insight derivation. Operator-triggered (never auto-fires on Phase 1 completion). Walks the parent's `:Section` chunks in pages via the read-only MCP tool `mcp__memory__conversation-archive-derive-insights`; surfaces high-confidence claims for per-row operator gate (`wire / skip / reject`) over four kinds — `mention`, `task`, `preference`, `observed-relationship`. Idempotent on `(elementId(chunk), kind, contentHash)` — re-runs collapse identical claims. Haiku runs on OAuth (admin-side LLM never the API key); confidence floor is a hedging-avoidance instruction in the system prompt, not a numeric post-filter. | Database operator |
44
+ | `memory/skills/conversation-archive` | Source-agnostic conversation transcript ingest. One skill for WhatsApp `_chat.txt`, Telegram, Signal, LinkedIn DMs, Zoom transcript, meeting minutes, iMessage, Slack, X DMs — `--source <enum>` selects the per-source normaliser. Single Bash entry — `bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source <enum> --owner-element-id <id> --participant-person-ids <csv> --scope <admin\|public>` — runs normalise → operator-confirms owner + every distinct sender → sessionize at gap-hours boundaries (default 12h) → classify each session in-turn (the dispatched specialist produces topic-bounded chunk JSON from the parsed lines; the server-side `memory-classify` step was deleted in Task 424, and Task 435 finishes the driver-side cleanup) → memory-ingest with `conversationIdentity` set (writes `:ConversationArchive`), `source=<enum>`. Re-imports are delta-append. Auto-creating participants is forbidden — any sender outside the operator-confirmed closed set LOUD-FAILs with `parser-miss`. Distinct from the live `whatsapp` plugin (Baileys). | Database operator |
45
+ | `memory/skills/conversation-archive-enrich` | Phase 2 for any named `:ConversationArchive` — source-agnostic per-row insight derivation. Operator-triggered (never auto-fires on Phase 1 completion). Walks the parent's `:Section` chunks in pages via the read-only MCP tool `mcp__memory__conversation-archive-derive-insights`; surfaces high-confidence claims for per-row operator gate (`wire / skip / reject`) over four kinds — `mention`, `task`, `preference`, `observed-relationship`. Idempotent on `(elementId(chunk), kind, contentHash)` — re-runs collapse identical claims. Confidence floor is a hedging-avoidance instruction in the system prompt, not a numeric post-filter; per Task 424 the LLM step now runs in-turn from the dispatched specialist rather than as a separate server-side OAuth round-trip. | Database operator |
46
46
 
47
47
  ### Claude Official (marketplace)
48
48
 
@@ -13,7 +13,7 @@ export interface EmailData {
13
13
  bodyPreview: string;
14
14
  receivedAt: string;
15
15
  accountId: string;
16
- screening?: "clean" | "suspicious" | "discarded";
16
+ screening?: "clean" | "suspicious" | "discarded" | "unscreened";
17
17
  screeningReason?: string;
18
18
  promptInjectionFlag?: boolean;
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/lib/graph.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,WAAW,CAAC;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAOtE;AA2CD;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAwCD,UAAU,WAAW;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAuK7E;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,SAAS,EAAE,GACpB,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBnF;AAOD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAO/B;AAOD,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAoClC"}
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/lib/graph.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,CAAC;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAOtE;AA2CD;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAwCD,UAAU,WAAW;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAuK7E;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,SAAS,EAAE,GACpB,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBnF;AAOD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAO/B;AAOD,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAoClC"}
@@ -33,7 +33,10 @@ import { loadCredentials, readPollState, updatePollState } from "../lib/credenti
33
33
  import { fetchSinceUid } from "../lib/imap.js";
34
34
  import { storeEmailMessages } from "../lib/graph.js";
35
35
  import { closeDriver } from "../lib/neo4j.js";
36
- import { screenEmail } from "../lib/screening.js";
36
+ // Task 424 screening.ts deleted. Task 432 replaces this fetch script with an
37
+ // operator-initiated email-ingest flow; until then, every fetched email lands
38
+ // with screening='unscreened' so downstream consumers know classification was
39
+ // skipped.
37
40
  // ---------------------------------------------------------------------------
38
41
  // Brand-aware config directory — reads configDir from brand.json stamped at install time.
39
42
  // No fallback: if brand.json is missing or incomplete, the platform wasn't properly installed.
@@ -165,50 +168,27 @@ async function main() {
165
168
  await updatePollState(accountId, maxUid || sinceUid, uidValidity);
166
169
  return;
167
170
  }
168
- // Classify each email via Haiku (OAuth, never API key — admin path).
169
- // screenEmail handles auth internally via callOauthLlm and degrades to
170
- // "suspicious" on any failure, so no pre-flight key check is needed here.
171
- const emailData = [];
172
- let countClean = 0;
173
- let countSuspicious = 0;
174
- let countDiscard = 0;
175
- for (const e of emails) {
176
- const screening = await screenEmail({
177
- fromAddress: e.fromAddress,
178
- fromName: e.fromName,
179
- subject: e.subject,
180
- bodyPreview: e.bodyPreview,
181
- });
182
- // Map verdict to storage value ("discard" → "discarded" on the node)
183
- const storageVerdict = screening.verdict === "discard" ? "discarded" : screening.verdict;
184
- log("INFO", `classified ${e.fromAddress} — verdict=${screening.verdict} reason="${screening.reason}" pi=${screening.promptInjectionRisk}`);
185
- if (screening.verdict === "clean")
186
- countClean++;
187
- else if (screening.verdict === "suspicious")
188
- countSuspicious++;
189
- else
190
- countDiscard++;
191
- emailData.push({
192
- messageId: e.messageId,
193
- inReplyTo: e.inReplyTo,
194
- toAddresses: e.toAddresses,
195
- ccAddresses: e.ccAddresses,
196
- uid: e.uid,
197
- uidValidity,
198
- mailbox: "INBOX",
199
- recipientAddress: config.agentAddress,
200
- fromAddress: e.fromAddress,
201
- fromName: e.fromName,
202
- subject: e.subject,
203
- bodyPreview: e.bodyPreview,
204
- receivedAt: e.date,
205
- accountId,
206
- screening: storageVerdict,
207
- screeningReason: screening.reason,
208
- promptInjectionFlag: screening.promptInjectionRisk || undefined,
209
- });
210
- }
211
- log("INFO", `classification summary: ${countClean} clean, ${countSuspicious} suspicious, ${countDiscard} discarded`);
171
+ // Task 424 — per-email Haiku screening removed. Operator-initiated
172
+ // triage replaces it under Task 432.
173
+ const emailData = emails.map((e) => ({
174
+ messageId: e.messageId,
175
+ inReplyTo: e.inReplyTo,
176
+ toAddresses: e.toAddresses,
177
+ ccAddresses: e.ccAddresses,
178
+ uid: e.uid,
179
+ uidValidity,
180
+ mailbox: "INBOX",
181
+ recipientAddress: config.agentAddress,
182
+ fromAddress: e.fromAddress,
183
+ fromName: e.fromName,
184
+ subject: e.subject,
185
+ bodyPreview: e.bodyPreview,
186
+ receivedAt: e.date,
187
+ accountId,
188
+ screening: "unscreened",
189
+ screeningReason: "Task 424 — screener removed; awaiting Task 432 operator-initiated triage",
190
+ }));
191
+ log("INFO", `fetched ${emailData.length} email(s); per-email classification skipped (operator-initiated triage pending)`);
212
192
  // Sort by receivedAt ascending so thread transcripts read chronologically
213
193
  // (storeEmailMessage appends in input order).
214
194
  emailData.sort((a, b) => a.receivedAt.localeCompare(b.receivedAt));
@@ -1 +1 @@
1
- {"version":3,"file":"email-fetch.js","sourceRoot":"","sources":["../../src/scripts/email-fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"email-fetch.js","sourceRoot":"","sources":["../../src/scripts/email-fetch.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory",
3
- "description": "Graph memory plugin. Provides memory-search (with optional `fields` projection for known-shape lookups), memory-rank, memory-write, memory-update, and the :Report surface (memory-report-write / memory-report-read-latest / memory-report-list) for reading from, writing to, and updating the Neo4j knowledge graph. Includes conversational memory — organic preference learning, evidence-backed recall, and transparent 'what do you know about me?' responses. Document ingestion (memory-classify + memory-ingest) supports two modes: `document` (default) for unstructured PDF/web content → :KnowledgeDocument (keyed on `attachmentId`) + :Section, and `chat` for conversation transcripts → :ConversationArchive (Task 397, keyed on `conversationIdentity`) + :Section chunks; two parent labels, two writer paths chosen by which identity property is set. Conversation-archive Phase 2 (`conversation-archive-derive-insights`) walks chunks of one named archive and emits per-row claim proposals for operator-gated wiring; `conversation-archive-enrich-rejection` records (or undoes) durable per-row rejections so already-triaged claims do not re-surface on re-runs. Ships four skills: `conversational-memory`, `document-ingest`, `conversation-archive` (source-agnostic transcript ingest for WhatsApp, Telegram, Signal, LinkedIn DMs, Zoom, meeting minutes, iMessage, Slack), and `conversation-archive-enrich` (per-row operator-gated insight derivation over a named archive's chunks).",
3
+ "description": "Graph memory plugin. Provides memory-search (with optional `fields` projection for known-shape lookups), memory-write, memory-update, and the :Report surface (memory-report-write / memory-report-read-latest / memory-report-list) for reading from, writing to, and updating the Neo4j knowledge graph. Includes conversational memory — organic preference learning, evidence-backed recall, and transparent 'what do you know about me?' responses. Document ingestion goes through memory-ingest; the dispatched specialist produces typed-section JSON in-turn from the loaded ontology. Two modes: `document` (default) for unstructured PDF/web content → :KnowledgeDocument (keyed on `attachmentId`) + :Section, and `chat` for conversation transcripts → :ConversationArchive (keyed on `conversationIdentity`) + :Section chunks; two parent labels, two writer paths chosen by which identity property is set. Conversation-archive Phase 2 (`conversation-archive-derive-insights`) walks chunks of one named archive and emits per-row claim proposals for operator-gated wiring; `conversation-archive-enrich-rejection` records (or undoes) durable per-row rejections so already-triaged claims do not re-surface on re-runs. Ships four skills: `conversational-memory`, `document-ingest`, `conversation-archive` (source-agnostic transcript ingest for WhatsApp, Telegram, Signal, LinkedIn DMs, Zoom, meeting minutes, iMessage, Slack), and `conversation-archive-enrich` (per-row operator-gated insight derivation over a named archive's chunks).",
4
4
  "version": "0.1.0",
5
5
  "author": {
6
6
  "name": "Rubytech LLC"