Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ three commits past it), and a bug report can name a release instead of a sha nob
Sections dated before 2026-09-19 predate the cycle and stay as they are.

## Unreleased
- fix(doctor, test-stack-up): **in a cloud container, a missing Docker daemon is now reported as normal, with the Docker-free route, instead of a warning that says to start it.** The Claude Code on the web container has the docker CLI but no daemon, and the agent cannot start one. Doctor used to WARN "docker daemon is not responding … sudo systemctl start docker", so sessions tried, failed, and reported "cannot start the docker daemon" as a blocker, until the user said to use `mxcli run --local`. Now the cloud lane prints: no Docker here, normal, do not try to start it; build check = exec.sh's mxbuild gate; run the app = `./mxcli run --local`. On a desktop (Docker or Podman, stopped or absent) the warning and start hint stay, plus one line saying a container is optional: the mxbuild gate needs none, and Studio Pro's Run Locally or `mxcli run --local` runs the app. The no-runtime text no longer says the build check needs Docker. `test-stack-up.sh` with the app down and no reachable Docker/Podman now stops with the Docker-free route instead of failing inside `mxcli docker run`. — MendixMau
- fix(gate-check): **the stage-decision readers now read only the Decisions table, and Stage 7 accepts a dated CONFIRMED.** `has_confirmed_decision` (Stages 3 and 4) and the Stage 7 cutover check scanned every pipe row in the register, so an Open-questions row numbered 4 or 7 with Status CONFIRMED passed that stage with no decision behind it. Both now count only rows under a header whose first cell is `Stage`; a register with no such header keeps the old every-row scan. Stage 7 also matched the status string-exactly, so `CONFIRMED 2026-08-10` failed there while passing every other stage (TD-07); it now uses the same word-anchored match. Positive control: the pre-fix script passes Stages 4 and 7 on an Open-questions-only register and fails Stage 7 on the dated status. Fixture T13–T15 in `test-bug03-gates.sh` — MendixMau
- learn(bug-logs): **`BUG-DRAFT-grant-association-generalization-member`** — a member association owned by another module's entity cannot be named in a `grant` statement, so `revoke` + `re-grant` silently drops that member access and `mx check` reports CE0066; patch-only workaround provided. Found fixing a guest-groups association in a Mendix app (mxcli v0.23.0, Mendix 11.12.2). — MendixMau
- chore(inbox): **triage of `contrib/inbox/`: removed 15 promoted/obsolete files, gave the rest neutral names and scrubbed identifiers.** Gone: the ten machine-diff `*-patches.md` files from 2026-09-14, the 2026-09-27 field-project patch file, the built company-brain idea, and three already-promoted or superseded bug dumps. Kept for now: `2026-09-27-mxcli-upstream-issues.md`, because five drafts under `bug-logs/pending-github-issues/` cite it as their source. Four remaining files were renamed to `field-project-{a,b,c}` names; project and app names, home-style paths and personal names inside the 17 remaining entries were replaced with neutral labels or placeholders (technical content unchanged). — MendixMau
Expand Down
36 changes: 28 additions & 8 deletions bin/doctor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,20 @@ container_start_hint() {
esac
fi
note "Then re-run: bin/doctor.sh${PROJECT_DIR:+ $PROJECT_DIR} (this section is skipped by --quick)"
note "Not required, if you would rather not run one: the build check (exec.sh's mxbuild gate) needs no"
note "container, and Studio Pro's Run Locally or ./mxcli run --local runs the app without one."
}

# cloud_no_daemon — the Claude Code on the web container ships the docker CLI but no running
# daemon, and the agent cannot start one there. Telling it "sudo systemctl start docker" sent
# sessions off trying, then reporting "cannot start the docker daemon" as a blocker — while the
# mxbuild gate (exec.sh) and `mxcli run --local` both work with no Docker at all. So in the cloud
# lane a missing daemon is reported as the normal state, with the Docker-free route, not a WARN.
cloud_no_daemon() {
ok "no $RUNTIME_LABEL in this cloud container — normal here, and not a blocker. Do not try to start it."
note "Build check: exec.sh's mxbuild gate — mxbuild is a plain binary, no Docker needed."
note "Run the app: ./mxcli run --local (add --hub for a preview URL) — skills/cloud-dev-environment.md."
note "Snapshot first: mxcli run --local consolidates a split-model .mpr (bug-logs, CRITICAL)."
}

