Files
multi-agent-mux/.agents/reports/canary-projects-multi-agent-mux-creator-cline/report-16bdc99c.md
T

11 KiB

Cross-Code Review Report: Installation Integrity for lib_py/agents Assets

Job ID: 16bdc99c Reviewer: cline (session: herdr:canary-projects-multi-agent-mux-creator-cline) Review Target: deploy/INSTALL.md and deploy/install.sh (plus install_mam.sh, remove.sh, update.sh, lib_ownership.sh, gitea-ci.yml) — verifying latest assets including lib_py/agents/ are reflected when installing to other projects Base Commit: clean working tree (git diff HEAD = no changes since base) Date: 2026-08-13


1. Executive Summary

This review verifies that the MAM installation toolchain correctly distributes, tracks, and removes the newly introduced lib_py/agents/ package (BaseAgentAdapter, adapter registry, CLI bridge) when installing MAM into target projects. The review covers both installation paths (install.sh remote and install_mam.sh local-clone), the uninstaller (remove.sh), the updater (update.sh), the ownership rules (lib_ownership.sh), CI lint coverage (gitea-ci.yml), and the user-facing installation guide (INSTALL.md).

Verdict: PASS — All four deploy scripts correctly handle the lib_py/agents/ directory tree. The is_framework_owned() glob (.agents/skills/*) classifies all 9 lib_py/agents/**/*.py files as framework-owned, ensuring they are copied, hash-tracked, manifest-registered, and cleanly removed. CI's recursive glob (lib_py/**/*.py) and flake8 lib_py/ correctly cover nested files. INSTALL.md prerequisites and command examples are consistent with the documented install_mam.sh installer. Two Low-severity findings are non-blocking.


2. Scope & Methodology

2.1 Files Reviewed

File Role Lines
deploy/install.sh Rev.2 remote installer (curl/git/tar -> staging -> 3-way hash reconciliation) 621
deploy/install_mam.sh Local-clone installer (rsync-based) 336
deploy/remove.sh Uninstaller (manifest-driven + fallback) 320
deploy/update.sh Updater (remove -> fetch latest install.sh) 247
deploy/lib_ownership.sh Single source of truth for framework-owned / registry file classification 29
deploy/INSTALL.md User-facing installation & quick-start guide 134
deploy/README.md Deployment & Gitea integration reference 83
deploy/gitea-ci.yml CI pipeline (shellcheck, flake8, py_compile, pytest) ~110

2.2 Verification Methods

  1. Static syntax checks: bash -n on all 5 shell scripts; py_compile on all 9 lib_py/agents/ Python files + paths.py + state.py.
  2. Ownership classification test: Sourced lib_ownership.sh and ran is_framework_owned() / is_registry_file() against every lib_py/agents/**/*.py path.
  3. Find-loop simulation: Python walk replicating install.sh's find . -type f + skip patterns to confirm all 9 agent files are captured.
  4. Test execution: 3 adapter contract tests + 11 deploy registry-merge tests + 14 deploy freshness/layout tests = 28 tests, all PASS.
  5. Cross-document consistency: Grepped INSTALL.md vs README.md for installer references; verified CLI flags (--target, --force) match actual script argument parsers.
  6. CI coverage analysis: Inspected gitea-ci.yml flake8 and py_compile glob patterns for recursive coverage of nested lib_py/agents/ files.

3. Installation Path Analysis

3.1 deploy/install.sh (Rev.2 Remote Installer)

Asset fetch (lines 117-153): Three fetch methods -- local cp -R, git clone --depth 1, or curl | tar -xz. All populate a staging directory with the full repo tree.

Copy loop (lines 187-354): The core mechanism uses find . -type f (recursive) over the staged .agents/ directory, skipping only reports/, references/, *.tmp, *.log, *.pyc, __pycache__/. It does NOT exclude lib_py/agents/. Each file is classified by is_framework_owned() (matching .agents/skills/*), which classifies all lib_py/agents/**/*.py files as framework-owned (verified by direct test). is_registry_file() returns NO for agent files (only .agents/hooks.json is registry), so they get wholesale copy/update via 3-way hash reconciliation, not key-merge.

Hash DB (lines 409-434): FRAMEWORK_LEDGER records every framework-owned file pair. SHA256 hashes computed for all, including lib_py/agents/ files.

Manifest (lines 155-157, 258-260): Every copied framework file appended to .mam/install_manifest.txt.

Sanity gate (lines 98-115, 463): check_assets_present() checks 7 representative core files. Does NOT include lib_py/agents/ -- but this is a fast representative-sample guard. The copy loop's find captures everything. See F-2.

3.2 deploy/install_mam.sh (Local-Clone Installer)

rsync copy (line 126): rsync -a with excludes for .git/, /reports/, /references/, *.log, *.tmp, __pycache__/, *.pyc. Recursive copy preserves directory structure -> copies entire lib_py/agents/ tree. Excludes do NOT target lib_py/ or agents/.

Manifest (line 163): find .agents -type f -print records all files including lib_py/agents/**/*.py.

Hash DB (lines 172-206): Iterates manifest, classifies via is_framework_owned(), computes SHA256 for all framework files.

3.3 deploy/remove.sh (Uninstaller)

Manifest mode (lines 75-81): Reads .mam/install_manifest.txt and deletes each listed file individually -> covers all lib_py/agents/**/*.py entries.

Fallback mode (lines 83-108): fallback_assets array includes ".agents/skills/lib_py" as a directory entry. delete_asset uses rm -rf on directory entries -> removes entire lib_py/ tree including agents/ subdirectory.

3.4 deploy/update.sh (Updater)

Flow (lines 182-199): Runs remove.sh --force (manifest-driven cleanup) then fetches and pipes latest install.sh from remote via curl | bash. Target inherits full install.sh coverage from section 3.1.

3.5 CI Coverage (deploy/gitea-ci.yml)

  • flake8 (lines 72, 74): flake8 .agents/skills/lib_py/ recursively traverses Python packages, covering lib_py/agents/ and lib_py/agents/adapters/.
  • py_compile (line 79): glob.glob('.agents/skills/lib_py/**/*.py', recursive=True) -- recursive glob correctly captures nested files. (This was the CI glob fix from the A-4 BaseAgentAdapter introduction job.)

4. INSTALL.md Consistency Check

4.1 Prerequisites (Section 1)

Prerequisite in INSTALL.md Verified Against Status
herdr install_mam.sh:94 DEPS array PASS
python3 install_mam.sh:94 DEPS array PASS
uuidgen install_mam.sh:94 DEPS array PASS
rsync install_mam.sh:94 DEPS + :126 usage PASS
pyyaml install_mam.sh:113 import yaml, sqlite3 PASS
sqlite3 (built-in) install_mam.sh:113 import yaml, sqlite3 PASS

4.2 Command Examples (Section 2)

INSTALL.md Example Actual Script Flag Status
bash deploy/install_mam.sh --target /path/... install_mam.sh:39 `-t --target`
bash deploy/install_mam.sh --target ... --force install_mam.sh:43 `-f --force`

4.3 Documented Operations

  1. "Dependency diagnosis" -- install_mam.sh:92-117 checks DEPS + Python modules. PASS
  2. "Rules & skills replication" -- install_mam.sh:120-127 rsync .agents/ recursively. PASS
  3. "Guidelines propagation" -- install_mam.sh:220-234 copies/injects AGENTS.md. PASS
  4. "Gitignore exclusion" -- install_mam.sh:236-291 injects .gitignore managed block. PASS

4.4 Quick Start Workflow (Section 3)

All 6 workflow examples (Create, Attach, Resume, Stop/Purge, Mux-Loop, Orc-Onboard) reference correct script paths under .agents/skills/multi-agent-mux-*/scripts/. Verified against actual file tree.


5. Findings

F-1 (Low / Info) -- INSTALL.md documents only install_mam.sh, not install.sh

Location: deploy/INSTALL.md (entire document) Observation: INSTALL.md references install_mam.sh 4 times but install.sh 0 times. The repo has two installers: install_mam.sh (local-clone, documented in INSTALL.md) and install.sh (Rev.2 remote curl, documented in deploy/README.md, used by update.sh). Impact: A user reading only INSTALL.md learns about the local-clone path but not the remote one-liner. However, deploy/README.md documents the remote installer, and INSTALL.md is placed under .agents/ in target projects where the local-clone workflow is relevant. Assessment: Documentation structure choice (README = developer reference, INSTALL.md = user manual), not a bug. Non-blocking.

F-2 (Low / Info) -- check_assets_present() does not include a lib_py/agents/ file

Location: deploy/install.sh:98-115 Observation: The sanity-check function verifies 7 representative core files. It does not include any lib_py/agents/ file. Impact: None in practice. The function is a fast pre/post guard -- the actual copy loop uses find . -type f which captures all files recursively. All three fetch methods (git clone, tar extract, cp -R) copy the entire tree, making a partial-drop scenario implausible. Recommendation: Adding .agents/skills/lib_py/agents/__init__.py to core_files would provide defense-in-depth. Optional, non-blocking.


6. Test Results

Test Suite Tests Result
tests/test_a4_adapter_contract.py 3 All PASS
tests/test_deploy_registry_merge.py 11 All PASS
tests/test_deploy_freshness.py 11 All PASS
tests/test_deploy_layout.py 3 All PASS
Total 28 All PASS

Static Analysis

Check Result
bash -n all 5 shell scripts PASS
py_compile all 9 lib_py/agents/**/*.py + paths.py + state.py PASS
is_framework_owned() on 5 lib_py/agents/ paths All FRAMEWORK
is_registry_file() on lib_py/agents/registry.py Correctly NO
Find-loop simulation (recursive walk + skip patterns) 9/9 agent files captured
CI flake8 + py_compile glob coverage Recursive lib_py/**/*.py covers nested

7. Conclusion

The installation toolchain provides complete, end-to-end coverage for the lib_py/agents/ package across all lifecycle operations:

  1. Install (both paths): Recursive find/rsync + .agents/skills/* ownership glob -> all 9 agent files copied, hash-tracked, and manifest-registered.
  2. Update: remove.sh (manifest-driven) + install.sh (fresh fetch) -> full replacement with preserved user configs.
  3. Remove: Manifest entries + fallback .agents/skills/lib_py directory -> clean uninstall with no orphaned agent files.
  4. CI: Recursive flake8 + py_compile glob -> nested agent files are lint-checked on every push.
  5. INSTALL.md: Prerequisites, command flags, and documented operations are consistent with the install_mam.sh installer.

The two findings (F-1, F-2) are both Low/Info severity and non-blocking. No design-level rework or escalation is needed.


[VERDICT: PASS]