@rubytech/create-maxy-code 0.1.157 → 0.1.158
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 +3 -2
- package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +140 -0
- package/payload/platform/plugins/admin/hooks/pre-turn-graph-pass.sh +33 -84
- package/payload/platform/plugins/admin/hooks/session-end-retrospective.sh +32 -91
- package/payload/platform/plugins/docs/references/deployment.md +3 -1
- package/payload/platform/plugins/memory/PLUGIN.md +3 -3
- package/payload/platform/plugins/memory/mcp/dist/index.js +11 -12
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts +35 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js +80 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js.map +1 -0
- package/payload/platform/plugins/memory/references/schema-base.md +2 -2
- package/payload/platform/scripts/smoke-boot-services.sh +191 -41
- package/payload/server/public/assets/{admin-DJW5VnQ1.js → admin-3fLFD5h_.js} +22 -22
- package/payload/server/public/index.html +1 -1
|
@@ -1,16 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
#
|
|
3
3
|
# smoke-boot-services.sh — boot every compiled service against a synthetic
|
|
4
|
-
# install fixture,
|
|
5
|
-
#
|
|
4
|
+
# install fixture, run the cypher schema against a live Neo4j, and assert
|
|
5
|
+
# every startup-self-test the production boot would log fires here.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
7
|
+
# Failure modes caught (Task 438):
|
|
8
|
+
# - specialist-tool-drift: a specialist template (or per-account override)
|
|
9
|
+
# names a tool the plugin does not export.
|
|
10
|
+
# - system-prompt-sentinels: the composer drops a `<name>` the
|
|
11
|
+
# IDENTITY.md prose references.
|
|
12
|
+
# - identity-drift: IDENTITY.md mentions a `<name>` the composer does not
|
|
13
|
+
# emit.
|
|
14
|
+
# - cypher-schema: schema.cypher contains syntax the live Neo4j rejects
|
|
15
|
+
# (e.g. Neo4j 4 `DROP FULLTEXT INDEX` against a Neo4j 5 parser).
|
|
16
|
+
# - module-load: the original Task 099 motivation — `require()` in ESM,
|
|
17
|
+
# missing externals, stray top-level throws.
|
|
18
|
+
#
|
|
19
|
+
# Fixture shape: the temp install dir mirrors what the installer writes on
|
|
20
|
+
# first boot. Real templates are copied (not stubs) so the drift gates run
|
|
21
|
+
# against the same content production would see:
|
|
22
|
+
# $INSTALL_DIR/platform/config/brand.json
|
|
23
|
+
# $INSTALL_DIR/platform/plugins/<name>/PLUGIN.md (real manifests)
|
|
24
|
+
# $INSTALL_DIR/platform/templates/agents/admin/*.md (real templates)
|
|
25
|
+
# $INSTALL_DIR/platform/templates/specialists/agents/*.md (real templates)
|
|
26
|
+
# $INSTALL_DIR/data/accounts/<uuid>/account.json
|
|
27
|
+
# $INSTALL_DIR/data/accounts/<uuid>/agents/admin/{IDENTITY,SOUL,AGENTS}.md
|
|
28
|
+
# $INSTALL_DIR/data/accounts/<uuid>/specialists/agents/*.md (per-account)
|
|
29
|
+
# $INSTALL_DIR/.claude/ (CLAUDE_CONFIG_DIR)
|
|
30
|
+
#
|
|
31
|
+
# Cypher gate: apply schema.cypher to the dev's local Neo4j via cypher-shell.
|
|
32
|
+
# NEO4J_URI / NEO4J_USER / NEO4J_PASSWORD must be set (same shape as
|
|
33
|
+
# seed-neo4j.sh — the maintainer's existing local install). The gate is a
|
|
34
|
+
# real apply, not parse-only: schema commands use `IF NOT EXISTS` / `IF
|
|
35
|
+
# EXISTS` and the dev's Neo4j is the test surface — pollution is the point.
|
|
36
|
+
# If cypher-shell is absent or NEO4J_URI is unset, the gate exits non-zero
|
|
37
|
+
# so the publish blocker maps to the same code path a real install hits.
|
|
14
38
|
#
|
|
15
39
|
# Service list: extend SERVICES below as additional services adopt the
|
|
16
40
|
# smoke gate. Each entry needs a fixture function that creates the temp
|
|
@@ -42,28 +66,28 @@ cleanup() {
|
|
|
42
66
|
}
|
|
43
67
|
trap cleanup EXIT
|
|
44
68
|
|
|
45
|
-
# Build the synthetic install dir for claude-session-manager.
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
# $INSTALL_DIR/platform/plugins/<name>/PLUGIN.md (real manifests — tool surface)
|
|
49
|
-
# $INSTALL_DIR/platform/templates/specialists/agents/*.md (real shipped set)
|
|
50
|
-
# $INSTALL_DIR/data/accounts/<uuid>/account.json
|
|
51
|
-
# $INSTALL_DIR/data/accounts/<uuid>/agents/admin/{IDENTITY,SOUL}.md
|
|
69
|
+
# Build the synthetic install dir for claude-session-manager. Layout mirrors
|
|
70
|
+
# what the installer writes on first boot, with REAL template content (not
|
|
71
|
+
# stubs) so the drift gates fire against the same files production sees.
|
|
52
72
|
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# MCP binaries are not needed — the drift check parses frontmatter only.
|
|
73
|
+
# Why real-templates: a 0-specialist or empty-IDENTITY fixture lets every
|
|
74
|
+
# drift gate fall through trivially (Task 438). The 0.1.155 install regressed
|
|
75
|
+
# because the librarian per-account override referenced an MCP tool the
|
|
76
|
+
# memory plugin no longer exports — a defect the smoke fixture missed because
|
|
77
|
+
# the fixture's per-account specialists dir was empty.
|
|
59
78
|
fixture_claude_session_manager() {
|
|
60
79
|
local install_dir="$1"
|
|
61
80
|
local platform_root="$install_dir/platform"
|
|
81
|
+
local templates_src="$REPO_ROOT/platform/templates"
|
|
62
82
|
local account_id="00000000-0000-4000-8000-000000000000"
|
|
63
83
|
local account_dir="$install_dir/data/accounts/$account_id"
|
|
64
84
|
|
|
65
85
|
mkdir -p "$platform_root/config"
|
|
66
86
|
mkdir -p "$account_dir/agents/admin"
|
|
87
|
+
mkdir -p "$account_dir/agents/public"
|
|
88
|
+
mkdir -p "$account_dir/specialists/agents"
|
|
89
|
+
mkdir -p "$account_dir/.claude"
|
|
90
|
+
mkdir -p "$install_dir/.claude"
|
|
67
91
|
|
|
68
92
|
cat > "$platform_root/config/brand.json" <<'BRAND'
|
|
69
93
|
{
|
|
@@ -72,20 +96,39 @@ fixture_claude_session_manager() {
|
|
|
72
96
|
}
|
|
73
97
|
BRAND
|
|
74
98
|
|
|
75
|
-
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
99
|
+
# account.json field set mirrors the live template's required fields
|
|
100
|
+
# (resolveAccount throws on missing adminModel/publicModel). Values just
|
|
101
|
+
# need to satisfy the field check — boot never hits Anthropic.
|
|
102
|
+
cat > "$account_dir/account.json" <<JSON
|
|
103
|
+
{
|
|
104
|
+
"accountId": "$account_id",
|
|
105
|
+
"tier": "smoke-test",
|
|
106
|
+
"adminModel": "claude-sonnet-4-6",
|
|
107
|
+
"publicModel": "claude-haiku-4-5"
|
|
108
|
+
}
|
|
109
|
+
JSON
|
|
110
|
+
|
|
111
|
+
# Real admin templates — the drift gate reads the per-account IDENTITY.md;
|
|
112
|
+
# SOUL/AGENTS are not boot-gated but presence is convention.
|
|
113
|
+
cp "$templates_src/agents/admin/IDENTITY.md" "$account_dir/agents/admin/IDENTITY.md"
|
|
114
|
+
cp "$templates_src/agents/admin/SOUL.md" "$account_dir/agents/admin/SOUL.md"
|
|
115
|
+
[ -f "$templates_src/agents/admin/AGENTS.md" ] && cp "$templates_src/agents/admin/AGENTS.md" "$account_dir/agents/admin/AGENTS.md"
|
|
116
|
+
[ -f "$templates_src/agents/public/IDENTITY.md" ] && cp "$templates_src/agents/public/IDENTITY.md" "$account_dir/agents/public/IDENTITY.md"
|
|
117
|
+
|
|
118
|
+
# Real per-account specialist overrides — the drift gate walks
|
|
119
|
+
# $accountDir/specialists/agents/ alongside the template path. 0.1.155
|
|
120
|
+
# regressed because this dir was empty in the smoke fixture; a per-account
|
|
121
|
+
# override referencing a withdrawn tool slipped through to a real install.
|
|
122
|
+
for specialist in "$templates_src/specialists/agents/"*.md; do
|
|
123
|
+
[ -f "$specialist" ] && cp "$specialist" "$account_dir/specialists/agents/$(basename "$specialist")"
|
|
124
|
+
done
|
|
125
|
+
|
|
126
|
+
# Real templates copied into $PLATFORM_ROOT/templates so the drift gate's
|
|
127
|
+
# template-path walk sees the same content as production.
|
|
128
|
+
mkdir -p "$platform_root/templates/agents/admin"
|
|
129
|
+
mkdir -p "$platform_root/templates/specialists/agents"
|
|
130
|
+
cp "$templates_src/agents/admin/"*.md "$platform_root/templates/agents/admin/" 2>/dev/null || true
|
|
131
|
+
cp "$templates_src/specialists/agents/"*.md "$platform_root/templates/specialists/agents/"
|
|
89
132
|
|
|
90
133
|
# Real plugin manifests — loadToolSurface walks platform/plugins/*/PLUGIN.md
|
|
91
134
|
# to build the tool surface. An empty plugins dir gives an empty `all` set,
|
|
@@ -129,21 +172,34 @@ run_one() {
|
|
|
129
172
|
|
|
130
173
|
# Spawn the service. PLATFORM_ROOT is the synthetic platform dir; loadConfig
|
|
131
174
|
# walks $(dirname PLATFORM_ROOT)/data/accounts for the account dir.
|
|
175
|
+
# CLAUDE_CONFIG_DIR + NEO4J_URI + NEO4J_PASSWORD are stamped to satisfy the
|
|
176
|
+
# manager's env-presence checks at boot. NEO4J values are dummies — the
|
|
177
|
+
# manager only asserts non-empty here, it does not connect. The cypher-
|
|
178
|
+
# schema gate runs separately against the dev's real Neo4j.
|
|
132
179
|
PLATFORM_ROOT="$install_dir/platform" \
|
|
133
180
|
CLAUDE_SESSION_MANAGER_PORT="$port" \
|
|
134
181
|
CLAUDE_SESSION_MANAGER_PERSIST_DIR="$install_dir/persist" \
|
|
182
|
+
CLAUDE_CONFIG_DIR="$install_dir/.claude" \
|
|
183
|
+
NEO4J_URI="bolt://127.0.0.1:65535" \
|
|
184
|
+
NEO4J_PASSWORD="smoke" \
|
|
135
185
|
node "$dist_path" >"$log_file" 2>&1 &
|
|
136
186
|
local pid=$!
|
|
137
187
|
|
|
138
|
-
# Poll up to
|
|
188
|
+
# Poll up to 10s for the final readiness signal (identity-drift line — last
|
|
189
|
+
# startup-self-test logged) or any fast-fail line. The boot port= line fires
|
|
190
|
+
# before self-tests; using it as the kill trigger lost the drift gates'
|
|
191
|
+
# output (Task 438). identity-drift=ok|fail is the last log line on the
|
|
192
|
+
# self-test path; boot-failed reason= is the fast-fail surface.
|
|
139
193
|
local boot_line=""
|
|
140
194
|
local fatal_line=""
|
|
195
|
+
local readiness_line=""
|
|
141
196
|
local waited_ms=0
|
|
142
|
-
while [ "$waited_ms" -lt
|
|
197
|
+
while [ "$waited_ms" -lt 10000 ]; do
|
|
143
198
|
if [ -s "$log_file" ]; then
|
|
199
|
+
readiness_line="$(grep -m1 -E 'startup-self-test identity-drift=' "$log_file" || true)"
|
|
144
200
|
boot_line="$(grep -m1 -E '^\[claude-session-manager\] boot port=' "$log_file" || true)"
|
|
145
|
-
fatal_line="$(grep -m1 -E '^\[.*\] fatal ' "$log_file" || true)"
|
|
146
|
-
if [ -n "$
|
|
201
|
+
fatal_line="$(grep -m1 -E '^\[.*\] fatal |boot-failed reason=' "$log_file" || true)"
|
|
202
|
+
if [ -n "$readiness_line" ] || [ -n "$fatal_line" ]; then break; fi
|
|
147
203
|
fi
|
|
148
204
|
if ! kill -0 "$pid" 2>/dev/null; then break; fi
|
|
149
205
|
sleep 0.1
|
|
@@ -182,6 +238,17 @@ run_one() {
|
|
|
182
238
|
cat "$log_file" >&2
|
|
183
239
|
return 1
|
|
184
240
|
fi
|
|
241
|
+
# boot-failed lines mean the manager rejected a startup-self-test before
|
|
242
|
+
# printing the boot line. Surface the gate-specific reason verbatim — same
|
|
243
|
+
# signal a real device would print to journald.
|
|
244
|
+
local boot_failed_line
|
|
245
|
+
boot_failed_line="$(grep -m1 -E 'boot-failed reason=' "$log_file" || true)"
|
|
246
|
+
if [ -n "$boot_failed_line" ]; then
|
|
247
|
+
echo "[smoke] service=$name reason=boot-failed matched=$boot_failed_line" >&2
|
|
248
|
+
echo "--- log ($log_file) ---" >&2
|
|
249
|
+
cat "$log_file" >&2
|
|
250
|
+
return 1
|
|
251
|
+
fi
|
|
185
252
|
if [ -z "$boot_line" ]; then
|
|
186
253
|
echo "[smoke] service=$name reason=no-boot-line matched=" >&2
|
|
187
254
|
echo "--- log ($log_file) ---" >&2
|
|
@@ -197,7 +264,86 @@ run_one() {
|
|
|
197
264
|
return 1
|
|
198
265
|
fi
|
|
199
266
|
|
|
200
|
-
|
|
267
|
+
# Assert every startup-self-test the manager would log on a real boot fired
|
|
268
|
+
# here. The fixture-from-real-templates change above is what makes these
|
|
269
|
+
# gates non-trivial — without the per-account specialists/IDENTITY copies,
|
|
270
|
+
# the drift gates would log =ok against an empty surface.
|
|
271
|
+
local required_tests=(
|
|
272
|
+
"startup-self-test specialist-tool-drift=ok"
|
|
273
|
+
"startup-self-test system-prompt-sentinels=ok"
|
|
274
|
+
"startup-self-test identity-drift=ok"
|
|
275
|
+
)
|
|
276
|
+
for test_line in "${required_tests[@]}"; do
|
|
277
|
+
if ! grep -qF "$test_line" "$log_file"; then
|
|
278
|
+
echo "[smoke] service=$name reason=startup-self-test-missing expected=\"$test_line\"" >&2
|
|
279
|
+
echo "--- log ($log_file) ---" >&2
|
|
280
|
+
cat "$log_file" >&2
|
|
281
|
+
return 1
|
|
282
|
+
fi
|
|
283
|
+
done
|
|
284
|
+
|
|
285
|
+
echo "[smoke-boot] service=$name specialist-tool-drift=ok system-prompt-sentinels=ok identity-drift=ok boot=ok elapsed-ms=$elapsed_ms"
|
|
286
|
+
return 0
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
# Apply schema.cypher to the dev's local Neo4j via cypher-shell. Catches
|
|
290
|
+
# Neo4j 4/5 syntax drift (e.g. 0.1.151's `DROP FULLTEXT INDEX`) the same way
|
|
291
|
+
# a real `seed-neo4j.sh` apply would. The dev's database is the test surface;
|
|
292
|
+
# schema commands use IF NOT EXISTS / IF EXISTS so re-runs are idempotent.
|
|
293
|
+
#
|
|
294
|
+
# Hard prerequisite: NEO4J_URI (and a password source) must be set, and
|
|
295
|
+
# cypher-shell must be on PATH. Absence = publish refusal — the maintainer
|
|
296
|
+
# already runs Neo4j locally for their own brand install.
|
|
297
|
+
run_cypher_schema() {
|
|
298
|
+
local schema_path="$REPO_ROOT/platform/neo4j/schema.cypher"
|
|
299
|
+
if [ ! -f "$schema_path" ]; then
|
|
300
|
+
echo "[smoke-boot] cypher-schema=fail err=schema-missing path=$schema_path" >&2
|
|
301
|
+
return 1
|
|
302
|
+
fi
|
|
303
|
+
|
|
304
|
+
if ! command -v cypher-shell >/dev/null 2>&1; then
|
|
305
|
+
echo "[smoke-boot] cypher-schema=fail err=cypher-shell-not-on-path" >&2
|
|
306
|
+
echo "[smoke-boot] cypher-schema requires a local Neo4j (cypher-shell on PATH) — same toolchain seed-neo4j.sh uses." >&2
|
|
307
|
+
return 1
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
if [ -z "${NEO4J_URI:-}" ]; then
|
|
311
|
+
echo "[smoke-boot] cypher-schema=fail err=neo4j-uri-unset env=NEO4J_URI" >&2
|
|
312
|
+
return 1
|
|
313
|
+
fi
|
|
314
|
+
|
|
315
|
+
local neo4j_user="${NEO4J_USER:-neo4j}"
|
|
316
|
+
local neo4j_password="${NEO4J_PASSWORD:-}"
|
|
317
|
+
if [ -z "$neo4j_password" ]; then
|
|
318
|
+
# Fall back to the same password-file convention seed-neo4j.sh uses.
|
|
319
|
+
local pw_file="$REPO_ROOT/platform/config/.neo4j-password"
|
|
320
|
+
if [ -f "$pw_file" ]; then
|
|
321
|
+
neo4j_password="$(cat "$pw_file")"
|
|
322
|
+
fi
|
|
323
|
+
fi
|
|
324
|
+
if [ -z "$neo4j_password" ]; then
|
|
325
|
+
echo "[smoke-boot] cypher-schema=fail err=neo4j-password-unset env=NEO4J_PASSWORD" >&2
|
|
326
|
+
return 1
|
|
327
|
+
fi
|
|
328
|
+
|
|
329
|
+
local log_file="$TMP_ROOT/cypher-schema.log"
|
|
330
|
+
local statement_count
|
|
331
|
+
# Count CREATE/DROP/CALL statement-starts. Approximate but stable signal
|
|
332
|
+
# for the log line; the real authority is cypher-shell's exit code.
|
|
333
|
+
statement_count="$(grep -cE '^(CREATE|DROP|CALL)\b' "$schema_path" || true)"
|
|
334
|
+
|
|
335
|
+
if ! cypher-shell -u "$neo4j_user" -p "$neo4j_password" -a "$NEO4J_URI" \
|
|
336
|
+
--non-interactive --fail-fast --format plain < "$schema_path" \
|
|
337
|
+
> "$log_file" 2>&1; then
|
|
338
|
+
local first_err
|
|
339
|
+
first_err="$(grep -m1 -E '^(Invalid|Error|Neo\.)' "$log_file" || head -1 "$log_file" || true)"
|
|
340
|
+
echo "[smoke-boot] cypher-schema=fail err=${first_err:-unknown}" >&2
|
|
341
|
+
echo "--- log ($log_file) ---" >&2
|
|
342
|
+
cat "$log_file" >&2
|
|
343
|
+
return 1
|
|
344
|
+
fi
|
|
345
|
+
|
|
346
|
+
echo "[smoke-boot] cypher-schema=ok statements=$statement_count uri=$NEO4J_URI"
|
|
201
347
|
return 0
|
|
202
348
|
}
|
|
203
349
|
|
|
@@ -259,4 +405,8 @@ for entry in "${MCP_PLUGINS[@]}"; do
|
|
|
259
405
|
fi
|
|
260
406
|
done
|
|
261
407
|
|
|
408
|
+
if ! run_cypher_schema; then
|
|
409
|
+
rc=1
|
|
410
|
+
fi
|
|
411
|
+
|
|
262
412
|
exit "$rc"
|