if [ "$NO_DOCKER" = 1 ]; then
Expand All @@ -774,7 +788,12 @@ elif [ -n "$CONTAINER_RUNTIME" ]; then
container_daemon_up || DOCKER_STATE=$?
case "$DOCKER_STATE" in
0)
ok "$RUNTIME_LABEL responding — mxcli docker check + test-stack-up.sh (app up, e2e, screenshots) available" ;;
ok "$RUNTIME_LABEL responding — mxcli docker run + test-stack-up.sh (app up, e2e, screenshots) available" ;;
*) [ "$ENV_LANE" = cloud ] && DOCKER_STATE=cloud ;;
esac
case "$DOCKER_STATE" in
0) ;;
cloud) cloud_no_daemon ;;
2)
warn "$CONTAINER_RUNTIME is installed but '$CONTAINER_RUNTIME info' gave no answer within ${DOCKER_PROBE_SECS} s — treated as not running."
note "That silent wait is what makes a setup look hung. Raise the bound with"
Expand All @@ -790,19 +809,20 @@ elif [ -n "$CONTAINER_RUNTIME" ]; then
# Never elsewhere — Windows launch paths vary and Linux needs sudo. Podman is left alone:
# `podman machine start` on a machine that has never run `podman machine init` is not a safe
# guess to make on someone's behalf.
if [ "$DOCKER_STATE" != 0 ] && [ "$INSTALL" = 1 ] && [ "$CONTAINER_RUNTIME" = docker ] && [ "$PLATFORM" = macos ] && [ -d /Applications/Docker.app ]; then
if [ "$DOCKER_STATE" != 0 ] && [ "$DOCKER_STATE" != cloud ] && [ "$INSTALL" = 1 ] && [ "$CONTAINER_RUNTIME" = docker ] && [ "$PLATFORM" = macos ] && [ -d /Applications/Docker.app ]; then
if open -a Docker 2>/dev/null; then
note "--install: launched Docker Desktop (open -a Docker). Give it ~30-90 s, then re-run doctor."
fi
fi
elif [ "$ENV_LANE" = cloud ]; then
cloud_no_daemon
else
warn "no container runtime found — neither docker nor podman. One is recommended for new builders."
note "It is what lets the agent verify its own build: 'mxcli docker check' (deep model+build"
note "verification) and project-bin/test-stack-up.sh (Postgres + the app up, Playwright e2e,"
note "page screenshots) both need it. Without it, only mxbuild verifies the model and a human"
note "must open Studio Pro to see whether anything actually renders."
note "No-container fallback for just running the app: 'mxcli run --local' against a native"
note "PostgreSQL (host:PORT)."
note "The build check does NOT need it: exec.sh's mxbuild gate is a plain binary. What it adds"
note "is the running app in a container: project-bin/test-stack-up.sh (Postgres + the app up,"
note "Playwright e2e, page screenshots)."
note "No-container route for running the app: 'mxcli run --local' against a native"
note "PostgreSQL (host:PORT) — the same route the cloud lane uses."
note "Docker Desktop needs a paid licence at larger companies, and is NOT required: Podman is"
note "the licence-free option (docker-CLI compatible; doctor probes it directly, so no docker"
note "shim is needed). Rancher Desktop and colima (macOS) are the other common substitutes."
Expand Down
23 changes: 22 additions & 1 deletion project-bin/test-stack-up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,28 @@ fi
# --- Bring up the app -------------------------------------------------------
if [ $APP_FOUND -ne 0 ]; then
if [ "$MODE" = "nodocker" ]; then
bad "App down and --no-docker given. Click Run Locally in Studio Pro, then re-run --check."
bad "App down and --no-docker given. Click Run Locally in Studio Pro (or, with no Studio Pro, ./mxcli run --local), then re-run --check."
exit 1
fi
# No reachable Docker (or Podman) daemon: say so and name the Docker-free route, instead of letting
# `mxcli docker run` fail with a daemon error the agent then reports as "cannot start Docker".
# A cloud container ships the docker CLI with no daemon; that is normal, not a blocker.
# Bounded: a stopped Docker Desktop can leave `docker info` silent for minutes.
_RT=docker; command -v docker >/dev/null 2>&1 || _RT=podman
if ! command -v "$_RT" >/dev/null 2>&1; then _DK=1; else
"$_RT" info >/dev/null 2>&1 & _dk_pid=$!; _dk_w=0; _DK=
while kill -0 "$_dk_pid" 2>/dev/null; do
[ "$_dk_w" -ge 15 ] && { kill "$_dk_pid" 2>/dev/null; _DK=2; break; }
sleep 1; _dk_w=$((_dk_w + 1))
done
[ -n "$_DK" ] || { wait "$_dk_pid"; _DK=$?; }
fi
if [ "$_DK" != 0 ]; then
bad "App down and no Docker/Podman reachable, so this script cannot build the app container."
echo " Normal in a cloud container, and fine on a desktop without one. Run the app without it:"
echo " Studio Pro: Run Locally. No Studio Pro:"
echo " ./mxcli run --local -p $(basename "$MPR") # flags: skills/cloud-dev-environment.md"
echo " Snapshot first — mxcli run --local consolidates a split-model .mpr. Then re-run with --check."
exit 1
fi
if [ -z "$MXCLI" ]; then
Expand Down
15 changes: 13 additions & 2 deletions tests/wave2/test-doctor-docker-probe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ echo "doctor docker probe — $DOCTOR"

