@rubytech/create-maxy-code 0.1.222 → 0.1.223

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/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import { classifyPortHolder } from "./preflight-port-classifier.js";
18
18
  import { parsePluginList, computeInstallActions, computeConfigureActions, parseExternalPlugins, } from "./lib/plugin-install.js";
19
19
  import { findPremiumMcpDirs } from "./lib/premium-mcp-discover.js";
20
20
  import { pickLanInterface, mergeSmbConf, formatSambaMarker, } from "./samba-provision.js";
21
- import { networkInterfaces, userInfo, homedir } from "node:os";
21
+ import { networkInterfaces, userInfo } from "node:os";
22
22
  const PAYLOAD_DIR = resolve(import.meta.dirname, "../payload");
23
23
  // Brand manifest — read from payload to derive all brand-specific installation values.
24
24
  // The bundler stamps brand.json into the payload at build time.
@@ -3276,51 +3276,6 @@ WantedBy=multi-user.target
3276
3276
  // and fail with EADDRINUSE. Fresh installs: the stop is a no-op.
3277
3277
  const unitName = BRAND.serviceName.replace(".service", "");
3278
3278
  const claudeSessionManagerUnitShort = claudeSessionManagerUnitName.replace(".service", "");
3279
- // Task 579 — admin-enumeration acceptance gate. Runs against the
3280
- // freshly-deployed payload before the systemctl restart cluster so a
3281
- // regression in the admin tool surface fails the install and keeps
3282
- // the old service running. The harness exit code is the gate; a
3283
- // non-zero exit logs the JSONL evidence path to install.log and
3284
- // process.exit(1) before we touch any unit. Set MAXY_SKIP_ENUMERATE_GATE=1
3285
- // to bypass for cases where the operator is iterating on a different
3286
- // surface and accepts the regression risk; absence is the default.
3287
- if (!process.env.MAXY_SKIP_ENUMERATE_GATE) {
3288
- const harness = join(INSTALL_DIR, "platform/plugins/admin/__tests__/admin-can-enumerate.test.sh");
3289
- if (existsSync(harness)) {
3290
- const brandConfigDir = join(homedir(), BRAND.configDir, ".claude");
3291
- console.log(" Running admin-enumerate acceptance gate...");
3292
- const gateResult = spawnSync("bash", [harness], {
3293
- stdio: "inherit",
3294
- env: {
3295
- ...process.env,
3296
- CLAUDE_CONFIG_DIR: brandConfigDir,
3297
- INSTALL_DIR,
3298
- },
3299
- });
3300
- if (gateResult.status !== 0) {
3301
- const installLog = join(homedir(), BRAND.configDir, "logs", "install.log");
3302
- const ts = new Date().toISOString();
3303
- try {
3304
- mkdirSync(dirname(installLog), { recursive: true });
3305
- appendFileSync(installLog, `${ts} [admin-enumerate-gate] FAIL exit=${gateResult.status ?? "null"} — admin seat could not locate seeded site within budget. Payload NOT swapped into systemd.\n`);
3306
- }
3307
- catch {
3308
- // best-effort
3309
- }
3310
- console.error(`\n ❌ admin-enumerate gate failed (exit ${gateResult.status ?? "null"}).\n` +
3311
- ` The new payload is on disk at ${INSTALL_DIR} but systemd was NOT restarted.\n` +
3312
- ` Old service is still running. See ${installLog} for one-line summary.\n`);
3313
- process.exit(1);
3314
- }
3315
- console.log(" admin-enumerate gate passed.");
3316
- }
3317
- else {
3318
- console.log(` [admin-enumerate-gate] SKIP reason=harness-not-on-disk path=${harness}`);
3319
- }
3320
- }
3321
- else {
3322
- console.log(" [admin-enumerate-gate] SKIP reason=MAXY_SKIP_ENUMERATE_GATE=1");
3323
- }
3324
3279
  spawnSync("systemctl", ["--user", "stop", unitName], { stdio: "inherit" });
