@rubytech/create-realagent 1.0.828 → 1.0.829
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/package.json +1 -1
- package/payload/platform/neo4j/schema.cypher +2 -1
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +39 -54
- package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +26 -58
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +2 -2
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +4 -4
- package/payload/platform/plugins/memory/mcp/dist/index.js +18 -218
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +103 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +30 -20
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts +16 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js +12 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +2 -138
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +10 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +148 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +1 -64
- 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 +6 -336
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +7 -11
- 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 +1 -11
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +21 -17
- 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 +77 -37
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +2 -0
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +54 -4
- package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
- package/payload/platform/scripts/seed-neo4j.sh +15 -14
- package/payload/platform/templates/specialists/agents/database-operator.md +9 -15
- package/payload/server/chunk-CUSH3UXP.js +2305 -0
- package/payload/server/chunk-IWNDVGKT.js +10077 -0
- package/payload/server/chunk-KC7NUABI.js +654 -0
- package/payload/server/chunk-WUVXPZIV.js +1116 -0
- package/payload/server/client-pool-3TM3SRIA.js +32 -0
- package/payload/server/cloudflare-task-tracker-4NIODMGL.js +19 -0
- package/payload/server/maxy-edge.js +3 -3
- package/payload/server/neo4j-migrations-XTQ4WEV6.js +428 -0
- package/payload/server/server.js +6 -6
- package/payload/platform/plugins/whatsapp-import/PLUGIN.md +0 -48
- package/payload/platform/plugins/whatsapp-import/bin/ingest.mjs +0 -617
- package/payload/platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh +0 -98
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/delta-append.test.ts +0 -163
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export-lrm.test.ts +0 -83
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export.test.ts +0 -678
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/sessionize.test.ts +0 -91
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/to-classifier-input.test.ts +0 -59
- package/payload/platform/plugins/whatsapp-import/lib/src/delta-cursor.ts +0 -54
- package/payload/platform/plugins/whatsapp-import/lib/src/derive-keys.ts +0 -82
- package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +0 -22
- package/payload/platform/plugins/whatsapp-import/lib/src/parse-export.ts +0 -471
- package/payload/platform/plugins/whatsapp-import/lib/src/sessionize.ts +0 -81
- package/payload/platform/plugins/whatsapp-import/lib/src/to-classifier-input.ts +0 -48
- package/payload/platform/plugins/whatsapp-import/lib/tsconfig.json +0 -9
- package/payload/platform/plugins/whatsapp-import/lib/vitest.config.ts +0 -9
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +0 -124
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/conversation-archive-shape.md +0 -143
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/export-parse.md +0 -109
package/package.json
CHANGED
|
@@ -269,7 +269,8 @@ OPTIONS {
|
|
|
269
269
|
//
|
|
270
270
|
// :PARTICIPANT_IN edges from :Person/:AdminUser to :ConversationArchive are
|
|
271
271
|
// MERGEd on every ingest (idempotent); the operator confirms each participant
|
|
272
|
-
// up front via the
|
|
272
|
+
// up front via the document-ingest skill's chat-mode participant flow
|
|
273
|
+
// (Task 894 — supersedes the prior whatsapp-import skill).
|
|
273
274
|
// ----------------------------------------------------------
|
|
274
275
|
|
|
275
276
|
CREATE CONSTRAINT conversation_archive_identity_unique IF NOT EXISTS
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"plugins/*/mcp"
|
|
7
7
|
],
|
|
8
8
|
"scripts": {
|
|
9
|
-
"build": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json &&
|
|
10
|
-
"build:lib": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json
|
|
9
|
+
"build": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json && NODE_OPTIONS='--max-old-space-size=8192' tsc -b plugins/*/mcp/tsconfig.json",
|
|
10
|
+
"build:lib": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p lib/task-secrets/tsconfig.json",
|
|
11
11
|
"build:memory": "tsc -p plugins/memory/mcp/tsconfig.json",
|
|
12
12
|
"build:contacts": "tsc -p plugins/contacts/mcp/tsconfig.json",
|
|
13
13
|
"build:telegram": "tsc -p plugins/telegram/mcp/tsconfig.json",
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Regression test for archive-ingest-surface-gate.sh (Task 855).
|
|
2
|
+
# Regression test for archive-ingest-surface-gate.sh (Task 855, trimmed by Task 894).
|
|
3
3
|
#
|
|
4
|
-
# Covers:
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
4
|
+
# Covers (post-Task-894):
|
|
5
|
+
# 1. Edit on /platform/plugins/<x>/lib/* → BLOCKED
|
|
6
|
+
# 2. Edit on benign path → ALLOWED
|
|
7
|
+
# 3. Bash with `npx vitest`/`bun test`/`npm test` → BLOCKED
|
|
8
|
+
# 4. PreToolUse memory-archive-write w/ archiveType=linkedin-connections → ALLOWED
|
|
9
|
+
# 5. Default-allow emits a [archive-ingest-gate] decision=allow log line
|
|
10
|
+
# 6. Parse-error flag lifecycle: PostToolUse on any *-export-parse / *-import-parse
|
|
11
|
+
# with isError:true sets flag; subsequent PreToolUse blocks; UserPromptSubmit
|
|
12
|
+
# clears; stale flag (>600s) auto-clears; parse-success leaves flag absent.
|
|
13
|
+
# 7. Bypass attempts: nested file_path in old_string + top-level file_path in
|
|
14
|
+
# lib/* → BLOCKED.
|
|
15
|
+
# 8. Fail-closed terminal check.
|
|
16
|
+
#
|
|
17
|
+
# Removed by Task 894:
|
|
18
|
+
# - WhatsApp-specific MCP-tool blocks (the three legacy whatsapp-export tools
|
|
19
|
+
# no longer exist; chat archives flow through memory-classify mode='chat'
|
|
20
|
+
# and memory-ingest parentLabel='ConversationArchive' via document-ingest).
|
|
21
|
+
# - memory-archive-write archiveType='whatsapp-export' block (the enum value
|
|
22
|
+
# was dropped from memory-archive-write).
|
|
23
|
+
#
|
|
24
|
+
# A generic LinkedIn-shaped fixture stands in for the parse-error lifecycle —
|
|
25
|
+
# the gate's PostToolUse pattern matches `mcp__*__*-export-parse` /
|
|
26
|
+
# `mcp__*__*-import-parse`, so any plausible parser tool name exercises the
|
|
27
|
+
# flag-set / flag-clear path.
|
|
21
28
|
|
|
22
29
|
set -u
|
|
23
30
|
|
|
@@ -51,18 +58,20 @@ run_case() {
|
|
|
51
58
|
fi
|
|
52
59
|
}
|
|
53
60
|
|
|
54
|
-
#
|
|
61
|
+
# Plugin-source-edit block ------------------------------------------------
|
|
55
62
|
|
|
56
|
-
run_case "Edit on platform/plugins/
|
|
57
|
-
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/Users/x/repo/platform/plugins/
|
|
63
|
+
run_case "Edit on platform/plugins/linkedin-import/lib/src/parse.ts → BLOCKED" \
|
|
64
|
+
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/Users/x/repo/platform/plugins/linkedin-import/lib/src/parse.ts","old_string":"a","new_string":"b"}}' \
|
|
58
65
|
2
|
|
59
66
|
|
|
60
67
|
run_case "Edit on README.md → ALLOWED" \
|
|
61
68
|
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/Users/x/repo/README.md","old_string":"a","new_string":"b"}}' \
|
|
62
69
|
0
|
|
63
70
|
|
|
71
|
+
# Test-runner block (Bash) ------------------------------------------------
|
|
72
|
+
|
|
64
73
|
run_case "Bash 'npx vitest run' → BLOCKED" \
|
|
65
|
-
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npx vitest run
|
|
74
|
+
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npx vitest run x.test.ts"}}' \
|
|
66
75
|
2
|
|
67
76
|
|
|
68
77
|
run_case "Bash 'ls -la' → ALLOWED" \
|
|
@@ -77,45 +86,18 @@ run_case "Bash 'npm test' → BLOCKED" \
|
|
|
77
86
|
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npm test"}}' \
|
|
78
87
|
2
|
|
79
88
|
|
|
80
|
-
#
|
|
81
|
-
|
|
82
|
-
run_case "PreToolUse mcp__memory__whatsapp-export-parse → BLOCKED" \
|
|
83
|
-
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__whatsapp-export-parse","tool_input":{"filePath":"/tmp/_chat.txt","accountId":"acct1","timezone":"Europe/London"}}' \
|
|
84
|
-
2
|
|
85
|
-
|
|
86
|
-
run_case "PreToolUse mcp__memory__whatsapp-export-insight-write → BLOCKED" \
|
|
87
|
-
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__whatsapp-export-insight-write","tool_input":{"kind":"MENTIONS","name":"Joel"}}' \
|
|
88
|
-
2
|
|
89
|
-
|
|
90
|
-
run_case "PreToolUse memory-archive-write w/ archiveType=whatsapp-export → BLOCKED" \
|
|
91
|
-
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a","rows":[]}}' \
|
|
92
|
-
2
|
|
89
|
+
# memory-archive-write — LinkedIn passes through unchanged ----------------
|
|
93
90
|
|
|
94
91
|
run_case "PreToolUse memory-archive-write w/ archiveType=linkedin-connections → ALLOWED" \
|
|
95
92
|
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"archiveType":"linkedin-connections","ownerNodeId":"x","accountId":"a","rows":[]}}' \
|
|
96
93
|
0
|
|
97
94
|
|
|
98
|
-
# Bypass attempts (Task 855 code-review C1): nested archiveType in rows[0]
|
|
99
|
-
# or conversation must NOT defeat the block. The gate must read the
|
|
100
|
-
# top-level tool_input.archiveType, not the first textual occurrence.
|
|
101
|
-
run_case "BYPASS: nested rows[0].archiveType=linkedin + top-level archiveType=whatsapp-export → BLOCKED" \
|
|
102
|
-
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"rows":[{"archiveType":"linkedin-connections"}],"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a"}}' \
|
|
103
|
-
2
|
|
104
|
-
|
|
105
|
-
run_case "BYPASS: conversation.archiveType=linkedin + top-level archiveType=whatsapp-export → BLOCKED" \
|
|
106
|
-
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"conversation":{"archiveType":"linkedin-connections","conversationId":"x"},"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a","rows":[]}}' \
|
|
107
|
-
2
|
|
108
|
-
|
|
109
95
|
# Plugin-source-edit path block must read tool_input.file_path top-level,
|
|
110
96
|
# not a nested file_path in old_string/new_string.
|
|
111
97
|
run_case "BYPASS: nested file_path in old_string + top-level file_path in lib/* → BLOCKED" \
|
|
112
|
-
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/repo/platform/plugins/
|
|
98
|
+
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/repo/platform/plugins/linkedin-import/lib/src/parse.ts","old_string":"file_path:/safe/path","new_string":"x"}}' \
|
|
113
99
|
2
|
|
114
100
|
|
|
115
|
-
run_case "PreToolUse Bash invoking whatsapp-ingest.sh → ALLOWED" \
|
|
116
|
-
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"bash platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh /tmp/chat.zip --owner-element-id 4:abc:1 --subject-person-id 4:abc:2 --scope admin --filter all"}}' \
|
|
117
|
-
0
|
|
118
|
-
|
|
119
101
|
# Default-allow log-line check
|
|
120
102
|
LOG=$(printf '%s' '{"hook_event_name":"PreToolUse","tool_name":"Read","tool_input":{"file_path":"/tmp/foo"}}' | bash "$HOOK" 2>&1 1>/dev/null)
|
|
121
103
|
if printf '%s' "$LOG" | grep -q '\[archive-ingest-gate\] decision=allow tool=Read reason=default'; then
|
|
@@ -136,10 +118,13 @@ else
|
|
|
136
118
|
FAIL=$((FAIL + 1))
|
|
137
119
|
fi
|
|
138
120
|
|
|
139
|
-
# Parse-error flag lifecycle (preserved)
|
|
121
|
+
# Parse-error flag lifecycle (preserved). The gate's PostToolUse pattern is
|
|
122
|
+
# `mcp__*__*-export-parse` / `mcp__*__*-import-parse` — exercise via the
|
|
123
|
+
# linkedin-import-parse name (synthetic — the linkedin importer currently
|
|
124
|
+
# uses memory-archive-write, but the gate matches by tool name shape).
|
|
140
125
|
rm -f "$FLAG_FILE"
|
|
141
126
|
run_case "PostToolUse parse-error sets flag (exit 0)" \
|
|
142
|
-
'{"hook_event_name":"PostToolUse","tool_name":"
|
|
127
|
+
'{"hook_event_name":"PostToolUse","tool_name":"mcp__memory__linkedin-import-parse","tool_input":{"filePath":"connections.csv"},"tool_response":{"isError":true,"content":[{"type":"text","text":"parse-error file=connections.csv line=1 reason=missing-header"}]}}' \
|
|
143
128
|
0
|
|
144
129
|
[[ -f "$FLAG_FILE" ]] && { echo "PASS: parse-error flag created"; PASS=$((PASS+1)); } \
|
|
145
130
|
|| { echo "FAIL: parse-error flag NOT created" >&2; FAIL=$((FAIL+1)); }
|
|
@@ -168,7 +153,7 @@ run_case "Stale flag auto-clears, PreToolUse Read → ALLOWED" \
|
|
|
168
153
|
# PostToolUse parse-success leaves flag absent
|
|
169
154
|
rm -f "$FLAG_FILE"
|
|
170
155
|
run_case "PostToolUse parse-success (isError:false) does NOT set flag" \
|
|
171
|
-
'{"hook_event_name":"PostToolUse","tool_name":"
|
|
156
|
+
'{"hook_event_name":"PostToolUse","tool_name":"mcp__memory__linkedin-import-parse","tool_input":{"filePath":"connections.csv"},"tool_response":{"isError":false,"content":[{"type":"text","text":"{\"parsedLines\":[]}"}]}}' \
|
|
172
157
|
0
|
|
173
158
|
[[ ! -f "$FLAG_FILE" ]] && { echo "PASS: parse-success leaves flag absent"; PASS=$((PASS+1)); } \
|
|
174
159
|
|| { echo "FAIL: parse-success incorrectly created flag" >&2; FAIL=$((FAIL+1)); }
|
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Archive-ingest surface gate (Task 855, updated by Task 891).
|
|
2
|
+
# Archive-ingest surface gate (Task 855, updated by Task 891, trimmed by Task 894).
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
# Task 855
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# `
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
4
|
+
# Three enforcements, one script — phase decided by `hook_event_name` on stdin.
|
|
5
|
+
# Task 855 narrowed the database-operator subagent's effective surface during
|
|
6
|
+
# archive ingestion. Task 894 retired the WhatsApp `_chat.txt` deterministic
|
|
7
|
+
# parser and its three legacy MCP tools entirely — chat archives now flow
|
|
8
|
+
# through the unified `document-ingest` pipeline (`memory-classify` mode='chat'
|
|
9
|
+
# + `memory-ingest` parentLabel='ConversationArchive'). The WhatsApp-specific
|
|
10
|
+
# block lists were removed because the tools they referenced no longer exist
|
|
11
|
+
# and the `archiveType=whatsapp-export` enum value was dropped from
|
|
12
|
+
# `memory-archive-write`. The remaining blocks still cover LinkedIn and any
|
|
13
|
+
# future flat-dataset archive types that ship per-source parsers.
|
|
13
14
|
#
|
|
14
|
-
# 1.
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# mcp__memory__whatsapp-export-insight-pass (Task 891 — deleted, retired)
|
|
22
|
-
# mcp__memory__memory-archive-write (only when `archiveType` is
|
|
23
|
-
# `whatsapp-export`; LinkedIn
|
|
24
|
-
# and other archiveTypes pass
|
|
25
|
-
# through unchanged.)
|
|
15
|
+
# 1. Parse-error gate: PostToolUse on any `mcp__*__*-export-parse` /
|
|
16
|
+
# `mcp__*__*-import-parse` tool whose `tool_response.isError == true`
|
|
17
|
+
# writes a flag file. Subsequent PreToolUse on ANY tool blocks until
|
|
18
|
+
# UserPromptSubmit clears the flag. A 600s TTL is the cross-session safety
|
|
19
|
+
# net. Preserved from Task 846 because LinkedIn and future per-source archive
|
|
20
|
+
# parsers still use the legacy MCP path until they migrate to their own
|
|
21
|
+
# deterministic Bash entries.
|
|
26
22
|
#
|
|
27
23
|
# 2. PreToolUse Edit/Write/NotebookEdit: deny writes under
|
|
28
24
|
# `*platform/plugins/*/lib/*` (parser/CSV-shape source for any *-import or
|
|
@@ -32,18 +28,10 @@
|
|
|
32
28
|
# 3. PreToolUse Bash: deny commands invoking JavaScript test runners
|
|
33
29
|
# (vitest|bun test|npm test|npx jest|node .*vitest). Preserved from Task 846.
|
|
34
30
|
#
|
|
35
|
-
# 4.
|
|
36
|
-
# `mcp__*__*-import-parse` tool whose `tool_response.isError == true`
|
|
37
|
-
# writes a flag file. Subsequent PreToolUse on ANY tool blocks until
|
|
38
|
-
# UserPromptSubmit clears the flag. A 600s TTL is the cross-session safety
|
|
39
|
-
# net. Preserved from Task 846 because LinkedIn and future per-source archive
|
|
40
|
-
# parsers still use the legacy MCP path until they migrate to their own
|
|
41
|
-
# deterministic Bash entries.
|
|
42
|
-
#
|
|
43
|
-
# 5. Logging: every PreToolUse decision emits one line in the format
|
|
31
|
+
# 4. Logging: every PreToolUse decision emits one line in the format
|
|
44
32
|
# [archive-ingest-gate] decision=<allow|block> tool=<name> reason=<r> ...
|
|
45
33
|
# so the operator can grep the full decision trail for one ingest from
|
|
46
|
-
# server.log
|
|
34
|
+
# server.log.
|
|
47
35
|
#
|
|
48
36
|
# Exit codes follow Claude Code hook protocol: 0 = allow, 2 = block (stderr
|
|
49
37
|
# message shown to the agent). Fail-closed on terminal stdin to match
|
|
@@ -140,21 +128,12 @@ if [ -f "$FLAG_FILE" ]; then
|
|
|
140
128
|
fi
|
|
141
129
|
fi
|
|
142
130
|
|
|
143
|
-
# --- Block 2: legacy WhatsApp MCP tools — denied unconditionally ----------
|
|
144
|
-
case "$TOOL_NAME" in
|
|
145
|
-
mcp__memory__whatsapp-export-parse|mcp__memory__whatsapp-export-insight-write|mcp__memory__whatsapp-export-insight-pass)
|
|
146
|
-
emit_decision "block" "denied-mcp-legacy" \
|
|
147
|
-
"Blocked: ${TOOL_NAME} is a retired path. Task 891 ships the chunked-archive contract — invoke 'bash platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh <archive> --owner-element-id <id> --participant-person-ids <csv> --scope <admin|public>' once. Parse, sessionize, classify (mode=chat), and memory-ingest (parentLabel=ConversationArchive) all run in-process; do not call legacy MCP tools. Phase 2 insight derivation is deferred to its own follow-up task."
|
|
148
|
-
;;
|
|
149
|
-
esac
|
|
150
|
-
|
|
151
131
|
# Helper: extract a top-level field from `tool_input` via python3 — never via
|
|
152
132
|
# grep+sed against the raw JSON, which would pick the first textual occurrence
|
|
153
|
-
# including nested-object matches (`rows[0].archiveType`,
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
#
|
|
157
|
-
# downstream block conditions skip cleanly.
|
|
133
|
+
# including nested-object matches (`rows[0].archiveType`, etc.) and let a
|
|
134
|
+
# malicious payload bypass the block. python3 is the project standard for
|
|
135
|
+
# JSON-aware hook parsing (mirrors lane-gate.sh:31-46). On parse failure
|
|
136
|
+
# return empty string — downstream block conditions skip cleanly.
|
|
158
137
|
extract_tool_input_field() {
|
|
159
138
|
local field="$1"
|
|
160
139
|
printf '%s' "$INPUT" | python3 -c "
|
|
@@ -167,18 +146,7 @@ except Exception:
|
|
|
167
146
|
" 2>/dev/null || echo ""
|
|
168
147
|
}
|
|
169
148
|
|
|
170
|
-
# --- Block
|
|
171
|
-
# LinkedIn and future archiveTypes flow unchanged through memory-archive-write.
|
|
172
|
-
# Only `archiveType=whatsapp-export` is now restricted to the script path.
|
|
173
|
-
if [ "$TOOL_NAME" = "mcp__memory__memory-archive-write" ]; then
|
|
174
|
-
ARCHIVE_TYPE=$(extract_tool_input_field archiveType)
|
|
175
|
-
if [ "$ARCHIVE_TYPE" = "whatsapp-export" ]; then
|
|
176
|
-
emit_decision "block" "denied-mcp-legacy archiveType=whatsapp-export" \
|
|
177
|
-
"Blocked: memory-archive-write with archiveType='whatsapp-export' is a retired path. Task 891 ships the chunked-archive contract — invoke 'bash platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh <archive> --owner-element-id <id> --participant-person-ids <csv> --scope <admin|public>' once. Other archiveTypes (linkedin-connections, …) flow through memory-archive-write unchanged."
|
|
178
|
-
fi
|
|
179
|
-
fi
|
|
180
|
-
|
|
181
|
-
# --- Block 4: plugin-source path block (Edit/Write/NotebookEdit) -----------
|
|
149
|
+
# --- Block 2: plugin-source path block (Edit/Write/NotebookEdit) -----------
|
|
182
150
|
case "$TOOL_NAME" in
|
|
183
151
|
Edit|Write|NotebookEdit)
|
|
184
152
|
FILE_PATH=$(extract_tool_input_field file_path)
|
|
@@ -191,7 +159,7 @@ case "$TOOL_NAME" in
|
|
|
191
159
|
;;
|
|
192
160
|
esac
|
|
193
161
|
|
|
194
|
-
# --- Block
|
|
162
|
+
# --- Block 3: shell test-runner block (Bash) -------------------------------
|
|
195
163
|
COMMAND=""
|
|
196
164
|
if [ "$TOOL_NAME" = "Bash" ]; then
|
|
197
165
|
COMMAND=$(extract_tool_input_field command)
|
|
@@ -227,8 +227,8 @@ Invoke the `business-profile` skill, passing the `taskId` so the skill can threa
|
|
|
227
227
|
|
|
228
228
|
Personal mode does not register a `LocalBusiness`. The `AdminUser` and personal-profile `Person` nodes were written deterministically at PIN setup time (Task 830 — `writeAdminUserAndPerson`, run as `createdBy.agent === 'system'` and therefore exempt from the action-provenance gate), so this step only enriches the existing Person with operator-identity fields and links it to the `UserProfile`:
|
|
229
229
|
|
|
230
|
-
1. **
|
|
231
|
-
2. **
|
|
230
|
+
1. **Elicit Person properties that help {{productName}} serve this operator.** Open by default — identity (email, phone, names), context (where they live, languages they speak, what they do, who they work for), or anything else the operator volunteers that makes future assistance more useful. The personal-profile Person is comprehensive, not enumerated: ask in one short conversational message for what feels natural to volunteer at first contact, accept whatever the operator offers, do not chase a fixed list. The user may decline any field; record what they provide.
|
|
231
|
+
2. **Persist via `profile-update.personFields`.** Pass a single object whose keys are the Person properties the operator volunteered, in the operator's volunteered phrasing — the central schema validator handles synonyms (e.g. `phone` rejects with "use telephone") and Forbidden Properties (e.g. `name` rejects with "use givenName + familyName"); the agent does not pre-rewrite. The tool resolves the personal-profile Person via `(au:AdminUser {userId:$you})-[:OWNS]->(p:Person)` server-side and throws loudly if the OWNS edge is missing rather than silently no-oping (the PIN-setup path is the only place that edge is created — a missing edge means PIN setup never ran or was rolled back).
|
|
232
232
|
3. **Append the step + record the facts.** Call `task-update` with both `appendStep:"identity-attached"` AND `note:"Identity attached — email=<value-or-declined>, telephone=<value-or-declined>"` (use the actual values the operator supplied; for declines write the literal `declined`). One call, both fields. The note carries the operator-meaningful audit content; the step is the phase marker.
|
|
233
233
|
4. **Link the personal-profile `Person` to the `UserProfile`.** Call `memory-search` to resolve the `UserProfile` elementId for the operator (the lazy `loadUserProfile` write created it on the first admin session). Then call `memory-update` on the Person to add the `HAS_PROFILE` edge to the UserProfile. (`HAS_PROFILE` from `:Person` is a sibling pattern to the existing `AdminUser→HAS_PROFILE→UserProfile`; both are valid sources for the same edge type. See [schema-base.md Relationship Patterns](../../../memory/references/schema-base.md).)
|
|
234
234
|
5. **Close the action record.** Call `task-update` with both `appendStep:"profile-linked"` AND `note:"Profile linked — Person=<elementId>, UserProfile=<elementId>"` (the resolved elementIds from steps 2 and 4). Then call `task-complete(taskId)`.
|
|
@@ -40,7 +40,7 @@ These are enabled during onboarding and can be added or removed at any time. Som
|
|
|
40
40
|
| `waitlist` | Waitlist lifecycle — extract sign-ups from conversations, review | — |
|
|
41
41
|
| `replicate` | Image generation — three models for photorealistic, design, and fast draft images | Content producer, Research assistant |
|
|
42
42
|
| `linkedin-import` | Import a LinkedIn Basic Data Export — Profile and Connections today, more CSVs as references land | Database operator |
|
|
43
|
-
|
|
|
43
|
+
| WhatsApp `_chat.txt` archive | (No dedicated plugin.) Chat archives are document-shaped narrative content and route through the unified `document-ingest` skill with `mode='chat'` and `parentLabel='ConversationArchive'`. The skill confirms participants up front (owner + others, no auto-creation), computes `archiveSha256` for cleanup-on-re-ingest discipline, and lets `memory-classify`'s chat prompt produce `:Section:Conversation` chunks bounded by topic transitions. Distinct from the live `whatsapp` plugin (Baileys QR-pairing channel). | Database operator |
|
|
44
44
|
|
|
45
45
|
### Claude Official (marketplace)
|
|
46
46
|
|
|
@@ -20,8 +20,6 @@ tools:
|
|
|
20
20
|
- memory-edit-attachment
|
|
21
21
|
- memory-rename-attachment
|
|
22
22
|
- memory-archive-write
|
|
23
|
-
- whatsapp-export-parse
|
|
24
|
-
- whatsapp-export-insight-write
|
|
25
23
|
- conversation-list
|
|
26
24
|
- conversation-search
|
|
27
25
|
- profile-read
|
|
@@ -85,9 +83,9 @@ Graph hygiene is **agent-directed, case by case** — no autonomous rule engine,
|
|
|
85
83
|
|
|
86
84
|
The owner's profile and preferences accumulate organically from conversation — never from questionnaires. Load the conversational memory skill via `plugin-read` for full guidance on when to observe preferences, how to handle remember/forget requests, and how to answer "what do you know about me?" transparently with confidence scores and evidence trail.
|
|
87
85
|
|
|
88
|
-
## UserProfile Field Management
|
|
86
|
+
## UserProfile + Person Field Management
|
|
89
87
|
|
|
90
|
-
`profile-update` serves
|
|
88
|
+
`profile-update` serves three purposes: managing Preference nodes (category/key/value), setting top-level UserProfile node properties via `profileFields`, and setting Person properties on the operator's personal-profile Person via `personFields`.
|
|
91
89
|
|
|
92
90
|
Settable UserProfile fields: `timezone` (IANA format, e.g. `Europe/London`), `locale`, `givenName`, `role`, `expertise`. These are account metadata stored directly on the UserProfile node — distinct from Preference nodes, which represent learned behavioural patterns.
|
|
93
91
|
|
|
@@ -98,6 +96,8 @@ Example — setting a user's timezone:
|
|
|
98
96
|
|
|
99
97
|
Restricted fields (`accountId`, `embedding`, `profileVersion`) cannot be set via `profileFields`.
|
|
100
98
|
|
|
99
|
+
**Personal-profile Person via `personFields`.** The personal-profile Person is open by default — the agent decides which Person properties best help it serve this operator (identity, contact, context); the central schema validator enforces synonym + Forbidden Properties rejection (per `references/schema-base.md`). Writes route to the personal-profile Person via the OWNS edge from the AdminUser. Validation runs in `mode: "update"` so the required-property loop is skipped on partial SET (givenName/familyName were established at PIN setup). Pass any Person properties the operator volunteers; the validator surfaces synonym (e.g. `phone`) and forbidden (e.g. `name`) errors with descriptive messages. No allow-list, no enumeration — see the schema-base.md Person row notes for the doctrine.
|
|
100
|
+
|
|
101
101
|
## Schema References
|
|
102
102
|
|
|
103
103
|
Before any structured write, load `references/schema-base.md` via `plugin-read`. This defines property naming rules, required-property groups for documented types, forbidden-property rules, and relationship patterns. If the `LocalBusiness` node has a `businessType` property, also load the matching vertical schema (`references/schema-{businessType}.md`) — it extends the base with vertical-specific types. Confirm which schemas were consulted before writing.
|