# 1. hanging daemon: bounded, and says so
S0=$(date +%s)
PATH="$T/hang:$PATH" MXTK_DOCKER_PROBE_SECS=2 bash "$DOCTOR" > "$T/hang.out" 2>&1
# Cases 1-2 are the desktop/devcontainer lanes: CLAUDE_CODE_REMOTE cleared, so the fixture
# means the same thing when it runs inside a cloud session. Case 2b is the cloud lane.
PATH="$T/hang:$PATH" CLAUDE_CODE_REMOTE= MXTK_DOCKER_PROBE_SECS=2 bash "$DOCTOR" > "$T/hang.out" 2>&1
S1=$(date +%s)
if [ $((S1 - S0)) -lt 40 ]; then ok "hanging docker: doctor finished in $((S1 - S0)) s (bound 2 s)"; else fail "hanging docker: doctor took $((S1 - S0)) s — the bound is not biting"; fi
assert_contains "$T/hang.out" "probing the docker daemon (bounded: 2 s" "hanging docker: announces the probe and its bound before waiting"
Expand All @@ -39,10 +41,19 @@ assert_contains "$T/hang.out" "Then re-run: bin/doctor.sh" "hanging docker: says
assert_missing "$T/hang.out" "docker daemon responding" "hanging docker: not reported as up"

# 2. daemon down, answering at once
PATH="$T/down:$PATH" bash "$DOCTOR" > "$T/down.out" 2>&1
PATH="$T/down:$PATH" CLAUDE_CODE_REMOTE= bash "$DOCTOR" > "$T/down.out" 2>&1
assert_contains "$T/down.out" "daemon is not responding" "down docker: reported as not responding"
assert_contains "$T/down.out" "To start it:" "down docker: carries a start command"
assert_missing "$T/down.out" "gave no answer within" "down docker: a fast 'down' is not called a timeout"
assert_contains "$T/down.out" "Not required, if you would rather not run one" "down docker: says a container is optional"

# 2b. cloud container: docker CLI, no daemon — the normal state there, never a start command.
# (Sessions told "sudo systemctl start docker" tried, failed, and reported it as a blocker.)
PATH="$T/down:$PATH" CLAUDE_CODE_REMOTE=true bash "$DOCTOR" > "$T/cloud.out" 2>&1
assert_contains "$T/cloud.out" "normal here, and not a blocker" "cloud, no daemon: reported as normal"
assert_contains "$T/cloud.out" "mxcli run --local" "cloud, no daemon: names the Docker-free run route"
assert_missing "$T/cloud.out" "To start it:" "cloud, no daemon: no start command"
assert_missing "$T/cloud.out" "WARN docker is installed" "cloud, no daemon: not a WARN"

# 3. daemon up
PATH="$T/up:$PATH" bash "$DOCTOR" > "$T/up.out" 2>&1
Expand Down
Loading