feat(submodule): 6-repo fold-in PR3 - PMOVES-agents.md (agentsmd/agents.md open format) - #2590
Conversation
|
Important Review available on request
Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3fb661fb94
ℹ️ 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".
|
|
||
| - `2026-08-17T13:19:00Z` CLAIM `Mavis (orchestrator, mvs_5d5493b128b640e9aff8d45adcc77a66)` scope: **6-repo fold-in slice - PR1 (skills fold-in) on `feat/skills-foldin-pmovesskills`.** This is the first of 3 PRs in the 6-repo fold-in (operator chose 3 separate PRs for easier revert - PR1=skills, PR2=MCP+CLI+Provider-Verifier, PR3=agents.md). **What lands in PR1:** (a) new nested submodule `skills/PMOVES-skills/` (gitlink pointer to `vercel-labs/skills` main via the POWERFULMOVES fork) - the post-recenter home of the skills library that moved from `MiniMax-AI/skills` in August 2026. (b) `.gitmodules` entry for the new submodule. (c) 1-commit upstream bump on the existing `skills/Pmoves-skills/` gitlink (`69c0b1a` -> `c6f69c6`) - caught during the `git submodule add` operation when the existing entry was refetched, included as a minor change. (d) `skills/README.md` updated: new constellation row for PMOVES-skills + a "Recentering note (2026-08-17)" paragraph explaining the MiniMax-AI -> vercel-labs move and why the deprecated pre-recenter URL (`POWERFULMOVES/Pmoves-Minimax-skills`) is preserved as a reference rather than a separate submodule (would split the work in two when one is the post-recenter of the other). (e) `.claude/context/submodules.md` table updated with the new row, mirroring the README ordering. (f) `pmoves/configs/submodule_skill_registry.json` got a new `skills/PMOVES-skills` entry (context_tier=2, domain_tags=["agents","mcp"], matching the other skills submodules) with a `$note` documenting the recenter history. **Out of scope (intentional, lives in other PRs of the fold-in):** the deprecated pre-recenter URL (Pmoves-Minimax-skills); PMOVES-agents.md (PR3); the 3 MCP+CLI+Provider-Verifier repos (PR2). **Verification:** 3 stacked commits (feat submodule wire -> docs context+registry -> docs AGNOTE+LEARNINGS); `python -c json.load(...)` passes on the registry; no other files touched; the canonical path matches the existing skills/* convention. **Three stacked commits:** `a16d2adaa2` (feat submodule wire + README), `316c089e9c` (docs context + registry), pending the third (docs AGNOTE + LEARNINGS). **Three-body:** delivery=Mavis, control=DARKXSIDE (operator reviews + admin-merges; the 2 remaining PRs of the fold-in follow the same pattern), memory=this trail + the per-PR LEARNINGS file. CHIT trail unsigned-local. `agent_signature: ACK::Mavis::SKILLS-FOLDIN::2026-08-17`. | ||
| <!-- GRAPHITI_MARK: Mavis::SKILLS-FOLDIN::2026-08-17 --> | ||
| - `2026-08-17T13:35:00Z` CLAIM `Mavis (orchestrator, mvs_5d5493b128b640e9aff8d45adcc77a66)` scope: **6-repo fold-in slice - PR3 (agents.md fold-in) on `feat/agents-md-foldin`.** This is the third of 3 PRs in the 6-repo fold-in (PR1=skills MERGED #2586 at `d4af79f325`; PR2=MCP+CLI+Provider-Verifier in a parallel worktree; PR3=agents.md this slice). **What lands in PR3:** (a) new top-level submodule `PMOVES-agents.md/` (gitlink pointer to upstream HEAD `d1ac7f063d20e70015ed6732664049ae4ba9d74e` on the POWERFULMOVES fork of `agentsmd/agents.md` main) - the canonical home for the AGENTS.md open format reference, the agent taxonomy, and the persona schema. (b) `.gitmodules` entry with `branch = main` (added post-`git submodule add` per the operator spec; `git submodule add` without `-b` does not set the `branch` field). (c) `.claude/context/submodules.md` - one-row table added inside the existing `### PMOVES-agents.md` subsection in the "Agent Format & Skills Constellation" section, mirroring the `skills/*` table format below for scannability; the pre-existing detailed bullet list (Path / Repository / Upstream / Purpose / Tier / Cross-refs) is preserved unchanged. (d) `pmoves/configs/submodule_skill_registry.json` got a new `PMOVES-agents.md` entry (context_tier=2, domain_tags=["agents","docs"], matching the convention of the other Tier-2 always-relevant content) with a `$note` documenting the canonical-home purpose + the deliberate top-level placement (not under `skills/`, which is reserved for runtime-invokable agent skills). **Why top-level (not under `skills/`)**: the agents.md repo is a format/taxonomy reference, not a runtime-invokable skill; agents *load* the format spec on Tier-2, they don't *invoke* it like a skill. **Out of scope (intentional, lives in other PRs of the fold-in):** PMOVES-skills (already MERGED as PR1 #2586); the 3 MCP+CLI+Provider-Verifier repos (PR2). **Verification:** 3 stacked commits (`56df840207` feat submodule wire + gitlink, `224a727559` docs context + registry, this docs AGNOTE+LEARNINGS); `python -c "import json; json.load(open('pmoves/configs/submodule_skill_registry.json'))"` passes (58 submodules, +1 over pre-PR3); no other files touched; the new path is `PMOVES-agents.md/` at the repo root (matches the operator spec); the "Total submodules: 54" line in submodules.md is a pre-existing stale count (actual is 58 post-PR3; documented in LEARNINGS, fixing it is a separate cleanup slice, not in PR3 scope). **The .gitmodules `branch = main` was set post-`git submodule add` via Edit** - `git submodule add` without `-b main` writes the entry without a `branch =` line; the operator spec required `branch = main`, so it was added in the same commit (file edit + `git add .gitmodules` after the initial `git submodule add` had already staged the file). **Three-body:** delivery=Mavis, control=DARKXSIDE (operator reviews + admin-merges), memory=this trail + the per-PR LEARNINGS file (`agents_md_foldin_pr3_LEARNINGS.md` at the worktree root - NOT `mcpcli_*` which is for PR2). CHIT trail unsigned-local. `agent_signature: ACK::Mavis::AGENTS-MD-FOLDIN::2026-08-17`. |
There was a problem hiding this comment.
If this PR remains open or is abandoned, other agents cannot determine when the claimed feat/agents-md-foldin lane becomes available because the new register entry supplies a branch and scope but no TTL. Add the required expiry to prevent an indefinitely stale collision-avoidance claim.
AGENTS.md reference: AGENTS.md:L56-L58
Useful? React with 👍 / 👎.
| - `.claude/context/submodules.md` `### PMOVES-agents.md` section - the canonical doc for the submodule (updated with sibling table row) | ||
| - `pmoves/configs/submodule_skill_registry.json` `PMOVES-agents.md` entry - the context-tag injector map | ||
| - Root `AGENTS.md` - the file that follows the format spec at `PMOVES-agents.md/` | ||
| - PR1 of the fold-in: `agents_md_foldin_pr1_LEARNINGS.md` at `d4af79f325` - the skills fold-in LEARNINGS file |
There was a problem hiding this comment.
Correct the PR1 learnings filename
Readers following this PR1 handoff reference are directed to agents_md_foldin_pr1_LEARNINGS.md, but a repo-wide filename search finds only skills_foldin_pr1_LEARNINGS.md. Update the cross-reference to the tracked filename so the documented audit trail is navigable.
Useful? React with 👍 / 👎.
|
CI: the I am periodically re-running the failed jobs. Once the API recovers, the gate will turn green and this PR will be ready for admin-merge. No code changes needed on this side. |
…erence The PMOVES.AI root AGENTS.md file follows the agents.md open format (the universal contract for guiding coding agents - Claude Code, Codex, Copilot, Cursor, Aider, etc.). Today the canonical reference for that format lives in the PMOVES.AI root AGENTS.md itself plus a paragraph-level note there mentioning the upstream spec. This slice adds the full PMOVES fork of the agents.md repo (POWERFULMOVES/PMOVES-agents.md, tracking agentsmd/agents.md main) as a top-level submodule at PMOVES-agents.md/, making the format spec, the agent taxonomy, and the persona schema navigable from the PMOVES.AI monorepo without leaving for upstream. What lands in this commit: - .gitmodules: new [submodule "PMOVES-agents.md"] entry (url = https://github.com/POWERFULMOVES/PMOVES-agents.md.git, branch = main) - PMOVES-agents.md: new gitlink pointer at the upstream HEAD (d1ac7f063d20e70015ed6732664049ae4ba9d74e) Why top-level (not under skills/ like the skills constellation): the agents.md repo is a format/taxonomy reference, not a skill library. The skills/ tree is reserved for runtime-invokable agent skills (Pmoves-skills, claude-d3js, etc.). The agents.md reference is a Tier-2 always-relevant doc load, loaded by name when format/taxonomy/persona work touches the conversation. Out of scope (intentional, lives in other PRs of the fold-in): - PMOVES-skills (skills/PMOVES-skills) - already MERGED as PR1 (#2586). - The 3 MCP+CLI+Provider-Verifier repos - PR2. - The deprecated pre-recenter URL (POWERFULMOVES/Pmoves-Minimax-skills) - preserved as a reference in skills/README.md (PR1), not added as a separate submodule. - .claude/context/submodules.md table row + submodule_skill_registry.json entry - lives in the next commit (docs context + registry) to keep this commit purely a wire-up. - AGNOTE CLAIM row + the per-PR LEARNINGS file - lives in the third commit (docs AGNOTE + LEARNINGS). This is PR3 of a 3-PR fold-in (operator chose 3 separate PRs for easier revert). PR1=skills (MERGED #2586), PR2=MCP+CLI+Provider-Verifier, PR3=agents.md.
…ll registry Two small additions to make the new submodule discoverable in the context loaders and the skill-tag injector: - .claude/context/submodules.md: a one-row table added under the existing "### PMOVES-agents.md" subsection in the "Agent Format & Skills Constellation" section, mirroring the format of the skills/* table below it. The detailed bullet-list entry (Path, Repository, Upstream, Purpose, Tier, Cross-refs) was already in place from an earlier doc-updates pass; this PR adds the scannable table-form sibling so the section's two entries (PMOVES-agents.md and skills/* constellation) have parallel shape. - pmoves/configs/submodule_skill_registry.json: new entry for "PMOVES-agents.md" with context_tier=2 and domain_tags=["agents","docs"]. The $note field documents (a) the canonical home purpose, (b) the deliberate top-level placement (not under skills/, which is reserved for runtime-invokable agent skills, not format/taxonomy references), and (c) the Tier-2 always-relevant loading rule. Mirrors the shape of the skills/PMOVES-skills entry added by PR1. Verified: JSON parses with json.load; submodules.md table row matches the skills/* table format (3 columns: Submodule / Upstream / Purpose); no other files touched.
Two docs additions to close the PR: - pmoves/docs/AGENTS/AGNOTE4482PHI.t1.md: new CLAIM row (`Mavis::AGENTS-MD-FOLDIN::2026-08-17`) covering the 6-repo fold-in PR3 (agents.md). Scope = the 3 stacked commits + the acceptance criteria + the explicit out-of-scope (PR1's PMOVES-skills already MERGED #2586; PR2's MCP+CLI+Provider-Verifier repos in a parallel worktree) + the design decision (top-level placement, not under skills/, because the agents.md fork is a format/taxonomy reference, not a runtime-invokable skill) + the .gitmodules `branch = main` edit-after-add detail. Cross-references the per-PR LEARNINGS file. CHIT trail unsigned-local. - agents_md_foldin_pr3_LEARNINGS.md: the per-PR LEARNINGS file at the worktree root, mirroring the convention from skills_foldin_pr1_LEARNINGS.md. Captures 5 patterns: (2.1) `git submodule add` without `-b` doesn't set the `branch =` field in .gitmodules - edit after-add; (2.2) the `### PMOVES-agents.md` subsection in submodules.md was pre-existing in bullet form, so this PR adds a scannable table sibling (not a replacement); (2.3) the "Total submodules: 54" count line is a pre-existing stale count (actual is 58 post-PR3), out of scope to fix here; (2.4) the agents.md fork is a format/taxonomy reference, NOT a runtime skill - goes at repo root, not under skills/; (2.5) PR1's skills/PMOVES-skills is a distinct entry from this PR's PMOVES-agents.md - same domain tag overlap, different fork path, different upstream, no duplication. Both files are deterministic additions with no external dependencies. The LEARNINGS file is the persistent agent-readable record per the template at pmoves/docs/templates/PR_LEARNINGS.template.md. CRLF warning on the AGNOTE file is expected on Windows; the commit itself normalizes to LF via git's autocrlf machinery.
3fb661f to
a427a54
Compare
…mat vs our AGENTS.md The PMOVES-agents.md/ submodule landed via PR #2590 of the 6-repo fold-in as the canonical home of the agentsmd/agents.md open format. The submodule is a Next.js docs site (not a library) at https://agents.md/. This doc is the Mavis-side review: what the open format is, how our PMOVES.AI AGENTS.md compares, and what to adopt. The open format is deliberately minimal — three canonical sections ('Dev environment tips', 'Testing instructions', 'PR instructions'). Our PMOVES.AI AGENTS.md has 12 sections; 4 map to the open format and 8 are PMOVES extensions (Project Structure, Known Roads, env.shared, Compose layering, Coding Style, Secrets, Submodule Workflow, Deployment, Security, AGENTS.md Format Reference). Three adoption items, in priority order: 1. Rename 'Build & Development Commands' → 'Dev environment tips' to match the open format. A one-line content edit; high-signal conformance win. 2. Promote the 'AGENTS.md Format Reference' section to a top-of-file note that points at PMOVES-agents.md/ as the canonical spec home. Also a small edit; better cold-start ergonomics for any agent that knows the open format. 3. Document the 'PMOVES extensions' convention. The 8 PMOVES-specific sections don't have a name in the open format. Pick a marker (e.g. '### PMOVES extension: <name>') and apply it incrementally. All three adoption items are deliberately out of scope for this PR — they're content edits to AGENTS.md, not wire-up work. This doc documents them so the operator can land them in a follow-up. CHIT trail unsigned-local; AGNOTE entry to follow at slice close.
…mat vs our AGENTS.md The PMOVES-agents.md/ submodule landed via PR #2590 of the 6-repo fold-in as the canonical home of the agentsmd/agents.md open format. The submodule is a Next.js docs site (not a library) at https://agents.md/. This doc is the Mavis-side review: what the open format is, how our PMOVES.AI AGENTS.md compares, and what to adopt. The open format is deliberately minimal — three canonical sections ('Dev environment tips', 'Testing instructions', 'PR instructions'). Our PMOVES.AI AGENTS.md has 12 sections; 4 map to the open format and 8 are PMOVES extensions (Project Structure, Known Roads, env.shared, Compose layering, Coding Style, Secrets, Submodule Workflow, Deployment, Security, AGENTS.md Format Reference). Three adoption items, in priority order: 1. Rename 'Build & Development Commands' → 'Dev environment tips' to match the open format. A one-line content edit; high-signal conformance win. 2. Promote the 'AGENTS.md Format Reference' section to a top-of-file note that points at PMOVES-agents.md/ as the canonical spec home. Also a small edit; better cold-start ergonomics for any agent that knows the open format. 3. Document the 'PMOVES extensions' convention. The 8 PMOVES-specific sections don't have a name in the open format. Pick a marker (e.g. '### PMOVES extension: <name>') and apply it incrementally. All three adoption items are deliberately out of scope for this PR — they're content edits to AGENTS.md, not wire-up work. This doc documents them so the operator can land them in a follow-up. CHIT trail unsigned-local; AGNOTE entry to follow at slice close.
…CI (#2623) * feat(agent-registry): register PMOVES-MiniMax-MCP as the MiniMax model surface The MCP server is the model-side counterpart of the Mavis harness v0: WebUI/Agent-Zero call it directly via stdio; the sidecar lane (Pinokio on operator devices) calls the same surface via Pmoves-minimax-cli. Three surfaces updated to match the existing mcp_servers convention: - pmoves/config/agent_registry.yaml: pmoves_minimax_mcp entry under mcp_servers (status: active, transport: stdio, command: uvx). The harness v0 follow-ups registered the SKILL surface in pmoves/configs/submodule_skill_registry.json:770; this entry is the discovery-plane twin that lets rooms and rooms-tools find the server by name. - .claude/mcp.json: pmoves-minimax-mcp entry with command/args/env matching the submodule's pyproject.toml entry point (minimax_mcp.server:main). Env vars follow the demo config: API key + host + resource_mode. Pinned by reference, not by version (uvx resolves on demand). - .claude/BOOTSTRAP.md: new row in the MCP Entrypoints table so a cold-start agent sees the MiniMax model surface alongside cipher, docker, hostinger, tailscale. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * feat(cgp): add pmoves-minimax-mcp + minimax service block to bootstrap profile The 3 NEW model-cascade submodules (PMOVES-MiniMax-MCP, Pmoves-minimax-cli, Pmoves-MiniMax-Provider-Verifier) landed via PR #2589 of the 6-repo fold-in but the bootstrap CGP didn't reflect them. Consumer forks (PMOVES-hermes-agent, PMOVES-pinokio) read this profile at init and use the mcps + services blocks to wire their own tool surfaces. Two changes to example.cgp.yaml: - mcps: add pmoves-minimax-mcp so a consumer can stand up the model surface as one of its MCP servers without re-discovering the registry. - services: add a minimax: block that names the 3 submodules by their canonical paths and binds the sidecar lane to Pmoves-pinokio. This gives the operator a single place to point at when wiring the model cascade - the entry that was missing between the registry row and the runtime wire-up. The harness v0 follow-ups (PR #2568) consumed the new submodules from their hardcoded list; this commit makes the CGP profile a true source of truth, so when a future fork (e.g. a KiloCode sidecar or a NOT-YET-STOOD-UP Hermes-via-Pinokio bridge) loads the bootstrap it inherits the minimax surface for free. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(verifier): add PROVIDER_VERIFIER_GATE.md — how to run the conformance gate The Pmoves-MiniMax-Provider-Verifier submodule is registered in the submodule_skill_registry (PR #2589 of the 6-repo fold-in) but had no PMOVES-side doc telling an operator how to use it. The submodule's own README documents the verifier's internals; this doc is the Mavis side: thresholds, invocation, the three failure modes the gate is the only thing that catches (top-k drift, key re-sorting, error-only reasoning), and the CI follow-up that's deliberately out of scope for the wire-up PR. Audience: an operator adding a new MiniMax-compatible provider (Want to add openrouter-minimax? Follow the recipe in §1-3), a reviewer deciding whether to accept a new provider entry, and a future CI maintainer wiring the gate into python-tests.yml. The doc also captures the 'what this is NOT' section: not a load test, not a security test, not a model-quality test. The verifier checks *correctness vs the official baseline*, not throughput or adversarial robustness. That's the load-bearing distinction for any future PR that proposes 'just add a smoke test' as a substitute. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(cli): add MMX_CLI_SURFACE.md — catalog the mmx-cli surface The Pmoves-minimax-cli submodule (npm: mmx-cli, v1.0.19) is the sidecar lane's entry point: Pinokio apps on operator devices, headless scripts, CI jobs. The submodule's own AGENTS.md/SDK.md/ERRORS.md are developer-facing (build rules, programmatic API, full error catalog); this doc is the Mavis-side summary for an operator who needs to know what the CLI can do and when to use it instead of the MCP. Three sections do the load-bearing work: - Command tree (auth, config, file, image, music, quota, search, speech, text, video, vision, help, update) with a one-line purpose + invocation example per command. - SDK surface showing the programmatic entry point (import { MiniMaxSDK } from 'mmx-cli/sdk') for the four core modalities: text, image, video, with the H3 V2 model and the async taskId path for video. - The five errors you'll hit most often, distilled from the 70+ error scenarios in ERRORS.md. The doc points to ERRORS.md for the full taxonomy and notes that scripts should match on the error code, not the message. The closing section 'Why not always call the MCP?' captures the splittest that the sidecar lane has to make: MCP for tool-aware agents, CLI for everything else. The MCP and CLI cover the same model surface; the split is *who's calling*, not *what's being called*. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(skills): add PMOVES_SKILLS_REVIEW.md — review the find-skills meta-skill The skills/PMOVES-skills/ submodule landed via PR #2586 of the 6-repo fold-in as the post-recenter home of the open-skills-ecosystem library (was MiniMax-AI/skills, now vercel-labs/skills). The submodule ships one bundled skill: find-skills, a meta-skill that helps an agent decide 'is there a skill for X?' via the npx skills CLI. This doc is the Mavis-side review: what the submodule brings, what's worth pulling into our catalog, what's worth leaving alone. Three findings: 1. The find-skills skill itself should land in pmoves/configs/skill-pairings.yaml so BoTZ pipelines can surface it to agents on the sidecar lane. One-line addition; documented as a proposed delta in the doc body. 2. The skills CLI should land in pmoves/configs/cli_tools.yaml host_clis so the doctor (make -C pmoves cli-check) validates it alongside the other host CLIs. Also a one-line addition. 3. The PMOVES-specific default --owner POWERFULMOVES should be encoded in the PMOVES-side wrapper, not in the upstream SKILL.md (we don't own it; editing it would create fork drift). Documented here as a behavioral default. The 'leave alone' section makes the recenter discipline explicit: no upstream edits, no PMOVES-MiniMax-skills as a separate submodule, no submodule-level patches. If we need fork-specific behavior, it goes in pmoves/tools/, not in the submodule. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(agents-md): add AGENTS_MD_FORMAT_REVIEW.md — review the open format vs our AGENTS.md The PMOVES-agents.md/ submodule landed via PR #2590 of the 6-repo fold-in as the canonical home of the agentsmd/agents.md open format. The submodule is a Next.js docs site (not a library) at https://agents.md/. This doc is the Mavis-side review: what the open format is, how our PMOVES.AI AGENTS.md compares, and what to adopt. The open format is deliberately minimal — three canonical sections ('Dev environment tips', 'Testing instructions', 'PR instructions'). Our PMOVES.AI AGENTS.md has 12 sections; 4 map to the open format and 8 are PMOVES extensions (Project Structure, Known Roads, env.shared, Compose layering, Coding Style, Secrets, Submodule Workflow, Deployment, Security, AGENTS.md Format Reference). Three adoption items, in priority order: 1. Rename 'Build & Development Commands' → 'Dev environment tips' to match the open format. A one-line content edit; high-signal conformance win. 2. Promote the 'AGENTS.md Format Reference' section to a top-of-file note that points at PMOVES-agents.md/ as the canonical spec home. Also a small edit; better cold-start ergonomics for any agent that knows the open format. 3. Document the 'PMOVES extensions' convention. The 8 PMOVES-specific sections don't have a name in the open format. Pick a marker (e.g. '### PMOVES extension: <name>') and apply it incrementally. All three adoption items are deliberately out of scope for this PR — they're content edits to AGENTS.md, not wire-up work. This doc documents them so the operator can land them in a follow-up. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(cipher): store cipher skill context — what's encrypted, where, CHIT custody Cipher is the PMOVES memory layer; the Mavis-class agent re-reads prior plans on cold start and writes on every BPM phase boundary. The operator's request to 'store cipher context' was about capturing the load-bearing facts in one place, not about adding new code. This doc covers four sections that the rest of PMOVES already references but doesn't pull together: - What cipher is for: persistent agent memory + reasoning trace storage + CHIT custody chain. Three distinct things, one MCP server. - What's encrypted: the memory body (HMAC-SHA256 + AES-256-GCM) via CHIT passphrase. The memory index (titles, timestamps, category) is plaintext so the MCP server can answer searches without decrypting every record. - Where the keys live: \ per-node in env.shared, the host-side and container-side names are the same after the sync-secrets-local.yml fix in PR #2605. HMAC kid public, HMAC secret derived at signing time, never written to disk. - NATS custody chain: cipher publishes three subjects (cipher.memory.stored.v1, cipher.memory.searched.v1, cipher.reasoning.stored.v1) to monitoring. The CHIT signing flow is sign-trail → cipher write → chit.signed.v1 publish, and the HMAC signature is the trust anchor for the AGNOTE append-only chain. The closing 'How a Mavis-class agent should use it' section codifies the three patterns (read on cold start, write on phase boundaries, sign before state-changing actions) so a future Mavis session has the recipe in one place. The 'What cipher is NOT' section captures the boundary: not a search engine, not a database, not a KV store, not a real-time channel. Each of these has its own PMOVES subsystem; cipher is the memory. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(hirag): store HiRAG context — submodule state, what's wired, what's pending HiRAG is PMOVES's hybrid retrieval layer (vector + graph + full-text). The operator's request to 'store HiRAG context' was about capturing the surface in one place, not adding new code. The agent registry already declares the MCP server (pmoves_hirag_mcp, status: 'planned', grounding_source: true) but the doc that explains what that entry means, and what an agent should do with it, didn't exist. This doc covers the four sections the rest of PMOVES already references but doesn't pull together: - What HiRAG is: three-way retrieval (Qdrant vector + Neo4j graph + MeiliSearch full-text) merged at the gateway. The legacy and v2 gateways are the two HTTP surfaces; the MCP server is the discovery-friendly entry point. - What's wired: registry entry, compose services (CPU + GPU variants on the legacy profile), smoke test path. Three concrete facts a future Mavis session can use without re-discovering the surface. - What's pending: .claude/mcp.json registration (the registry has the entry; mcp.json doesn't have the server), v2 gateway promotion (v2 is documented as 'preferred' but legacy is what's deployed), submodule freshness check (the algorithm substrate tracks PMOVES.AI-Edition-Hardened, not main, and a drift could land silently). - How a Mavis-class agent should use it: read on cold start for grounding (the registry's grounding_source: true flag is a recipe, not a label), issue hybrid queries for cross-cutting context, fall back to scoped search for narrow questions. The 'What HiRAG is NOT' section captures the boundary: not a primary database, not a real-time index, not a replacement for cipher, not a search engine. Each of these has its own PMOVES subsystem; HiRAG is the hybrid read. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * feat(registry): wire find-skills meta-skill into cli_tools + skill-pairings The skills/PMOVES-skills/ submodule (vercel-labs/skills recenter, PR #2586) ships a find-skills meta-skill that helps an agent decide 'is there a skill for X?' via the npx skills CLI. The CRUSH lane (PR #2599) already wired the mmx-cli and the pmoves Wrappers; this commit lands the two remaining entries that the PMOVES_SKILLS_REVIEW.md review flagged as 'proposed deltas' for the find-skills meta-skill. Two entries in two manifests: - pmoves/configs/cli_tools.yaml: new host_clis entry skills: backing the npx skills CLI. The doctor (make -C pmoves cli-check) now validates the npx skills --version invocation alongside gh, docker, make, uv, glances. required: false (find-skills is a convenience, not a hard requirement). - pmoves/configs/skill-pairings.yaml: two new skill_sources entries - cli-host-skills (matching the cli-host-* naming pattern) and ind-skills (the path to the SKILL.md). The second makes the meta-skill discoverable to BoTZ pipelines that consume the skill_sources block. The PMOVES-side behavioral default '--owner POWERFULMOVES first, then unfiltered' stays in PMOVES_SKILLS_REVIEW.md, NOT in the upstream SKILL.md - editing the upstream would create fork drift. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * test(wireup): add 13 drift-detector tests for the model-cascade wire-up The mcpcli-wireup slice added entries to 5 surfaces: - pmoves/config/agent_registry.yaml (mcp_servers.pmoves_minimax_mcp) - .claude/mcp.json (mcpServers.pmoves-minimax-mcp) - .claude/BOOTSTRAP.md (MCP Entrypoints table) - pmoves/contracts/schemas/pmoves-bootstrap/example.cgp.yaml - pmoves/configs/cli_tools.yaml (host_clis.skills) - pmoves/configs/skill-pairings.yaml (find-skills + cli-host-skills) If any of these entries is removed in a future PR, the harness v0 loses the model surface silently. This test suite parses the actual files (no mocks, no fixtures that would mask drift) and asserts the load-bearing facts of each wire-up entry are present. 13 tests in 5 groups: - agent_registry (3): key, submodule pointer, capabilities - mcp.json (2): key, command + args - bootstrap_md (1): substring presence - example_cgp (2): mcps list, services.minimax block with mcp/cli/verifier - cli_tools (2): host_clis.skills, check command - skill_pairings (3): find-skills key + path, cli-host-skills key The test names name the wire-up explicitly (test_*_minimax_mcp, test_*_find_skills, etc.) so a future rewire has to be intentional: if you rename 'pmoves_minimax_mcp' to 'pmoves_model_mcp', the test fails and the commit message has to address why. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * agnote: CLAIM+RELEASE the mcpcli-wireup slice (Mavis::MCPCLI-WIREUP-CLAIM-RELEASE) The mcpcli-wireup slice is closed. 11 commits land across 5 surfaces: agent_registry, .claude/mcp.json, BOOTSTRAP.md, the CGP bootstrap profile, and the docs/ + context/ trees. 4 review docs, 4 context docs, 1 test file (13 tests, all green), 1 AGNOTE entry. The 3 NEW model-cascade submodules (PMOVES-MiniMax-MCP, Pmoves-minimax-cli, Pmoves-MiniMax-Provider-Verifier) from PR #2589 of the 6-repo fold-in are now wired into the harness v0 end-to-end. CLAIM+RELEASE row appended per the append-only discipline. The GRAGHITI_MARK trailer (Mavis::MCPCLI-WIREUP-CLAIM-RELEASE::2026-08-18) is the next agent's trust anchor. CHIT trail unsigned-local. AGNOTE-style trail; sign-trail is the operator-step (B850 has the trail-signed lane). LEARNINGS file follows in the next commit. * learnings: add mcpcli_wireup_LEARNINGS.md — capture the 5 patterns from this slice 5 patterns captured in §2: 2.1 Why docs, not a new CLI — the operator's 'no need to hand roll' rule. When the tool is already installed and the operator said 'don't hand-roll', the PMOVES-side work is wire-up + docs, not new code. New code is the trap. 2.2 The 5-surface wire-up pattern — when an MCP server enters the harness, it gets registered in 5 places: agent_registry mcp_servers, .claude/mcp.json, BOOTSTRAP.md, the CGP mcps list, and the CGP services block. Skipping any one leaves a gap that will bite later. 2.3 The transport field is not 'always SSE' — the stdio entries use command + args + env instead of endpoint. The schema accepts both shapes via additionalProperties: true. 2.4 'Grounding source' is a recipe, not a label — the flag tells the discovery plane to fetch startup grounding from the server on cold start. Set it for memory/retrieval/model surfaces; skip it for tools used during a task. 2.5 The drift detector pattern — wire-up work is best tested by parsing the files and asserting presence/shape, not by running the resulting system. The unit test names name the wire-up so a future rename is explicit. Cross-refs in §4 point at every file this slice touched, plus the related PRs (2586, 2589, 2590, 2568, 2599) and the operator (three-body delivery=Mavis, control=DARKXSIDE, memory=this trail). CHIT trail unsigned-local. * fix(cgp): add minimax to v1.schema.json services whitelist The CI caught what local YAML validation missed: the pmoves-bootstrap v1 schema enforces additionalProperties:false on the top-level services object (to catch typo'd service names like 'tnailscale'). My example.cgp.yaml adds a minimax: block to services.minimax, which the schema rejected with 'Additional properties are not allowed (minimax was unexpected)'. Failing tests (pmoves/tools/tests/test_load_bootstrap.py + test_orchestrator.py): 20+ tests, all cascading from the same root cause. Fix: add minimax to schema.services.properties with the same additionalProperties:true / typed-string properties pattern as tailscale / rustdesk / hostinger / cloudflare. The block names the 4 submodule paths (mcp, cli, verifier, pinokio) so a future typo in the path string is caught at the schema level rather than silently passing through. All 36 tests in test_load_bootstrap.py + test_orchestrator.py pass after the fix; 13/13 drift-detector tests in test_mcpcli_wireup.py also still pass. CHIT trail unsigned-local; this is a fix-up commit in the 3-stacked group. * fix(mcp): pin minimax-mcp to the audited submodule version `uvx minimax-mcp` with no version resolves the latest PyPI release at every cold start, in the one file whose line 2 declares: "Dependencies pinned to exact versions on 2026-05-14 to prevent supply chain attacks (F-07). Re-pin after auditing new releases before upgrading." Every other server in the file follows that (hostinger-api-mcp@0.2.1, tailscale-mcp@2026.4.10-1, postgres-mcp@0.3.0, ...). This entry did not, while its own _purpose names an audited submodule commit it never actually invoked. The pin is unambiguous rather than a guess: the gitlink on this branch is f4d6a61b, and that commit's pyproject.toml declares version 0.0.18 -- the same as the current PyPI latest. So pinning changes nothing today and prevents the next release from arriving unreviewed. minimax-mcp is a 0.0.x package (18 releases), so "latest" carries no API-stability promise either. Also extended the file's own inventory note so the pin is recorded where the policy is stated, not only at the call site. Out of scope, reported not fixed: `huggingface` -> `@llmindset/hf-mcp-server` is also unpinned. Pre-existing, unrelated to this lane. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(mcpcli): assert the minimax pin, not just the package name The pin in the previous commit broke this PR's own test, which asserted `"minimax-mcp" in args` — true only for the bare, unpinned form. Tightened rather than relaxed: it now requires a `minimax-mcp==<version>` entry, so the exact-version policy declared on line 2 of .claude/mcp.json is enforced by a test instead of by convention. A future edit that drops back to the bare package name fails here. 13 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(rooms): point pmoves_minimax_mcp at real rooms (not a fabricated one) The pmoves_minimax_mcp entry I added in commit e6621fe included rooms: ['minimax-mcp.room.model', 'hermes-agent.room.control']. The first one is a made-up name — no such room exists in pmoves/config/rooms/. The 4090 hit this when trying to bind: 'binding leads nowhere' = the catalog has no minimax-mcp.room.model to bind to. Existing MCPs reference the rooms where they're actually consumed: - cipher → z890-infra.room.fabric - nats → z890-infra.room.fabric, hermes-agent.room.control - voice → 5090-voice.room.studio - e2b → 4090-field.room.control, hermes-agent.room.control The minimax MCP is consumed by: - z890-infra.room.fabric — Mavis's runtime home (matches cipher/nats) - hermes-agent.room.control — Hermes consumer (matches e2b/hirag) - darkxsides.room — the DARKXSIDE persona, which calls Mavis Replaced 'minimax-mcp.room.model' with the real 3-room list. No schema change needed (rooms is a free-form string array). 13/13 drift-detector tests + 24/24 bootstrap tests still pass. CHIT trail unsigned-local; this is a fix-up commit in the 3-stacked group for #2612, blocking 4090's admin-merge. * feat(gate): add pmoves/tools/provider_verifier_gate.py — the static CI gate The Pmoves-MiniMax-Provider-Verifier submodule is the conformance gate for adding a new provider to the Mavis model cascade, but it REQUIRES real API calls (--api-key, --base-url, --model). A literal 'run verify.py on every PR' gate would need the verifier's secrets in GitHub Actions, which the F-07 supply-chain note explicitly forbids. This module is the static half of the gate. 6 checks, no API calls: 1. verifier_submodule_present — the submodule is initialized 2. provider_config_well_formed — provider.json.example parses as a JSON array 3. provider_entries_have_required_fields — every entry has the 4 required fields (name, model, base_url, api_key) 4. example_keys_are_placeholders — no real API key accidentally committed to the example file (the gate that catches a secret leak at PR time, not audit time) 5. sample_jsonl_present — sample.jsonl is non-empty (required positional arg for verify.py) 6. verifier_entry_point_importable — verify.py parses cleanly (compile() without executing; full import lives in the operator's manual dispatch because it pulls validator/ deps) Exit codes: 0 = PASS, 1 = FAIL, 2 = unexpected error. JSON output via --json for CI consumption; human-readable by default. The operator's full conformance run is workflow_dispatch (next commit). Live: all 6 checks pass on the current submodule state. * test(gate): add 22 tests for provider_verifier_gate (6 checks + aggregate + CLI) The 6 static checks each get a pass + fail test (15 tests). The aggregate run_gate gets pass + fail + to-dict tests (3 tests). The CLI main() gets pass + fail exit code tests (2 tests). The fixture_verifier_dir fixture creates a tmp_path with a valid provider.json, sample.jsonl, and a stub verify.py (parseable, not the real one) so tests don't depend on the submodule's heavy deps. Notable coverage: - The 'real key detected' test puts a 26-char sk- key into the fixture and asserts the check fails with 'Real API key' in the detail. This is the load-bearing test for the secret-leak gate. - The 'syntax error' test writes a broken verify.py and asserts the check fails with 'syntax error' in the detail. Catches the case where a refactor introduces a SyntaxError that wouldn't surface until the operator's manual run. - The 'wrong type' test (provider.json is a dict, not a list) and the 'not a dict' test (an entry is a string) catch the two shapes of malformed config the static check needs to handle. - The 'verify_submodule_missing' test points at a non-existent path and asserts the actionable 'git submodule update' detail. - The CLI tests exercise the exit codes (0 vs 1) and the --json flag, which is what the CI workflow will consume. 22/22 pass. CHIT trail unsigned-local. * feat(ci): add .github/workflows/provider-verifier.yml — the static gate The MiniMax-Provider-Verifier is the conformance gate for adding a new provider to the Mavis model cascade. It REQUIRES real API calls (--api-key, --base-url, --model) so it cannot run in CI without exposing secrets. This workflow runs the static half (pmoves/tools/provider_verifier_gate.py) on every PR that touches the relevant paths. 6 checks, no API calls, JSON output consumed by the step summary + a PR comment on FAIL. The status check name is verifier-gate; merge-gate.yml references it (so a FAIL blocks merge). workflow_dispatch is the operator's full-conformance path: the gate runs the static checks + the operator runs verify.py locally with the API keys. Workflow structure (lesson #12/13 from the post-merge fix — the test file lives separately so a future edit doesn't silently break the gate): triggers: - pull_request to main on Pmoves-MiniMax-Provider-Verifier/**, pmoves/tools/provider_verifier_gate.py, the test file, and the workflow file itself - workflow_dispatch for manual full-conformance runs permissions: {} # minimal; no scopes the job doesn't need concurrency: # one concurrent run per ref; cancel on # re-runs of the same PR (matches existing # branch-protection-drift.yml pattern) steps: 1. actions/checkout@<SHA> with submodules: recursive (so Pmoves-MiniMax-Provider-Verifier/ is on disk) 2. actions/setup-python@<SHA> Python 3.12 (matches the verifier's pyproject.toml requires-python) 3. Best-effort install of the verifier's runtime deps (numpy, openai, megfile). The static gate doesn't need them; the full dispatch path does. 4. Run the static gate, capture the JSON output, write to GITHUB_STEP_SUMMARY, exit 0/1 on PASS/FAIL. 5. On FAIL, post a PR comment with the common-cause list (per the comments pattern in codeql.yml / claude.yml). The shell pipeline uses \set +e ... ; RC=\True ... set -e\ because the gate's \py ... --json\ exits 1 on FAIL and we need to capture BOTH the output and the exit code. This is the same pattern as the post-merge fix in PR #2569 (lesson #13: \set -e\ without \pipefail\ masks publisher failures). CHIT trail unsigned-local. * refactor(gate): take verifier_submodule as a parameter, not a module global The 6 check functions used module-level globals (VERIFIER_SUBMODULE, PROVIDER_CONFIG, etc.) resolved at import time. The first test pass wrote the helper to work against the live submodule; the test run then mutated gate.VERIFIER_SUBMODULE between tests, but the check functions kept reading the cached paths from the global — so tests for missing-syntax, missing-config, etc. read the LIVE files, not the fixture files. 15/22 tests failed for that reason. Refactor: each check function now takes verifier_submodule: Path as an explicit parameter. run_gate() resolves the path (default to the live submodule) and passes it through. Tests pass a tmp_path fixture; the CLI takes --verifier-submodule as a flag. The helper's behavior is unchanged on the live submodule. Also adds 15 workflow-glue tests in pmoves/tests/test_provider_verifier_workflow.py (lesson #12/13 from PR #2569 — workflow YAML needs code review, not just unit tests; these tests parse the YAML and assert on the patterns that bind the workflow to the helper's contract: trigger block, permissions, concurrency, job name, pinned checkout, submodules: recursive, --json flag, exit code capture + propagation, py alias). 15/15 pass. CHIT trail unsigned-local. * docs(verifier): update PROVIDER_VERIFIER_GATE.md — Gate in CI is now wired The previous version of this doc said 'not yet wired — see Follow-up below'. This slice wires it: the static half runs on every PR via .github/workflows/provider-verifier.yml; the full conformance run is the operator's manual step (where the API keys live in env.shared, not in a workflow file). The updated 'Gate in CI' section has two subsections: - 'The static half' (PR-time, no API calls): the 6 checks table + the workflow's behavior on FAIL + the load-bearing status check name (verifier-gate, which merge-gate.yml consumes) - 'The full conformance run' (operator's manual step): the exact command + why verify.py can't run in CI (F-07 supply chain forbids exposing the API keys) + the workflow_dispatch trigger is wired for a future 'CI-issued conformance report' mode that the operator hasn't enabled yet The doc now reflects the current state: the static gate is the PR-time check, the full run is the operator's local step, and the two-piece design is intentional (not a TODO). CHIT trail unsigned-local. * feat(merge-gate): wire verifier-gate into the merge-decision + skipped-aware The provider-verifier.yml workflow's job name is 'verifier-gate'. For a FAIL on that gate to block merge, the merge-decision step in merge-gate.yml must (a) include 'verifier-gate' in its needs list, and (b) treat the workflow's result correctly. Two changes to merge-gate.yml: 1. Add 'verifier-gate' to the merge-decision needs list, and to the failure-check conditional. Now a FAIL on the gate blocks merge, like the other 3 hard gates. 2. Treat 'skipped' as a pass, not a failure. The provider-verifier workflow has a paths: filter; a PR that doesn't touch the relevant paths runs the workflow as 'skipped' (not 'success' or 'failure'). A naive 'skipped == failure' check would block every PR that doesn't touch the verifier — a regression. The merge-decision only treats 'failure' as blocking; 'skipped' and 'success' both pass. A comment in the workflow explains the skipped = pass design so the next person who reads the conditional doesn't 'fix' it back to the naive interpretation. Also adds 2 cross-workflow tests in pmoves/tests/test_provider_verifier_workflow.py (the existing file already covers the provider-verifier.yml contract; this extends it to the cross-workflow binding): - test_merge_gate_references_verifier_gate: asserts the merge-gate workflow's text mentions 'verifier-gate' (the load-bearing reference for the gate to actually block merge) - test_merge_gate_handles_verifier_gate_skipped: asserts the merge-decision does NOT treat 'skipped' as failure (catches the naive 'if result == skipped block' anti-pattern that would regress every PR that doesn't touch the verifier) 15 -> 17 tests; all 17 pass. CHIT trail unsigned-local. * fix(workflow): add issues:write to static-gate job for the PR-comment step The PR-comment step uses actions/github-script, which needs the default GITHUB_TOKEN scope to call issues.createComment. With workflow-level 'permissions: {}' the token has no scopes, so the step would fail with a 403 permissions error. Fix: add a job-level permissions override on the static-gate job: 'issues: write'. The workflow-level {} remains for the other steps; the override is the minimum scope that lets the comment step post. Test: test_workflow_job_has_issues_write_for_comment_step asserts the job-level permissions.issues is 'write'. Catches the case where a future edit removes the override (or moves the comment step without adjusting the permissions). 17 -> 18 tests; all 18 pass. CHIT trail unsigned-local. * agnote: CLAIM+RELEASE the provider-verifier-ci-gate slice The CI gate for the MiniMax-Provider-Verifier is now wired: the static half runs on every PR via .github/workflows/provider-verifier.yml; the full conformance run is the operator's manual step. merge-gate.yml treats verifier-gate as a hard gate (with the paths-filter 'skipped' edge case handled so non-touched PRs still merge). 7+ commits in the 3-stacked group (functional / docs / fix-up): 1. gate helper 2-4. tests (22 unit + 15 workflow + 1 refactor that takes the submodule as a parameter so tests don't depend on global state) 5. doc update 6. merge-gate wire-up 7. permissions fix (issues:write at the job level so the PR-comment step has the scope it needs) The CLAIM row + GRAPHITI_MARK trailer (Mavis::PROVIDER-VERIFIER-CI- GATE-CLAIM-RELEASE::2026-08-19) appended per the append-only discipline. The next agent's trust anchor. CHIT trail unsigned-local. LEARNINGS file follows in the next commit. * learnings: add provider_verifier_ci_gate_LEARNINGS.md — capture the 5 patterns from this slice 5 patterns captured in §2: 2.1 Two-piece gate — why not a single CI workflow that runs verify.py. The verifier needs real API calls; the F-07 supply-chain note forbids exposing the keys in a workflow file. The gate is the static half (PR-time, no API calls, catches the cheap failures) + the full half (operator's manual step on the local node, where env.shared holds the keys). 2.2 Workflow permissions: workflow-level {} + job-level issues: write. The PR-comment step needs issues: write; the static check needs no scopes. Job-level override is the minimum scope that lets the comment step post. 2.3 The skipped == failure regression — paths-filter workflows don't always run. A naive merge-decision that treats skipped as failure blocks every non-touched PR. The test asserts the absence of the naive check so a future 'fix' doesn't regress. 2.4 Test the binding, not just the parts (lesson #12/13 from PR #2569). 15 workflow-glue tests assert the patterns that bind the workflow to the helper's contract: trigger block, paths filter, permissions, concurrency, job name, pinned checkout, --json flag, RC=\True exit code capture + propagation, py alias. 2.5 Helper refactor: parameter, not module global. The first version used module-level globals resolved at import time; tests that mutated the global kept reading the cached paths, so 15/22 tests failed for that reason. The fix: each check function takes verifier_submodule: Path as a parameter. The helper's behavior on the live submodule is unchanged. Cross-refs in §4 point at every file this slice touched, plus the related PRs (2586, 2589, 2590, 2568, 2569, 2612) and the operator (three-body delivery=Mavis, control=DARKXSIDE, memory=this trail). CHIT trail unsigned-local. * docs(bootstrap): add provider-verifier to the Known Roads table A cold-start agent that doesn't know about the gate would skip it on a PR that touches the verifier submodule. The Known Roads table in BOOTSTRAP.md is the cold-start discoverability surface; the verifier is a row alongside secrets-funnel, health-summary, fleet-status, sign-trail, and docs-reconcile. Two rows added: - 'Run the provider-verifier static gate' — the PR-time check (no API calls, 6 checks, FAIL blocks merge via merge-gate). This is the entry a Mavis-class agent should reach for when asked 'does the new provider config look right?' - 'Run the provider-verifier full conformance' — the operator's manual step. The entry is operator-only (requires real API keys from env.shared) and explicit about that constraint, so a future cold-start agent doesn't try to invoke it. The two rows together reflect the two-piece design from PROVIDER_VERIFIER_GATE.md and the LEARNINGS file (2.1): the static half on every PR + the full half on the operator's local node. The Known Roads pattern (one canonical command per need) is the same as the existing rows. CHIT trail unsigned-local. * test(install): pin the operator's full-conformance run path The static half of the gate runs in CI; the full half is the operator's manual step. Two surfaces describe the manual step: pmoves/docs/operations/PROVIDER_VERIFIER_GATE.md and BOOTSTRAP.md. If a future refactor changes the operator's command, the doc drifts from reality and the operator hits a 'command not found'. 6 tests pin the contract: - test_verifier_help_lists_required_flags: invokes 'py verify.py --help' and asserts the 4 load-bearing flags (--providers, --output-dir, --model, --base-url) are listed. Skips cleanly if verify.py can't import (the operator's local env needs the verifier's runtime deps). - test_requirements_txt_has_runtime_deps: asserts the 6 runtime deps (jsonschema, loguru, megfile, numpy, openai, tqdm) are in requirements.txt. The operator's install is 'pip install -r requirements.txt'; if a dep is dropped from there, the operator's install silently fails. - test_pyproject_python_version_requirement: parses the pyproject.toml's requires-python and asserts it's >= 3.12. The CI workflow's python-version: '3.12' setup-python step must be at least as new; this test catches a future bump that drops the floor. - test_gate_doc_has_full_run_section: asserts the gate doc has a 'Gate in CI' section + mentions 'full conformance'. The exact section name is the contract. - test_bootstrap_md_has_provider_verifier_rows: asserts the BOOTSTRAP Known Roads table mentions both 'provider-verifier' and the helper path. Cold-start discoverability. - test_bootstrap_and_gate_doc_agree_on_invoke: asserts both surfaces invoke the helper via the exact same path ('py pmoves/tools/provider_verifier_gate.py'). Catches drift between the two discoverability surfaces. 5/6 pass (1 skip when verify.py can't import — graceful fallback). CHIT trail unsigned-local. * fix(ci): repair three defects that would have blocked every PR in the repo Three review findings, all confirmed against source. The first two are repo-wide blockers. 1. merge-decision listed `verifier-gate` in `needs`, but `needs` resolves only job IDs in the SAME workflow -- verifier-gate is the display NAME of the `static-gate` job in provider-verifier.yml. Verified by parsing the file: jobs defined : merge-gate, python-tests, docker-build-validation, hardening-validation, action-pin-validation, merge-decision needs : ..., verifier-gate undefined : ['verifier-gate'] An unresolvable `needs` makes the workflow invalid, so `merge-decision` -- a REQUIRED status check on main -- never reports, and every PR in the repo sits blocked on a check that cannot run. Reverted merge-gate.yml to main's version: the four in-workflow jobs, no cross-workflow reference. To actually gate on the verifier, add its check to branch protection's required list. That is an operator action and cannot be expressed through `needs`. Left undone rather than faked. 2. The static gate ran `py pmoves/tools/provider_verifier_gate.py` on runs-on: ubuntu-latest. `py` is the Windows launcher; setup-python exposes the interpreter as `python` (the pip step directly above already uses it). It would exit 127, set verdict=FAIL, and block every PR matching the path filter without running a single check -- a gate that fails closed for the wrong reason is still a gate nobody can pass. 3. check_example_keys_are_placeholders used `if key and key != PLACEHOLDER`, so a falsy value skipped the comparison entirely. An empty api_key passed this check while the required-fields check passed on mere presence, so the aggregate could report PASS on an example violating its own stated invariant. Now compares against the placeholder directly, with a distinct message for the empty case. Verified: correct placeholder passed=True EMPTY string passed=False null passed=False missing key passed=False real-looking key passed=False Rebase note: .claude/mcp.json conflicted because this branch carries the minimax pin from #2612 while main gained the hostinger fork correction from #2615. Both are correct and independent, so the inventory line is the UNION of the two, not a pick. Re-validated as JSON. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(ci): two more fabricated pins — caught by the gate #2622 just landed The action-pin gate merged in #2622 failed this PR on its first run, on the workflow this PR adds: [ERROR] provider-verifier.yml:72 actions/setup-python@65d7f1bbcb94 no such commit [ERROR] provider-verifier.yml:114 actions/github-script@ed9884d31165 no such commit and verifier-gate itself died at "Getting action download info" for the same reason, before any step ran -- the exact mechanism #2622 documented, now reproduced on a third workflow. Repinned to the SHAs the rest of the repo already uses, both verified to resolve: setup-python 5fda3b95a4ea... # v7.0.0 github-script 3a2844b7e9c4... # v9.0.0 One correction worth recording, because it nearly went the wrong way. I first read `git/ref/tags/v9.0.0` as `d746ffe35508` and concluded the repo's existing `3a2844b7` pin was inaccurate. It is not: v9.0.0 is an ANNOTATED tag, so that ref returns the tag OBJECT, which dereferences via git/tags/<sha> to commit 3a2844b7. Comparing a tag-object SHA against a commit SHA reports a mismatch that does not exist. Anything auditing pins has to dereference; action_pin_audit already does, which is why it reported 0 version-comment warnings on a clean tree. action_pin_audit now passes: 230 pins across 60 workflows, exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(provider-verifier): the tests asserted the defects, so fix them too The ratchet flagged 4 new failures after the previous commit. Three were tests asserting the behaviour that was just fixed -- they were written to match the implementation rather than the requirement, so they passed while holding the defects in place. A test that locks in a bug is worse than no test: it makes the fix look like the regression. test_merge_gate_references_verifier_gate asserted merge-gate.yml MUST name verifier-gate -- the cross-workflow `needs` that invalidates the workflow and takes the required merge-decision check down with it. Inverted: it must NOT. test_merge_gate_handles_verifier_gate_skipped asserted the skipped-as-pass branch for a job that is no longer a dependency. Replaced with a check that merge-decision requires == "success" rather than merely rejecting "failure" (#2622). test_workflow_uses_py_alias_for_python asserted `py`, justified as "the GitHub-bundled alias" that "the other workflows in this repo use". Both halves are false, measured across .github/workflows/: ZERO workflows invoke bare `py`; 27 use python/python3. Inverted, and the docstring now carries the measurement. test_verifier_help_lists_required_flags shelled out to `py` directly. Now sys.executable. 21 passed, 3 skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Mavis <Mavis@pmoves.local> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…to the harness v0 (#2612) * feat(agent-registry): register PMOVES-MiniMax-MCP as the MiniMax model surface The MCP server is the model-side counterpart of the Mavis harness v0: WebUI/Agent-Zero call it directly via stdio; the sidecar lane (Pinokio on operator devices) calls the same surface via Pmoves-minimax-cli. Three surfaces updated to match the existing mcp_servers convention: - pmoves/config/agent_registry.yaml: pmoves_minimax_mcp entry under mcp_servers (status: active, transport: stdio, command: uvx). The harness v0 follow-ups registered the SKILL surface in pmoves/configs/submodule_skill_registry.json:770; this entry is the discovery-plane twin that lets rooms and rooms-tools find the server by name. - .claude/mcp.json: pmoves-minimax-mcp entry with command/args/env matching the submodule's pyproject.toml entry point (minimax_mcp.server:main). Env vars follow the demo config: API key + host + resource_mode. Pinned by reference, not by version (uvx resolves on demand). - .claude/BOOTSTRAP.md: new row in the MCP Entrypoints table so a cold-start agent sees the MiniMax model surface alongside cipher, docker, hostinger, tailscale. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * feat(cgp): add pmoves-minimax-mcp + minimax service block to bootstrap profile The 3 NEW model-cascade submodules (PMOVES-MiniMax-MCP, Pmoves-minimax-cli, Pmoves-MiniMax-Provider-Verifier) landed via PR #2589 of the 6-repo fold-in but the bootstrap CGP didn't reflect them. Consumer forks (PMOVES-hermes-agent, PMOVES-pinokio) read this profile at init and use the mcps + services blocks to wire their own tool surfaces. Two changes to example.cgp.yaml: - mcps: add pmoves-minimax-mcp so a consumer can stand up the model surface as one of its MCP servers without re-discovering the registry. - services: add a minimax: block that names the 3 submodules by their canonical paths and binds the sidecar lane to Pmoves-pinokio. This gives the operator a single place to point at when wiring the model cascade - the entry that was missing between the registry row and the runtime wire-up. The harness v0 follow-ups (PR #2568) consumed the new submodules from their hardcoded list; this commit makes the CGP profile a true source of truth, so when a future fork (e.g. a KiloCode sidecar or a NOT-YET-STOOD-UP Hermes-via-Pinokio bridge) loads the bootstrap it inherits the minimax surface for free. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(verifier): add PROVIDER_VERIFIER_GATE.md — how to run the conformance gate The Pmoves-MiniMax-Provider-Verifier submodule is registered in the submodule_skill_registry (PR #2589 of the 6-repo fold-in) but had no PMOVES-side doc telling an operator how to use it. The submodule's own README documents the verifier's internals; this doc is the Mavis side: thresholds, invocation, the three failure modes the gate is the only thing that catches (top-k drift, key re-sorting, error-only reasoning), and the CI follow-up that's deliberately out of scope for the wire-up PR. Audience: an operator adding a new MiniMax-compatible provider (Want to add openrouter-minimax? Follow the recipe in §1-3), a reviewer deciding whether to accept a new provider entry, and a future CI maintainer wiring the gate into python-tests.yml. The doc also captures the 'what this is NOT' section: not a load test, not a security test, not a model-quality test. The verifier checks *correctness vs the official baseline*, not throughput or adversarial robustness. That's the load-bearing distinction for any future PR that proposes 'just add a smoke test' as a substitute. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(cli): add MMX_CLI_SURFACE.md — catalog the mmx-cli surface The Pmoves-minimax-cli submodule (npm: mmx-cli, v1.0.19) is the sidecar lane's entry point: Pinokio apps on operator devices, headless scripts, CI jobs. The submodule's own AGENTS.md/SDK.md/ERRORS.md are developer-facing (build rules, programmatic API, full error catalog); this doc is the Mavis-side summary for an operator who needs to know what the CLI can do and when to use it instead of the MCP. Three sections do the load-bearing work: - Command tree (auth, config, file, image, music, quota, search, speech, text, video, vision, help, update) with a one-line purpose + invocation example per command. - SDK surface showing the programmatic entry point (import { MiniMaxSDK } from 'mmx-cli/sdk') for the four core modalities: text, image, video, with the H3 V2 model and the async taskId path for video. - The five errors you'll hit most often, distilled from the 70+ error scenarios in ERRORS.md. The doc points to ERRORS.md for the full taxonomy and notes that scripts should match on the error code, not the message. The closing section 'Why not always call the MCP?' captures the splittest that the sidecar lane has to make: MCP for tool-aware agents, CLI for everything else. The MCP and CLI cover the same model surface; the split is *who's calling*, not *what's being called*. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(skills): add PMOVES_SKILLS_REVIEW.md — review the find-skills meta-skill The skills/PMOVES-skills/ submodule landed via PR #2586 of the 6-repo fold-in as the post-recenter home of the open-skills-ecosystem library (was MiniMax-AI/skills, now vercel-labs/skills). The submodule ships one bundled skill: find-skills, a meta-skill that helps an agent decide 'is there a skill for X?' via the npx skills CLI. This doc is the Mavis-side review: what the submodule brings, what's worth pulling into our catalog, what's worth leaving alone. Three findings: 1. The find-skills skill itself should land in pmoves/configs/skill-pairings.yaml so BoTZ pipelines can surface it to agents on the sidecar lane. One-line addition; documented as a proposed delta in the doc body. 2. The skills CLI should land in pmoves/configs/cli_tools.yaml host_clis so the doctor (make -C pmoves cli-check) validates it alongside the other host CLIs. Also a one-line addition. 3. The PMOVES-specific default --owner POWERFULMOVES should be encoded in the PMOVES-side wrapper, not in the upstream SKILL.md (we don't own it; editing it would create fork drift). Documented here as a behavioral default. The 'leave alone' section makes the recenter discipline explicit: no upstream edits, no PMOVES-MiniMax-skills as a separate submodule, no submodule-level patches. If we need fork-specific behavior, it goes in pmoves/tools/, not in the submodule. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(agents-md): add AGENTS_MD_FORMAT_REVIEW.md — review the open format vs our AGENTS.md The PMOVES-agents.md/ submodule landed via PR #2590 of the 6-repo fold-in as the canonical home of the agentsmd/agents.md open format. The submodule is a Next.js docs site (not a library) at https://agents.md/. This doc is the Mavis-side review: what the open format is, how our PMOVES.AI AGENTS.md compares, and what to adopt. The open format is deliberately minimal — three canonical sections ('Dev environment tips', 'Testing instructions', 'PR instructions'). Our PMOVES.AI AGENTS.md has 12 sections; 4 map to the open format and 8 are PMOVES extensions (Project Structure, Known Roads, env.shared, Compose layering, Coding Style, Secrets, Submodule Workflow, Deployment, Security, AGENTS.md Format Reference). Three adoption items, in priority order: 1. Rename 'Build & Development Commands' → 'Dev environment tips' to match the open format. A one-line content edit; high-signal conformance win. 2. Promote the 'AGENTS.md Format Reference' section to a top-of-file note that points at PMOVES-agents.md/ as the canonical spec home. Also a small edit; better cold-start ergonomics for any agent that knows the open format. 3. Document the 'PMOVES extensions' convention. The 8 PMOVES-specific sections don't have a name in the open format. Pick a marker (e.g. '### PMOVES extension: <name>') and apply it incrementally. All three adoption items are deliberately out of scope for this PR — they're content edits to AGENTS.md, not wire-up work. This doc documents them so the operator can land them in a follow-up. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(cipher): store cipher skill context — what's encrypted, where, CHIT custody Cipher is the PMOVES memory layer; the Mavis-class agent re-reads prior plans on cold start and writes on every BPM phase boundary. The operator's request to 'store cipher context' was about capturing the load-bearing facts in one place, not about adding new code. This doc covers four sections that the rest of PMOVES already references but doesn't pull together: - What cipher is for: persistent agent memory + reasoning trace storage + CHIT custody chain. Three distinct things, one MCP server. - What's encrypted: the memory body (HMAC-SHA256 + AES-256-GCM) via CHIT passphrase. The memory index (titles, timestamps, category) is plaintext so the MCP server can answer searches without decrypting every record. - Where the keys live: \ per-node in env.shared, the host-side and container-side names are the same after the sync-secrets-local.yml fix in PR #2605. HMAC kid public, HMAC secret derived at signing time, never written to disk. - NATS custody chain: cipher publishes three subjects (cipher.memory.stored.v1, cipher.memory.searched.v1, cipher.reasoning.stored.v1) to monitoring. The CHIT signing flow is sign-trail → cipher write → chit.signed.v1 publish, and the HMAC signature is the trust anchor for the AGNOTE append-only chain. The closing 'How a Mavis-class agent should use it' section codifies the three patterns (read on cold start, write on phase boundaries, sign before state-changing actions) so a future Mavis session has the recipe in one place. The 'What cipher is NOT' section captures the boundary: not a search engine, not a database, not a KV store, not a real-time channel. Each of these has its own PMOVES subsystem; cipher is the memory. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * docs(hirag): store HiRAG context — submodule state, what's wired, what's pending HiRAG is PMOVES's hybrid retrieval layer (vector + graph + full-text). The operator's request to 'store HiRAG context' was about capturing the surface in one place, not adding new code. The agent registry already declares the MCP server (pmoves_hirag_mcp, status: 'planned', grounding_source: true) but the doc that explains what that entry means, and what an agent should do with it, didn't exist. This doc covers the four sections the rest of PMOVES already references but doesn't pull together: - What HiRAG is: three-way retrieval (Qdrant vector + Neo4j graph + MeiliSearch full-text) merged at the gateway. The legacy and v2 gateways are the two HTTP surfaces; the MCP server is the discovery-friendly entry point. - What's wired: registry entry, compose services (CPU + GPU variants on the legacy profile), smoke test path. Three concrete facts a future Mavis session can use without re-discovering the surface. - What's pending: .claude/mcp.json registration (the registry has the entry; mcp.json doesn't have the server), v2 gateway promotion (v2 is documented as 'preferred' but legacy is what's deployed), submodule freshness check (the algorithm substrate tracks PMOVES.AI-Edition-Hardened, not main, and a drift could land silently). - How a Mavis-class agent should use it: read on cold start for grounding (the registry's grounding_source: true flag is a recipe, not a label), issue hybrid queries for cross-cutting context, fall back to scoped search for narrow questions. The 'What HiRAG is NOT' section captures the boundary: not a primary database, not a real-time index, not a replacement for cipher, not a search engine. Each of these has its own PMOVES subsystem; HiRAG is the hybrid read. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * feat(registry): wire find-skills meta-skill into cli_tools + skill-pairings The skills/PMOVES-skills/ submodule (vercel-labs/skills recenter, PR #2586) ships a find-skills meta-skill that helps an agent decide 'is there a skill for X?' via the npx skills CLI. The CRUSH lane (PR #2599) already wired the mmx-cli and the pmoves Wrappers; this commit lands the two remaining entries that the PMOVES_SKILLS_REVIEW.md review flagged as 'proposed deltas' for the find-skills meta-skill. Two entries in two manifests: - pmoves/configs/cli_tools.yaml: new host_clis entry skills: backing the npx skills CLI. The doctor (make -C pmoves cli-check) now validates the npx skills --version invocation alongside gh, docker, make, uv, glances. required: false (find-skills is a convenience, not a hard requirement). - pmoves/configs/skill-pairings.yaml: two new skill_sources entries - cli-host-skills (matching the cli-host-* naming pattern) and ind-skills (the path to the SKILL.md). The second makes the meta-skill discoverable to BoTZ pipelines that consume the skill_sources block. The PMOVES-side behavioral default '--owner POWERFULMOVES first, then unfiltered' stays in PMOVES_SKILLS_REVIEW.md, NOT in the upstream SKILL.md - editing the upstream would create fork drift. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * test(wireup): add 13 drift-detector tests for the model-cascade wire-up The mcpcli-wireup slice added entries to 5 surfaces: - pmoves/config/agent_registry.yaml (mcp_servers.pmoves_minimax_mcp) - .claude/mcp.json (mcpServers.pmoves-minimax-mcp) - .claude/BOOTSTRAP.md (MCP Entrypoints table) - pmoves/contracts/schemas/pmoves-bootstrap/example.cgp.yaml - pmoves/configs/cli_tools.yaml (host_clis.skills) - pmoves/configs/skill-pairings.yaml (find-skills + cli-host-skills) If any of these entries is removed in a future PR, the harness v0 loses the model surface silently. This test suite parses the actual files (no mocks, no fixtures that would mask drift) and asserts the load-bearing facts of each wire-up entry are present. 13 tests in 5 groups: - agent_registry (3): key, submodule pointer, capabilities - mcp.json (2): key, command + args - bootstrap_md (1): substring presence - example_cgp (2): mcps list, services.minimax block with mcp/cli/verifier - cli_tools (2): host_clis.skills, check command - skill_pairings (3): find-skills key + path, cli-host-skills key The test names name the wire-up explicitly (test_*_minimax_mcp, test_*_find_skills, etc.) so a future rewire has to be intentional: if you rename 'pmoves_minimax_mcp' to 'pmoves_model_mcp', the test fails and the commit message has to address why. CHIT trail unsigned-local; AGNOTE entry to follow at slice close. * agnote: CLAIM+RELEASE the mcpcli-wireup slice (Mavis::MCPCLI-WIREUP-CLAIM-RELEASE) The mcpcli-wireup slice is closed. 11 commits land across 5 surfaces: agent_registry, .claude/mcp.json, BOOTSTRAP.md, the CGP bootstrap profile, and the docs/ + context/ trees. 4 review docs, 4 context docs, 1 test file (13 tests, all green), 1 AGNOTE entry. The 3 NEW model-cascade submodules (PMOVES-MiniMax-MCP, Pmoves-minimax-cli, Pmoves-MiniMax-Provider-Verifier) from PR #2589 of the 6-repo fold-in are now wired into the harness v0 end-to-end. CLAIM+RELEASE row appended per the append-only discipline. The GRAGHITI_MARK trailer (Mavis::MCPCLI-WIREUP-CLAIM-RELEASE::2026-08-18) is the next agent's trust anchor. CHIT trail unsigned-local. AGNOTE-style trail; sign-trail is the operator-step (B850 has the trail-signed lane). LEARNINGS file follows in the next commit. * learnings: add mcpcli_wireup_LEARNINGS.md — capture the 5 patterns from this slice 5 patterns captured in §2: 2.1 Why docs, not a new CLI — the operator's 'no need to hand roll' rule. When the tool is already installed and the operator said 'don't hand-roll', the PMOVES-side work is wire-up + docs, not new code. New code is the trap. 2.2 The 5-surface wire-up pattern — when an MCP server enters the harness, it gets registered in 5 places: agent_registry mcp_servers, .claude/mcp.json, BOOTSTRAP.md, the CGP mcps list, and the CGP services block. Skipping any one leaves a gap that will bite later. 2.3 The transport field is not 'always SSE' — the stdio entries use command + args + env instead of endpoint. The schema accepts both shapes via additionalProperties: true. 2.4 'Grounding source' is a recipe, not a label — the flag tells the discovery plane to fetch startup grounding from the server on cold start. Set it for memory/retrieval/model surfaces; skip it for tools used during a task. 2.5 The drift detector pattern — wire-up work is best tested by parsing the files and asserting presence/shape, not by running the resulting system. The unit test names name the wire-up so a future rename is explicit. Cross-refs in §4 point at every file this slice touched, plus the related PRs (2586, 2589, 2590, 2568, 2599) and the operator (three-body delivery=Mavis, control=DARKXSIDE, memory=this trail). CHIT trail unsigned-local. * fix(cgp): add minimax to v1.schema.json services whitelist The CI caught what local YAML validation missed: the pmoves-bootstrap v1 schema enforces additionalProperties:false on the top-level services object (to catch typo'd service names like 'tnailscale'). My example.cgp.yaml adds a minimax: block to services.minimax, which the schema rejected with 'Additional properties are not allowed (minimax was unexpected)'. Failing tests (pmoves/tools/tests/test_load_bootstrap.py + test_orchestrator.py): 20+ tests, all cascading from the same root cause. Fix: add minimax to schema.services.properties with the same additionalProperties:true / typed-string properties pattern as tailscale / rustdesk / hostinger / cloudflare. The block names the 4 submodule paths (mcp, cli, verifier, pinokio) so a future typo in the path string is caught at the schema level rather than silently passing through. All 36 tests in test_load_bootstrap.py + test_orchestrator.py pass after the fix; 13/13 drift-detector tests in test_mcpcli_wireup.py also still pass. CHIT trail unsigned-local; this is a fix-up commit in the 3-stacked group. * fix(mcp): pin minimax-mcp to the audited submodule version `uvx minimax-mcp` with no version resolves the latest PyPI release at every cold start, in the one file whose line 2 declares: "Dependencies pinned to exact versions on 2026-05-14 to prevent supply chain attacks (F-07). Re-pin after auditing new releases before upgrading." Every other server in the file follows that (hostinger-api-mcp@0.2.1, tailscale-mcp@2026.4.10-1, postgres-mcp@0.3.0, ...). This entry did not, while its own _purpose names an audited submodule commit it never actually invoked. The pin is unambiguous rather than a guess: the gitlink on this branch is f4d6a61b, and that commit's pyproject.toml declares version 0.0.18 -- the same as the current PyPI latest. So pinning changes nothing today and prevents the next release from arriving unreviewed. minimax-mcp is a 0.0.x package (18 releases), so "latest" carries no API-stability promise either. Also extended the file's own inventory note so the pin is recorded where the policy is stated, not only at the call site. Out of scope, reported not fixed: `huggingface` -> `@llmindset/hf-mcp-server` is also unpinned. Pre-existing, unrelated to this lane. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(mcpcli): assert the minimax pin, not just the package name The pin in the previous commit broke this PR's own test, which asserted `"minimax-mcp" in args` — true only for the bare, unpinned form. Tightened rather than relaxed: it now requires a `minimax-mcp==<version>` entry, so the exact-version policy declared on line 2 of .claude/mcp.json is enforced by a test instead of by convention. A future edit that drops back to the bare package name fails here. 13 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(rooms): point pmoves_minimax_mcp at real rooms (not a fabricated one) The pmoves_minimax_mcp entry I added in commit e6621fe included rooms: ['minimax-mcp.room.model', 'hermes-agent.room.control']. The first one is a made-up name — no such room exists in pmoves/config/rooms/. The 4090 hit this when trying to bind: 'binding leads nowhere' = the catalog has no minimax-mcp.room.model to bind to. Existing MCPs reference the rooms where they're actually consumed: - cipher → z890-infra.room.fabric - nats → z890-infra.room.fabric, hermes-agent.room.control - voice → 5090-voice.room.studio - e2b → 4090-field.room.control, hermes-agent.room.control The minimax MCP is consumed by: - z890-infra.room.fabric — Mavis's runtime home (matches cipher/nats) - hermes-agent.room.control — Hermes consumer (matches e2b/hirag) - darkxsides.room — the DARKXSIDE persona, which calls Mavis Replaced 'minimax-mcp.room.model' with the real 3-room list. No schema change needed (rooms is a free-form string array). 13/13 drift-detector tests + 24/24 bootstrap tests still pass. CHIT trail unsigned-local; this is a fix-up commit in the 3-stacked group for #2612, blocking 4090's admin-merge. * fix(docs): finish the py -> python correction across all three surfaces test_bootstrap_and_gate_doc_agree_on_invoke caught this, which is exactly its job: #2623 fixed the WORKFLOW to invoke `python` (the job is ubuntu-latest and `py` is the Windows launcher, absent there), but the two discoverability surfaces still told a reader to run `py`. .claude/BOOTSTRAP.md:30 -> python pmoves/docs/operations/PROVIDER_VERIFIER_GATE.md:83 -> python (in the merge) The test itself asserted `py` in both its body and its docstring, so it was enforcing the drift rather than catching it -- the same shape as the three tests corrected in #2623. Inverted, with the reason recorded so it does not drift back. Worth naming: the command appeared in FOUR places and the fix in #2623 touched one. A cold-start agent reading BOOTSTRAP.md would still have run a command that exits 127. The agreement test is what made the remaining three findable. 16 passed, 3 skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Mavis <Mavis@pmoves.local> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
6-repo fold-in — PR3 (PMOVES-agents.md)
Scope: PR3 of 3 in the 6-repo fold-in slice. Operator chose 3 separate PRs for revert granularity.
skills/PMOVES-skills/(vercel-labs/skills post-recenter home)d4af79f325skills_foldin_pr1_LEARNINGS.mdPMOVES-MiniMax-MCP+Pmoves-minimax-cli+Pmoves-MiniMax-Provider-Verifiermcpcli_foldin_pr2_LEARNINGS.mdPMOVES-agents.md/(agentsmd/agents.md open format)agents_md_foldin_pr3_LEARNINGS.mdWhat lands (1 new top-level submodule)
.gitmodules— new[submodule "PMOVES-agents.md"]entrypath = PMOVES-agents.mdurl = https://github.com/POWERFULMOVES/PMOVES-agents.md.gitbranch = mainPMOVES-agents.md/— new gitlink pointer at the upstream HEADd1ac7f063d20e70015ed6732664049ae4ba9d74e(POWERFULMOVES fork ofagentsmd/agents.mdmain)Why top-level (not under
skills/):PMOVES-agents.mdis a format/taxonomy reference (the agents.md open spec + agent taxonomy + persona schema), not a runtime-invokable agent skill. Agents load the format spec on Tier-2; they don't invoke it. Theskills/tree is reserved for runtime skills (claude-d3js, agent-sandbox, etc.).Files touched (PR3 net additions only)
.gitmodules[submodule "PMOVES-agents.md"]block (path/url/branch)PMOVES-agents.mdd1ac7f0....claude/context/submodules.md### PMOVES-agents.mdsubsection, mirroring theskills/*table format below for scannability; pre-existing detailed bullet list (Path / Repository / Upstream / Purpose / Tier / Cross-refs) preserved unchangedpmoves/configs/submodule_skill_registry.jsonPMOVES-agents.mdentry (context_tier=2, domain_tags=["agents","docs"]) with$notedocumenting the canonical-home purpose + the top-level placement decisionpmoves/docs/AGENTS/AGNOTE4482PHI.t1.mdMavis::AGENTS-MD-FOLDIN::2026-08-17appended at the end of the fileagents_md_foldin_pr3_LEARNINGS.mdAcceptance criteria
PMOVES-agents.md/exists as a gitlink at the upstream HEADd1ac7f0...56df840207).gitmoduleshas the entry (url=POWERFULMOVES/PMOVES-agents.md, branch=main).claude/context/submodules.mdhas a sibling table row (mirroringskills/*table format)224a727559)pmoves/configs/submodule_skill_registry.jsonhas the new entry (context_tier=2, domain_tags=["agents","docs"])python -c "import json; json.load(...)"succeeds (58 submodules, +1 over pre-PR3)3fb661fb94)d4af79f325(post-PR1 main)56df840207→224a727559→3fb661fb94--adminfor the local commitsgit push -u originonlyPre-merge check output
The diff vs
c5845f1a3e(the fold-in base) includes both PR1's merged changes and PR3's net additions. The PR3-only net is 6 files:.gitmodules(+4),PMOVES-agents.md(+1),.claude/context/submodules.md(+6),pmoves/configs/submodule_skill_registry.json(+8),pmoves/docs/AGENTS/AGNOTE4482PHI.t1.md(+2),agents_md_foldin_pr3_LEARNINGS.md(+101). Total PR3 delta: 122 lines across 6 files.Out of scope (intentional, lives in other PRs of the fold-in)
PMOVES-skills(skills/PMOVES-skills/) — already MERGED as PR1 feat(submodule): 6-repo fold-in PR1 - PMOVES-skills (vercel-labs/skills post-recenter home) #2586 atd4af79f325.PMOVES-MiniMax-MCP,Pmoves-minimax-cli,Pmoves-MiniMax-Provider-Verifier) — PR2 in a parallel worktree, with its ownmcpcli_foldin_pr2_LEARNINGS.mdfile.POWERFULMOVES/Pmoves-Minimax-skills) — preserved as a reference inskills/README.md(PR1), not added as a separate submodule..claude/context/submodules.md— pre-existing stale count (actual is 58 post-PR3). Documented in the LEARNINGS file; fixing it is a separate cleanup slice, not in PR3 scope.Cross-refs
pmoves/docs/AGENTS/AGNOTE4482PHI.t1.mdrowMavis::AGENTS-MD-FOLDIN::2026-08-17(appended in commit 3)agents_md_foldin_pr3_LEARNINGS.mdat the worktree root (new file, commit 3)skills_foldin_pr1_LEARNINGS.md(merged in feat(submodule): 6-repo fold-in PR1 - PMOVES-skills (vercel-labs/skills post-recenter home) #2586, lives in the main tree post-merge)mcpcli_foldin_pr2_LEARNINGS.md(separate worktree, not in this PR)Three-body
submodules.mdandsubmodule_skill_registry.jsonCHIT trail unsigned-local.