@rubytech/create-maxy 1.0.883 → 1.0.885
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/lib/graph-mcp/dist/index.js +45 -0
- package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-mcp/src/index.ts +47 -0
- package/payload/platform/lib/mcp-eager/dist/index.d.ts +61 -0
- package/payload/platform/lib/mcp-eager/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/mcp-eager/dist/index.js +49 -0
- package/payload/platform/lib/mcp-eager/dist/index.js.map +1 -0
- package/payload/platform/lib/mcp-eager/src/index.ts +78 -0
- package/payload/platform/lib/mcp-eager/tsconfig.json +8 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +48 -76
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/index.js +10 -9
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/docs/references/internals.md +13 -0
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
- package/payload/platform/plugins/email/mcp/dist/index.js +10 -9
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +9 -8
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +9 -8
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/tasks/mcp/dist/index.js +15 -14
- package/payload/platform/plugins/tasks/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/index.js +4 -3
- package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/index.js +9 -8
- package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -1
- package/payload/platform/scripts/__tests__/logs-read-prefix.sh +85 -240
- 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/premium-plugins/real-agency/BUNDLE.md +1 -1
- package/payload/server/chunk-5PQU2HW2.js +11672 -0
- package/payload/server/chunk-NPKQWE3S.js +1431 -0
- package/payload/server/chunk-ZVO5ASQA.js +11660 -0
- package/payload/server/client-pool-QUMX7OUT.js +34 -0
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/server.js +123 -121
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Task
|
|
2
|
+
# Task 1006 — prefix-match harness for logs-read.sh.
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# 3. More-specific prefix disambiguates
|
|
8
|
-
# 4. Zero matches → reason=file-not-found-in-either-shape with glob patterns
|
|
9
|
-
# 5. Full 36-char UUID still resolves (regression boundary)
|
|
10
|
-
# 6. Preflush prefix match
|
|
11
|
-
# 7. Preflush ambiguity (Pass 1 zero, Pass 2 multiple)
|
|
12
|
-
# 8. Every per-conversation type (agent-stream, session, error, public)
|
|
13
|
-
# resolves under prefix-match
|
|
4
|
+
# Task 998 introduced 8-char-prefix resolution; Task 1006 collapses the
|
|
5
|
+
# writer's two-shape contract to one (`claude-agent-stream-<sessionKey>.log`).
|
|
6
|
+
# The prefix match still applies, now against a single basename shape.
|
|
14
7
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
8
|
+
# Cases:
|
|
9
|
+
# 1. 8-char prefix resolves a full sessionKey-named file.
|
|
10
|
+
# 2. Multiple matches → ambiguous-prefix, exit 1, never picks silently.
|
|
11
|
+
# 3. More-specific prefix disambiguates.
|
|
12
|
+
# 4. Zero matches → exit 1 with file-not-found trailer.
|
|
13
|
+
# 5. Full 36-char sessionKey still resolves (regression boundary).
|
|
14
|
+
# 6. Every per-session type (agent-stream, session, error, public)
|
|
15
|
+
# resolves under prefix-match.
|
|
17
16
|
set -euo pipefail
|
|
18
17
|
|
|
19
18
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -26,9 +25,6 @@ fi
|
|
|
26
25
|
PASS=0
|
|
27
26
|
FAIL=0
|
|
28
27
|
|
|
29
|
-
# logs-read.sh resolves PLATFORM_ROOT from its own location; mirror the
|
|
30
|
-
# logs-read.test.sh convention by symlinking the script into an ephemeral
|
|
31
|
-
# install tree per case.
|
|
32
28
|
setup_install_tree() {
|
|
33
29
|
local root="$1"
|
|
34
30
|
mkdir -p "$root/platform/scripts"
|
|
@@ -58,281 +54,130 @@ run_case() {
|
|
|
58
54
|
fi
|
|
59
55
|
}
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
local root="/tmp/maxy-logs-read-prefix-1-$$"
|
|
57
|
+
case_8char_prefix_resolves_full() {
|
|
58
|
+
local root="/tmp/maxy-prefix-test-1-$$"
|
|
64
59
|
local script
|
|
65
60
|
script=$(setup_install_tree "$root")
|
|
66
61
|
local logdir="$root/data/accounts/acct-test/logs"
|
|
67
|
-
local
|
|
68
|
-
|
|
69
|
-
echo "prefix-match-sentinel" > "$logdir/$filename"
|
|
70
|
-
|
|
71
|
-
local stdout stderr rc=0
|
|
72
|
-
stdout=$("$script" "3483269d" system 2>/tmp/logs-read-prefix-stderr-1-$$) || rc=$?
|
|
73
|
-
stderr=$(cat /tmp/logs-read-prefix-stderr-1-$$)
|
|
74
|
-
rm -f /tmp/logs-read-prefix-stderr-1-$$
|
|
62
|
+
local sk="abcd1234-5678-90ab-cdef-1234567890ab"
|
|
63
|
+
echo "sentinel-1" > "$logdir/claude-agent-stream-${sk}.log"
|
|
75
64
|
|
|
65
|
+
local rc=0
|
|
66
|
+
local stdout
|
|
67
|
+
stdout=$("$script" "abcd1234" agent-stream 2>/dev/null) || rc=$?
|
|
76
68
|
cleanup_install_tree "$root"
|
|
77
69
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
echo " stdout missing sentinel: $stdout"; return 1
|
|
81
|
-
fi
|
|
82
|
-
if [[ "$stderr" != *"matched_shape=full"* ]]; then
|
|
83
|
-
echo " stderr missing matched_shape=full: $stderr"; return 1
|
|
84
|
-
fi
|
|
85
|
-
if [[ "$stdout" != *"$filename"* ]]; then
|
|
86
|
-
echo " header missing matched filename: $stdout"; return 1
|
|
87
|
-
fi
|
|
70
|
+
[[ $rc -eq 0 ]] || { echo " expected exit 0, got $rc"; return 1; }
|
|
71
|
+
[[ "$stdout" == *"sentinel-1"* ]] || { echo " missing sentinel"; return 1; }
|
|
88
72
|
return 0
|
|
89
73
|
}
|
|
90
74
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
local root="/tmp/maxy-logs-read-prefix-2-$$"
|
|
75
|
+
case_ambiguous_prefix_refuses() {
|
|
76
|
+
local root="/tmp/maxy-prefix-test-2-$$"
|
|
94
77
|
local script
|
|
95
78
|
script=$(setup_install_tree "$root")
|
|
96
79
|
local logdir="$root/data/accounts/acct-test/logs"
|
|
97
|
-
echo "
|
|
98
|
-
echo "
|
|
99
|
-
|
|
100
|
-
local
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
80
|
+
echo "a" > "$logdir/claude-agent-stream-abcd1111.log"
|
|
81
|
+
echo "b" > "$logdir/claude-agent-stream-abcd2222.log"
|
|
82
|
+
|
|
83
|
+
local rc=0
|
|
84
|
+
"$script" "abcd" agent-stream >/dev/null 2>/tmp/prefix-stderr-2-$$ || rc=$?
|
|
85
|
+
local stderr
|
|
86
|
+
stderr=$(cat /tmp/prefix-stderr-2-$$)
|
|
87
|
+
rm -f /tmp/prefix-stderr-2-$$
|
|
105
88
|
cleanup_install_tree "$root"
|
|
106
89
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
echo " stderr missing reason=ambiguous-prefix: $stderr"; return 1
|
|
110
|
-
fi
|
|
111
|
-
if [[ "$stderr" != *"matches=2"* ]]; then
|
|
112
|
-
echo " stderr missing matches=2: $stderr"; return 1
|
|
113
|
-
fi
|
|
114
|
-
if [[ "$stderr" != *"claude-agent-stream-aaaaaaaa-1111-A.log"* ]]; then
|
|
115
|
-
echo " stderr missing candidate A: $stderr"; return 1
|
|
116
|
-
fi
|
|
117
|
-
if [[ "$stderr" != *"claude-agent-stream-aaaaaaaa-2222-B.log"* ]]; then
|
|
118
|
-
echo " stderr missing candidate B: $stderr"; return 1
|
|
119
|
-
fi
|
|
120
|
-
# Body must NOT contain either sentinel — refusal means no body emitted.
|
|
121
|
-
if [[ -n "$stdout" ]]; then
|
|
122
|
-
echo " stdout non-empty on ambiguous refusal: $stdout"; return 1
|
|
123
|
-
fi
|
|
90
|
+
[[ $rc -eq 1 ]] || { echo " expected exit 1, got $rc"; return 1; }
|
|
91
|
+
[[ "$stderr" == *"ambiguous-prefix"* ]] || { echo " stderr missing ambiguous-prefix: $stderr"; return 1; }
|
|
124
92
|
return 0
|
|
125
93
|
}
|
|
126
94
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
local root="/tmp/maxy-logs-read-prefix-3-$$"
|
|
95
|
+
case_more_specific_prefix_resolves() {
|
|
96
|
+
local root="/tmp/maxy-prefix-test-3-$$"
|
|
130
97
|
local script
|
|
131
98
|
script=$(setup_install_tree "$root")
|
|
132
99
|
local logdir="$root/data/accounts/acct-test/logs"
|
|
133
|
-
echo "
|
|
134
|
-
echo "
|
|
135
|
-
|
|
136
|
-
local stdout stderr rc=0
|
|
137
|
-
stdout=$("$script" "aaaaaaaa-1111" system 2>/tmp/logs-read-prefix-stderr-3-$$) || rc=$?
|
|
138
|
-
stderr=$(cat /tmp/logs-read-prefix-stderr-3-$$)
|
|
139
|
-
rm -f /tmp/logs-read-prefix-stderr-3-$$
|
|
100
|
+
echo "a" > "$logdir/claude-agent-stream-abcd1111.log"
|
|
101
|
+
echo "b" > "$logdir/claude-agent-stream-abcd2222.log"
|
|
140
102
|
|
|
103
|
+
local rc=0
|
|
104
|
+
local stdout
|
|
105
|
+
stdout=$("$script" "abcd1111" agent-stream 2>/dev/null) || rc=$?
|
|
141
106
|
cleanup_install_tree "$root"
|
|
142
107
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if [[ "$stdout" == *"TWO"* ]]; then echo " stdout contained TWO: $stdout"; return 1; fi
|
|
146
|
-
if [[ "$stderr" != *"matched_shape=full"* ]]; then
|
|
147
|
-
echo " stderr missing matched_shape=full: $stderr"; return 1
|
|
148
|
-
fi
|
|
108
|
+
[[ $rc -eq 0 ]] || { echo " expected exit 0, got $rc"; return 1; }
|
|
109
|
+
[[ "$stdout" == *"a"* ]] || { echo " missing sentinel"; return 1; }
|
|
149
110
|
return 0
|
|
150
111
|
}
|
|
151
112
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
local root="/tmp/maxy-logs-read-prefix-4-$$"
|
|
113
|
+
case_zero_match_miss() {
|
|
114
|
+
local root="/tmp/maxy-prefix-test-4-$$"
|
|
155
115
|
local script
|
|
156
116
|
script=$(setup_install_tree "$root")
|
|
157
117
|
|
|
158
|
-
local
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
118
|
+
local rc=0
|
|
119
|
+
"$script" "nomatch1" agent-stream >/dev/null 2>/tmp/prefix-stderr-4-$$ || rc=$?
|
|
120
|
+
local stderr
|
|
121
|
+
stderr=$(cat /tmp/prefix-stderr-4-$$)
|
|
122
|
+
rm -f /tmp/prefix-stderr-4-$$
|
|
163
123
|
cleanup_install_tree "$root"
|
|
164
124
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
echo " stderr missing reason=file-not-found-in-either-shape: $stderr"; return 1
|
|
168
|
-
fi
|
|
169
|
-
if [[ "$stderr" != *"tried=[claude-agent-stream-xxxxxxxx*.log, claude-agent-stream-preflush-xxxxxxxx*.log]"* ]]; then
|
|
170
|
-
echo " stderr missing tried=[<glob>, <glob>]: $stderr"; return 1
|
|
171
|
-
fi
|
|
125
|
+
[[ $rc -eq 1 ]] || { echo " expected exit 1, got $rc"; return 1; }
|
|
126
|
+
[[ "$stderr" == *"file-not-found"* ]] || { echo " stderr missing file-not-found"; return 1; }
|
|
172
127
|
return 0
|
|
173
128
|
}
|
|
174
129
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
local root="/tmp/maxy-logs-read-prefix-5-$$"
|
|
130
|
+
case_full_sessionkey_resolves() {
|
|
131
|
+
local root="/tmp/maxy-prefix-test-5-$$"
|
|
178
132
|
local script
|
|
179
133
|
script=$(setup_install_tree "$root")
|
|
180
134
|
local logdir="$root/data/accounts/acct-test/logs"
|
|
181
|
-
local
|
|
182
|
-
|
|
183
|
-
echo "regression-sentinel" > "$logdir/$filename"
|
|
184
|
-
|
|
185
|
-
local stdout stderr rc=0
|
|
186
|
-
stdout=$("$script" "$full_uuid" system 2>/tmp/logs-read-prefix-stderr-5-$$) || rc=$?
|
|
187
|
-
stderr=$(cat /tmp/logs-read-prefix-stderr-5-$$)
|
|
188
|
-
rm -f /tmp/logs-read-prefix-stderr-5-$$
|
|
135
|
+
local sk="11111111-2222-3333-4444-555555555555"
|
|
136
|
+
echo "sentinel-5" > "$logdir/claude-agent-stream-${sk}.log"
|
|
189
137
|
|
|
138
|
+
local rc=0
|
|
139
|
+
local stdout
|
|
140
|
+
stdout=$("$script" "$sk" agent-stream 2>/dev/null) || rc=$?
|
|
190
141
|
cleanup_install_tree "$root"
|
|
191
142
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
echo " stdout missing sentinel: $stdout"; return 1
|
|
195
|
-
fi
|
|
196
|
-
if [[ "$stderr" != *"matched_shape=full"* ]]; then
|
|
197
|
-
echo " stderr missing matched_shape=full: $stderr"; return 1
|
|
198
|
-
fi
|
|
143
|
+
[[ $rc -eq 0 ]] || { echo " expected exit 0, got $rc"; return 1; }
|
|
144
|
+
[[ "$stdout" == *"sentinel-5"* ]] || { echo " missing sentinel"; return 1; }
|
|
199
145
|
return 0
|
|
200
146
|
}
|
|
201
147
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
local root="/tmp/maxy-logs-read-prefix-6-$$"
|
|
148
|
+
case_every_per_session_type() {
|
|
149
|
+
local root="/tmp/maxy-prefix-test-6-$$"
|
|
205
150
|
local script
|
|
206
151
|
script=$(setup_install_tree "$root")
|
|
207
152
|
local logdir="$root/data/accounts/acct-test/logs"
|
|
208
|
-
|
|
209
|
-
echo "
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
fi
|
|
225
|
-
return 0
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
# --- Case 7: preflush ambiguity (Pass 1 zero, Pass 2 multiple) ---
|
|
229
|
-
case_preflush_ambiguity() {
|
|
230
|
-
local root="/tmp/maxy-logs-read-prefix-7-$$"
|
|
231
|
-
local script
|
|
232
|
-
script=$(setup_install_tree "$root")
|
|
233
|
-
local logdir="$root/data/accounts/acct-test/logs"
|
|
234
|
-
echo "P1" > "$logdir/claude-agent-stream-preflush-cccccccc-111.log"
|
|
235
|
-
echo "P2" > "$logdir/claude-agent-stream-preflush-cccccccc-222.log"
|
|
236
|
-
|
|
237
|
-
local stdout stderr rc=0
|
|
238
|
-
stdout=$("$script" "cccccccc" system 2>/tmp/logs-read-prefix-stderr-7-$$) || rc=$?
|
|
239
|
-
stderr=$(cat /tmp/logs-read-prefix-stderr-7-$$)
|
|
240
|
-
rm -f /tmp/logs-read-prefix-stderr-7-$$
|
|
241
|
-
|
|
242
|
-
cleanup_install_tree "$root"
|
|
243
|
-
|
|
244
|
-
if [[ $rc -ne 1 ]]; then echo " expected exit 1, got $rc"; return 1; fi
|
|
245
|
-
if [[ "$stderr" != *"reason=ambiguous-prefix"* ]]; then
|
|
246
|
-
echo " stderr missing reason=ambiguous-prefix: $stderr"; return 1
|
|
247
|
-
fi
|
|
248
|
-
if [[ "$stderr" != *"matches=2"* ]]; then
|
|
249
|
-
echo " stderr missing matches=2: $stderr"; return 1
|
|
250
|
-
fi
|
|
251
|
-
if [[ "$stderr" != *"claude-agent-stream-preflush-cccccccc-111.log"* ]]; then
|
|
252
|
-
echo " stderr missing preflush candidate 1: $stderr"; return 1
|
|
253
|
-
fi
|
|
254
|
-
if [[ "$stderr" != *"claude-agent-stream-preflush-cccccccc-222.log"* ]]; then
|
|
255
|
-
echo " stderr missing preflush candidate 2: $stderr"; return 1
|
|
256
|
-
fi
|
|
257
|
-
return 0
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
# --- Case 8: every per-conversation type resolves under prefix-match ---
|
|
261
|
-
# Parameterised over the four prefix_for_type values:
|
|
262
|
-
# agent-stream → claude-agent-stream-
|
|
263
|
-
# session → sse-events-
|
|
264
|
-
# error → claude-agent-stderr-
|
|
265
|
-
# public → public-agent-stream-
|
|
266
|
-
case_all_types_prefix_match() {
|
|
267
|
-
local root="/tmp/maxy-logs-read-prefix-8-$$"
|
|
268
|
-
local script
|
|
269
|
-
script=$(setup_install_tree "$root")
|
|
270
|
-
local logdir="$root/data/accounts/acct-test/logs"
|
|
271
|
-
local full_uuid="7d49ef21-1234-4567-89ab-cdef01234567"
|
|
272
|
-
|
|
273
|
-
echo "sentinel-agent-stream" > "$logdir/claude-agent-stream-${full_uuid}.log"
|
|
274
|
-
echo "sentinel-session" > "$logdir/sse-events-${full_uuid}.log"
|
|
275
|
-
echo "sentinel-error" > "$logdir/claude-agent-stderr-${full_uuid}.log"
|
|
276
|
-
echo "sentinel-public" > "$logdir/public-agent-stream-${full_uuid}.log"
|
|
277
|
-
|
|
278
|
-
local pairs=(
|
|
279
|
-
"agent-stream|sentinel-agent-stream"
|
|
280
|
-
"session|sentinel-session"
|
|
281
|
-
"error|sentinel-error"
|
|
282
|
-
"public|sentinel-public"
|
|
283
|
-
)
|
|
284
|
-
local fail=0
|
|
285
|
-
local pair t expected_sentinel
|
|
286
|
-
for pair in "${pairs[@]}"; do
|
|
287
|
-
t="${pair%%|*}"
|
|
288
|
-
expected_sentinel="${pair##*|}"
|
|
289
|
-
local stdout stderr rc=0
|
|
290
|
-
stdout=$("$script" "7d49ef21" "$t" 2>/tmp/logs-read-prefix-stderr-8-$$) || rc=$?
|
|
291
|
-
stderr=$(cat /tmp/logs-read-prefix-stderr-8-$$)
|
|
292
|
-
rm -f /tmp/logs-read-prefix-stderr-8-$$
|
|
293
|
-
if [[ $rc -ne 0 ]]; then echo " [$t] expected exit 0, got $rc — stderr: $stderr"; fail=1; continue; fi
|
|
294
|
-
if [[ "$stdout" != *"$expected_sentinel"* ]]; then
|
|
295
|
-
echo " [$t] missing sentinel '$expected_sentinel': $stdout"; fail=1
|
|
296
|
-
fi
|
|
297
|
-
if [[ "$stderr" != *"matched_shape=full"* ]]; then
|
|
298
|
-
echo " [$t] stderr missing matched_shape=full: $stderr"; fail=1
|
|
299
|
-
fi
|
|
153
|
+
local sk="abcdef00-0000-0000-0000-000000000000"
|
|
154
|
+
echo "stream" > "$logdir/claude-agent-stream-${sk}.log"
|
|
155
|
+
echo "err" > "$logdir/claude-agent-stderr-${sk}.log"
|
|
156
|
+
echo "sse" > "$logdir/sse-events-${sk}.log"
|
|
157
|
+
echo "pub" > "$logdir/public-agent-stream-${sk}.log"
|
|
158
|
+
|
|
159
|
+
local ok=1
|
|
160
|
+
for type in agent-stream error session public; do
|
|
161
|
+
local out
|
|
162
|
+
out=$("$script" "abcdef00" "$type" 2>/dev/null) || ok=0
|
|
163
|
+
case "$type" in
|
|
164
|
+
agent-stream) [[ "$out" == *"stream"* ]] || ok=0 ;;
|
|
165
|
+
error) [[ "$out" == *"err"* ]] || ok=0 ;;
|
|
166
|
+
session) [[ "$out" == *"sse"* ]] || ok=0 ;;
|
|
167
|
+
public) [[ "$out" == *"pub"* ]] || ok=0 ;;
|
|
168
|
+
esac
|
|
300
169
|
done
|
|
301
|
-
|
|
302
|
-
cleanup_install_tree "$root"
|
|
303
|
-
[[ $fail -eq 0 ]]
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
# --- Case 9: conv_id with shell metacharacters is rejected ---
|
|
307
|
-
case_metacharacter_rejected() {
|
|
308
|
-
local root="/tmp/maxy-logs-read-prefix-9-$$"
|
|
309
|
-
local script
|
|
310
|
-
script=$(setup_install_tree "$root")
|
|
311
|
-
|
|
312
|
-
local stdout stderr rc=0
|
|
313
|
-
# Use a backslash-escaped wildcard to feed it as a literal argument.
|
|
314
|
-
stdout=$("$script" "ab*cd" system 2>/tmp/logs-read-prefix-stderr-9-$$) || rc=$?
|
|
315
|
-
stderr=$(cat /tmp/logs-read-prefix-stderr-9-$$)
|
|
316
|
-
rm -f /tmp/logs-read-prefix-stderr-9-$$
|
|
317
|
-
|
|
318
170
|
cleanup_install_tree "$root"
|
|
319
|
-
|
|
320
|
-
if [[ $rc -ne 2 ]]; then echo " expected exit 2 (usage), got $rc"; return 1; fi
|
|
321
|
-
if [[ "$stderr" != *"invalid characters"* ]]; then
|
|
322
|
-
echo " stderr missing invalid-characters guard: $stderr"; return 1
|
|
323
|
-
fi
|
|
171
|
+
[[ $ok -eq 1 ]] || { echo " one or more per-session types failed to resolve"; return 1; }
|
|
324
172
|
return 0
|
|
325
173
|
}
|
|
326
174
|
|
|
327
|
-
run_case "8-char prefix resolves full
|
|
328
|
-
run_case "ambiguous prefix
|
|
329
|
-
run_case "more-specific prefix disambiguates"
|
|
330
|
-
run_case "zero matches → file-not-found
|
|
331
|
-
run_case "full 36-char
|
|
332
|
-
run_case "
|
|
333
|
-
run_case "preflush ambiguity refused" case_preflush_ambiguity
|
|
334
|
-
run_case "every per-conversation type prefix-matches" case_all_types_prefix_match
|
|
335
|
-
run_case "shell metacharacters rejected" case_metacharacter_rejected
|
|
175
|
+
run_case "8-char prefix resolves full sessionKey file" case_8char_prefix_resolves_full
|
|
176
|
+
run_case "ambiguous prefix refuses to pick" case_ambiguous_prefix_refuses
|
|
177
|
+
run_case "more-specific prefix disambiguates" case_more_specific_prefix_resolves
|
|
178
|
+
run_case "zero matches → file-not-found" case_zero_match_miss
|
|
179
|
+
run_case "full 36-char sessionKey resolves" case_full_sessionkey_resolves
|
|
180
|
+
run_case "every per-session type resolves" case_every_per_session_type
|
|
336
181
|
|
|
337
182
|
echo ""
|
|
338
183
|
echo "================================================"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# log-adherence-check.sh — Task 1006 existence contract diagnostic.
|
|
3
|
+
#
|
|
4
|
+
# Reads every sessionKey under the active install's per-account logs and
|
|
5
|
+
# asserts that a resolvable claude-agent-stream-<sessionKey>.log exists for
|
|
6
|
+
# each. Runs hourly on-device in addition to the in-process timer wired
|
|
7
|
+
# from platform/ui/app/lib/claude-agent/logging.ts; both are intentionally
|
|
8
|
+
# redundant — one runs inside the server process, this one runs out of band
|
|
9
|
+
# so a stalled server still leaves a fresh adherence record.
|
|
10
|
+
#
|
|
11
|
+
# Emits one `[log-tee] adherence-check window=24h sessions=N misses=M ts=...`
|
|
12
|
+
# line to the platform server log on every run. Per-miss lines surface as
|
|
13
|
+
# `[log-tee] missing-on-resolve sessionKey=<8> surface=adherence-script
|
|
14
|
+
# reason=file-not-on-disk`. `misses=0` is the steady state.
|
|
15
|
+
#
|
|
16
|
+
# Exit codes:
|
|
17
|
+
# 0 No misses (steady state).
|
|
18
|
+
# 1 At least one miss recorded.
|
|
19
|
+
# 2 Usage / environment error.
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# --- Resolve install dir, the same way logs-read.sh does. ---
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
24
|
+
PLATFORM_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
25
|
+
INSTALL_DIR="$(dirname "$PLATFORM_ROOT")"
|
|
26
|
+
INSTALL_DIR_NAME=$(basename "$INSTALL_DIR")
|
|
27
|
+
CONFIG_DIR="$HOME/.$INSTALL_DIR_NAME"
|
|
28
|
+
SERVER_LOG="$CONFIG_DIR/logs/server.log"
|
|
29
|
+
|
|
30
|
+
ACCOUNTS_DIR="$INSTALL_DIR/data/accounts"
|
|
31
|
+
if [[ ! -d "$ACCOUNTS_DIR" ]]; then
|
|
32
|
+
echo "[log-adherence-check] accounts directory missing: $ACCOUNTS_DIR" >&2
|
|
33
|
+
exit 2
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Window: only count session keys whose stream-log file was modified in the
|
|
37
|
+
# last 24h. This avoids fingerprinting long-archived sessions that have aged
|
|
38
|
+
# out via the 7-day retention purge.
|
|
39
|
+
WINDOW_HOURS=24
|
|
40
|
+
|
|
41
|
+
# Collect every basename-derived sessionKey from claude-agent-stream-*.log
|
|
42
|
+
# files across all account log directories, filtered to the active window.
|
|
43
|
+
declare -a KEYS=()
|
|
44
|
+
shopt -s nullglob
|
|
45
|
+
for log_dir in "$ACCOUNTS_DIR"/*/logs; do
|
|
46
|
+
for f in "$log_dir"/claude-agent-stream-*.log; do
|
|
47
|
+
if [[ -f "$f" ]]; then
|
|
48
|
+
# find -mmin needs minutes; 24h = 1440 min.
|
|
49
|
+
if find "$f" -mmin "-$((WINDOW_HOURS * 60))" -print -quit | grep -q .; then
|
|
50
|
+
base=$(basename "$f")
|
|
51
|
+
key="${base#claude-agent-stream-}"
|
|
52
|
+
key="${key%.log}"
|
|
53
|
+
KEYS+=("$key")
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
done
|
|
57
|
+
done
|
|
58
|
+
shopt -u nullglob
|
|
59
|
+
|
|
60
|
+
# De-duplicate sessionKeys (one session may emit multiple .log files via
|
|
61
|
+
# sibling prefixes; the existence contract is per-sessionKey).
|
|
62
|
+
declare -A SEEN=()
|
|
63
|
+
declare -a UNIQUE=()
|
|
64
|
+
for k in "${KEYS[@]:-}"; do
|
|
65
|
+
if [[ -z "${SEEN[$k]:-}" ]]; then
|
|
66
|
+
SEEN[$k]=1
|
|
67
|
+
UNIQUE+=("$k")
|
|
68
|
+
fi
|
|
69
|
+
done
|
|
70
|
+
|
|
71
|
+
SESSIONS=${#UNIQUE[@]}
|
|
72
|
+
MISSES=0
|
|
73
|
+
|
|
74
|
+
# For each sessionKey, verify the agent-stream file is present. Misses
|
|
75
|
+
# surface as a missing-on-resolve line. The file we just listed must
|
|
76
|
+
# exist by definition; this loop catches the case where a sessionKey was
|
|
77
|
+
# referenced in tee/register emissions on server.log but the file itself
|
|
78
|
+
# was unlinked between the scan and the check (very rare, but visible).
|
|
79
|
+
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
80
|
+
for k in "${UNIQUE[@]:-}"; do
|
|
81
|
+
found=0
|
|
82
|
+
for log_dir in "$ACCOUNTS_DIR"/*/logs; do
|
|
83
|
+
if [[ -f "$log_dir/claude-agent-stream-${k}.log" ]]; then
|
|
84
|
+
found=1
|
|
85
|
+
break
|
|
86
|
+
fi
|
|
87
|
+
done
|
|
88
|
+
if [[ $found -eq 0 ]]; then
|
|
89
|
+
MISSES=$((MISSES + 1))
|
|
90
|
+
echo "${TS} [log-tee] missing-on-resolve sessionKey=${k:0:8} surface=adherence-script reason=file-not-on-disk" >> "$SERVER_LOG" 2>/dev/null || true
|
|
91
|
+
fi
|
|
92
|
+
done
|
|
93
|
+
|
|
94
|
+
echo "${TS} [log-tee] adherence-check window=${WINDOW_HOURS}h sessions=${SESSIONS} misses=${MISSES} surface=script ts=${TS}" >> "$SERVER_LOG" 2>/dev/null || true
|
|
95
|
+
echo "[log-adherence-check] sessions=${SESSIONS} misses=${MISSES} window=${WINDOW_HOURS}h"
|
|
96
|
+
|
|
97
|
+
if [[ $MISSES -gt 0 ]]; then
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
exit 0
|