72 lines
5.3 KiB
Markdown
72 lines
5.3 KiB
Markdown
# REPORT A1207
|
|
|
|
Date: 2026-08-13
|
|
Branch: `fix/869-lease-probe-timeout`
|
|
Starting head: `2373a5ad345fb316ad2460f6390baab1f45ba08f`
|
|
Base: `216cd72226cd9ee17eea461cfe7cd0e010a22f02`
|
|
|
|
## What changed
|
|
|
|
- Added Python behavior tests using isolated temporary directories and marker-writing fake `mosaic` executables. They prove that the supplied `PATH` wins over ambient `os.environ["PATH"]`, and that absent or empty supplied `PATH` values do not search ambient paths, platform defaults, or the current directory.
|
|
- Bound Python override behavior with executable fakes: a valid `MOSAIC_LEASE_VERSION_PROBE_COMMAND` wins over supplied and ambient `PATH`; an invalid override returns `None` without PATH fallback.
|
|
- Added a Python runner binding test that captures kwargs and requires `timeout=10.0`. Existing timeout, transport-error, and nonzero-exit checks remain fail-closed with `None`.
|
|
- Added the optional TypeScript dependency-injection seam `CapabilityProbeExecFile`, defaulting to the existing real `execFileSync` implementation. Production callers have no behavior change.
|
|
- Added TypeScript tests that capture child-process options and require exactly `timeout: 10_000`. Injected timeout, spawn-error, nonzero-exit, unparseable JSON, and malformed-object cases all return `null`.
|
|
- Removed the ambient no-dependency TypeScript smoke case that could execute a built checkout's real CLI. Default resolver and supervisor behavior retain their isolated tests, while capability transport tests now use an isolated artifact or the injected transport.
|
|
|
|
No Python production code changed relative to `2373a5ad`. The only production delta is the optional TypeScript child-process injection seam.
|
|
|
|
## Hermeticity incident and correction
|
|
|
|
An initial ambient-lookup mutation run exposed that the pre-existing Python "not resolvable" test left ambient process PATH uncontrolled. On this host, that mutation resolved and executed the host `mosaic` capability probe. A post-build intermediate TypeScript run also let the pre-existing no-dependency smoke case execute the checkout's built `dist/cli.js` capability probe. No `claude` process was run. I then isolated the Python test's ambient PATH, removed the TypeScript ambient smoke case, repeated the PATH mutation using only marker-writing temporary fakes, and repeated the final suites without either real probe path.
|
|
|
|
## Mutation evidence
|
|
|
|
Each mutation was applied independently, its focused suite was run, and the production source was restored before the final run.
|
|
|
|
| Mutation | Result | Reddened test name(s) |
|
|
| ------------------------------------------------------------------------------------------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `shutil.which("mosaic", path=environ.get("PATH", ""))` to ambient `shutil.which("mosaic")` | RED, three failures | `ProbeActivationCapabilityTest.test_supplied_path_wins_over_ambient_process_path`; `ProbeActivationCapabilityTest.test_absent_or_empty_supplied_path_never_falls_back_or_executes` for both absent and empty PATH subtests |
|
|
| Python `PROBE_TIMEOUT_SECONDS: 10.0` to `2.0` | RED, one failure | `ProbeActivationCapabilityTest.test_probe_passes_ten_second_timeout_to_runner` |
|
|
| TypeScript `LEASE_CAPABILITY_PROBE_TIMEOUT_MS: 10_000` to `2_000` | RED, one failure | `defaultCapabilityProbe > passes the exact ten-second timeout to the injected child-process transport` |
|
|
|
|
## Final test run
|
|
|
|
Dependencies were installed first with `pnpm install --frozen-lockfile`. Workspace dependencies were then built with `pnpm --filter '@mosaicstack/mosaic...' run build` so package type declarations were available.
|
|
|
|
```text
|
|
$ cd packages/mosaic && python3 src/mutator-gate/version_coupling_unittest.py
|
|
...................
|
|
----------------------------------------------------------------------
|
|
Ran 19 tests in 0.007s
|
|
|
|
OK
|
|
|
|
$ pnpm exec vitest run src/commands/lease-activation-probe.spec.ts
|
|
✓ src/commands/lease-activation-probe.spec.ts (20 tests) 80ms
|
|
Test Files 1 passed (1)
|
|
Tests 20 passed (20)
|
|
```
|
|
|
|
```text
|
|
$ pnpm exec prettier --check packages/mosaic/src/commands/lease-activation-probe.ts packages/mosaic/src/commands/lease-activation-probe.spec.ts
|
|
Checking formatting...
|
|
All matched files use Prettier code style!
|
|
|
|
$ pnpm --filter @mosaicstack/mosaic lint
|
|
> eslint src
|
|
|
|
$ pnpm --filter @mosaicstack/mosaic typecheck
|
|
> tsc --noEmit
|
|
|
|
$ python3 -m py_compile packages/mosaic/src/mutator-gate/version_coupling_unittest.py packages/mosaic/framework/tools/lease-broker/activation_version_gate.py
|
|
|
|
$ git diff --check
|
|
```
|
|
|
|
All commands above exited zero.
|
|
|
|
## Ambiguities skipped
|
|
|
|
None.
|