Skip to content

feat(preflight): deterministic submodule lane + showtime verify pages - #627

Merged
POWERFULMOVES merged 9 commits into
PMOVES.AI-Edition-Hardenedfrom
feat/submodule-layer-deterministic-validation
Feb 16, 2026
Merged

POWERFULMOVES merged 9 commits into
PMOVES.AI-Edition-Hardenedfrom
feat/submodule-layer-deterministic-validation

Conversation

@POWERFULMOVES

@POWERFULMOVES POWERFULMOVES commented Feb 16, 2026

Copy link
Copy Markdown
Owner

Summary

  • add deterministic submodule-layer validator workflow with per-module run-all target
  • add showtime clickable verification artifacts (HTML/Markdown/JSON) for UI/pages/API links
  • wire new targets into layered static/runtime audit flow and showtime bring-up/smoke

Changes

  • new tooling:
    • pmoves/tools/submodule_layer_runall.py
    • pmoves/tools/showtime_verify_links.py
  • make targets in pmoves/mk/preflight.mk:
    • submodule-layer-validate-all
    • submodule-layer-validate-all-strict
    • showtime-links
    • showtime-links-open
    • showtime-links-strict
  • docs updates:
    • pmoves/docs/MAKE_TARGETS.md
    • pmoves/docs/NEXT_STEPS.md

Local validation

  • python -m py_compile pmoves/tools/submodule_layer_validate.py pmoves/tools/submodule_layer_runall.py pmoves/tools/showtime_verify_links.py
  • make -C pmoves submodule-layer-validate-all ARGS="--allow-uninitialized --skip-python-compile"
  • make -C pmoves submodule-layer-validate-all-strict ARGS="--allow-uninitialized --skip-python-compile" (expected strict fail on warnings in current uninitialized audit worktree)
  • make -C pmoves showtime-links
  • make -C pmoves showtime-links-strict (expected fail when required endpoint is down)

