@rubytech/create-maxy 1.0.884 → 1.0.886
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 +7 -0
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +21 -50
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
- package/payload/platform/scripts/__tests__/logs-read-prefix.sh +85 -240
- package/payload/platform/scripts/check-no-conversation-id-leaks.mjs +165 -0
- package/payload/platform/scripts/conversation-id-allowlist.txt +151 -0
- package/payload/platform/scripts/log-adherence-check.sh +100 -0
- package/payload/platform/scripts/logs-read.sh +71 -141
- package/payload/platform/scripts/logs-read.test.sh +47 -104
- package/payload/platform/scripts/seed-neo4j.sh +46 -0
- package/payload/premium-plugins/real-agency/BUNDLE.md +1 -1
- package/payload/server/chunk-IFMZ5I3E.js +1460 -0
- package/payload/server/chunk-MOAY7KG2.js +11667 -0
- package/payload/server/chunk-NPKQWE3S.js +1431 -0
- package/payload/server/chunk-ZVO5ASQA.js +11660 -0
- package/payload/server/client-pool-M6NS5G2U.js +34 -0
- package/payload/server/client-pool-QUMX7OUT.js +34 -0
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/server.js +181 -137
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Task
|
|
2
|
+
# Task 1006 — bash harness for logs-read.sh single-shape resolution.
|
|
3
3
|
#
|
|
4
|
-
# Covers the
|
|
5
|
-
# 1.
|
|
6
|
-
# 2.
|
|
7
|
-
# 3.
|
|
8
|
-
# 4. Both present (promotion race) → full wins + stale-preflush signal to server.log
|
|
4
|
+
# Covers the three cases the new contract demands:
|
|
5
|
+
# 1. sessionKey-named file present → bytes returned, exit 0.
|
|
6
|
+
# 2. No file → exit 1 + missing-on-resolve appended to server.log.
|
|
7
|
+
# 3. Ambiguous prefix (multiple matches) → exit 1, never picks silently.
|
|
9
8
|
#
|
|
10
9
|
# MIRROR: see platform/ui/app/lib/logs-read-resolve.ts for the canonical
|
|
11
|
-
#
|
|
10
|
+
# single-shape contract and its TS unit tests.
|
|
12
11
|
set -euo pipefail
|
|
13
12
|
|
|
14
13
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -18,28 +17,17 @@ if [[ ! -x "$LOGS_READ" ]]; then
|
|
|
18
17
|
exit 1
|
|
19
18
|
fi
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
FULL_NAME="claude-agent-stream-${CONV_ID}.log"
|
|
24
|
-
PREFLUSH_NAME="claude-agent-stream-preflush-${PREFLUSH_SLICE}.log"
|
|
25
|
-
# Task 998 — miss trailer now lists glob patterns, not literal filenames,
|
|
26
|
-
# because Pass 1 / Pass 2 prefix-glob `${prefix}${conv_id}*.log`.
|
|
27
|
-
FULL_GLOB="claude-agent-stream-${CONV_ID}*.log"
|
|
28
|
-
PREFLUSH_GLOB="claude-agent-stream-preflush-${PREFLUSH_SLICE}*.log"
|
|
20
|
+
SESSION_KEY="8c264cfb-441f-48bf-9811-9fa3ad3b51dc"
|
|
21
|
+
FILE_NAME="claude-agent-stream-${SESSION_KEY}.log"
|
|
29
22
|
|
|
30
23
|
PASS=0
|
|
31
24
|
FAIL=0
|
|
32
25
|
|
|
33
|
-
# logs-read.sh resolves PLATFORM_ROOT from the script location, and uses
|
|
34
|
-
# INSTALL_DIR = $PLATFORM_ROOT/.. and ACCOUNTS_DIR = $INSTALL_DIR/data/accounts.
|
|
35
|
-
# The test creates a fake install tree with the real script symlinked in.
|
|
36
26
|
setup_install_tree() {
|
|
37
27
|
local root="$1"
|
|
38
28
|
mkdir -p "$root/platform/scripts"
|
|
39
29
|
mkdir -p "$root/data/accounts/acct-test/logs"
|
|
40
30
|
mkdir -p "$HOME/.$(basename "$root")/logs"
|
|
41
|
-
# Symlink the script under test into the fake tree so PLATFORM_ROOT resolves
|
|
42
|
-
# to $root/platform and the account logs are discovered.
|
|
43
31
|
ln -sf "$LOGS_READ" "$root/platform/scripts/logs-read.sh"
|
|
44
32
|
echo "$root/platform/scripts/logs-read.sh"
|
|
45
33
|
}
|
|
@@ -50,8 +38,6 @@ cleanup_install_tree() {
|
|
|
50
38
|
rm -rf "$HOME/.$(basename "$root")"
|
|
51
39
|
}
|
|
52
40
|
|
|
53
|
-
# Each case uses its own ephemeral install tree. Install-tree basename is
|
|
54
|
-
# unique so configDir (~/.{installDir}) does not collide.
|
|
55
41
|
run_case() {
|
|
56
42
|
local name="$1"
|
|
57
43
|
shift
|
|
@@ -66,16 +52,16 @@ run_case() {
|
|
|
66
52
|
fi
|
|
67
53
|
}
|
|
68
54
|
|
|
69
|
-
# --- Case 1:
|
|
70
|
-
|
|
55
|
+
# --- Case 1: sessionKey-named file present → exit 0 ---
|
|
56
|
+
case_file_present() {
|
|
71
57
|
local root="/tmp/maxy-logs-read-test-1-$$"
|
|
72
58
|
local script
|
|
73
59
|
script=$(setup_install_tree "$root")
|
|
74
60
|
local logdir="$root/data/accounts/acct-test/logs"
|
|
75
|
-
echo "
|
|
61
|
+
echo "sessionkey-content-sentinel" > "$logdir/$FILE_NAME"
|
|
76
62
|
|
|
77
63
|
local stdout stderr rc
|
|
78
|
-
stdout=$("$script" "$
|
|
64
|
+
stdout=$("$script" "$SESSION_KEY" system 2>/tmp/maxy-logs-read-stderr-1-$$) || rc=$?
|
|
79
65
|
rc=${rc:-0}
|
|
80
66
|
stderr=$(cat /tmp/maxy-logs-read-stderr-1-$$)
|
|
81
67
|
rm -f /tmp/maxy-logs-read-stderr-1-$$
|
|
@@ -86,56 +72,66 @@ case_full_only() {
|
|
|
86
72
|
echo " expected exit 0, got $rc"
|
|
87
73
|
return 1
|
|
88
74
|
fi
|
|
89
|
-
if [[ "$stdout" != *"
|
|
75
|
+
if [[ "$stdout" != *"sessionkey-content-sentinel"* ]]; then
|
|
90
76
|
echo " stdout missing sentinel"
|
|
91
77
|
return 1
|
|
92
78
|
fi
|
|
93
|
-
if [[ "$stderr" != *"
|
|
94
|
-
echo " stderr missing
|
|
79
|
+
if [[ "$stderr" != *"matched=1"* ]]; then
|
|
80
|
+
echo " stderr missing matched=1: $stderr"
|
|
95
81
|
return 1
|
|
96
82
|
fi
|
|
97
83
|
return 0
|
|
98
84
|
}
|
|
99
85
|
|
|
100
|
-
# --- Case 2:
|
|
101
|
-
|
|
86
|
+
# --- Case 2: no file → exit 1 + missing-on-resolve in server.log ---
|
|
87
|
+
case_missing() {
|
|
102
88
|
local root="/tmp/maxy-logs-read-test-2-$$"
|
|
103
89
|
local script
|
|
104
90
|
script=$(setup_install_tree "$root")
|
|
105
|
-
local
|
|
106
|
-
|
|
91
|
+
local server_log="$HOME/.$(basename "$root")/logs/server.log"
|
|
92
|
+
: > "$server_log"
|
|
107
93
|
|
|
108
|
-
local
|
|
109
|
-
|
|
110
|
-
|
|
94
|
+
local rc=0
|
|
95
|
+
"$script" "$SESSION_KEY" system >/dev/null 2>/tmp/maxy-logs-read-stderr-2-$$ || rc=$?
|
|
96
|
+
local stderr
|
|
111
97
|
stderr=$(cat /tmp/maxy-logs-read-stderr-2-$$)
|
|
112
98
|
rm -f /tmp/maxy-logs-read-stderr-2-$$
|
|
99
|
+
local server_log_contents
|
|
100
|
+
server_log_contents=$(cat "$server_log" 2>/dev/null || echo "")
|
|
113
101
|
|
|
114
102
|
cleanup_install_tree "$root"
|
|
115
103
|
|
|
116
|
-
if [[ $rc -ne
|
|
117
|
-
echo " expected exit
|
|
104
|
+
if [[ $rc -ne 1 ]]; then
|
|
105
|
+
echo " expected exit 1, got $rc"
|
|
118
106
|
return 1
|
|
119
107
|
fi
|
|
120
|
-
if [[ "$
|
|
121
|
-
echo "
|
|
108
|
+
if [[ "$stderr" != *"reason=file-not-found"* ]]; then
|
|
109
|
+
echo " stderr missing reason=file-not-found: $stderr"
|
|
122
110
|
return 1
|
|
123
111
|
fi
|
|
124
|
-
if [[ "$
|
|
125
|
-
echo "
|
|
112
|
+
if [[ "$server_log_contents" != *"missing-on-resolve"* ]]; then
|
|
113
|
+
echo " server.log missing missing-on-resolve emission: $server_log_contents"
|
|
114
|
+
return 1
|
|
115
|
+
fi
|
|
116
|
+
if [[ "$server_log_contents" != *"surface=logs-read-sh"* ]]; then
|
|
117
|
+
echo " server.log emission missing surface tag"
|
|
126
118
|
return 1
|
|
127
119
|
fi
|
|
128
120
|
return 0
|
|
129
121
|
}
|
|
130
122
|
|
|
131
|
-
# --- Case 3:
|
|
132
|
-
|
|
123
|
+
# --- Case 3: ambiguous prefix → exit 1 without picking ---
|
|
124
|
+
case_ambiguous() {
|
|
133
125
|
local root="/tmp/maxy-logs-read-test-3-$$"
|
|
134
126
|
local script
|
|
135
127
|
script=$(setup_install_tree "$root")
|
|
128
|
+
local logdir="$root/data/accounts/acct-test/logs"
|
|
129
|
+
echo "a" > "$logdir/claude-agent-stream-deadbeef-aaaa.log"
|
|
130
|
+
echo "b" > "$logdir/claude-agent-stream-deadbeef-bbbb.log"
|
|
136
131
|
|
|
137
|
-
local
|
|
138
|
-
|
|
132
|
+
local rc=0
|
|
133
|
+
"$script" "deadbeef" system >/dev/null 2>/tmp/maxy-logs-read-stderr-3-$$ || rc=$?
|
|
134
|
+
local stderr
|
|
139
135
|
stderr=$(cat /tmp/maxy-logs-read-stderr-3-$$)
|
|
140
136
|
rm -f /tmp/maxy-logs-read-stderr-3-$$
|
|
141
137
|
|
|
@@ -145,69 +141,16 @@ case_neither() {
|
|
|
145
141
|
echo " expected exit 1, got $rc"
|
|
146
142
|
return 1
|
|
147
143
|
fi
|
|
148
|
-
if [[ "$stderr" != *"
|
|
149
|
-
echo " stderr missing
|
|
150
|
-
return 1
|
|
151
|
-
fi
|
|
152
|
-
if [[ "$stderr" != *"reason=file-not-found-in-either-shape"* ]]; then
|
|
153
|
-
echo " stderr missing reason=file-not-found-in-either-shape: $stderr"
|
|
154
|
-
return 1
|
|
155
|
-
fi
|
|
156
|
-
return 0
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
# --- Case 4: both present (promotion race) → full wins + stale signal ---
|
|
160
|
-
case_both_present() {
|
|
161
|
-
local root="/tmp/maxy-logs-read-test-4-$$"
|
|
162
|
-
local script
|
|
163
|
-
script=$(setup_install_tree "$root")
|
|
164
|
-
local logdir="$root/data/accounts/acct-test/logs"
|
|
165
|
-
echo "full-content-sentinel-4" > "$logdir/$FULL_NAME"
|
|
166
|
-
echo "preflush-content-sentinel-4" > "$logdir/$PREFLUSH_NAME"
|
|
167
|
-
local server_log="$HOME/.$(basename "$root")/logs/server.log"
|
|
168
|
-
: > "$server_log"
|
|
169
|
-
|
|
170
|
-
local stdout stderr rc=0
|
|
171
|
-
stdout=$("$script" "$CONV_ID" system 2>/tmp/maxy-logs-read-stderr-4-$$) || rc=$?
|
|
172
|
-
stderr=$(cat /tmp/maxy-logs-read-stderr-4-$$)
|
|
173
|
-
rm -f /tmp/maxy-logs-read-stderr-4-$$
|
|
174
|
-
|
|
175
|
-
local server_log_contents
|
|
176
|
-
server_log_contents=$(cat "$server_log" 2>/dev/null || echo "")
|
|
177
|
-
|
|
178
|
-
cleanup_install_tree "$root"
|
|
179
|
-
|
|
180
|
-
if [[ $rc -ne 0 ]]; then
|
|
181
|
-
echo " expected exit 0, got $rc"
|
|
182
|
-
return 1
|
|
183
|
-
fi
|
|
184
|
-
if [[ "$stdout" != *"full-content-sentinel-4"* ]]; then
|
|
185
|
-
echo " stdout missing full sentinel (full must win): $stdout"
|
|
186
|
-
return 1
|
|
187
|
-
fi
|
|
188
|
-
if [[ "$stdout" == *"preflush-content-sentinel-4"* ]]; then
|
|
189
|
-
echo " stdout contained preflush sentinel — preflush must be ignored when full exists"
|
|
190
|
-
return 1
|
|
191
|
-
fi
|
|
192
|
-
if [[ "$stderr" != *"matched_shape=full"* ]]; then
|
|
193
|
-
echo " stderr missing matched_shape=full"
|
|
194
|
-
return 1
|
|
195
|
-
fi
|
|
196
|
-
if [[ "$server_log_contents" != *"stale-preflush-detected"* ]]; then
|
|
197
|
-
echo " server.log missing stale-preflush-detected signal: $server_log_contents"
|
|
198
|
-
return 1
|
|
199
|
-
fi
|
|
200
|
-
if [[ "$server_log_contents" != *"$PREFLUSH_NAME"* ]]; then
|
|
201
|
-
echo " server.log stale signal missing preflush path"
|
|
144
|
+
if [[ "$stderr" != *"reason=ambiguous-prefix"* ]]; then
|
|
145
|
+
echo " stderr missing ambiguous-prefix trailer: $stderr"
|
|
202
146
|
return 1
|
|
203
147
|
fi
|
|
204
148
|
return 0
|
|
205
149
|
}
|
|
206
150
|
|
|
207
|
-
run_case "
|
|
208
|
-
run_case "
|
|
209
|
-
run_case "
|
|
210
|
-
run_case "both present → full wins + stale signal" case_both_present
|
|
151
|
+
run_case "sessionKey file present → exit 0" case_file_present
|
|
152
|
+
run_case "no file → exit 1 + missing-on-resolve" case_missing
|
|
153
|
+
run_case "ambiguous prefix → exit 1, refuses to pick" case_ambiguous
|
|
211
154
|
|
|
212
155
|
echo ""
|
|
213
156
|
echo "================================================"
|
|
@@ -490,6 +490,52 @@ fi
|
|
|
490
490
|
|
|
491
491
|
echo "$SCHEMA_CYPHER" | "$CYPHER_SHELL" -u "$NEO4J_USER" -p "$NEO4J_PASSWORD" -a "$NEO4J_URI"
|
|
492
492
|
|
|
493
|
+
# ------------------------------------------------------------------
|
|
494
|
+
# Task 1007 — sessionKey backfill (idempotent, runs every seed pass).
|
|
495
|
+
#
|
|
496
|
+
# Conversation and Message rows minted before Task 985 carry only
|
|
497
|
+
# `conversationId`. The new canonical identifier is `sessionKey` (same
|
|
498
|
+
# UUID shape). This block copies conversationId → sessionKey on every
|
|
499
|
+
# row where sessionKey is still null, leaving rows that already carry
|
|
500
|
+
# sessionKey untouched. Re-runs are no-ops. The legacy
|
|
501
|
+
# `conversation_id_unique` constraint and `m.conversationId` index
|
|
502
|
+
# stay until the full code-rename slice lands and no path reads the
|
|
503
|
+
# legacy field; the drop happens in Task 1007's open completion scope.
|
|
504
|
+
# ------------------------------------------------------------------
|
|
505
|
+
echo "==> Backfilling sessionKey on :Conversation and :Message..."
|
|
506
|
+
BACKFILL_RESULT=$("$CYPHER_SHELL" -u "$NEO4J_USER" -p "$NEO4J_PASSWORD" -a "$NEO4J_URI" --format plain << 'BACKFILL_EOF'
|
|
507
|
+
MATCH (c:Conversation)
|
|
508
|
+
WHERE c.sessionKey IS NULL AND c.conversationId IS NOT NULL
|
|
509
|
+
SET c.sessionKey = c.conversationId
|
|
510
|
+
RETURN count(c) AS conversations_backfilled;
|
|
511
|
+
MATCH (m:Message)
|
|
512
|
+
WHERE m.sessionKey IS NULL AND m.conversationId IS NOT NULL
|
|
513
|
+
SET m.sessionKey = m.conversationId
|
|
514
|
+
RETURN count(m) AS messages_backfilled;
|
|
515
|
+
MATCH (c:Conversation) WHERE c.sessionKey IS NULL RETURN count(c) AS conversations_null_after;
|
|
516
|
+
MATCH (m:Message) WHERE m.sessionKey IS NULL RETURN count(m) AS messages_null_after;
|
|
517
|
+
BACKFILL_EOF
|
|
518
|
+
)
|
|
519
|
+
# Emit the migration-1007 adherence lines on stderr so they land in server.log
|
|
520
|
+
# the same as every other log line. Non-zero null counts after backfill are P0:
|
|
521
|
+
# they indicate orphan rows that carry neither identifier and need operator
|
|
522
|
+
# attention before the constraint flip in Task 1011.
|
|
523
|
+
echo "$BACKFILL_RESULT" | python3 -c "
|
|
524
|
+
import sys, re
|
|
525
|
+
rows = [r.strip() for r in sys.stdin.read().splitlines() if r.strip() and not r.strip().startswith(('conversations_', 'messages_'))]
|
|
526
|
+
nums = [int(r) for r in rows if re.fullmatch(r'\d+', r)]
|
|
527
|
+
if len(nums) >= 4:
|
|
528
|
+
conv_bf, msg_bf, conv_null, msg_null = nums[0], nums[1], nums[2], nums[3]
|
|
529
|
+
print(f'[migration-1007] conversation-row-backfill rows={conv_bf} outcome=ok', file=sys.stderr)
|
|
530
|
+
print(f'[migration-1007] message-row-backfill rows={msg_bf} outcome=ok', file=sys.stderr)
|
|
531
|
+
print(f'[migration-1007] adherence-check label=Conversation rows-with-null-sessionkey={conv_null}', file=sys.stderr)
|
|
532
|
+
print(f'[migration-1007] adherence-check label=Message rows-with-null-sessionkey={msg_null}', file=sys.stderr)
|
|
533
|
+
if conv_null > 0 or msg_null > 0:
|
|
534
|
+
print(f'[migration-1007] adherence-check P0=true reason=null-sessionkey-after-backfill', file=sys.stderr)
|
|
535
|
+
else:
|
|
536
|
+
print(f'[migration-1007] backfill output unparseable rows={len(nums)}', file=sys.stderr)
|
|
537
|
+
"
|
|
538
|
+
|
|
493
539
|
# ------------------------------------------------------------------
|
|
494
540
|
# 3. Create AdminUser node + ADMIN_OF relationship
|
|
495
541
|
# ------------------------------------------------------------------
|
|
@@ -17,7 +17,7 @@ plugins:
|
|
|
17
17
|
|
|
18
18
|
# Real Agency
|
|
19
19
|
|
|
20
|
-
Premium plugin bundle for UK estate agency professionals. Purchasing this bundle grants access to all 11 sub-plugins, each independently activatable via `enabledPlugins`.
|
|
20
|
+
Premium plugin bundle for UK estate agency professionals. Purchasing this bundle grants access to all 11 sub-plugins, each independently activatable via `enabledPlugins`. Every admin boot reconciles `account.json` `enabledPlugins` against on-disk presence: any sub-plugin from the `plugins:` list above whose `platform/plugins/<sub>/PLUGIN.md` exists gets stamped via an idempotent set-union, so `mcp__loop__*` tools and the other sub-plugin surfaces are visible to the admin agent from the first turn after install — and on first boot post-deploy for accounts that already had the bundle on disk from a prior install. Disable individual sub-plugins with `plugin-toggle-enabled`. The bundle also delivers three specialist roles (negotiator, valuer, and compliance) that embed domain knowledge from the sub-plugins and operate autonomously with Loop CRM tools.
|
|
21
21
|
|
|
22
22
|
## Specialist Roles
|
|
23
23
|
|