3325
3280
  spawnSync("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
3326
3281
  spawnSync("systemctl", ["--user", "enable", edgeUnitShort], { stdio: "inherit" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.222",
3
+ "version": "0.1.223",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -1,129 +0,0 @@
1
- #!/usr/bin/env bash
2
- # admin-can-enumerate.test.sh
3
- #
4
- # Acceptance gate for Task 579. Verifies that a fresh admin session
5
- # locates a file under <accountDir>/sites/ on the FIRST enumeration
6
- # attempt — no slug guessing, no `EISDIR`, no false-empty 200s, no
7
- # "Log directory does not exist" against a path that resolves
8
- # elsewhere. The gate runs from the installer post-install step against
9
- # the freshly-deployed payload, before systemd services are restarted
10
- # into it. A non-zero exit aborts the deploy and the old payload keeps
11
- # running.
12
- #
13
- # Required environment:
14
- # CLAUDE_CONFIG_DIR per-brand .claude directory (e.g. ~/.realagent-code/.claude)
15
- # INSTALL_DIR the brand install root (e.g. ~/realagent-code)
16
- #
17
- # Exit codes:
18
- # 0 pass — admin enumerated and emitted the seeded path within budget
19
- # 1 fail — one or more assertions tripped (see stderr for the line)
20
- # 2 setup error — could not seed test account or could not invoke claude
21
-
22
- set -euo pipefail
23
-
24
- CONFIG_DIR="${CLAUDE_CONFIG_DIR:?CLAUDE_CONFIG_DIR not set}"
25
- INSTALL_DIR="${INSTALL_DIR:?INSTALL_DIR not set}"
26
-
27
- if ! command -v claude >/dev/null 2>&1; then
28
- echo "[admin-enumerate-gate] setup-error reason=claude-not-on-path" >&2
29
- exit 2
30
- fi
31
- if ! command -v jq >/dev/null 2>&1; then
32
- echo "[admin-enumerate-gate] setup-error reason=jq-not-on-path" >&2
33
- exit 2
34
- fi
35
-
36
- ACCOUNTS_DIR="$INSTALL_DIR/data/accounts"
37
- TEST_ACCT_ID="enumerate-gate-$$"
38
- TEST_ACCT_DIR="$ACCOUNTS_DIR/$TEST_ACCT_ID"
39
- JSONL_OUT=$(mktemp)
40
- EXIT=0
41
-
42
- cleanup() {
43
- rm -rf "$TEST_ACCT_DIR"
44
- if [ "$EXIT" -eq 0 ]; then
45
- rm -f "$JSONL_OUT"
46
- else
47
- echo "[admin-enumerate-gate] evidence-jsonl=$JSONL_OUT" >&2
48
- fi
49
- }
50
- trap cleanup EXIT
51
-
52
- # Seed: one target site + 5 decoys. Target index.html is the file the
53
- # agent must locate and emit the absolute path for.
54
- mkdir -p "$TEST_ACCT_DIR/sites/exp-uk-got-talent"
55
- echo "<html><body>eXp Has Got Talent</body></html>" > "$TEST_ACCT_DIR/sites/exp-uk-got-talent/index.html"
56
- for decoy in alpha-corp-careers beta-properties gamma-events delta-news epsilon-portal; do
57
- mkdir -p "$TEST_ACCT_DIR/sites/$decoy"
58
- echo "<html>decoy</html>" > "$TEST_ACCT_DIR/sites/$decoy/index.html"
59
- done
60
-
61
- TARGET_PATH="$TEST_ACCT_DIR/sites/exp-uk-got-talent/index.html"
62
-
63
- PROMPT="find the eXp Has Got Talent site in this account and print the absolute path to its index.html"
64
-
65
- # Spawn claude headless against the test account. ACCOUNT_ID + the
66
- # MAXY_SESSION_ROLE/PLATFORM_ROOT env are what the platform MCPs read
67
- # to scope themselves; PLATFORM_ROOT resolves the on-disk payload that
68
- # was just deployed. JSONL goes to a file we parse below.
69
- ACCOUNT_ID="$TEST_ACCT_ID" \
70
- MAXY_SESSION_ROLE="admin" \
71
- PLATFORM_ROOT="$INSTALL_DIR/platform" \
72
- CLAUDE_CONFIG_DIR="$CONFIG_DIR" \
73
- claude -p "$PROMPT" --output-format=stream-json --verbose \
74
- > "$JSONL_OUT" 2>&1 \
75
- || { echo "[admin-enumerate-gate] setup-error reason=claude-spawn-failed exit=$?" >&2; EXIT=2; exit 2; }
76
-
77
- fail() {
78
- echo "[admin-enumerate-gate] FAIL $1" >&2
79
- EXIT=1
80
- }
81
-
82
- # Assertion 1: the target path appears verbatim in some assistant turn
83
- # or tool-use input. Either as the agent's final message or as an arg
84
- # passed to a tool.
85
- if ! grep -F -q "$TARGET_PATH" "$JSONL_OUT"; then
86
- fail "correct-path-not-emitted target=$TARGET_PATH"
87
- fi
88
-
89
- # Assertion 2: zero forbidden error patterns from the surfaces this
90
- # task fixed.
91
- FORBIDDEN_HITS=$(grep -E -c "EISDIR|Log directory does not exist|Plugin file not found|page has no readable text content" "$JSONL_OUT" || true)
92
- if [ "${FORBIDDEN_HITS:-0}" -gt 0 ]; then
93
- fail "forbidden-error-patterns=$FORBIDDEN_HITS"
94
- fi
95
-
96
- # Assertion 3: total tool-use calls from the user prompt to the
97
- # correct-path emission are at most 3. The earlier failing run issued
98
- # ~15.
99
- TOOL_USE_COUNT=$(jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' < "$JSONL_OUT" 2>/dev/null | wc -l | tr -d ' ' || echo 0)
100
- if [ "${TOOL_USE_COUNT:-0}" -gt 3 ]; then
101
- fail "tool-use-budget-exceeded count=$TOOL_USE_COUNT cap=3"
102
- fi
103
-
104
- # Assertion 4: the FIRST disk-listing tool call returns an enumeration
105
- # of <accountDir>/sites/. "Disk-listing" means LS, Glob, or Bash with
106
- # `ls`. We accept any of those as the first relevant call; what we
107
- # reject is a Read against a directory path.
108
- FIRST_DIR_TOOL=$(jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | {name, input} | @json' < "$JSONL_OUT" 2>/dev/null \
109
- | jq -r 'select(.name=="LS" or .name=="Glob" or (.name=="Bash" and (.input.command // "" | test("\\bls\\b")))) | .name' \
110
- | head -1)
111
- if [ -z "$FIRST_DIR_TOOL" ]; then
112
- fail "no-disk-listing-tool-call-emitted"
113
- fi
114
-
115
- # Assertion 5: no Read tool call against a path under <accountDir>/sites/
116
- # that is a directory (would have produced EISDIR pre-fix; should not
117
- # even be attempted now).
118
- BAD_READ=$(jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Read") | .input.file_path // ""' < "$JSONL_OUT" 2>/dev/null \
119
- | while read -r p; do
120
- [ -n "$p" ] && [ -d "$p" ] && echo "$p"
121
- done | head -1)
122
- if [ -n "$BAD_READ" ]; then
123
- fail "read-against-directory path=$BAD_READ"
124
- fi
125
-
126
- if [ "$EXIT" -eq 0 ]; then
127
- echo "[admin-enumerate-gate] PASS target=$TARGET_PATH tool-use-count=$TOOL_USE_COUNT first-dir-tool=$FIRST_DIR_TOOL"
128
- fi
129
- exit "$EXIT"