Notes

  • untracked generated evidence remains local-only (pmoves/docs/evidence/*) and is not part of this PR.

Summary by CodeRabbit

  • New Features

    • Deterministic submodule-layer validation and aggregated run-all targets for automated module hygiene checks.
    • Showtime clickable verification reports and strict link-check targets for endpoint and service readiness.
    • New command-line tooling for lightweight environment bootstrapping, secrets hydration/hardening, runner mapping/orchestration, and comprehensive tooling/script audits.
  • Documentation

    • Expanded Make targets docs and NEXT_STEPS with validation, showtime verification, and audit workflow guidance.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a manifest and Make targets for deterministic submodule-layer validation; introduces multiple new command-line tools for bootstrapping, submodule validation/orchestration, secrets hydration/audit, runner management/mapping, and Showtime endpoint verification; updates docs and build infra to wire these tools into audit and bringup flows.

Changes

Cohort / File(s) Summary
Submodule Reference & Manifest
PMOVES-Agent-Zero (submodule), pmoves/configs/submodule_layer_validation_manifest.json
Submodule pointer updated; added JSON manifest describing required files, python_compile rules, known typos, and per-submodule overrides for layer validation.
Makefile & Build Targets
pmoves/mk/preflight.mk, pmoves/docs/MAKE_TARGETS.md
Added many new public phony targets and variables (submodule-layer-validate*, audit-layers*, showtime-links*), integrated validation and showtime link checks into preflight/bringup flows.
Documentation / Next Steps
pmoves/docs/NEXT_STEPS.md, pmoves/docs/AGENTS/CODEX_CIPHER_MEMORY_IMPLEMENTATION_MAP.md, pmoves/docs/AGENTS/CODEX_OPERATOR_HOME.md
Documented new validation lanes, showtime link artifacts, and added Codex/Cipher implementation mapping doc; updated NEXT_STEPS with new lanes and artifacts.
Submodule Validation Tools
pmoves/tools/submodule_layer_validate.py, pmoves/tools/submodule_layer_runall.py
New deterministic submodule validator and runall orchestrator: git/.gitmodules parsing, remote checks, nested .gitmodules validation, Python compile checks, JSON/Markdown evidence generation, and per-module aggregation.
Showtime Verification & Watcher
pmoves/tools/showtime_verify_links.py, pmoves/tools/showtime_watch.py
New tools to check endpoint health and render JSON/MD/HTML reports (showtime-links) and a live readiness watcher (showtime_watch) with optional Rich UI and strict-mode behavior.
Secrets & CHIT Tools
pmoves/tools/chit_manifest_sync.py, pmoves/tools/runtime_secrets_hydrate.py, pmoves/tools/secrets_hardening_audit.py
Added CHIT v2→v1 sync tool, runtime secrets hydrator (inspects containers/status and updates env files), and a repository secrets-hardening auditor.
Runner & Infrastructure Helpers
pmoves/tools/local_cert_runners.py, pmoves/tools/runner_lane_map.py, pmoves/tools/bootstrap_light_env.py
Added Docker-backed local runner manager, lane-to-host mapping and live status checker, and a uv-first lightweight bootstrap script for venv creation and requirements installation.
Tooling Audit
pmoves/tools/tooling_script_audit.py
New comprehensive tooling-script audit: token-overlap detection, canonical workflows/targets checks, environment seed validation, and Markdown report generation.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Validator as Submodule<br/>Validator
    participant Manifest
    participant Git
    participant Filesystem
    participant PythonCheck as Python<br/>Compiler
    participant Reports as JSON/MD

    User->>Validator: run submodule-layer-validate
    Validator->>Manifest: load manifest & policy
    Validator->>Git: parse .gitmodules & status
    loop per submodule
        Validator->>Filesystem: check required/top-level files
        Filesystem-->>Validator: file results
        Validator->>Git: check remote commit reachability
        Git-->>Validator: reachability result
        Validator->>PythonCheck: run python_compile_check (if enabled)
        PythonCheck-->>Validator: compile results
    end
    Validator->>Reports: aggregate findings, write JSON & MD
    Reports-->>User: artifacts written
Loading
sequenceDiagram
    participant User
    participant Showtime as Showtime<br/>Verify
    participant Endpoints
    participant Docker
    participant Renderer

    User->>Showtime: run showtime-links
    Showtime->>Endpoints: load endpoint definitions
    par Health checks and service snapshot
        Showtime->>Endpoints: HTTP health probes
        Endpoints-->>Showtime: status codes/errors
        Showtime->>Docker: compose services snapshot
        Docker-->>Showtime: service list
    end
    Showtime->>Showtime: filter worker services
    Showtime->>Renderer: render JSON / MD / HTML
    Renderer-->>User: write artifacts (and optionally open HTML)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐰 I hopped through manifests and scripts so bright,
Validated submodules deep into the night,
I checked the endpoints, tended secrets tight,
Launched runners, built reports — what a sight!
A burrow of tools, vetted and light. 🌿

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely identifies the main changes: adding deterministic submodule layer validation and showtime verification pages, directly matching the content of the changeset.
Description check ✅ Passed The PR description follows the template structure with Summary and Changes sections documenting the additions, includes local validation commands confirming testing was performed, and notes about generated evidence.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into PMOVES.AI-Edition-Hardened

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/submodule-layer-deterministic-validation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread pmoves/tools/runtime_secrets_hydrate.py Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pmoves/docs/NEXT_STEPS.md (1)

333-338: ⚠️ Potential issue | 🟡 Minor

Duplicate content: the entire block from Line 333 onward is a stale copy of earlier sections.

Lines 333–459 repeat the # PMOVES v5 • NEXT_STEPS header and most of the Immediate, n8n Flow Operations, Backlog Snapshot, Later, and Next Session Focus sections already present above, but with stale timestamps (2025-09-26, 2025-10-05) and missing the newer entries. This looks like a leftover from a prior merge. Remove the duplicate block to avoid confusion and keep a single authoritative section.

As per coding guidelines, "Refresh both docs/ROADMAP.md and docs/NEXT_STEPS.md when significant features ship, priorities move, or a new sprint starts; adjust their _Last updated timestamps".

🤖 Fix all issues with AI agents
In `@pmoves/docs/MAKE_TARGETS.md`:
- Around line 190-191: Update the "bringup-showtime" bullet so it lists the JSON
evidence artifact as well as the HTML/MD outputs: mention that the target emits
pmoves/docs/SHOWTIME_VERIFY_LINKS.html|.md and
pmoves/docs/evidence/showtime_links.json (to match the existing showtime-links
entry). Locate the text containing the existing strings
"SHOWTIME_VERIFY_LINKS.html|.md" and adjust the sentence to explicitly include
"pmoves/docs/evidence/showtime_links.json" so both descriptions are consistent.

In `@pmoves/tools/bootstrap_light_env.py`:
- Around line 30-35: The --requirements argument currently uses action="append"
with default=["tools/requirements-lite.txt"], causing user values to be appended
rather than replace; change the parser.add_argument call for "--requirements" to
use default=None (keep action="append"), and in the entry point (e.g., main() or
where args are processed) add a conditional that sets args.requirements =
["tools/requirements-lite.txt"] if args.requirements is None so defaulting
happens post-parse and user-specified values replace the default.

In `@pmoves/tools/chit_manifest_sync.py`:
- Line 10: The module-level bare import "import yaml" in
pmoves/tools/chit_manifest_sync.py can raise ImportError if PyYAML isn't
installed; either add a pmoves/tools/requirements-lite.txt listing PyYAML or
wrap the import in a try/except like manifest_audit.py does and raise SystemExit
with a clear message instructing the user to install PyYAML (include the package
name and optional install command), so that the import failure is handled
gracefully at startup.

In `@pmoves/tools/runner_lane_map.py`:
- Around line 363-371: The code unconditionally sets strict_fail =
bool(unmapped) which makes unmapped lanes cause exit 2 even when args.strict is
false; change the logic so strict_fail is only driven by unmapped/other checks
when args.strict is true. Specifically, initialize strict_fail = False, then if
args.strict set strict_fail = bool(unmapped) and, if args.enforce_phase, OR in
bool(phase_failures) else OR in bool(unavailable) (using the same symbols:
strict_fail, args.strict, args.enforce_phase, unmapped, phase_failures,
unavailable) so the non-zero exit is only returned when --strict is passed.

In `@pmoves/tools/runtime_secrets_hydrate.py`:
- Around line 160-168: The current or-chain for MEILI_MASTER_KEY (and similarly
FIREFLY_APP_KEY/FIREFLY_ACCESS_TOKEN) lets stub values like "changeme"
short-circuit and prevents secrets.token_urlsafe from being used; update the
logic used by set_if_missing to treat placeholder values as missing by
filtering/normalizing env_values and container-found values before the or-chain
(e.g., trim and compare against known placeholders like "changeme" or empty
string), or introduce a small helper (used by _find_container_env_value result
and env_values.get(...).strip()) that returns None for placeholders so that
secrets.token_urlsafe(24) will be selected when appropriate; adjust usages for
MEILI_MASTER_KEY and FIREFLY_APP_KEY to use this sanitation.
🧹 Nitpick comments (16)
pmoves/tools/secrets_hardening_audit.py (1)

27-36: Consider skipping additional high-volume directories in candidate_files().

The function already skips .git, but rglob("*") will still traverse node_modules, __pycache__, .venv*, dist, build, etc. For a large monorepo this can noticeably slow the audit. Adding a few more skip patterns would help.

♻️ Suggested skip set
 def candidate_files() -> Iterable[Path]:
     allowed = {".md", ".py", ".sh", ".yaml", ".yml", ".json", ".txt"}
+    skip_dirs = {".git", "node_modules", "__pycache__", ".venv", ".venv-pmoves", "dist", "build"}
     for path in REPO_ROOT.rglob("*"):
         if not path.is_file():
             continue
-        if ".git" in path.parts:
+        if skip_dirs & set(path.parts):
             continue
         if path.suffix.lower() not in allowed:
             continue
         yield path
pmoves/tools/runtime_secrets_hydrate.py (1)

33-54: _write_env_file reads the file even when updates is empty.

Minor: if updates is empty, the function still reads, re-indexes, and rewrites the file. The caller guards this (if not updates: return 0), so this is not triggered today, but a defensive early return would make the function safer for future callers.

pmoves/mk/preflight.mk (1)

115-122: showtime-links* targets use $(PYTHON) while submodule-layer-validate* targets use $(PRECHECK_PY).

On Windows, $(PRECHECK_PY) resolves to py -3 while $(PYTHON) may differ. If showtime-links can be invoked standalone during preflight (outside bring-up), consider using $(PRECHECK_PY) for consistency, or document that these targets require a full Python environment.

pmoves/tools/showtime_watch.py (1)

32-42: probe() opens URLs without scheme validation.

urlopen accepts file:// and other non-HTTP schemes. Since ENDPOINTS is imported from flight_check_retro and should only contain http:///https:// URLs, this is low risk. A one-line guard would harden it against accidental misconfiguration upstream.

🛡️ Optional scheme guard
 def probe(url: str, timeout: float = 2.5) -> tuple[bool, int]:
+    if not url.startswith(("http://", "https://")):
+        return False, 0
     try:
         with urlopen(url, timeout=timeout) as resp:
pmoves/tools/bootstrap_light_env.py (1)

56-57: Bare subprocess.run(cmd, check=True) gives poor error UX on failure.

When a subprocess fails, the raw CalledProcessError traceback is printed. For a user-facing bootstrap tool, consider catching it and printing a friendlier message with the failed command and return code.

pmoves/tools/chit_manifest_sync.py (1)

214-219: --check mode is sensitive to alias ordering, not just content.

yaml.safe_dump(next_manifest, sort_keys=False) preserves insertion order. If the existing v1 manifest was hand-edited with aliases in a different order, --check will report "OUT-OF-SYNC" even with no semantic difference. This is acceptable if the tool is the sole writer of the v1 manifest, but worth noting for operators who might hand-edit.

pmoves/tools/local_cert_runners.py (2)

86-110: Runner token visible via docker inspect and Docker socket grants full host Docker access.

Two security posture notes:

  1. RUNNER_TOKEN passed via -e is readable in docker inspect. Consider using Docker secrets or a file-mount if the environment requires stronger isolation.
  2. Mounting /var/run/docker.sock gives the runner container full control over the host Docker daemon. This is standard for self-hosted GHA runners but should be documented as a conscious trust decision.

Neither is a blocker — both are typical trade-offs for local-cert runners — but worth calling out for operational awareness.


56-79: Token fallback chain is sound; consider logging which source was used.

The registration_token function checks lane-specific env → shared env → gh api call. For operator debugging, it would help to print which token source was selected (without printing the token itself).

pmoves/tools/showtime_verify_links.py (1)

23-24: Fragile sys.path manipulation for sibling import.

Inserting into sys.path at import time and importing flight_check_retro.ENDPOINTS couples this script to a specific directory layout and produces a confusing error if the module is missing. Consider a guarded import with a clear error message.

♻️ Proposed guarded import
 sys.path.insert(0, str(Path(__file__).resolve().parent))
-from flight_check_retro import ENDPOINTS  # type: ignore
+try:
+    from flight_check_retro import ENDPOINTS  # type: ignore
+except ImportError as exc:
+    raise SystemExit(
+        f"Cannot import ENDPOINTS from flight_check_retro — "
+        f"ensure the module exists in {Path(__file__).resolve().parent}: {exc}"
+    ) from exc
pmoves/tools/runner_lane_map.py (2)

130-148: load_runners doesn't paginate — repos with >100 runners will be silently truncated.

Unlike the cmd_status function in local_cert_runners.py which uses --paginate, this function requests a single page of 100 runners. Consider using gh api --paginate or iterating pages to avoid silent truncation.

♻️ Proposed fix using gh --paginate
 def load_runners(repo: str) -> list[Runner]:
-    cmd = ["gh", "api", f"repos/{repo}/actions/runners?per_page=100"]
-    proc = subprocess.run(cmd, capture_output=True, text=True, check=False)
+    cmd = ["gh", "api", "--paginate", f"repos/{repo}/actions/runners?per_page=100", "--jq", ".runners"]
+    proc = subprocess.run(cmd, capture_output=True, text=True, check=False)
     if proc.returncode != 0:
         msg = proc.stderr.strip() or proc.stdout.strip() or "unknown gh api error"
         raise RuntimeError(msg)
-    payload = json.loads(proc.stdout)
+    items: list[dict] = []
+    for line in proc.stdout.strip().splitlines():
+        if line.strip():
+            items.extend(json.loads(line))
     runners: list[Runner] = []
-    for item in payload.get("runners", []):
+    for item in items:

Alternatively, keep the current approach if you're confident the runner count stays under 100.


90-100: Regex-based YAML discovery is adequate but limited.

RUNS_ON_LIST_RE only matches runs-on: [...] on a single line. Multi-line array syntax, matrix expressions, and bare-string runs-on: are skipped. This is an acceptable trade-off for tooling that only targets self-hosted multi-label lanes, but worth documenting the limitation.

pmoves/tools/tooling_script_audit.py (2)

439-463: Redundant startswith check.

lower.startswith("pmoves") on Line 451 already matches strings starting with "pmoves-", making the second condition redundant.

♻️ Simplified condition
-        if not (lower.startswith("pmoves") or lower.startswith("pmoves-")):
+        if not lower.startswith("pmoves"):

90-115: parse_gitmodules is duplicated across 4 tools with different signatures and implementations.

Found in tooling_script_audit.py, submodule_layer_runall.py, submodule_layer_validate.py, and submodule_sitrep.py. However, they are not "nearly identical"—they have different return types (name+path tuples, name+path+url tuples, and dictionaries) and implementations (regex parsing vs. configparser). Evaluate whether a shared utility is warranted; if extracted, account for the different return types and data requirements.

pmoves/tools/submodule_layer_runall.py (1)

70-76: read_summary silently returns (1, 0) on any parse failure — consider distinguishing real errors from missing files.

If the validator crashes before writing the JSON, this function defaults to 1 error, which is reasonable. However, it might mask the root cause. Consider logging the exception or differentiating "file not found" from "malformed JSON" for operator debugging.

pmoves/tools/submodule_layer_validate.py (2)

221-237: py_compile.compile writes .pyc files into submodule __pycache__ directories as a side effect.

Each compiled file creates (or updates) a .pyc in __pycache__/ under the submodule tree. While these are typically gitignored, it pollutes the working tree. You can avoid this by redirecting the bytecode output.

♻️ Suppress .pyc side effect
+import os
 ...
 def python_compile_check(module_root: Path, max_files: int) -> tuple[str, str]:
+    # Prevent py_compile from writing .pyc files into submodule trees
+    old_dont_write = os.environ.get("PYTHONDONTWRITEBYTECODE")
+    os.environ["PYTHONDONTWRITEBYTECODE"] = "1"
     py_files: list[Path] = []
     ...
     try:
         for path in py_files:
             py_compile.compile(str(path), doraise=True)
     except py_compile.PyCompileError as exc:
+        if old_dont_write is None:
+            os.environ.pop("PYTHONDONTWRITEBYTECODE", None)
+        else:
+            os.environ["PYTHONDONTWRITEBYTECODE"] = old_dont_write
         return "fail", str(exc)
+    if old_dont_write is None:
+        os.environ.pop("PYTHONDONTWRITEBYTECODE", None)
+    else:
+        os.environ["PYTHONDONTWRITEBYTECODE"] = old_dont_write
     return "pass", f"compiled-files={len(py_files)}"

Or more simply, redirect the .pyc output to a temp file:

     try:
         for path in py_files:
-            py_compile.compile(str(path), doraise=True)
+            py_compile.compile(str(path), cfile=os.devnull, doraise=True)
     except py_compile.PyCompileError as exc:

165-177: remote_commit_reachable uses substring match on ls-remote output.

Line 174: any(commit in line for line in ...) does a substring match. While full 40-char SHA collisions are extremely unlikely, an exact-prefix match would be more precise.

♻️ Use startswith for exact prefix match
-    matched = any(commit in line for line in proc.stdout.splitlines())
+    matched = any(line.startswith(commit) or line.split("\t", 1)[0] == commit for line in proc.stdout.splitlines())

Comment thread pmoves/docs/MAKE_TARGETS.md Outdated
Comment on lines 190 to 191
- Emits clickable verification artifacts (`pmoves/docs/SHOWTIME_VERIFY_LINKS.html|.md`) with pages/UI/API links and helper worker container states.
- Tuning knobs: `SHOWTIME_INTERVAL`, `SHOWTIME_MAX_SECONDS`, `SHOWTIME_WATCH=0`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

bringup-showtime description omits the JSON evidence artifact.

Line 190 mentions HTML and MD artifacts but the tool also produces pmoves/docs/evidence/showtime_links.json. The showtime-links entry at Line 198 correctly lists all three. Consider aligning for consistency.

🤖 Prompt for AI Agents
In `@pmoves/docs/MAKE_TARGETS.md` around lines 190 - 191, Update the
"bringup-showtime" bullet so it lists the JSON evidence artifact as well as the
HTML/MD outputs: mention that the target emits
pmoves/docs/SHOWTIME_VERIFY_LINKS.html|.md and
pmoves/docs/evidence/showtime_links.json (to match the existing showtime-links
entry). Locate the text containing the existing strings
"SHOWTIME_VERIFY_LINKS.html|.md" and adjust the sentence to explicitly include
"pmoves/docs/evidence/showtime_links.json" so both descriptions are consistent.

Comment on lines +30 to +35
parser.add_argument(
"--requirements",
action="append",
default=["tools/requirements-lite.txt"],
help="Requirements file(s) relative to pmoves/ (repeatable).",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

action="append" with a list default will append to it, not replace it.

With default=["tools/requirements-lite.txt"] and action="append", passing --requirements custom.txt yields ["tools/requirements-lite.txt", "custom.txt"] instead of the expected ["custom.txt"]. This is a well-known argparse gotcha.

🐛 Proposed fix: use `default=None` and set the default post-parse
     parser.add_argument(
         "--requirements",
         action="append",
-        default=["tools/requirements-lite.txt"],
+        default=None,
         help="Requirements file(s) relative to pmoves/ (repeatable).",
     )

Then in main():

     args = parse_args()
+    if args.requirements is None:
+        args.requirements = ["tools/requirements-lite.txt"]
     venv_path = resolve_under_pmoves(args.venv)
🤖 Prompt for AI Agents
In `@pmoves/tools/bootstrap_light_env.py` around lines 30 - 35, The --requirements
argument currently uses action="append" with
default=["tools/requirements-lite.txt"], causing user values to be appended
rather than replace; change the parser.add_argument call for "--requirements" to
use default=None (keep action="append"), and in the entry point (e.g., main() or
where args are processed) add a conditional that sets args.requirements =
["tools/requirements-lite.txt"] if args.requirements is None so defaulting
happens post-parse and user-specified values replace the default.

Comment thread pmoves/tools/chit_manifest_sync.py Outdated
from pathlib import Path
from typing import Any, Dict, Iterable, List, Mapping, Sequence, Tuple

import yaml

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all requirements files in pmoves and check for PyYAML
echo "=== Searching for requirements files containing PyYAML ==="
find pmoves -type f -name '*requirements*' -o -name 'pyproject.toml' -o -name 'setup.py' | head -20

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 1239


🏁 Script executed:

#!/bin/bash
# Check if PyYAML or yaml is listed in requirements files
echo "=== Checking pmoves/tools/ for requirements files ==="
ls -la pmoves/tools/ | grep -i req
echo ""
echo "=== Checking pmoves/ for requirements files ==="
ls -la pmoves/ | grep -i req
echo ""
echo "=== Full search for requirements files ==="
find pmoves -name '*requirements*' -type f

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 3786


🏁 Script executed:

#!/bin/bash
# Search for PyYAML in all files
echo "=== Searching for PyYAML references ==="
rg -i 'pyyaml|PyYAML' pmoves/ --type py
echo ""
echo "=== Checking requirements files content ==="
find pmoves -name '*requirements*' -type f -exec echo "File: {}" \; -exec cat {} \;

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 50381


🏁 Script executed:

#!/bin/bash
# More specific search for requirements-lite in pmoves/tools
echo "=== Looking for requirements-lite.txt in pmoves/tools ==="
find pmoves/tools -name '*requirements*' -type f

echo ""
echo "=== Checking if pyproject.toml in pmoves has PyYAML ==="
grep -i 'pyyaml\|yaml' pmoves/pyproject.toml || echo "PyYAML not found in pyproject.toml"

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 216


🏁 Script executed:

#!/bin/bash
# Check what files are in pmoves/tools directory
echo "=== Contents of pmoves/tools directory ==="
ls -la pmoves/tools/

echo ""
echo "=== Check chit_manifest_sync.py for any setup comments ==="
head -30 pmoves/tools/chit_manifest_sync.py

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 7741


🏁 Script executed:

#!/bin/bash
# Check for bootstrap scripts that might install dependencies
echo "=== Looking for bootstrap-lite or lightweight environment setup ==="
find pmoves -name '*bootstrap*' -o -name '*lite*' -type f | grep -v '.pyc' | head -20

echo ""
echo "=== Check if manifest_audit.py shows how PyYAML is handled ==="
grep -A5 -B5 'PyYAML' pmoves/tools/manifest_audit.py

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 1746


🏁 Script executed:

#!/bin/bash
# Check if there's any shared requirements or dependencies documentation
echo "=== Look for any requirements files at pmoves root or similar patterns ==="
find pmoves -maxdepth 2 -name 'requirements*.txt' -o -name '*.txt' | grep -i req

echo ""
echo "=== Check bootstrap_light_env.py to understand dependency model ==="
head -50 pmoves/tools/bootstrap_light_env.py

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 1575


🏁 Script executed:

#!/bin/bash
# Check if requirements-lite.txt actually exists in pmoves/tools
echo "=== Does pmoves/tools/requirements-lite.txt exist? ==="
ls -la pmoves/tools/requirements-lite.txt 2>&1

echo ""
echo "=== Full path check ==="
test -f pmoves/tools/requirements-lite.txt && echo "File exists" || echo "File DOES NOT exist"

echo ""
echo "=== Check what bootstrap_light_env.py does when it's missing ==="
grep -A10 'def.*requirements\|def.*install' pmoves/tools/bootstrap_light_env.py | head -40

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 1004


🏁 Script executed:

#!/bin/bash
# Let's see the full bootstrap_light_env.py to understand the dependency model
wc -l pmoves/tools/bootstrap_light_env.py
tail -100 pmoves/tools/bootstrap_light_env.py

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 3066


Create pmoves/tools/requirements-lite.txt and include PyYAML, or add error handling for the missing import.

This tool imports yaml (PyYAML) at module scope (line 10) without fallback error handling. The file pmoves/tools/requirements-lite.txt does not exist, and PyYAML is not listed in pmoves/pyproject.toml. Runtime import failure will occur if PyYAML is not pre-installed. Compare with pmoves/tools/manifest_audit.py, which wraps the yaml import in try/except and raises a clear SystemExit message when the dependency is missing—this tool should follow the same pattern or ensure the dependency is declared.

🤖 Prompt for AI Agents
In `@pmoves/tools/chit_manifest_sync.py` at line 10, The module-level bare import
"import yaml" in pmoves/tools/chit_manifest_sync.py can raise ImportError if
PyYAML isn't installed; either add a pmoves/tools/requirements-lite.txt listing
PyYAML or wrap the import in a try/except like manifest_audit.py does and raise
SystemExit with a clear message instructing the user to install PyYAML (include
the package name and optional install command), so that the import failure is
handled gracefully at startup.

Comment thread pmoves/tools/runner_lane_map.py Outdated
Comment on lines +363 to +371
strict_fail = bool(unmapped)
if args.strict:
if args.enforce_phase:
strict_fail = strict_fail or bool(phase_failures)
else:
strict_fail = strict_fail or bool(unavailable)
if strict_fail:
return 2
return 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unmapped lanes always cause exit 2, even without --strict.

strict_fail = bool(unmapped) on Line 363 is evaluated unconditionally, so unmapped lanes cause a non-zero exit regardless of --strict. The --strict help text says "Exit non-zero on unmapped lanes or unavailable live lanes", implying both checks should be gated.

🐛 Proposed fix to gate unmapped check behind --strict
-    strict_fail = bool(unmapped)
-    if args.strict:
+    strict_fail = False
+    if args.strict:
+        strict_fail = bool(unmapped) or bool(unavailable)
         if args.enforce_phase:
-            strict_fail = strict_fail or bool(phase_failures)
-        else:
-            strict_fail = strict_fail or bool(unavailable)
+            strict_fail = strict_fail or bool(phase_failures)
     if strict_fail:
         return 2
     return 0
🤖 Prompt for AI Agents
In `@pmoves/tools/runner_lane_map.py` around lines 363 - 371, The code
unconditionally sets strict_fail = bool(unmapped) which makes unmapped lanes
cause exit 2 even when args.strict is false; change the logic so strict_fail is
only driven by unmapped/other checks when args.strict is true. Specifically,
initialize strict_fail = False, then if args.strict set strict_fail =
bool(unmapped) and, if args.enforce_phase, OR in bool(phase_failures) else OR in
bool(unavailable) (using the same symbols: strict_fail, args.strict,
args.enforce_phase, unmapped, phase_failures, unavailable) so the non-zero exit
is only returned when --strict is passed.

Comment on lines +160 to +168
# Pull runtime-emitted labels from running containers when available.
set_if_missing(
"MEILI_MASTER_KEY",
_find_container_env_value(
containers, name_tokens=("meili",), keys=("MEILI_MASTER_KEY", "MEILI_ENV")
)
or env_values.get("MEILI_MASTER_KEY", "").strip()
or secrets.token_urlsafe(24),
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Placeholder values in env file are never replaced by secrets.token_urlsafe() due to short-circuit evaluation.

The or chain at Lines 163–167 includes env_values.get("MEILI_MASTER_KEY", "").strip() before secrets.token_urlsafe(24). If the env file already contains MEILI_MASTER_KEY=changeme, the or chain short-circuits at step 2 with "changeme" (truthy), so the token is never generated. Then set_if_missing receives "changeme", detects it as a placeholder, but re-sets the same placeholder value — effectively a no-op.

The same pattern applies to FIREFLY_APP_KEY (Lines 170–176) if FIREFLY_ACCESS_TOKEN contains a placeholder.

🐛 Proposed fix: filter out placeholder values before the `or` chain
+    def _non_placeholder(val: str) -> str:
+        """Return val only if it is not a placeholder, else empty string."""
+        v = val.strip()
+        return v if v and not _looks_placeholder(v) else ""
+
     set_if_missing(
         "MEILI_MASTER_KEY",
         _find_container_env_value(
             containers, name_tokens=("meili",), keys=("MEILI_MASTER_KEY", "MEILI_ENV")
         )
-        or env_values.get("MEILI_MASTER_KEY", "").strip()
+        or _non_placeholder(env_values.get("MEILI_MASTER_KEY", ""))
         or secrets.token_urlsafe(24),
     )
     set_if_missing(
         "FIREFLY_APP_KEY",
         _find_container_env_value(
             containers, name_tokens=("firefly", "wealth"), keys=("FIREFLY_APP_KEY", "APP_KEY")
         )
-        or env_values.get("FIREFLY_ACCESS_TOKEN", "").strip()
+        or _non_placeholder(env_values.get("FIREFLY_ACCESS_TOKEN", ""))
         or secrets.token_urlsafe(24),
     )
🤖 Prompt for AI Agents
In `@pmoves/tools/runtime_secrets_hydrate.py` around lines 160 - 168, The current
or-chain for MEILI_MASTER_KEY (and similarly
FIREFLY_APP_KEY/FIREFLY_ACCESS_TOKEN) lets stub values like "changeme"
short-circuit and prevents secrets.token_urlsafe from being used; update the
logic used by set_if_missing to treat placeholder values as missing by
filtering/normalizing env_values and container-found values before the or-chain
(e.g., trim and compare against known placeholders like "changeme" or empty
string), or introduce a small helper (used by _find_container_env_value result
and env_values.get(...).strip()) that returns None for placeholders so that
secrets.token_urlsafe(24) will be selected when appropriate; adjust usages for
MEILI_MASTER_KEY and FIREFLY_APP_KEY to use this sanitation.

@POWERFULMOVES
POWERFULMOVES changed the base branch from main to PMOVES.AI-Edition-Hardened February 16, 2026 02:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pmoves/docs/AGENTS/CODEX_OPERATOR_HOME.md (1)

2-2: ⚠️ Potential issue | 🟡 Minor

Update the “Last updated” date to reflect this change.

The doc now includes a new link, so the date should reflect the current edit window (2026-02-16). As per coding guidelines, keep status claims aligned with evidence in runbooks and smokes.

✏️ Suggested fix
-_Last updated: 2026-02-14_
+_Last updated: 2026-02-16_
🤖 Fix all issues with AI agents
In `@pmoves/docs/AGENTS/CODEX_CIPHER_MEMORY_IMPLEMENTATION_MAP.md`:
- Around line 65-77: Replace the definitive cleanliness claims under the
"Clean/near-clean worktrees" and "Dirty worktrees requiring triage" sections
with guidance to verify state at runtime—e.g., change entries like
`PMOVES.AI-hardened-audit`, `PMOVES.AI`, and `PMOVES.AI-slice-cipher` to a
checklist or operator note that instructs readers to run git status/inspect
merge state (or link to the runbook/smoke tests) rather than asserting they are
clean/dirty; update the section header text and any bullet wording to indicate
these are examples or require verification instead of factual snapshots.

Comment on lines +65 to +77
### Clean/near-clean worktrees
- `PMOVES.AI-hardened-audit` (clean)
- `PMOVES.AI-hardened-ci` (clean)
- `PMOVES.AI-slice-ci-ghcr` (clean)
- `PMOVES.AI-submodule-audit` (clean after artifact cleanup)

### Dirty worktrees requiring triage
- `PMOVES.AI` (root branch): large mixed change-set (code, docs, workflows, submodules)
- `PMOVES.AI-main-audit`: many submodule pointer edits and integration updates pending commit policy
- `PMOVES.AI-slice-cipher`: includes unresolved merge conflicts (`UU`) in:
- `.gitignore`
- `pmoves/docker-compose.yml`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid asserting live worktree cleanliness in docs.

These status claims are environment-specific and will drift quickly; they should be phrased as a checklist (“verify clean/dirty via git status”) or moved to a local/operator note instead of a definitive snapshot. As per coding guidelines, keep status claims aligned with evidence in runbooks and smokes.

✏️ Suggested rewrite
-### Clean/near-clean worktrees
-- `PMOVES.AI-hardened-audit` (clean)
-- `PMOVES.AI-hardened-ci` (clean)
-- `PMOVES.AI-slice-ci-ghcr` (clean)
-- `PMOVES.AI-submodule-audit` (clean after artifact cleanup)
-
-### Dirty worktrees requiring triage
-- `PMOVES.AI` (root branch): large mixed change-set (code, docs, workflows, submodules)
-- `PMOVES.AI-main-audit`: many submodule pointer edits and integration updates pending commit policy
-- `PMOVES.AI-slice-cipher`: includes unresolved merge conflicts (`UU`) in:
-  - `.gitignore`
-  - `pmoves/docker-compose.yml`
+### Worktree hygiene checklist (verify locally)
+- Run `git status --short` in each worktree.
+- Flag any worktree with `UU` or large mixed change-sets for triage.
+- Prefer documenting local findings in your operator notes or runbook evidence.
🤖 Prompt for AI Agents
In `@pmoves/docs/AGENTS/CODEX_CIPHER_MEMORY_IMPLEMENTATION_MAP.md` around lines 65
- 77, Replace the definitive cleanliness claims under the "Clean/near-clean
worktrees" and "Dirty worktrees requiring triage" sections with guidance to
verify state at runtime—e.g., change entries like `PMOVES.AI-hardened-audit`,
`PMOVES.AI`, and `PMOVES.AI-slice-cipher` to a checklist or operator note that
instructs readers to run git status/inspect merge state (or link to the
runbook/smoke tests) rather than asserting they are clean/dirty; update the
section header text and any bullet wording to indicate these are examples or
require verification instead of factual snapshots.

@POWERFULMOVES
POWERFULMOVES merged commit 5aa290b into PMOVES.AI-Edition-Hardened Feb 16, 2026
6 checks passed
@POWERFULMOVES
POWERFULMOVES deleted the feat/submodule-layer-deterministic-validation branch February 16, 2026 05:45
@POWERFULMOVES
POWERFULMOVES restored the feat/submodule-layer-deterministic-validation branch February 16, 2026 05:45
@POWERFULMOVES
POWERFULMOVES deleted the feat/submodule-layer-deterministic-validation branch March 9, 2026 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants