Skip to content

reconcile(z890): node onto main + CHIT/tokenism/guard fixes found along the way - #2184

Merged
POWERFULMOVES merged 11 commits into
mainfrom
local/pmoves-hermes-z890-reconciled
Jul 22, 2026
Merged

reconcile(z890): node onto main + CHIT/tokenism/guard fixes found along the way#2184
POWERFULMOVES merged 11 commits into
mainfrom
local/pmoves-hermes-z890-reconciled

Conversation

@POWERFULMOVES

@POWERFULMOVES POWERFULMOVES commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Reconcile Z890 node onto main + fleet fixes found along the way

Reconciles the local/pmoves-hermes-z890-config node branch (which had forked ~2 months back with 11 local commits) cleanly onto current main, carrying only the intentional work and dropping stale/stopgap commits. Along the way it fixes three real bugs that live on main and affect the whole fleet.

Fleet-worthy fixes (belong on main regardless of the node)

  • fix(tokenism) — CHIT signing was down fleet-wide because the running pmoves-tokenism:pmoves-latest image is an orphan tag no CI workflow builds (ModuleNotFoundError: No module named 'pmoves'). Repoints TOKENISM_IMAGE to the real CI-built name (pmoves-tokenism-simulator:edge, which images.yaml+build-images.yml actually publish) and adds explicit PYTHONPATH=/app. Verified: locally-built image passes the import acceptance test (from pmoves.tools.chit_security import sign_cgp, verify_cgp → OK). Main's Dockerfile already packages pmoves/tools (fix(packaging): ensure service Dockerfiles package pmoves.tools #2070/fix(secrets): route remaining CHIT_PASSPHRASE reads through services.common.env #2125); the gaps were the tag + PYTHONPATH.
  • fix(evo-controller) — line 63 read the CHIT signing secret via os.getenv while the rest of the file uses the get_secret helper. get_secret is a strict superset (env var first, then {KEY}_FILE), so behavior is preserved and Docker secret file-mounting works. Unblocks the secrets-audit hard-gate that otherwise fails secrets-funnel from a clean checkout.
  • fix(damage-control) — exempt git rm from the recursive-delete + no-delete guards ((?<!git\s) mirroring the existing docker/podman exclusion). git rm is a reversible index operation, categorically different from rm -rf. Verified: git rm passes; real rm -rf and no-delete-path deletes still block.
  • known-roads topic domain — adds the topic Known-Road guard domain (main had compose/schema/dockerfile but not topic) + trail entries.
  • Pinokio design/plan docs — the combined PMOVES-Pinokio customization architecture spec + implementation plan (pairs with the pbnj-submodule work in chore(pbnj): convert to submodule of combined PMOVES-pinokio fork #2175).

Node config (z890)

  • z890-infra.room.fabric.json reconciled onto main's schema (added required stage field; validates).
  • 5 pmoves-* skills (legal-assist, folder-monitor, email-organizer, yt-monitor, n8n-archon-bridge), pmoves/launcher/, launcher_profile_select.py, and the profile .env.example (placeholders only).
  • Note: the z890 hardware profile needed no change — main already carries the correct Intel Core Ultra 7 265K / 20-core spec (tool-verified via glances autodetect; the stale local copy's AMD spec was wrong).

Explicitly NOT included

  • .hermes/ and the real profile .env (node-local secrets) stay untracked.
  • Handoff docs stay local-only.
  • The stale local commits (nats-ws, mcp-windows, cipher dual-home — already on main) and the stopgap compose commit (main renamed those services entirely) were dropped.

Follow-ups (not in this PR)

  • secrets_manifest_v2.yaml is missing 5 keys main's compose requires (LOGFLARE_PUBLIC/PRIVATE_ACCESS_TOKEN, SECRET_KEY_BASE, SUPABASE_DB_USER, VAULT_ENC_KEY), so a from-scratch secrets-funnel produces incomplete tier files. Add them to the manifest + re-funnel (funnel sources deterministically from the machine CHIT vault, so values stay consistent).
  • The live node cutover to main's compose is deferred (deliberate down→up under main's service names).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a PMOVES HERMES Z890 launcher profile with local-first model routing, platform integrations, and guided secret configuration.
    • Added workflows for legal review, email organization, folder monitoring, workflow automation, and media monitoring.
    • Added launcher tooling with configuration previews, backups, and environment template generation.
    • Expanded the Z890 room with new operator panels and workflow bindings.
  • Bug Fixes

    • Improved command safety so Git file removals are handled correctly.
    • Improved secure credential retrieval for controller operations.
  • Documentation

    • Added setup and usage guidance for launcher profiles and the new workflows.

POWERFULMOVES and others added 10 commits July 21, 2026 06:46
Aggregation Model A (submodule) reconciling combined PMOVES-pinokio fork with
distributed per-service launchers (crush, claude-code) + forked plugin/code.
Captures the closed-CLI constraint (claude-code integration via extension
surface + Agent SDK, not a binary fork). Design approved verbally; pending
written-spec review before writing-plans.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
auto-cli = Pinokio's built-in CLI launcher generator (use installable variant
for claude-code/crush). Submodule recurse handled by explicit git submodule
update --init --recursive in each launcher install.js (no Pinokio-clone dependency).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 atomic tasks (code fork+claude repoint, pmoves-claude-code launcher/scaffold,
PMOVES-pinokio assembly, meta-repo pbnj submodule, install repoint+validation).
Self-review fix: pmoves-claude-code launcher at repo root so its api submodule
places pinokio.js correctly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Respects PMOVES-crush's nested launcher structure; keeps version-pinning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… guards

