Closes followup #14 (runtime YDB-version drift) and stages 4b.1+4b.2
of the m-engine plan. Coordinated with m-test-engine commit 1e7a4cc
(Phase 4a: docker/mte introspection script).
* engine_driver.py
- `DockerDriver.mte_status()` — shells out to `docker exec <container>
mte status --json`; returns parsed dict or None (graceful on
non-zero rc, garbage output, container down).
- `EngineStatus.mte: dict | None` (default None). `to_dict()`
serialises it.
- `DockerDriver.status(*, verbose=False)` — verbose=True populates
`mte` and adds `runtime_ydb_version_drift` to mismatches when
`mte["release"]` != `manifest.ydb_version`. De-duped against the
static-label `ydb_version_drift` from Phase 3b.
- Protocol grew `mte_status()` and the `verbose` kwarg on `status()`.
* engine_cli.py
- `m engine status --verbose / -v` flag wired; text output gains an
"inside container (mte):" block with release/uptime/globals/
routines/mounted_repos. `--json` output gets the mte block via
EngineStatus.to_dict().
- `m engine watch` (new) — long-running poll of `mte_status()`;
emits one JSON-lines record per poll with `ts` wall-clock
timestamp. `--interval` (default 5s, min 0.1) controls cadence;
`--count N` caps the loop (`0` = until SIGINT). KeyboardInterrupt
→ clean exit rc 0.
- `m engine capabilities` payload advertises `watch` as
read_only:true.
* tests/test_engine_driver.py — 8 new tests for mte_status() (parse /
None on bad rc / None on garbage), status verbose folding, drift
detection, non-verbose skip, container-down skip.
* tests/test_engine_cli.py — 5 new tests for --verbose pass-through,
text/JSON rendering, watch JSON-lines + error-line behaviour.
* tests/test_doctor.py — single drive-by fix to
`test_doctor_cli_exits_one_when_any_fail`: monkeypatch
`docker_available` → False so the existing demote-when-engine-OK
path (a separate prior addition implementing followup #6) doesn't
override the test's expected `ydb_dist=FAIL` on hosts where docker
is healthy. Preserves the test's original intent without depending
on the local environment.
Full suite 1471 passing / 1 skipped (was 1453); ruff + mypy clean.
Live `m engine status --verbose` on this host correctly detected
`runtime_ydb_version_drift` because the running image is V7.1-002
(yottadb-base:latest-master tip) while the manifest declares
`ydb_version: "r2.02"`. `m engine watch --interval 0.2 --count 2`
emitted 2 valid JSON-lines records.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Closes Track C / step C2 in m-dev-tools-todo.md. Fresh-clone of m-cli on a Docker-equipped machine no longer needs a sibling tree-sitter-m/ checkout to install — the "self-contained" sprint bar (Tracks A + B + C) is now fully cleared.
Why
Track C of the org self-containment sprint replaced the path-dep on a sibling tree-sitter-m checkout with URL pins to GitHub-Release wheels. C1 (cibuildwheel job in prebuilds.yml) shipped earlier today; v0.1.1 is the first release whose attach-to-release produced and uploaded all platform wheels. This PR is the consumer-side flip.
Verification (local)
Notes
Test plan
🤖 Generated with Claude Code