fix(issue-12,8,7): keep broker password out of records, keep fresh install stamps, pack sibling workspaces
Issue #12 - MQTT_PASSWORD was copied into every job record, which any sub-agent can read. BrokerConfig.to_registry_block no longer persists it; broker_config_from_job layers the password back from the environment (.mam.env) at connect time, so publish_event still connects from the record. _atomic_write_record scrubs broker.password from any record it writes, and `registry.py scrub-secrets [--dry-run]` migrates an existing registry. auth_token/dispatch_token stay: the agent's own publish_event needs them. Issue #8 - update.sh restored the pre-update asset_hashes.txt and version.txt over the installer's fresh ones, so version.txt named the previous commit and remove.sh backed up every pristine updated file as "locally modified". The success path now keeps the installer's stamps and only merges install_state keys the re-install did not write (gitignore_created); the failure path still restores everything verbatim. Issue #7 - the shim's new-session took the first same-cwd pane, always found the full first workspace, judged it overflow and opened another workspace per agent (4 + 1 + 1). It now walks every same-cwd workspace in pane order and takes the first with an idle pane or room in its 2xK grid; a workspace is created only when all are full (4 + 2). Tests: test_issue7_workspace_packing.py (3; the mock herdr gains an opt-in per-workspace 2x2 geometry), test_issue8_update_state.py (1, real install+update cycle), test_issue12_registry_secrets.py (4); registry CLI snapshot and help capture refreshed for the intentional scrub-secrets subcommand; registry.md documents the broker block. Refs #12 #8 #7 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
8a09e022a6
commit
e629cc137f
12 files changed
+422
-52
No files matched your search
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Issue #8 — update.sh must keep the installer's fresh version.txt and
|
||||
asset_hashes.txt instead of restoring the pre-update copies.
|
||||
|
||||
Restoring them left version.txt naming the previous commit and made remove.sh
|
||||
compare against stale hashes, so every updated-but-pristine file was backed up
|
||||
as "locally modified". install_state is the one file whose old keys are
|
||||
merged back (gitignore_created from the original install).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def installed_workspace():
|
||||
temp = tempfile.mkdtemp(prefix="mam_issue8_")
|
||||
ws = Path(temp) / "workspace"
|
||||
ws.mkdir()
|
||||
env = os.environ.copy()
|
||||
env["MAM_REPO_URL"] = str(REPO_ROOT)
|
||||
env["MAM_SKIP_VENV"] = "1"
|
||||
env["MAM_INSTALLER_URL"] = "file://" + str(REPO_ROOT / "deploy" / "install.sh")
|
||||
res = subprocess.run(["bash", str(REPO_ROOT / "deploy" / "install.sh"), str(ws)],
|
||||
env=env, capture_output=True, text=True, timeout=600)
|
||||
assert res.returncode == 0, res.stderr
|
||||
try:
|
||||
yield ws, env
|
||||
finally:
|
||||
shutil.rmtree(temp, ignore_errors=True)
|
||||
|
||||
|
||||
def test_update_keeps_fresh_version_and_hashes_and_merges_install_state(installed_workspace):
|
||||
ws, env = installed_workspace
|
||||
mam = ws / ".mam"
|
||||
fresh_version = (mam / "version.txt").read_text()
|
||||
assert "commit=" in fresh_version
|
||||
|
||||
# Simulate the previous install: stale stamps and an install_state key the
|
||||
# re-install will not write again.
|
||||
(mam / "version.txt").write_text("source=old\ncommit=stale0000\nfetched_at=then\nmethod=git\n")
|
||||
(mam / "asset_hashes.txt").write_text("stale-hash-db\n")
|
||||
with open(mam / "install_state", "a") as fh:
|
||||
fh.write("custom_marker=kept\n")
|
||||
|
||||
res = subprocess.run(["bash", str(ws / ".mam_deploy" / "update.sh"), "--force"],
|
||||
cwd=str(ws), env=env, capture_output=True, text=True, timeout=600)
|
||||
assert res.returncode == 0, res.stderr + res.stdout
|
||||
|
||||
version = (mam / "version.txt").read_text()
|
||||
assert "stale0000" not in version, version
|
||||
assert "commit=" in version and version.strip() != ""
|
||||
hashes = (mam / "asset_hashes.txt").read_text()
|
||||
assert "stale-hash-db" not in hashes and hashes.strip(), "asset_hashes.txt must be the installer's fresh ledger"
|
||||
|
||||
state = (mam / "install_state").read_text()
|
||||
assert "custom_marker=kept" in state, state
|
||||
assert state.count("gitignore_created=1") == 1, "merged keys must not be duplicated:\n" + state
|
||||
Reference in new issue
Block a user