git-rm is a reversible git-index removal, categorically different from a
recursive filesystem delete. Adds (?<!git\s) to the four recursive/force
delete patterns (patterns.yaml) and the DELETE matcher (bash-tool-damage-control.py),
mirroring the existing docker/podman exclusion. Verified: git-index removals
pass; real recursive filesystem deletes and no-delete-path deletes still block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d onto main)

5 pmoves-* skills (legal-assist, folder-monitor, email-organizer, yt-monitor,
n8n-archon-bridge), pmoves/launcher/, launcher_profile_select.py, and the
profile .env.example (placeholders only). Node-local .env + .hermes stay untracked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add topic domain predicate (_is_topic_target) for pmoves/contracts/topics.json
  and register it in DOMAIN_PATTERNS alongside main's existing compose/schema/dockerfile
  domains (schema was already merged upstream; dockerfile untouched).
- Append 7 local trail lines (schema + topic grants) to known-roads.jsonl, additive
  only, no overlap with main's existing entries.

z890-coordinator.yaml needed no change: main already has the Intel Core Ultra 7 265K
hardware fix (commit 0f578bb), superseding the stale AMD Ryzen values in the local
WIP snapshot.

z890-infra.room.fabric.json left uncommitted: the local WIP version fails validation
against main's current room schema ('stage' is a required property, missing from the
WIP file). Not forced — needs a human decision on the correct stage value.
…TH (CHIT signing)

Build context/dockerfile path and pmoves.tools packaging were already
fixed on main via #2070/#2125. The remaining gap: docker-compose.yml's
TOKENISM_IMAGE default pointed at an orphan tag
(ghcr.io/powerfulmoves/pmoves-tokenism:pmoves-latest) that no CI
workflow ever builds. pmoves/images.yaml defines the real matrix entry
(name: pmoves-tokenism-simulator, context: pmoves, dockerfile:
services/tokenism-simulator/Dockerfile) which build-images.yml tags as
:edge. Repoint the default to that name/tag.

Also add explicit ENV PYTHONPATH=/app to the Dockerfile, mirroring the
hi-rag-gateway-v2 house pattern, so the pmoves.tools.* / services.common.*
imports resolve independent of invocation cwd.
…crets-audit)

Line 63 read the CHIT signing secret via os.getenv while the rest of the file
already uses the get_secret helper. get_secret is a strict superset (env var
first, then KEY_FILE indirection), so behavior is preserved and Docker secret
file-mounting now works. Unblocks the secrets-audit hard-gate in secrets-funnel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR updates damage-control rules, adds Known Roads topic validation, introduces a Z890 launcher profile and selector, wires new room workflows and skill specifications, documents combined Pinokio customization, and adjusts service credential and container defaults.

Changes

Damage-control and Known Roads

