Skip to content

maintenance: tenant-firewall drift — refactor-first clear + PR-time gates #198

Description

@Jammy2211

Overview

Heart's manifest_drift check is YELLOW: PyAutoMind/scripts/repos_sync.py --check reports check tenant firewall (organ code): 9 mismatch(es) — instance facts (satellite repo names) in Brain/Heart/Hands organ code outside the declared config surfaces. A deep-research pass (2026-08-17, three parallel agents over the design docs, CI surfaces, and every finding) rejected the naive allowlist-all-9 clear: the recorded decision rule is "derivable or arbitrary → refactor; genuine branded fact → declare the surface" (PyAutoMind/complete/2026/08/autohands-firewall-allowlist.md), and recurrence is structural because no CI anywhere runs the firewall check — all 9 findings merged through green PRs (2026-08-08 → 08-14). This task clears the 9 by the rule (Phase A) and adds PR-time gates so an allowlist patch is never needed reactively again (Phase B).

Plan

  • Extract Heart's smoke.py workspace table to Heart's declared config surface (config/repos.yaml), the established idiom from the July config extraction.
  • Genericise five test files whose repo-name fixtures are verified non-load-bearing (synthetic names can never drift); derive the Hands test's literals from its already-parsed SPECS.
  • Allowlist only the two justified findings (net +1 entry / +1 token, vs +8 entries for the naive clear), with the mandated exactness/negative-probe audit.
  • Add an --only check selector to repos_sync.py, then a firewall gate step to Brain/Heart/Hands PR CI (and a Mind-side leg for allowlist edits), so drift fails in the PR that authors it.
  • File the repos_sync --write config-surface stamper (assessment §8-4, the design's own endgame) as a separate draft prompt — out of scope here.
Detailed implementation plan

Research grounding (why this shape)

  • Design intent: the firewall exists for the config-diff fork model (PyAutoMind/docs/pyautobrain/pyautoscientist_generalisation_assessment.md §8; shipped prose in PyAutoBrain/docs/adoption/config_surfaces.md). FIREWALL_ALLOWLIST reached its intended terminal state 2026-07-10 (72 files / 262 tokens — "docstring examples + test fixtures + workspace-root defaults only", complete/2026/07/pyautoscientist-4b.md) and has since accreted to 109 files / 430 tokens via six reactive patches. The header forbids growing it casually.
  • Recurrence mechanics: Brain/Heart/Hands PR workflows are deliberately pytest-only; Mind's PR CI never executes repos_sync.py (a green Mind PR is NOT evidence the firewall passes — recorded in complete/2026/08/autohands-firewall-allowlist.md); Heart's manifest_drift.py is exit-0, local-only, folded into one YELLOW line, and invisible to the cloud health run (readiness.py --cloud lists it as unobserved). All 9 findings postdate the 2026-07-18 clear and postdate each repo's PR CI.
  • Forbidden shortcut (recorded, do not re-propose): teaching the checker to ignore comments/docstrings.

Affected Repositories

  • PyAutoMind (primary — allowlist, --only selector, check_heart extension, Mind CI leg)
  • PyAutoBrain (3 test-fixture genericisations, tests.yml gate step)
  • PyAutoHeart (smoke.py config extraction, 2 test genericisations, heart-tests.yml restructure + gate)
  • PyAutoHands (test derivation, tests.yml restructure + gate) — see Coordination below

Branch Survey (2026-08-17)

Repository Current Branch Dirty?
./PyAutoMind main clean (workflow-state commits only)
./PyAutoBrain main clean
./PyAutoHeart main clean
./PyAutoHands main clean — claimed by version-stamp-sync-guards (PyAutoHands#235, feature/version-stamp-sync-guards)

Suggested branch: feature/tenant-firewall-drift-aug (each repo)

Coordination: the PyAutoHands leg (test_pre_build_staging.py + tests.yml) must either wait for #235 to merge or land on its own branch with a rebase check afterward — do not touch the version-stamp task's files (autohands/ version-stamp/sync-guard code).

Phase A — clear the 9 by the decision rule

  1. PyAutoHeart/heart/smoke.py — extract, don't allowlist. WORKSPACES (WorkspaceSpec(key, directory, chain), ~lines 36-97) and IMPORT_NAMES (~line 99) are executable config (consumed for paths, PYTHONPATH, pip targets, import preflight, argparse choices). Move both to a smoke: block in PyAutoHeart/config/repos.yaml; load with a strict reader (KeyError on absence — twin precedents: heart/checks/version_skew.py workspace_library(), PyAutoHands/autohands/run_all.py _load_workspaces(); both from complete/2026/07/pyautoscientist-3b-config.md). Config YAML is firewall-exempt (check_tenant_firewall scans only .py/.sh). Reword the residual --root argparse help at smoke.py:591 from "PyAutoLabs organism root" to "organism root". Extend check_heart in PyAutoMind/scripts/repos_sync.py to validate the new smoke: block's repo names against the manifest (closes the same identity-unchecked gap version_skew: has).
  2. Genericise fixtures (all verified non-load-bearing; add a convention comment per the Aug 5 precedent so real names don't creep back):
    • PyAutoBrain/tests/test_worktree_conflict_guard.py — 7 tokens in active.md fixture strings; the awk in bin/worktree.sh does plain string compares, validates against no repo list → RepoA/RepoB. Keep the module docstring's two real drifted forms only if quoted as history (prefer rewording).
    • PyAutoBrain/tests/test_intake_dashboard.py (~110/121/132) — owner in a fake issue URL; the regex never inspects the owner → ExampleOrg.
    • PyAutoBrain/tests/test_profiling_conductor.py — fixture dir autolens_profiling; every _run passes --workspace explicitly → profiling_workspace (also proves the override is honoured).
    • PyAutoHeart/tests/test_smoke.py — already half-synthetic (demo_workspace, legacy_workspace); chain entries are used as dir names / ./name pip strings, preflight tests use empty chains → LibraryA/LibraryB; root tmp_path/"PyAutoLabs""organism".
    • PyAutoHeart/tests/test_release_run.py (~263) — per_project dict key is merged generically, never matched → demo_workspace.
  3. PyAutoHands/tests/test_pre_build_staging.py — derive in-file. The file already parses SPECS from pre_build.sh precisely so fixtures cannot drift; replace the arbitrary literals (autolens_assistant 141, autolens_workspace 176/216, HowToFit/autofit_workspace 204-211) with SPECS[i][0] picks, and pyautobase = tmp_path/"PyAutoLabs" (61) → neutral name (pre_build.sh derives PYAUTOBASE from its own location).
  4. Allowlist the two justified in PyAutoMind/scripts/repos_sync.py FIREWALL_ALLOWLIST:
    • extend "PyAutoBrain/agents/conductors/intake/_intake.py" with autofit_workspace (measured-noise docstring at ~890 — names+counts are the evidence for rejecting the file-spread threshold; the code itself already derives from the body map);
    • add "PyAutoBrain/tests/test_intake_reconcile_ranking.py": {PyAutoArray, PyAutoFit, PyAutoLabs, autofit_workspace, autolens_workspace} — assertions pin resolution against the live body map (_upstream_noise filtering requires real manifest names; slug == "PyAutoLabs/PyAutoFit").
    • Run the exactness audit mandated by complete/2026/08/autohands-firewall-allowlist.md (negative probes: a wrong token in these files must still fail).

Phase B — PR-time enforcement

  1. repos_sync.py main(): add --only <check-label> (repeatable or single) so a caller can run one leg; today it's all-or-nothing (lines ~845-874). Exit 1 only on the selected legs' drift.
  2. PyAutoBrain/.github/workflows/tests.yml: add a step python3 PyAutoMind/scripts/repos_sync.py --check --only "tenant firewall (organ code)" --root "$GITHUB_WORKSPACE". The workflow already checks out Brain at path: PyAutoBrain + PyAutoLabs/PyAutoMind at path: PyAutoMind — the exact layout --root needs; check_tenant_firewall skips organs not checked out, so it gates exactly Brain. (--only avoids the map-block legs reddening Brain PRs on unrelated Mind-side changes.)
  3. PyAutoHeart/.github/workflows/heart-tests.yml and PyAutoHands/.github/workflows/tests.yml: restructure from bare root checkout to path: PyAutoHeart|PyAutoHands + PyAutoLabs/PyAutoMind sibling; move pip/pytest under working-directory:; add the same --only firewall step. (Hands' "only pytest" header is a preference, not an invariant — it already concedes one cross-repo hole.)
  4. Mind-side leg: new job/workflow in PyAutoMind PR CI, path-filtered to scripts/repos_sync.py, checking out Mind + the three organs and running the firewall leg (full --check acceptable — absent repos early-return), so allowlist edits and over-grants are themselves verified.

Phase C — file, don't build

  1. Write PyAutoMind/draft/feature/pyautomind/repos-sync-config-stamper.md: teach repos_sync --write to stamp organ config surfaces from the body map + per-organ policy (assessment §8-4: "the only real engineering in the whole plan"; removes hand-mirroring). Reference this issue.

Key Files

  • PyAutoMind/scripts/repos_sync.py — FIREWALL_ALLOWLIST (+1 entry, +1 token), check_heart smoke-block leg, --only selector
  • PyAutoHeart/config/repos.yaml — new smoke: block; PyAutoHeart/heart/smoke.py — table → strict loader
  • PyAutoBrain/tests/{test_worktree_conflict_guard,test_intake_dashboard,test_profiling_conductor}.py, PyAutoHeart/tests/{test_smoke,test_release_run}.py, PyAutoHands/tests/test_pre_build_staging.py — fixture genericisation/derivation
  • PyAutoBrain/.github/workflows/tests.yml, PyAutoHeart/.github/workflows/heart-tests.yml, PyAutoHands/.github/workflows/tests.yml, Mind PR CI — gates

Verification

  1. python3 PyAutoMind/scripts/repos_sync.py --check --root <workspace-root>check tenant firewall (organ code): OK, all other legs unchanged, exit 0.
  2. Negative probes: insert a bogus manifest name into a genericised test file and into an allowlisted file → the check must flag both; remove before commit.
  3. pytest green in Mind, Brain, Heart, Hands (the genericised tests especially).
  4. Each amended workflow passes on its own PR — the gate step proving itself on the branch that adds it.
  5. Heart local: python3 PyAutoHeart/heart/checks/manifest_drift.py → "identity in sync"; YELLOW reason drops from readiness after merge to the canonical mains (Heart grades canonical checkouts, not worktrees).

Original Prompt

Click to expand starting prompt

See PyAutoMind/active/tenant-firewall-drift-aug.md (moved from draft/maintenance/pyautomind/ on issue creation) — includes the user's original request verbatim and the research conclusions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions