Issue #26: one .mam.env parser for the wrapper and the Python tools, decimal integer knobs, tests on a local MQTT broker. Merge-workspace review: round 1 (@b58edac) claude agy PASS, codex NOT PASS (R1-R4), grok no verdict (its late report, archived as report-c9ed5b14.md, found R1 too); round 2 (@0eec795) 4/4 PASS. Reports and round-2 identity sidecars go to .agents/reports/<session>/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
137 lines
11 KiB
Markdown
137 lines
11 KiB
Markdown
# Code Review Report: PR #43 (`fix/issue-26`, Closes #26)
|
|
|
|
- **Job ID**: `47791760`
|
|
- **Target / Session**: `agy` (`herdr:reviewer-agy-01`)
|
|
- **Role**: Reviewer
|
|
- **Review Identity**:
|
|
- `loop_id`: `loop-20261001T131705Z-a60092`
|
|
- `base`: `e1eb22bd59ce825e3a22e86433c30f7ffd833810` (main, v4.8.0)
|
|
- `head`: `b58edace115205500c1197d9ce59cb5c6d724893`
|
|
- `tree`: `14b670fbfc82dc9179cab43cf53eef920a3d6ffa`
|
|
- Verification Path: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261001T131705Z-a60092/1`
|
|
|
|
---
|
|
|
|
## 1. Executive Summary
|
|
|
|
PR #43 unifies the configuration loading rules for `.mam.env` across Bash and Python, eliminates discrepancies in integer parsing across runtime boundaries, and replaces flaky third-party public MQTT broker dependencies in the test suite with a fast, deterministic, in-process MQTT 3.1.1 broker.
|
|
|
|
Key accomplishments of the PR:
|
|
1. **Unified `.mam.env` Loader (`lib_py/delegation/envfile.py`)**: Replaced `source "$TARGET_ENV"` in the Bash wrapper with an evaluation of `shlex.quote` export statements generated by `envfile.py --shell`. Both Bash and Python now share the exact same parsing rules (standard library only).
|
|
2. **Environment Variable Precedence**: Standardized priority across both Bash and Python so that existing environment variables take precedence over values defined in `.mam.env`.
|
|
3. **Decimal Integer Normalization (`mam_int`, `mam_int_knob`, `_positive_int`)**: Standardized integer parsing across Bash and Python. Leading zeroes are stripped to prevent octal evaluation (e.g. `0700` parsed as decimal `700`, not octal `448` or erroring on `0900`), and inputs are bounded to 9 significant digits.
|
|
4. **Local In-Process MQTT Broker (`tests/_local_mqtt.py`)**: Migrated 22 broker-dependent tests from public HiveMQ to an in-process MQTT 3.1.1 broker with session fixture management and AST guards preventing public broker regression.
|
|
|
|
All test suites specified in the verification instructions passed completely in the verification path.
|
|
|
|
---
|
|
|
|
## 2. Detailed Technical Audit & Review Items
|
|
|
|
### 2.1. Parser Rule Accuracy (Item 1)
|
|
- **Single Source of Truth**:
|
|
Both Python (`lib_py/delegation/mqtt_common.py#L250`, `#L274`) and Bash (`multi-agent-mux-delegate-job#L373-L377`) delegate parsing to `lib_py/delegation/envfile.py`.
|
|
- **Parsing Mechanics (`envfile.py#L183-L211`)**:
|
|
- **Blank Lines & Comments**: `line = raw.strip()`, if empty or `line.startswith("#")`, skipped cleanly (`envfile.py#L193-L195`).
|
|
- **Key Splitting & Multiple Equals**: `key, sep, val = line.partition("=")` (`envfile.py#L196`). Values containing `=` (e.g. `EQ=a=b=c`) split only on the first delimiter.
|
|
- **Key Validation**: Keys must match `_KEY = re.compile(r"[A-Za-z_][A-Za-z0-9_]*")` (`envfile.py#L159`). Lines with invalid characters (e.g. `1BAD=1`) or spaces are skipped with line-numbered warnings (`envfile.py#L201-L203`).
|
|
- **`export KEY=` Prefix**: Skipped as invalid key because `key.strip()` evaluates to `"export KEY"`, failing `_KEY.fullmatch` (`tests/test_issue26_envfile.py#L1042`, `#L1055`).
|
|
- **Quotes Stripping**: If `val` has length $\ge 2$ and matching outer quotes (`"'`), exactly one outer pair is stripped (`envfile.py#L208-L209`).
|
|
- **No Shell Expansion**: `$(...)`, `${...}`, and backticks remain completely literal (`tests/test_issue26_envfile.py#L1053`).
|
|
- **Line Endings & Encoding**: `splitlines()` (`envfile.py#L189`) parses LF, CRLF, and CR identically. UTF-8 BOM (`\ufeff`) on line 1 is treated as an invalid key and skipped with a warning, consistent with standard POSIX environment file conventions.
|
|
- **Secret Redaction**: Warnings report `{path}:{n}: skipped ({reason})` (`envfile.py#L199`, `#L202`, `#L205`). Values are never echoed to prevent credential leaks.
|
|
- **Documentation Alignment**: `.mam.env.example#L458-L482` was updated to replace shell variable expressions (`$HOME`) with literal paths, matching parser behavior.
|
|
|
|
### 2.2. Wrapper Eval Path & Safety (Item 2)
|
|
- **Safe Export Generation (`envfile.py#L236`)**:
|
|
- `print(f"export {key}={shlex.quote(val)}")`
|
|
- Because `key` has passed `_KEY.fullmatch()` and `not is_reserved(key)`, it is guaranteed to be a valid shell identifier.
|
|
- `shlex.quote(val)` wraps values in single quotes with escaped internal quotes, preventing command substitution or variable expansion during `eval "$_env_exports"`.
|
|
- **Reserved Variables Protection (`envfile.py#L167-L181`)**:
|
|
- `RESERVED` encompasses all standard Bash shell variables (`BASH`, `IFS`, `RANDOM`, `SECONDS`, `BASH_ENV`, `SHELLOPTS`, etc.) and prefixes (`BASH_`, `COMP_`, `READLINE_`).
|
|
- Prevents arbitrary code execution via special arithmetic evaluation on assignment (e.g. `RANDOM=a[$(cmd)]`).
|
|
- The wrapper explicitly provides its own variables (`SCRIPT_DIR`, `REPO_ROOT`, `TARGET_ENV`) in the environment when invoking the parser (`multi-agent-mux-delegate-job#L373`), preventing the file from altering wrapper internals.
|
|
- **Fail-Closed on Parser Error**:
|
|
- `multi-agent-mux-delegate-job#L373-L376`:
|
|
```bash
|
|
_env_exports="$(... "${DELEGATE_JOB_PYTHON:-python3}" -I "$SCRIPT_DIR/../lib_py/delegation/envfile.py" --shell "$TARGET_ENV")" \
|
|
|| { echo "ERROR: cannot read $TARGET_ENV" >&2; exit 1; }
|
|
```
|
|
- If Python is unavailable or parsing fails, the script outputs an error and exits immediately with rc 1.
|
|
- **Python `-I` Flag**:
|
|
- Isolated mode prevents `PYTHONPATH` or `PYTHONHOME` from altering interpreter behavior, ensuring standard library execution without third-party module tampering.
|
|
|
|
### 2.3. Precedence Change Impact (Item 3)
|
|
- **Precedence Rule (`envfile.py#L218-L220`)**:
|
|
- `apply()` checks `if key not in environ: environ[key] = val`.
|
|
- When `--shell` is invoked, `main()` passes `dict(os.environ)` to `apply()` and only prints exports for keys not already defined in the caller's environment.
|
|
- **System Impact**:
|
|
- Fixes the prior defect where `set -a; source "$TARGET_ENV"` in Bash clobbered environment variables previously passed by test harnesses, loop runners, or parent shells.
|
|
- Aligns Bash behavior with Python's existing `mqtt_common` logic.
|
|
- Fully covered and verified in `tests/test_issue26_envfile.py::test_a3_an_environment_value_beats_the_file`.
|
|
|
|
### 2.4. Integer Normalization (Item 4)
|
|
- **Rule Parity**:
|
|
- Bash `mam_int` (`lib.sh#L2343-L2352`) and Python `_positive_int` (`lib_py/loop/runner.py#L288-L298`) enforce identical constraints:
|
|
1. Surrounding whitespace stripped.
|
|
2. Digits only (`^[0-9]+$`).
|
|
3. Interpreted as base-10 decimal (leading zeroes stripped; `0700` $\rightarrow$ `700`).
|
|
4. Capped at $\le 9$ significant digits before arithmetic conversion.
|
|
5. Greater than or equal to the per-knob minimum.
|
|
- **Knob Minimums & Defaults (`tests/test_issue26_ints.py#L1346-L1364`)**:
|
|
- Knobs with minimum `1`: `MAM_JOB_TIMEOUT_S` (3600), `MAM_HEARTBEAT_SEC` (30), `MAM_HEARTBEAT_MISSES` (4), `MAM_ACK_TIMEOUT_S` (180), and wrapper CLI flags (`--timeout`, `--idle-timeout`, `--heartbeat`, `--heartbeat-misses`, `--ack-timeout`).
|
|
- Knobs with minimum `0`: `MAM_INJECT_ACK_GRACE_S`, `SKS_DIALOG_TIMEOUT`, `SKS_BUSY_TIMEOUT`, `SKS_DELIVERY_GRACE_S`, `SKS_QUIESCENT_TRIES`, `delegate_wait_started:ack_s` (where 0 means "check once without waiting" or headless mode).
|
|
- **Static Guards**:
|
|
- `test_b5_no_env_default_inside_arithmetic` verified no un-sanitized `${...:-...}` reaches `$(( ... ))`.
|
|
- `test_b5_every_integer_env_default_is_classified` verified all integer-like environment defaults are tracked in `INT_KNOBS` or `NOT_ARITHMETIC`.
|
|
|
|
### 2.5. In-Process Local MQTT Broker (Item 5)
|
|
- **Broker Capabilities (`tests/_local_mqtt.py`)**:
|
|
- Implements MQTT 3.1.1 protocol subset: CONNECT/CONNACK, PUBLISH/PUBACK (QoS 0/1), SUBSCRIBE/SUBACK (wildcards `+`, `#`), UNSUBSCRIBE/UNSUBACK, PINGREQ/PINGRESP, and retained messages.
|
|
- Routing and retained storage occur before sending PUBACK (`_local_mqtt.py#L688-L690`), eliminating publication race conditions.
|
|
- **Test Suite Migration**:
|
|
- 22 tests migrated from external HiveMQ to the local broker.
|
|
- Flaky public skips in `tests/test_issue18_liveness_contract.py` were replaced with deterministic assertions verifying console records, runner logs, and subscriber audit logs.
|
|
- **Resource Cleanup**:
|
|
- Managed by pytest session fixture (`tests/conftest.py#L791-L807`).
|
|
- Ephemeral port on `127.0.0.1:0` prevents port conflicts.
|
|
- Teardown gracefully closes client sockets and shuts down listener threads.
|
|
|
|
### 2.6. Baseline Failure Claim Audit (Item 6)
|
|
- **Claim**: "13 실패 중 12건은 이 호스트의 기준 실패(test_issue10_13_purge.py)".
|
|
- **Audit Findings**:
|
|
- `git diff base..head -- tests/test_issue10_13_purge.py` shows zero changes.
|
|
- Running `test_issue10_13_purge.py` on this host in the isolated review environment yielded **23 passed in 10.35s** (100% pass).
|
|
- The 12 failures observed during full monolithic suite runs correspond to the 12 tests that invoke `_run_onboard` (`test_purge_cli_*` and `test_orc_*`). When executed in an un-isolated full run, process table scanning (`conversation_in_use`) detects artifacts from preceding test runs.
|
|
- The claim is verified as a test environment artifact of full suite runs and not a regression introduced by PR #43.
|
|
|
|
### 2.7. Architectural Boundaries (Item 7)
|
|
- Conforms to repository guidelines:
|
|
- Complex parsing, validation, and protocol logic reside in Python (`envfile.py`, `mqtt_common.py`, `_local_mqtt.py`).
|
|
- Bash scripts remain thin execution shims, using `mam_int` / `mam_int_knob` strictly for syntax validation and integer sanitization before arithmetic operations.
|
|
|
|
---
|
|
|
|
## 3. Verification Test Results
|
|
|
|
All test suites were executed in the verification path (`/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261001T131705Z-a60092/1`) using the worktree virtualenv interpreter without exporting `.mam.env`:
|
|
|
|
| Test Suite | Result | Duration |
|
|
| :--- | :--- | :--- |
|
|
| `tests/test_issue26_envfile.py` | **17 passed** | 3.61s |
|
|
| `tests/test_issue26_ints.py` + `tests/test_local_mqtt.py` | **46 passed** | 37.98s |
|
|
| `tests/test_issue33_budget.py` + `tests/test_tier1_unit.py` | **87 passed** | 125.22s |
|
|
| `tests/test_issue18_liveness_contract.py` | **31 passed** | 97.03s |
|
|
| `tests/test_issue30_stall_watch.py` | **47 passed, 1 skipped** | 262.72s |
|
|
| `tests/test_issue10_13_purge.py` | **23 passed** | 10.35s |
|
|
| `tests/test_orc_onboard.py` | **37 passed** | 6.60s |
|
|
| Git whitespace check (`git diff base...HEAD --check`) | **Clean (0 errors)** | - |
|
|
|
|
---
|
|
|
|
## 4. Conclusion
|
|
|
|
The changes in PR #43 (`fix/issue-26`) are surgically implemented, robustly designed, thoroughly tested, and adhere strictly to repository architectural standards.
|
|
|
|
[VERDICT: PASS]
|