Layer / File(s) Summary
Command filtering and topic authorization
.claude/hooks/damage-control/*
Filesystem delete detection now excludes git rm, and Known Roads recognizes PMOVES topic registry paths with associated trail metadata.

Launcher profiles and Z890 workflows

Layer / File(s) Summary
Launcher profile application
pmoves/launcher/*, pmoves/tools/launcher_profile_select.py, pmoves/config/profiles/*
Adds the Z890 launcher profile and a CLI that validates, merges, previews, and writes Hermes configuration plus secret-name templates.
Z890 room workflow wiring
pmoves/config/rooms/*
Adds legal, email, n8n/Archon, and media-monitor applications and bindings, with corresponding subjects and documentation references.
Workflow skill specifications
pmoves/skills/*
Documents email, folder, legal, workflow-bridge, and YouTube monitoring skills, including configuration, execution, and retention rules.

Combined Pinokio customization

Layer / File(s) Summary
Pinokio aggregation design
docs/superpowers/specs/*
Defines repository ownership, submodule topology, Claude Code integration, migration order, validation, and scope boundaries.
Pinokio implementation plan
docs/superpowers/plans/*
Sequences repository setup, launcher scaffolding, submodule assembly, meta-repository conversion, local installation, and recursive verification.

Runtime and image updates

Layer / File(s) Summary
Service runtime alignment
pmoves/services/evo-controller/app.py, pmoves/services/tokenism-simulator/*, pmoves/docker-compose.yml
Routes CHIT credentials through get_secret, updates the tokenism simulator image, and sets its container Python path.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LauncherCLI
  participant LauncherProfile
  participant HermesConfig
  participant SecretTemplate
  LauncherCLI->>LauncherProfile: Load and validate profile
  LauncherCLI->>HermesConfig: Merge Hermes overrides
  LauncherCLI->>SecretTemplate: Render blank secret entries
  LauncherCLI->>HermesConfig: Write configuration and backup
Loading

Possibly related PRs

Suggested labels: secrets-pipeline

Suggested reviewers: claudedev

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change set, but it misses required template sections like Summary, Testing, Required Checks, and Review Coordination. Add the required template sections with summary bullets, testing commands/output, required-check checkboxes, review coordination, and reviewer notes.
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% 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 title clearly states the main change: reconciling the z890 node onto main with related fixes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch local/pmoves-hermes-z890-reconciled

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.

@github-actions github-actions Bot added chit-aware Touches a CHIT-aware service — control-body signature gate applies compose Compose files / service Dockerfiles docs Documentation services Service source under pmoves/services/ config pmoves/config(s)/ changes governance AGNOTE register / agent definitions / damage-control hooks labels Jul 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Docker Hardening Validation

Hardening Validation Report

Validated: Tue Jul 21 17:26:14 UTC 2026

Services Checked

PMOVES.AI Docker Hardening Validation

[INFO] Checking: pmoves/docker-compose.hardened.yml

[INFO] Validating: hi-rag-gateway-v2
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: extract-worker
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: langextract
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: presign
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: render-webhook
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: retrieval-eval
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pdf-ingest
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: jellyfin-bridge
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: invidious-companion-proxy
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: ffmpeg-whisper
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-video
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-audio
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-v2-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: deepresearch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supaserch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: publisher-discord
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: mesh-agent
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-req
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-res
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: comfy-watcher
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: grayjay-plugin-host
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: agent-zero
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: p7-room-orchestrator
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: archon
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: channel-monitor
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pmoves-yt
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: notebook-sync
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supabase_service_role_key
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

[INFO] Validating: supabase_jwt_secret
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

[INFO] Validating: p7_control_token
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

======================================
Summary: 112 passed, 43 warnings, 0 errors

@github-actions

Copy link
Copy Markdown
Contributor

🔏 CHIT-aware change — control-body routing

This PR touches a CHIT-aware service (ports 8086/8087/8103/8106/8113/9224 surface). Before a Control-Body ACK:

  • the diff (or PR body) should reference a CHIT signature trail — chit.signed.v1, a CHIT: trailer, or a make -C pmoves sign-trail entry;
  • the chit-pr-audit-agent (.claude/agents/chit-pr-audit-agent.md) is the gate that grants/refuses ACK eligibility;
  • signing quickstart: pmoves/docs/AGENTS/CHIT_SIGNING_TUTORIAL.md.

Advisory routing only — the blocking contract check is CHIT Contract.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eab9edb883

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pmoves/config/rooms/z890-infra.room.fabric.json
Comment thread pmoves/launcher/profiles/pmoves-hermes-z890.json Outdated
Comment thread pmoves/tools/launcher_profile_select.py Outdated
Comment thread pmoves/tools/launcher_profile_select.py Fixed
Comment thread pmoves/tools/launcher_profile_select.py Fixed
Comment thread pmoves/tools/launcher_profile_select.py Fixed
…argets, dry-run mkdir + verified CodeQL suppressions

- room manifest: mark legal/email/n8n panels status:planned until routes exist (Codex)
- launcher profile: up-archon->up-archon-native (valid target); drop skills that arent make targets (Codex)
- launcher_profile_select.py: dry-run no longer creates the Hermes profile dir; lgtm suppressions for env_content writes/logs (KEY NAMES only, values blank) (Codex + CodeQL)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Docker Hardening Validation

Hardening Validation Report

Validated: Wed Jul 22 00:48:15 UTC 2026

Services Checked

PMOVES.AI Docker Hardening Validation

[INFO] Checking: pmoves/docker-compose.hardened.yml

[INFO] Validating: hi-rag-gateway-v2
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: extract-worker
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: langextract
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: presign
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: render-webhook
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: retrieval-eval
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pdf-ingest
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: jellyfin-bridge
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: invidious-companion-proxy
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: ffmpeg-whisper
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-video
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-audio
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-v2-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: deepresearch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supaserch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: publisher-discord
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: mesh-agent
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-req
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-res
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: comfy-watcher
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: grayjay-plugin-host
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: agent-zero
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: p7-room-orchestrator
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: archon
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: channel-monitor
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pmoves-yt
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: notebook-sync
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supabase_service_role_key
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

[INFO] Validating: supabase_jwt_secret
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

[INFO] Validating: p7_control_token
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

======================================
Summary: 112 passed, 43 warnings, 0 errors

Comment thread pmoves/tools/launcher_profile_select.py Dismissed
Comment thread pmoves/tools/launcher_profile_select.py Dismissed
Comment thread pmoves/tools/launcher_profile_select.py Dismissed

@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: 14

🧹 Nitpick comments (2)
docs/superpowers/specs/2026-07-20-pmoves-combined-pinokio-customization-design.md (1)

90-95: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Define staged documentation obligations.

Because this is a design-only spec and does not introduce service endpoints yet, do not add premature catalog entries. Instead, state which implementation stages must update .claude/context/nats-subjects.md and .claude/context/services-catalog.md, and reference pmoves/docs/AGENTS/PMOVES_AGENT_TOPOLOGY.md for the required topology diagrams.

Based on learnings, design-only specs must define explicit per-stage catalog obligations rather than documenting unbuilt endpoints.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@docs/superpowers/specs/2026-07-20-pmoves-combined-pinokio-customization-design.md`
around lines 90 - 95, Update the “Testing / validation” or related documentation
section to define explicit per-stage obligations for updating
.claude/context/nats-subjects.md and .claude/context/services-catalog.md,
without adding catalog entries for this design-only spec. State that stages
introducing or changing NATS subjects or services must update the corresponding
context document, and require topology diagrams to follow
pmoves/docs/AGENTS/PMOVES_AGENT_TOPOLOGY.md.

Sources: Coding guidelines, Learnings

pmoves/config/rooms/z890-infra.room.fabric.json (1)

487-498: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

New NATS subjects not reflected in the topology doc.

ops.email.triage.completed.v1 and media.transcript.ready.v1 are newly introduced here. As per coding guidelines, NATS event topology should be documented in .claude/context/nats-subjects.md (not included in this changeset).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/config/rooms/z890-infra.room.fabric.json` around lines 487 - 498,
Update .claude/context/nats-subjects.md to document the newly allowed NATS
subjects ops.email.triage.completed.v1 and media.transcript.ready.v1, matching
the existing topology documentation format and their publish configuration in
the policies section.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/hooks/damage-control/known_roads.py:
- Around line 81-99: Update _is_topic_target so topics.json is authorized only
when its immediate parent directory is contracts, while preserving the existing
PMOVES-owned tree requirement. Replace the broad contracts-segment check and add
negative coverage for nested and otherwise unrelated contracts paths.

In @.claude/hooks/damage-control/patterns.yaml:
- Around line 27-44: The `git rm` exemption is overly broad because both
enforcement layers match raw shell text and allow destructive deletions through
wrappers or inconsistent option forms. In
`.claude/hooks/damage-control/patterns.yaml` lines 27-44, replace the
negative-lookbehind patterns with command-aware matching that preserves
protection for filesystem `rm` while applying an explicit policy to `git rm`; in
`.claude/hooks/damage-control/bash-tool-damage-control.py` lines 80-82, apply
the same parsed-command policy to `READ_ONLY_BLOCKED` and `NO_DELETE_BLOCKED`.

In `@docs/superpowers/plans/2026-07-20-combined-pinokio-customization.md`:
- Around line 132-137: Remove the hardcoded PMOVES_NODE_ID value from the
bootstrap settings in the “Minimal PMOVES bootstrap config” step. Leave the
setting unset so each installation can obtain its node identity from runtime
environment or secret management.
- Around line 78-84: Update each “Commit + push + PR” step to use an atomic
topic branch rather than pushing directly to PMOVES.AI-Edition-Hardened: create
and push a uniquely named topic branch, open a PR targeting the hardened branch,
and document smoke-test commands/results plus reviewer notes before merge. Apply
this consistently to all three referenced plan sections.
- Around line 233-236: Update Step 4’s recursive submodule verification to
inspect every entry rather than filtering with grep pbnj. Make the check fail
when any recursive status line begins with -, +, or U, while accepting
initialized, conflict-free nested submodules.

In
`@docs/superpowers/specs/2026-07-20-pmoves-combined-pinokio-customization-design.md`:
- Around line 48-62: Update the topology Markdown code fence in the documented
repository layout near “PMOVES-pinokio” to specify the text language, preserving
the diagram content unchanged.
- Around line 42-44: The repository topology must explicitly distinguish Phase-1
direct submodules from thin in-tree launcher entries. In
docs/superpowers/specs/2026-07-20-pmoves-combined-pinokio-customization-design.md
lines 42-44, state whether plugin/code is included in Phase 1 and reflect the
finalized submodule/entry model across topology diagrams and .gitmodules
expectations. In
docs/superpowers/plans/2026-07-20-combined-pinokio-customization.md lines
165-194, update validation commands to verify sources/pmoves-crush as the actual
submodule while treating api/pmoves-crush as the thin launcher entry.

In `@pmoves/config/rooms/z890-infra.room.fabric.json`:
- Around line 3-6: Update the stage value in the Z890 Infra Fabric Room
configuration to match the Z890 launcher profile’s expected stage, while leaving
the version, display_name, and description unchanged.
- Line 486: Update the launcher_refs entry to use the documented up-archon
launcher name instead of up-archon-native, keeping the other launcher references
unchanged.

In `@pmoves/docker-compose.yml`:
- Line 3808: Update the TOKENISM_IMAGE default in docker-compose.ui.yml to
ghcr.io/powerfulmoves/pmoves-tokenism-simulator:edge, matching the default used
by the tokenism service in docker-compose.yml.

In `@pmoves/launcher/profiles/pmoves-hermes-z890.json`:
- Around line 9-13: Update the room.stage value in the z890-infra room
configuration within the pmoves-hermes-z890 profile to match the room manifest’s
rehearsal stage. Leave the room_id and suits entries unchanged.
- Around line 54-60: Align the Archon launcher reference in the profile with the
documented Make target: update the launcher_refs entry from up-archon-native to
up-archon, and keep the profile consistent with the corresponding room manifest.

In `@pmoves/skills/pmoves-n8n-archon-bridge/SKILL.md`:
- Around line 66-78: Update the local-running and next-implementation
documentation to use the configured make target up-archon-native instead of
up-archon, matching the launcher_refs entries in the referenced configuration
files. Preserve the existing command structure and surrounding n8n instructions.

In `@pmoves/tools/launcher_profile_select.py`:
- Around line 67-82: Update deep_merge so force only overwrites keys explicitly
present in overlay; preserve base values for keys absent from the launcher
profile, including when force=True. Continue recursively merging shared
dictionaries and applying existing force/empty-value behavior only to
overlay-provided keys.

---

Nitpick comments:
In
`@docs/superpowers/specs/2026-07-20-pmoves-combined-pinokio-customization-design.md`:
- Around line 90-95: Update the “Testing / validation” or related documentation
section to define explicit per-stage obligations for updating
.claude/context/nats-subjects.md and .claude/context/services-catalog.md,
without adding catalog entries for this design-only spec. State that stages
introducing or changing NATS subjects or services must update the corresponding
context document, and require topology diagrams to follow
pmoves/docs/AGENTS/PMOVES_AGENT_TOPOLOGY.md.

In `@pmoves/config/rooms/z890-infra.room.fabric.json`:
- Around line 487-498: Update .claude/context/nats-subjects.md to document the
newly allowed NATS subjects ops.email.triage.completed.v1 and
media.transcript.ready.v1, matching the existing topology documentation format
and their publish configuration in the policies section.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f0784133-bb8a-475e-9e66-094df62e0419

📥 Commits

Reviewing files that changed from the base of the PR and between 768c29f and ed8e86a.

📒 Files selected for processing (19)
  • .claude/hooks/damage-control/bash-tool-damage-control.py
  • .claude/hooks/damage-control/known-roads.jsonl
  • .claude/hooks/damage-control/known_roads.py
  • .claude/hooks/damage-control/patterns.yaml
  • docs/superpowers/plans/2026-07-20-combined-pinokio-customization.md
  • docs/superpowers/specs/2026-07-20-pmoves-combined-pinokio-customization-design.md
  • pmoves/config/profiles/pmoves-hermes-z890.env.example
  • pmoves/config/rooms/z890-infra.room.fabric.json
  • pmoves/docker-compose.yml
  • pmoves/launcher/README.md
  • pmoves/launcher/profiles/pmoves-hermes-z890.json
  • pmoves/services/evo-controller/app.py
  • pmoves/services/tokenism-simulator/Dockerfile
  • pmoves/skills/pmoves-email-organizer/SKILL.md
  • pmoves/skills/pmoves-folder-monitor/SKILL.md
  • pmoves/skills/pmoves-legal-assist/SKILL.md
  • pmoves/skills/pmoves-n8n-archon-bridge/SKILL.md
  • pmoves/skills/pmoves-yt-monitor/SKILL.md
  • pmoves/tools/launcher_profile_select.py

Comment on lines +81 to +99
def _is_topic_target(normalized_fwd: str) -> bool:
"""topic domain: the PMOVES NATS subject registry pmoves/contracts/topics.json.

topics.json is readOnly because a change to the subject contract ripples to
every publisher/subscriber and the shared `events.publish` topic validator.
It is NOT a *.schema.json, so the schema domain does not cover it; this domain
opens ONLY that one file under a `contracts` segment in a PMOVES-owned tree,
and — like schema — still requires a provable reason (pr:/issue:/handoff:).
"""
basename = os.path.basename(normalized_fwd).lower()
if basename != "topics.json":
return False
parts = normalized_fwd.lower().split("/")
if not any(
p == "pmoves" or p.startswith("pmoves-") or p.startswith("pmoves.")
for p in parts
):
return False
return "contracts" in parts

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Require topics.json to be the direct child of contracts.

return "contracts" in parts also authorizes paths such as pmoves/contracts/untrusted/topics.json and pmoves/untrusted/contracts/topics.json. Since this predicate controls a Known Road bypass, those paths could receive topic-domain authorization incorrectly.

Proposed fix
-    return "contracts" in parts
+    return any(
+        part == "contracts"
+        and index + 1 < len(parts)
+        and parts[index + 1] == "topics.json"
+        for index, part in enumerate(parts)
+    )

Add negative tests for nested and unrelated contracts paths.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/hooks/damage-control/known_roads.py around lines 81 - 99, Update
_is_topic_target so topics.json is authorized only when its immediate parent
directory is contracts, while preserving the existing PMOVES-owned tree
requirement. Replace the broad contracts-segment check and add negative coverage
for nested and otherwise unrelated contracts paths.

Comment on lines +27 to +44
# Negative lookbehinds exclude `docker rm`/`podman rm`/`git rm` — targeted
# container removal and reversible git-index removal are not mass filesystem
# destruction. `git rm` stages a tracked-file removal that git can recover;
# it is categorically different from `rm -rf`. The dangerous container forms
# (`docker rm $(docker ps -aq)`, `docker ps -q | xargs docker rm`, and
# their podman equivalents) are caught by dedicated hard-block rules
# further down the file ("Container sweep hard-blocks" section).
- pattern: '(?<!docker\s)(?<!podman\s)\brm\s+(-[^\s]*)*-[rRf]'
reason: rm with recursive or force flags (filesystem rm, not docker/podman)
- pattern: '(?<!docker\s)(?<!podman\s)(?<!git\s)\brm\s+(-[^\s]*)*-[rRf]'
reason: rm with recursive or force flags (filesystem rm, not docker/podman/git)

- pattern: '(?<!docker\s)(?<!podman\s)\brm\s+-[rRf]'
reason: rm with recursive or force flags (filesystem rm, not docker/podman)
- pattern: '(?<!docker\s)(?<!podman\s)(?<!git\s)\brm\s+-[rRf]'
reason: rm with recursive or force flags (filesystem rm, not docker/podman/git)

- pattern: '(?<!docker\s)(?<!podman\s)\brm\s+--recursive'
reason: rm with --recursive flag (filesystem rm, not docker/podman)
- pattern: '(?<!docker\s)(?<!podman\s)(?<!git\s)\brm\s+--recursive'
reason: rm with --recursive flag (filesystem rm, not docker/podman/git)

- pattern: '(?<!docker\s)(?<!podman\s)\brm\s+--force'
reason: rm with --force flag (filesystem rm, not docker/podman)
- pattern: '(?<!docker\s)(?<!podman\s)(?<!git\s)\brm\s+--force'
reason: rm with --force flag (filesystem rm, not docker/podman/git)

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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

The git rm exception is too broad in both enforcement layers.

Both layers inspect raw shell text, so wrappers can bypass deletion guards while valid Git option forms behave inconsistently. git rm also removes working-tree files and should not be treated as inherently non-destructive.

  • .claude/hooks/damage-control/patterns.yaml#L27-L44: replace the negative-lookbehind exception with command-aware matching and preserve protections for actual filesystem deletion.
  • .claude/hooks/damage-control/bash-tool-damage-control.py#L80-L82: apply the same parsed-command policy to READ_ONLY_BLOCKED and NO_DELETE_BLOCKED.
📍 Affects 2 files
  • .claude/hooks/damage-control/patterns.yaml#L27-L44 (this comment)
  • .claude/hooks/damage-control/bash-tool-damage-control.py#L80-L82
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/hooks/damage-control/patterns.yaml around lines 27 - 44, The `git
rm` exemption is overly broad because both enforcement layers match raw shell
text and allow destructive deletions through wrappers or inconsistent option
forms. In `.claude/hooks/damage-control/patterns.yaml` lines 27-44, replace the
negative-lookbehind patterns with command-aware matching that preserves
protection for filesystem `rm` while applying an explicit policy to `git rm`; in
`.claude/hooks/damage-control/bash-tool-damage-control.py` lines 80-82, apply
the same parsed-command policy to `READ_ONLY_BLOCKED` and `NO_DELETE_BLOCKED`.

Comment on lines +78 to +84
- [ ] **Step 5: Commit + push + PR**

```bash
git -C ../pmoves-code-fork add claude/pinokio.js
git -C ../pmoves-code-fork commit -m "feat(claude): launch claude-code with PMOVES-claude-code config dir"
git -C ../pmoves-code-fork push origin PMOVES.AI-Edition-Hardened
```

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Route repository changes through atomic PRs.

These steps push directly to hardened branches, contradicting the plan’s atomic-PR requirement. Push a topic branch, open the PR, and include smoke-test commands/results and reviewer notes before merge.

Also applies to: 144-149, 196-201

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-07-20-combined-pinokio-customization.md` around
lines 78 - 84, Update each “Commit + push + PR” step to use an atomic topic
branch rather than pushing directly to PMOVES.AI-Edition-Hardened: create and
push a uniquely named topic branch, open a PR targeting the hardened branch, and
document smoke-test commands/results plus reviewer notes before merge. Apply
this consistently to all three referenced plan sections.

Source: Coding guidelines

Comment on lines +132 to +137
- [ ] **Step 4: Minimal PMOVES bootstrap config** — `claude-config/settings.json`

```json
{ "$comment": "Minimal PMOVES bootstrap. Full hooks/skills/MCP substance is task #13.",
"env": { "PMOVES_NODE_ID": "z890" } }
```

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not hardcode the z890 node identity in shared config.

A shared PMOVES-claude-code checkout will be used by multiple nodes, so this makes every installation report itself as z890. Read the node ID from runtime environment/secret management or leave it unset in the committed bootstrap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-07-20-combined-pinokio-customization.md` around
lines 132 - 137, Remove the hardcoded PMOVES_NODE_ID value from the bootstrap
settings in the “Minimal PMOVES bootstrap config” step. Leave the setting unset
so each installation can obtain its node identity from runtime environment or
secret management.

Source: Coding guidelines

Comment on lines +233 to +236
- [ ] **Step 4: Verify + commit**

Run: `git submodule status --recursive | grep pbnj`
Expected: `pbnj` resolves with nested submodules.

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate nested submodules instead of filtering them out.

git submodule status --recursive | grep pbnj only proves the top-level pbnj entry appears; it does not verify nested submodule status. Check all recursive entries and fail on uninitialized or conflicted prefixes (-, +, or U).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-07-20-combined-pinokio-customization.md` around
lines 233 - 236, Update Step 4’s recursive submodule verification to inspect
every entry rather than filtering with grep pbnj. Make the check fail when any
recursive status line begins with -, +, or U, while accepting initialized,
conflict-free nested submodules.

Comment thread pmoves/docker-compose.yml
context: .
dockerfile: services/tokenism-simulator/Dockerfile
image: ${TOKENISM_IMAGE:-ghcr.io/powerfulmoves/pmoves-tokenism:pmoves-latest}
image: ${TOKENISM_IMAGE:-ghcr.io/powerfulmoves/pmoves-tokenism-simulator:edge}

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Synchronize the tokenism image default in the UI Compose override.

pmoves/docker-compose.ui.yml still defaults TOKENISM_IMAGE to ghcr.io/powerfulmoves/pmoves-tokenism:pmoves-latest, so UI-profile bring-up can override this change and run the old image. Update that parallel default to ghcr.io/powerfulmoves/pmoves-tokenism-simulator:edge.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/docker-compose.yml` at line 3808, Update the TOKENISM_IMAGE default in
docker-compose.ui.yml to ghcr.io/powerfulmoves/pmoves-tokenism-simulator:edge,
matching the default used by the tokenism service in docker-compose.yml.

Comment on lines +9 to +13
"room": {
"room_id": "z890-infra.room.fabric",
"stage": "live",
"suits": ["z890-infra", "pmoves-hermes", "legal-assist"]
},

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Room stage mismatch: profile says "live", room manifest says "rehearsal".

This profile declares room.stage: "live" for z890-infra.room.fabric, but the room manifest itself (pmoves/config/rooms/z890-infra.room.fabric.json) declares "stage": "rehearsal". This is a cross-file contract break — a launcher applying this profile would advertise the room as live when the manifest says otherwise, which can mislead operators about readiness.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/launcher/profiles/pmoves-hermes-z890.json` around lines 9 - 13, Update
the room.stage value in the z890-infra room configuration within the
pmoves-hermes-z890 profile to match the room manifest’s rehearsal stage. Leave
the room_id and suits entries unchanged.

Comment on lines +54 to +60
"launcher_refs": [
"up-agents",
"up-monitoring",
"secrets-funnel",
"up-n8n",
"up-archon-native"
],

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

up-archon-native referenced here, but the skill doc calls the Make target up-archon.

pmoves/skills/pmoves-n8n-archon-bridge/SKILL.md documents make -C pmoves up-archon, while this profile (and the room manifest) list up-archon-native. If the target names differ, the documented command will fail.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/launcher/profiles/pmoves-hermes-z890.json` around lines 54 - 60, Align
the Archon launcher reference in the profile with the documented Make target:
update the launcher_refs entry from up-archon-native to up-archon, and keep the
profile consistent with the corresponding room manifest.

Comment on lines +66 to +78
## Running locally

```bash
# Start n8n
make -C pmoves up-n8n

# Start Archon
make -C pmoves up-archon

# Verify n8n API
curl -u "$N8N_BASIC_AUTH_USER:$N8N_BASIC_AUTH_PASSWORD" \
http://localhost:5678/api/v1/workflows
```

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Documented Make target up-archon doesn't match the configured up-archon-native (see consolidated comment).

Both pmoves/launcher/profiles/pmoves-hermes-z890.json and pmoves/config/rooms/z890-infra.room.fabric.json list up-archon-native in launcher_refs, but this doc's "Running locally" section and "Next implementation steps" both reference make -C pmoves up-archon.

Also applies to: 105-111

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/skills/pmoves-n8n-archon-bridge/SKILL.md` around lines 66 - 78, Update
the local-running and next-implementation documentation to use the configured
make target up-archon-native instead of up-archon, matching the launcher_refs
entries in the referenced configuration files. Preserve the existing command
structure and surrounding n8n instructions.

Comment on lines +67 to +82
def deep_merge(base: dict[str, Any], overlay: dict[str, Any], force: bool = False) -> dict[str, Any]:
"""
Merge overlay into base. Recursively combine dicts. For non-dict values,
preserve existing non-empty base values unless force is True.
"""
result: dict[str, Any] = {}
for key in set(base.keys()) | set(overlay.keys()):
base_val = base.get(key)
overlay_val = overlay.get(key)
if isinstance(overlay_val, dict) and isinstance(base_val, dict):
result[key] = deep_merge(base_val, overlay_val, force)
elif force or is_empty(base_val):
result[key] = overlay_val
else:
result[key] = base_val
return result

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

--force silently nulls out config keys the profile doesn't override.

overlay.get(key) returns None for keys present only in base. Since the elif force or is_empty(base_val) branch fires whenever force=True — independent of whether key is actually in overlay — any existing config.yaml key absent from the launcher profile's hermes_config_overrides gets overwritten with None on --write --force. That contradicts the documented behavior ("Overwrite existing non-empty values with launcher defaults") and can wipe unrelated Hermes settings (a backup is created, but data is still lost from the active config).

🛠️ Proposed fix
 def deep_merge(base: dict[str, Any], overlay: dict[str, Any], force: bool = False) -> dict[str, Any]:
     result: dict[str, Any] = {}
     for key in set(base.keys()) | set(overlay.keys()):
+        if key not in overlay:
+            result[key] = base.get(key)
+            continue
         base_val = base.get(key)
-        overlay_val = overlay.get(key)
+        overlay_val = overlay[key]
         if isinstance(overlay_val, dict) and isinstance(base_val, dict):
             result[key] = deep_merge(base_val, overlay_val, force)
         elif force or is_empty(base_val):
             result[key] = overlay_val
         else:
             result[key] = base_val
     return result
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def deep_merge(base: dict[str, Any], overlay: dict[str, Any], force: bool = False) -> dict[str, Any]:
"""
Merge overlay into base. Recursively combine dicts. For non-dict values,
preserve existing non-empty base values unless force is True.
"""
result: dict[str, Any] = {}
for key in set(base.keys()) | set(overlay.keys()):
base_val = base.get(key)
overlay_val = overlay.get(key)
if isinstance(overlay_val, dict) and isinstance(base_val, dict):
result[key] = deep_merge(base_val, overlay_val, force)
elif force or is_empty(base_val):
result[key] = overlay_val
else:
result[key] = base_val
return result
def deep_merge(base: dict[str, Any], overlay: dict[str, Any], force: bool = False) -> dict[str, Any]:
"""
Merge overlay into base. Recursively combine dicts. For non-dict values,
preserve existing non-empty base values unless force is True.
"""
result: dict[str, Any] = {}
for key in set(base.keys()) | set(overlay.keys()):
if key not in overlay:
result[key] = base.get(key)
continue
base_val = base.get(key)
overlay_val = overlay[key]
if isinstance(overlay_val, dict) and isinstance(base_val, dict):
result[key] = deep_merge(base_val, overlay_val, force)
elif force or is_empty(base_val):
result[key] = overlay_val
else:
result[key] = base_val
return result
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/tools/launcher_profile_select.py` around lines 67 - 82, Update
deep_merge so force only overwrites keys explicitly present in overlay; preserve
base values for keys absent from the launcher profile, including when
force=True. Continue recursively merging shared dictionaries and applying
existing force/empty-value behavior only to overlay-provided keys.

@POWERFULMOVES
POWERFULMOVES merged commit bf5d4aa into main Jul 22, 2026
56 of 59 checks passed
@POWERFULMOVES
POWERFULMOVES deleted the local/pmoves-hermes-z890-reconciled branch July 22, 2026 03:20
POWERFULMOVES added a commit that referenced this pull request Jul 24, 2026
…:edge)

docker-compose.yml (source) pins tokenism-simulator to
pmoves-tokenism-simulator:edge (set in #2184), but docker-compose.ui.yml was
never regenerated and still referenced the old pmoves-tokenism:pmoves-latest.
This is the drift the 'Validate Compose Files' gate flags on main. Regenerated
with the pinned ruamel.yaml==0.19.1 for byte-stable output; ui.yml is the only
overlay that changed.

KNOWN_ROAD=compose:regenerate-overlays

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
POWERFULMOVES added a commit that referenced this pull request Jul 24, 2026
…:edge)

docker-compose.yml (source) pins tokenism-simulator to
pmoves-tokenism-simulator:edge (set in #2184), but docker-compose.ui.yml was
never regenerated and still referenced the old pmoves-tokenism:pmoves-latest.
This is the drift the 'Validate Compose Files' gate flags on main. Regenerated
with the pinned ruamel.yaml==0.19.1 for byte-stable output; ui.yml is the only
overlay that changed.

KNOWN_ROAD=compose:regenerate-overlays

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
POWERFULMOVES added a commit that referenced this pull request Jul 24, 2026
…:edge)

docker-compose.yml (source) pins tokenism-simulator to
pmoves-tokenism-simulator:edge (set in #2184), but docker-compose.ui.yml was
never regenerated and still referenced the old pmoves-tokenism:pmoves-latest.
This is the drift the 'Validate Compose Files' gate flags on main. Regenerated
with the pinned ruamel.yaml==0.19.1 for byte-stable output; ui.yml is the only
overlay that changed.

KNOWN_ROAD=compose:regenerate-overlays

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
POWERFULMOVES added a commit that referenced this pull request Jul 24, 2026
…:edge) (#2196)

* fix(compose): regenerate ui overlay — sync tokenism image to source (:edge)

docker-compose.yml (source) pins tokenism-simulator to
pmoves-tokenism-simulator:edge (set in #2184), but docker-compose.ui.yml was
never regenerated and still referenced the old pmoves-tokenism:pmoves-latest.
This is the drift the 'Validate Compose Files' gate flags on main. Regenerated
with the pinned ruamel.yaml==0.19.1 for byte-stable output; ui.yml is the only
overlay that changed.

KNOWN_ROAD=compose:regenerate-overlays

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(compose): reconcile agent overlay with current main

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Shaela Bello <slbello@uncg.edu>
POWERFULMOVES added a commit that referenced this pull request Jul 25, 2026
…c-stage leak) (#2222)

The z890 node reconcile (#2184) dropped the access block from
z890-infra.room.fabric.json. With access unset, is_public_room()
defaults to public, so the node-control room leaked onto the public
stage catalog — and test_stage_data's curation guard has been FAILING
ON MAIN since that merge (every branch rebasing onto main inherits the
red python-tests). Restore the pre-#2184 value: visibility unlisted.

Verified: test_stage_data 5/5, validate_room_manifests 9/9.

Co-authored-by: Shaela Bello <slbello@uncg.edu>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chit-aware Touches a CHIT-aware service — control-body signature gate applies compose Compose files / service Dockerfiles config pmoves/config(s)/ changes docs Documentation governance AGNOTE register / agent definitions / damage-control hooks services Service source under pmoves/services/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants