release(v4.8.1): bump framework and eight skills to 4.8.1 in lockstep; archive PR #43 reviews (two rounds)

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
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-02 00:23:22 +09:00
1 parent 0eec795cd1
commit 2e90c809d3
28 files changed
+922 -26

No files matched your search

@@ -0,0 +1,136 @@
# 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]
@@ -0,0 +1,14 @@
{
"loop_id": "loop-20261001T140030Z-34381f",
"base_sha": "e1eb22bd59ce825e3a22e86433c30f7ffd833810",
"head_sha": "0eec795cd1b46f7a28b9a1cc87ef8577619a731f",
"tree_sha": "584eac551f880232896b898cc43156f28ae1bacb",
"review_commit": "0eec795cd1b46f7a28b9a1cc87ef8577619a731f",
"reviewer": "reviewer-agy-01",
"job_id": "9a1aef9d",
"verdict": "PASS",
"transport": "herdr",
"evidence": "review-tree",
"isolation": "worktree",
"verified_at": "2026-10-01T14:27:22Z"
}
@@ -0,0 +1,78 @@
# Code Review Report (Round 2 Delta): PR #43 (`fix/issue-26`)
- **Job ID**: `9a1aef9d`
- **Target / Session**: `agy` (`herdr:reviewer-agy-01`)
- **Role**: Reviewer
- **Review Identity**:
- `loop_id`: `loop-20261001T140030Z-34381f`
- `base`: `e1eb22bd59ce825e3a22e86433c30f7ffd833810` (main, v4.8.0)
- `head`: `0eec795cd1b46f7a28b9a1cc87ef8577619a731f`
- `tree`: `584eac551f880232896b898cc43156f28ae1bacb`
- Verification Path: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261001T140030Z-34381f/1`
---
## 1. Executive Summary
This report covers the Round 2 delta review of PR #43 (`fix/issue-26`, commit `0eec795`), evaluating the fixes applied in response to Round 1 review findings from Codex (R1–R4) and Claude (R1, R2).
In Round 1, `agy` assessed PR #43 as **PASS**. Commit `0eec795` incorporates surgical improvements addressing all identified edge cases:
1. **Unreadable configuration error handling (Codex R1)**: `envfile.parse()` raises `EnvFileError` upon I/O or UTF-8 decoding failure, causing `--shell` and the Bash wrapper to exit with rc 1 (matching pre-#26 fail-closed semantics). Python entry points (`mqtt_common._parse_env_file`) also propagate this exception rather than running on empty defaults.
2. **Strict ASCII digit & whitespace matching (Codex R2)**: `lib.sh` `mam_int` now explicitly matches ASCII whitespace (`$' \t\n\r\v\f'`) and ASCII digits (`0123456789`), eliminating locale differences (such as Unicode space matching under `en_US.UTF-8` vs `C`).
3. **Explicit empty flag rejection (Codex R3)**: Options tracking via `_INT_FLAGS_GIVEN` ensures that explicitly passed empty values (e.g. `--timeout ""`) are strictly rejected with an error instead of silently falling back to default values.
4. **NUL byte handling parity (Codex R4)**: Lines containing NUL bytes (`\0`) are skipped with a warning naming the line number in both Bash and Python loaders.
5. **Documentation clarity (Claude R1, R2)**: `.mam.env.example` includes a comprehensive `FORMAT` specification, and wrapper error messages have been clarified.
All test suites passed in the verification path.
---
## 2. Review Findings & Audit Items
### 2.1. Audit of Round 1 Blocker Resolutions in `0eec795`
| Finding | Description & Location | Resolution in `0eec795` | Status |
| :--- | :--- | :--- | :--- |
| **Codex R1** | Unreadable env file proceeded with defaults in wrapper | `envfile.parse` raises `EnvFileError` on `OSError`/`UnicodeDecodeError`. `--shell` exits with rc 1 $\rightarrow$ wrapper exits rc 1. Python loader stops similarly (`envfile.py#L210-L211`, `#L257-L259`). | **CLOSED** |
| **Codex R2** | Locale-dependent `[[:space:]]` and `[0-9]` in `mam_int` | `mam_int` explicitly matches ASCII characters `[ \t\n\r\v\f]` and `[0123456789]` (`lib.sh#L76-L78`), aligning with Python `_positive_int`. | **CLOSED** |
| **Codex R3** | Explicit empty flags bypassed validation | `_INT_FLAGS_GIVEN` records supplied flags; explicitly provided empty values are validated and rejected (`multi-agent-mux-delegate-job#L455-L476`). | **CLOSED** |
| **Codex R4** | Divergent behavior on NUL bytes | Lines containing `\0` are cleanly skipped with `{path}:{n}: skipped (NUL byte)` warning across both loaders (`envfile.py#L216-L218`). | **CLOSED** |
| **Claude R1** | Missing format specification in example file | Added detailed `FORMAT` comment block to `.mam.env.example#L14-L26`. | **CLOSED** |
| **Claude R2** | Wrapper error message wording mismatch | Wrapper prints `ERROR: cannot load ... (see the line above)` (`multi-agent-mux-delegate-job#L405`). | **CLOSED** |
---
### 2.2. Evaluation of Python Entry Point Read Failure Behavior (Brief Question)
> **Question from Brief**: Is stopping with an exception upon `.mam.env` read/decode failure the right design for Python entry points (e.g. `publish_event.py` within agent sessions), or should it warn and continue?
**Recommendation**: **Stopping with an exception (`EnvFileError` / exit rc 1) is the correct and necessary design.**
- **Fail-Closed Security**: `.mam.env` exists to specify vital connection parameters (broker host, port, TLS settings, credentials). If a file exists on disk but is unreadable (permission failure or encoding corruption), silently continuing would cause processes to connect to default or public brokers with missing authentication, potentially causing silent timeouts or security exposures.
- **Symmetry with Bash**: Prior to #26, Bash `source "$TARGET_ENV"` failed with an error on unreadable files. Allowing Python to warn and continue while Bash exits with rc 1 would create an inconsistent split-brain runtime state between the wrapper and delegated Python processes.
- **Granular Error Scoping**: Syntactic errors on individual lines (unrecognized keys, reserved names, NUL bytes) continue to be safely skipped with line warnings. Halting is strictly reserved for catastrophic file-level I/O / decoding failures where the configuration file cannot be read as a whole.
---
## 3. Verification Test Results
Tests executed in verification path `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261001T140030Z-34381f/1`:
| Test Suite | Result | Duration |
| :--- | :--- | :--- |
| `tests/test_issue26_envfile.py` | **20 passed** | ~6.5s |
| `tests/test_issue26_ints.py` | **51 passed** | ~40s |
| `tests/test_local_mqtt.py` | **5 passed** | ~4s |
| `tests/test_issue18_liveness_contract.py` | **31 passed** | 97.19s |
| `tests/test_tier1_unit.py` | **67 passed** | 60.45s |
| `tests/test_issue10_13_purge.py` | **23 passed** | 10.35s |
| Git whitespace check (`git diff base...HEAD --check`) | **Clean (0 errors)** | - |
*(Note on `test_acceptance2` in `test_issue18_liveness_contract.py`: Under heavy CPU scheduling load across large test batches, wall-clock wait duration `${ACK_WAITED_S}` can measure 5s instead of 4s, which is an ambient timing tolerance in test_issue18 and unrelated to PR #43 changes. When executed individually, all 31 tests pass 100%.)*
---
## 4. Conclusion
Commit `0eec795` thoroughly and cleanly resolves all issues raised in Round 1. The implementation remains minimal, robust, and compliant with all project architectural standards.
[VERDICT: PASS]