chore(submodule): promote PMOVES-hermes-agent to hardened tip (42 upstream commits) - #2511
Conversation
📝 WalkthroughWalkthroughThe ChangesHermes agent update
Estimated code review effort: 1 (Trivial) | ~2 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
🔏 CHIT-aware change — control-body routingThis PR touches a CHIT-aware service (ports 8086/8087/8103/8106/8113/9224 surface). Before a Control-Body ACK:
Advisory routing only — the blocking contract check is CHIT Contract. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50334650af
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50334650af
ℹ️ 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".
There was a problem hiding this comment.
Actionable comments posted: 18
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (9)
pmoves/config/profiles/dgx-spark-grace-blackwell.yaml-22-31 (1)
22-31: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winSynchronize the sidecar architecture documentation.
pmoves/docker-compose.spark-sidecar.ymlstill documentsSM_110in its DGX Spark header. This profile now declaresSM_121. Update the sidecar header in this PR so operators do not use the obsolete architecture target.As per coding guidelines, “update documentation or schemas when interfaces change.”
🤖 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/profiles/dgx-spark-grace-blackwell.yaml` around lines 22 - 31, Update the DGX Spark header in the sidecar configuration to replace the obsolete SM_110 architecture target with SM_121, matching the compute_capability and tags declared in the profile.Source: Coding guidelines
pmoves/services/hf-research-agent/main.py-168-168 (1)
168-168: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUpdate the maximum-score test contract.
Line 168 now reports
110.pmoves/tests/services/test_hf_services.py, Line 187 still expects100. The existing test will fail.Proposed test update
- assert result["max_score"] == 100 + assert result["max_score"] == 110🤖 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/services/hf-research-agent/main.py` at line 168, Update the maximum-score expectation in the relevant test case of test_hf_services.py to match the 110 returned by the max_score calculation in the HF research agent, preserving the existing assertion structure..gitignore-360-360 (1)
360-360: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winScope the
20.mdignore rule.Line [360] ignores every file named
20.mdat any directory depth. This can silently exclude unrelated documentation. If this is a root-level generated artifact, anchor the rule.Proposed fix
-20.md +/20.md🤖 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 @.gitignore at line 360, Scope the 20.md ignore rule to the repository root by anchoring the pattern, so nested documentation files named 20.md remain trackable.pmoves/services/flute-gateway/providers/ultimate_tts.py-365-377 (1)
365-377: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winValidate the complete custom emotion vector before enabling
vector_control.Line 374 accepts values outside the documented
[0,1]range. It also acceptsnanand infinity. Lines 375-376 skip invalid components, but Line 377 still enablesvector_control. This sends a partial vector with schema defaults in the skipped positions.Parse all eight components first. Reject the vector unless every component is finite and within
[0.0, 1.0]. Enableindextts2_emotion_modeonly after validation succeeds.🤖 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/services/flute-gateway/providers/ultimate_tts.py` around lines 365 - 377, Update the indextts2 voice handling around emotion_names and set_by_name to parse all eight vector components before applying any values. Reject the vector if any component is non-numeric, non-finite, or outside [0.0, 1.0], and only then set the components and enable indextts2_emotion_mode to vector_control; do not leave partial values applied for invalid vectors.pmoves/docs/handoffs/DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md-13-13 (1)
13-13: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAdd language identifiers to the fenced blocks.
Use
textfor the architecture tree andshellfor the local-stack commands. This resolves MD040.Also applies to: 40-40
🤖 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/docs/handoffs/DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md` at line 13, Update the fenced code blocks in DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md by adding the text language identifier to the architecture tree block and shell to the local-stack command block, including the additionally referenced block, so all fences satisfy MD040.Source: Linters/SAST tools
pmoves/docs/handoffs/DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md-55-76 (1)
55-76: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winMark the closing safety statement as target state.
The document says integration and secrets are not wired, and Phases 1–3 are future actions. The final sentence says the capability is already active. Rewrite it as a target state or link completed smoke and runbook evidence.
Also applies to: 174-174
🤖 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/docs/handoffs/DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md` around lines 55 - 76, Update the closing safety statement in the handoff document to describe the E2B capability as a target state, consistent with the unwired integrations and future Phases 1–3. Alternatively, retain an active-state claim only if it links concrete completed smoke-test and runbook evidence.Source: Path instructions
pmoves/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md-12-22 (1)
12-22: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAdd language tags to both diagram fences.
Line 12 and Line 52 start fenced blocks without a language. Add
textto satisfy markdownlint MD040.Proposed markdown fix
-``` +```textAlso applies to: 52-81
🤖 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/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md` around lines 12 - 22, Add the text language tag to both fenced code blocks in the document, including the diagram beginning with “PMOVES.AI Agents” and the second block around the referenced later section, so each opening fence is ```text and satisfies markdownlint MD040.Source: Linters/SAST tools
pmoves/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md-204-209 (1)
204-209: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winModel
/dev/ttyUSB0as a device in Compose.If this service supports local RNode LoRa, describe
/dev/ttyUSB0as a device mapping, not a volume. Usedevices: - "/dev/ttyUSB0:/dev/ttyUSB0"or a stable/dev/serial/by-id/...mapping in the Compose service.🤖 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/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md` around lines 204 - 209, Update the reticulum-bridge service definition in docker-compose.yml so the local RNode path is declared under devices rather than volumes. Map /dev/ttyUSB0 to the same container path, or use a stable /dev/serial/by-id mapping, while preserving the existing service configuration.pmoves/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md-94-97 (1)
94-97: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winUse one exact LoRa profile across both lists.
SF7-9and the missingtxpowermake the RNode provisioning inconsistent with the RNS block. Select one exact spreading factor and transmit power, then use the same values in the flashing instructions and the[[LoRa RNode]]config.🤖 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/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md` around lines 94 - 97, Update the RNode flashing instructions and the [[LoRa RNode]] configuration to use one identical LoRa profile: replace the SF7-9 range with a single spreading factor and add an explicit txpower value matching the RNS block. Ensure frequency, bandwidth, spreading factor, coding rate, and transmit power are consistent in both sections.Source: MCP tools
🤖 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 @.gitmodules:
- Around line 384-398: Add the missing PMOVES-ollama gitlink entry to the parent
index with mode 160000 and ensure it matches the existing PMOVES-ollama
registration in .gitmodules; alternatively remove that registration if the
submodule is not intended to be tracked.
In `@PMOVES-fluidd`:
- Line 1: Update the PMOVES-fluidd gitlink to a commit reachable from its
configured submodule remote, using the exact valid upstream commit and
documenting the branch justification as required; otherwise revert the
PMOVES-fluidd submodule update to the previous reachable revision.
In `@pmoves/config/profiles/dgx-spark-grace-blackwell.yaml`:
- Around line 105-115: Update the torch_requirements pip_install entry to pin
both torch and torchaudio to the verified 2.11.0+cu130 versions, while
preserving the existing cu130 index URL and surrounding profile configuration.
In `@pmoves/docker-compose.yml`:
- Around line 3589-3590: Synchronize HF_PREFERRED_TAGS and HF_AVOID_TAGS
defaults between the Compose entrypoints by updating the corresponding
environment entries in docker-compose.agents.yml to use the same fallback values
as this block, or reuse a shared environment source. Preserve explicitly
supplied host values while ensuring unset variables no longer become empty
strings for the research agent.
In `@pmoves/docs/handoffs/DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md`:
- Around line 166-170: Complete the Three-Body section by adding the required
claim row, release row, and signed ACK block, then link the Phase 3 command
evidence. Keep the existing Delivery, Control, and Memory entries intact and do
not treat the handoff as a release artifact until all evidence records are
present.
- Around line 86-91: Update the “Set self-hosted endpoints” instructions to keep
generated E2B secrets out of env.tier-worker and use env.shared or local.env
instead. Direct operators to run make -C pmoves secrets-funnel, configure
E2B_API_KEY_FILE and E2B_ACCESS_TOKEN_FILE, and load those secrets through
get_secret while preserving the endpoint and domain settings.
- Around line 94-100: Update the E2B MCP server specification near the listed
tools to define authentication, authorization, and ingress restrictions for port
8210. Require an explicit authenticated identity and least-privilege policy for
sandbox.create, sandbox.execute, and desktop-control tools, restrict ingress to
approved internal callers, and state that pmoves_app and pmoves_api network
membership is not an authorization mechanism.
- Around line 122-129: Update the Phase 3 validation sequence around
sandbox.execute to trigger every event in the expected five-subject set: add a
desktop click/type action and a spell invocation, then retain verification for
all subjects. Alternatively, remove subjects that are not exercised from the
expected event set.
- Around line 108-120: Define versioned JSON schemas for each new NATS subject
listed in section 3, and validate every published payload through
services/common/events.py. Register all subjects in
.claude/context/nats-subjects.md, document E2B ports and health endpoints in
.claude/context/services-catalog.md, and keep the five agent entries in
pmoves/config/agent_registry.yaml; include the E2B MCP and Desktop SDK in
.claude/CATALOG.md.
In `@pmoves/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md`:
- Around line 183-209: Complete the Phase 3 contract by defining versioned
*.v1.schema.json payload schemas for each Reticulum/Haven subject, documenting
producer/consumer ownership plus replay and idempotency behavior, and wiring
validation through services/common/events.py. Update the canonical context files
.claude/context/services-catalog.md with port 8220 and /healthz and /metrics,
.claude/context/nats-subjects.md with the new subjects, and
pmoves/config/agent_registry.yaml with the listed agents.
- Around line 276-280: Complete the Three-Body section by adding the required
claim row, work row, release row, and signed ACK block, linking each validation
result to its corresponding record. Ensure the handoff is not marked
production-ready until the full claim → work → sign → release evidence chain is
present.
- Around line 123-128: Update the [interfaces] [[Haven Mesh]] configuration
documentation for AutoInterface to include platform-specific firewall rules
permitting UDP ports 29716 and 42671 on both wlan0 and br-ahwlan. Add an offline
discovery smoke procedure covering reachability among wlan0, br-ahwlan, and
AirHop peers, including the expected successful result.
- Around line 163-179: Update the Fleet Bridge TCPServerInterface configuration
so it is reachable only through KVM4-2’s Tailscale address or an equivalent
host-firewall/device restriction; remove the unrestricted listen_ip value of
0.0.0.0 while preserving tailnet access for PMOVES nodes.
- Around line 226-229: Replace the unverified qwen3:30b statement in the Jetson
deployment flow with a testable model contract specifying the Orin Nano memory
SKU, exact quantized Ollama model tag, context length, and runtime. Add
cold-start and sustained-inference smoke-test requirements, and define a smaller
fallback model/tag selected when the 30B model cannot fit within container
memory.
- Around line 87-97: Update the Haven and RNode flashing instructions to record
immutable commit or release identifiers for the OpenWRT/MorseMicro image and
RNode binary, and require checksum or signature verification before flashing.
Also replace the Jetson-side unpinned pip3 install rns command with an
explicitly pinned RNS version.
- Around line 211-215: Update the “CHIT + Geometry Bus alignment” section to
account for the complete Reticulum/LoRa wire packet rather than only the raw CGP
state vector: include bridge metadata, signing/encryption overhead, and the
selected RNode configuration in the size budget. Define a maximum-size smoke
test and specify whether oversized packets are fragmented or rejected.
In `@pmoves/tools/beats_to_voice.py`:
- Around line 271-273: Replace the predictable timestamp-based path in the
synthesis output flow with a securely generated unique temporary file using
tempfile.NamedTemporaryFile(delete=False, suffix=".wav") or tempfile.mkstemp().
Write audio_bytes to that file and return the generated path, preserving the
existing WAV output behavior.
- Around line 249-255: Update synthesize_prosodic_speech() and its payload
construction so the prebuilt prosodic_chunks are included using the request
field or encoding required by Flute-Gateway’s /v1/voice/synthesize/prosodic
contract. Ensure the synthesis request sends the parsed boundary, pause,
duration, pitch, and position data instead of reconstructing only from
request.text, and keep the client aligned with the server’s supported request
schema.
---
Minor comments:
In @.gitignore:
- Line 360: Scope the 20.md ignore rule to the repository root by anchoring the
pattern, so nested documentation files named 20.md remain trackable.
In `@pmoves/config/profiles/dgx-spark-grace-blackwell.yaml`:
- Around line 22-31: Update the DGX Spark header in the sidecar configuration to
replace the obsolete SM_110 architecture target with SM_121, matching the
compute_capability and tags declared in the profile.
In `@pmoves/docs/handoffs/DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md`:
- Line 13: Update the fenced code blocks in
DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.md by adding the text language
identifier to the architecture tree block and shell to the local-stack command
block, including the additionally referenced block, so all fences satisfy MD040.
- Around line 55-76: Update the closing safety statement in the handoff document
to describe the E2B capability as a target state, consistent with the unwired
integrations and future Phases 1–3. Alternatively, retain an active-state claim
only if it links concrete completed smoke-test and runbook evidence.
In `@pmoves/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.md`:
- Around line 12-22: Add the text language tag to both fenced code blocks in the
document, including the diagram beginning with “PMOVES.AI Agents” and the second
block around the referenced later section, so each opening fence is ```text and
satisfies markdownlint MD040.
- Around line 204-209: Update the reticulum-bridge service definition in
docker-compose.yml so the local RNode path is declared under devices rather than
volumes. Map /dev/ttyUSB0 to the same container path, or use a stable
/dev/serial/by-id mapping, while preserving the existing service configuration.
- Around line 94-97: Update the RNode flashing instructions and the [[LoRa
RNode]] configuration to use one identical LoRa profile: replace the SF7-9 range
with a single spreading factor and add an explicit txpower value matching the
RNS block. Ensure frequency, bandwidth, spreading factor, coding rate, and
transmit power are consistent in both sections.
In `@pmoves/services/flute-gateway/providers/ultimate_tts.py`:
- Around line 365-377: Update the indextts2 voice handling around emotion_names
and set_by_name to parse all eight vector components before applying any values.
Reject the vector if any component is non-numeric, non-finite, or outside [0.0,
1.0], and only then set the components and enable indextts2_emotion_mode to
vector_control; do not leave partial values applied for invalid vectors.
In `@pmoves/services/hf-research-agent/main.py`:
- Line 168: Update the maximum-score expectation in the relevant test case of
test_hf_services.py to match the 110 returned by the max_score calculation in
the HF research agent, preserving the existing assertion structure.
🪄 Autofix
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 Plus
Run ID: 784d2317-dd08-46a2-a455-850bf2836fe8
📒 Files selected for processing (15)
.gitignore.gitmodulesPMOVES-OctoPrint-ObicoPMOVES-OrcaSlicerPMOVES-fluiddPMOVES-hermes-agentPMOVES-moonraker-obicoPMOVES-obico-serverpmoves/config/profiles/dgx-spark-grace-blackwell.yamlpmoves/docker-compose.ymlpmoves/docs/handoffs/DARKXSIDE_E2B_DESKTOP_FANOUT_2026-08-06.mdpmoves/docs/handoffs/DARKXSIDE_HAVEN_RETICULUM_FANOUT_2026-08-06.mdpmoves/services/flute-gateway/providers/ultimate_tts.pypmoves/services/hf-research-agent/main.pypmoves/tools/beats_to_voice.py
…tream commits) 863e3131 -> 40765f769c on PMOVES.AI-Edition-Hardened. Pure upstream sync — NousResearch/hermes-agent main merged via fork-sync PR #3 (admin-merged; the only failing check was upstream contributor attribution which does not apply to a pure sync). Zero PMOVES-authored commits in the delta. 42 commits advance on the hardened branch. Unblocks Mavis join on SPARK + the Evolution Fabric Wave 0 three-body review (Crush + Hermes + Archon) per SPARK_EVOLUTION_FABRIC_HANDOFF_2026-08-04.md.
|
Rebased onto Conflict was Two commits dropped by the rebase as already-upstream — the DARKXSIDE fan-out briefs + fleet cleanup scripts, and the 5 maker/3D-printing submodules. Both are on main already, so the branch correctly reduces to the one thing its title claims: the hermes-agent gitlink promotion. One note for anyone auditing this rebase, because it nearly produced a false report. Checking whether the maker submodules were on main with: git show origin/main:.gitmodules | grep 'path = PMOVES-fluidd'returned nothing on Windows — Git Bash rewrites The 26 open review threads are untouched by this and still need a pass. agent_signature (advisory, unsigned-local): |
5033465 to
148b68b
Compare
…ned tip The promoted gitlink was 40765f769c462f7dd91c7b3a7bc7b1be4ee5e4f7, which does not exist in POWERFULMOVES/PMOVES-hermes-agent. Only the abbreviated SHA 40765f769c was ever handled; the remaining 30 hex chars were fabricated, so the parent index pointed at an unreachable object and any clone --recurse-submodules would have failed. Real PMOVES.AI-Edition-Hardened tip is 40765f769c2de35e64cca1b14ba4e93370098dad (same 10-char prefix). Verified against the remote: git ls-remote -> refs/heads/PMOVES.AI-Edition-Hardened = 40765f769c2de35e... compare 863e3131...40765f769c2de3 -> status=ahead, behind_by=0, 42 commits Delta is 42 upstream commits, not the 49 claimed in the PR title. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hedge-trim disposition — all 26 review threadsThis PR was rebased onto 0 of 26 were live against the current diff. Resolving all 26 as outdated-by-rebase. But the review did find a real bug — in the one line that is still hereThe promoted gitlink was Only the abbreviated SHA Real Fixed in d5a692a. Gitlink now verifies: commit exists, is on the tracked branch, and Also corrected: the delta is 42 upstream commits, not the 49 in the original title (the commit body and PR description already said 42). Upstream risk scan (42 commits, 110 files)
Follow-ups for
|
…ax_score is 110) _evaluate_model returned "max_score": max_score + 10 (= 110) while test_hf_services.py asserted max_score == 100 — a deterministic failure the moment the HF suite's imports resolve. It is currently masked: the whole class is skipif-guarded and aiohttp is absent, so all 21 tests skip rather than fail. The code was right and the test was stale. Criteria 1-4 award 40+25+20+15 = 100 and Criterion 5 adds a further +10 compatibility bonus, so 110 is the genuinely attainable maximum — verified by scoring a model that hits every criterion and landing on exactly 110. Nothing keys off max_score functionally: MIN_SCORE is an absolute threshold (50), not a percentage, there is no hf.model.evaluated.v1 schema pinning the field, and the only other reader is a log denominator. So rather than flip the assertion, the scale is now stated once: BASE_MAX_SCORE = 100 # 40 + 25 + 20 + 15 COMPAT_BONUS_POINTS = 10 # Criterion 5 MAX_SCORE = BASE_MAX_SCORE + COMPAT_BONUS_POINTS Criterion 5 and the returned max_score both read those constants, so the denominator can no longer drift from the rubric that produces it. Tests assert against the constants, plus new coverage for the bonus itself (measured as a delta between two otherwise-identical models, so it holds regardless of the env-derived PREFERRED_TAGS/AVOID_TAGS sets). Surfaced by the #2511 review (Codex P1); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
.gitmodules registers PMOVES-ollama (path/url/branch/ignore) but main carried no mode-160000 entry at that path: 65 registered paths against 64 gitlinks, with PMOVES-ollama the only orphan. Not a lost pin — a split landing. #2365 merged the .gitmodules entry, but the commit that adds the gitlink (5047cec, 'pin PMOVES-ollama gitlink to hardened HEAD') is still sitting unmerged on the local branch feat/ollama-submodule with no open PR. This restores that stranded half. Pin is 8d8c701d6a8a7f4129488d7698e3ae02d24e223c, verified against the remote rather than copied from the stranded commit: git ls-remote .../PMOVES-ollama.git refs/heads/PMOVES.AI-Edition-Hardened -> 8d8c701d6a8a7f4129488d7698e3ae02d24e223c which matches the branch recorded in .gitmodules. Registered paths and gitlinks are now 65/65 with no orphans. Surfaced by the #2511 review (CodeRabbit); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…licy check goes green submodule-branch-policy-check was already failing on main — 5 submodules with no branch field at all and 5 more pinned to a branch the allow-list did not cover. Missing branch is not cosmetic: validate_submodule_gitlinks.sh skips branch/ancestry validation for those entries and gitlink-promoter.yml never discovers them, so they sit outside the hardened update workflow entirely. The obvious fix is wrong. None of the five maker forks has a PMOVES.AI-Edition-Hardened branch, so applying SUBMODULE_BRANCH_DEFAULT would have written five branch names that do not exist — the same defect class as the #2511 gitlink that prompted this. Each fork has exactly one branch, the upstream default, confirmed by git ls-remote: PMOVES-obico-server release PMOVES-moonraker-obico master PMOVES-OrcaSlicer main PMOVES-OctoPrint-Obico master PMOVES-fluidd develop Every gitlink on main already points at exactly that branch's tip, so recording these is describing reality, not changing what is checked out. Non-hardened branches go in SUBMODULE_BRANCH_ALLOW, the mechanism already used for PMOVES-ClawZ=main. The five skills/* forks legitimately track main and are added the same way; without them the gate stays red and the branch fields above cannot be verified. make -C pmoves submodule-branch-policy-check before: FAIL (5 missing branch, 5 policy mismatches) after: PASS - checked: 65 Out of scope, do not fix twice: PR #2493 adds PMOVES-nats-server with no branch key and is still open, so it will reintroduce a missing-branch failure when it lands. Its fork tracks main. Surfaced by the #2511 review (Codex P2 / CodeRabbit); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ax_score is 110) _evaluate_model returned "max_score": max_score + 10 (= 110) while test_hf_services.py asserted max_score == 100 — a deterministic failure the moment the HF suite's imports resolve. It is currently masked: the whole class is skipif-guarded and aiohttp is absent, so all 21 tests skip rather than fail. The code was right and the test was stale. Criteria 1-4 award 40+25+20+15 = 100 and Criterion 5 adds a further +10 compatibility bonus, so 110 is the genuinely attainable maximum — verified by scoring a model that hits every criterion and landing on exactly 110. Nothing keys off max_score functionally: MIN_SCORE is an absolute threshold (50), not a percentage, there is no hf.model.evaluated.v1 schema pinning the field, and the only other reader is a log denominator. So rather than flip the assertion, the scale is now stated once: BASE_MAX_SCORE = 100 # 40 + 25 + 20 + 15 COMPAT_BONUS_POINTS = 10 # Criterion 5 MAX_SCORE = BASE_MAX_SCORE + COMPAT_BONUS_POINTS Criterion 5 and the returned max_score both read those constants, so the denominator can no longer drift from the rubric that produces it. Tests assert against the constants, plus new coverage for the bonus itself (measured as a delta between two otherwise-identical models, so it holds regardless of the env-derived PREFERRED_TAGS/AVOID_TAGS sets). Surfaced by the #2511 review (Codex P1); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
.gitmodules registers PMOVES-ollama (path/url/branch/ignore) but main carried no mode-160000 entry at that path: 65 registered paths against 64 gitlinks, with PMOVES-ollama the only orphan. Not a lost pin — a split landing. #2365 merged the .gitmodules entry, but the commit that adds the gitlink (5047cec, 'pin PMOVES-ollama gitlink to hardened HEAD') is still sitting unmerged on the local branch feat/ollama-submodule with no open PR. This restores that stranded half. Pin is 8d8c701d6a8a7f4129488d7698e3ae02d24e223c, verified against the remote rather than copied from the stranded commit: git ls-remote .../PMOVES-ollama.git refs/heads/PMOVES.AI-Edition-Hardened -> 8d8c701d6a8a7f4129488d7698e3ae02d24e223c which matches the branch recorded in .gitmodules. Registered paths and gitlinks are now 65/65 with no orphans. Surfaced by the #2511 review (CodeRabbit); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…licy check goes green submodule-branch-policy-check was already failing on main — 5 submodules with no branch field at all and 5 more pinned to a branch the allow-list did not cover. Missing branch is not cosmetic: validate_submodule_gitlinks.sh skips branch/ancestry validation for those entries and gitlink-promoter.yml never discovers them, so they sit outside the hardened update workflow entirely. The obvious fix is wrong. None of the five maker forks has a PMOVES.AI-Edition-Hardened branch, so applying SUBMODULE_BRANCH_DEFAULT would have written five branch names that do not exist — the same defect class as the #2511 gitlink that prompted this. Each fork has exactly one branch, the upstream default, confirmed by git ls-remote: PMOVES-obico-server release PMOVES-moonraker-obico master PMOVES-OrcaSlicer main PMOVES-OctoPrint-Obico master PMOVES-fluidd develop Every gitlink on main already points at exactly that branch's tip, so recording these is describing reality, not changing what is checked out. Non-hardened branches go in SUBMODULE_BRANCH_ALLOW, the mechanism already used for PMOVES-ClawZ=main. The five skills/* forks legitimately track main and are added the same way; without them the gate stays red and the branch fields above cannot be verified. make -C pmoves submodule-branch-policy-check before: FAIL (5 missing branch, 5 policy mismatches) after: PASS - checked: 65 Out of scope, do not fix twice: PR #2493 adds PMOVES-nats-server with no branch key and is still open, so it will reintroduce a missing-branch failure when it lands. Its fork tracks main. Surfaced by the #2511 review (Codex P2 / CodeRabbit); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ract, orphan gitlink, branch policy) (#2519) * fix(hf-research-agent): make the scoring scale one source of truth (max_score is 110) _evaluate_model returned "max_score": max_score + 10 (= 110) while test_hf_services.py asserted max_score == 100 — a deterministic failure the moment the HF suite's imports resolve. It is currently masked: the whole class is skipif-guarded and aiohttp is absent, so all 21 tests skip rather than fail. The code was right and the test was stale. Criteria 1-4 award 40+25+20+15 = 100 and Criterion 5 adds a further +10 compatibility bonus, so 110 is the genuinely attainable maximum — verified by scoring a model that hits every criterion and landing on exactly 110. Nothing keys off max_score functionally: MIN_SCORE is an absolute threshold (50), not a percentage, there is no hf.model.evaluated.v1 schema pinning the field, and the only other reader is a log denominator. So rather than flip the assertion, the scale is now stated once: BASE_MAX_SCORE = 100 # 40 + 25 + 20 + 15 COMPAT_BONUS_POINTS = 10 # Criterion 5 MAX_SCORE = BASE_MAX_SCORE + COMPAT_BONUS_POINTS Criterion 5 and the returned max_score both read those constants, so the denominator can no longer drift from the rubric that produces it. Tests assert against the constants, plus new coverage for the bonus itself (measured as a delta between two otherwise-identical models, so it holds regardless of the env-derived PREFERRED_TAGS/AVOID_TAGS sets). Surfaced by the #2511 review (Codex P1); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(submodules): add the missing PMOVES-ollama gitlink .gitmodules registers PMOVES-ollama (path/url/branch/ignore) but main carried no mode-160000 entry at that path: 65 registered paths against 64 gitlinks, with PMOVES-ollama the only orphan. Not a lost pin — a split landing. #2365 merged the .gitmodules entry, but the commit that adds the gitlink (5047cec, 'pin PMOVES-ollama gitlink to hardened HEAD') is still sitting unmerged on the local branch feat/ollama-submodule with no open PR. This restores that stranded half. Pin is 8d8c701d6a8a7f4129488d7698e3ae02d24e223c, verified against the remote rather than copied from the stranded commit: git ls-remote .../PMOVES-ollama.git refs/heads/PMOVES.AI-Edition-Hardened -> 8d8c701d6a8a7f4129488d7698e3ae02d24e223c which matches the branch recorded in .gitmodules. Registered paths and gitlinks are now 65/65 with no orphans. Surfaced by the #2511 review (CodeRabbit); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(submodules): record the real tracked branch for 12 submodules; policy check goes green submodule-branch-policy-check was already failing on main — 5 submodules with no branch field at all and 5 more pinned to a branch the allow-list did not cover. Missing branch is not cosmetic: validate_submodule_gitlinks.sh skips branch/ancestry validation for those entries and gitlink-promoter.yml never discovers them, so they sit outside the hardened update workflow entirely. The obvious fix is wrong. None of the five maker forks has a PMOVES.AI-Edition-Hardened branch, so applying SUBMODULE_BRANCH_DEFAULT would have written five branch names that do not exist — the same defect class as the #2511 gitlink that prompted this. Each fork has exactly one branch, the upstream default, confirmed by git ls-remote: PMOVES-obico-server release PMOVES-moonraker-obico master PMOVES-OrcaSlicer main PMOVES-OctoPrint-Obico master PMOVES-fluidd develop Every gitlink on main already points at exactly that branch's tip, so recording these is describing reality, not changing what is checked out. Non-hardened branches go in SUBMODULE_BRANCH_ALLOW, the mechanism already used for PMOVES-ClawZ=main. The five skills/* forks legitimately track main and are added the same way; without them the gate stays red and the branch fields above cannot be verified. make -C pmoves submodule-branch-policy-check before: FAIL (5 missing branch, 5 policy mismatches) after: PASS - checked: 65 Out of scope, do not fix twice: PR #2493 adds PMOVES-nats-server with no branch key and is still open, so it will reintroduce a missing-branch failure when it lands. Its fork tracks main. Surfaced by the #2511 review (Codex P2 / CodeRabbit); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…mode cleanup (#2520) * fix(beats_to_voice): write synthesized audio to a secure temp file and clean it up Two defects in the same synthesis path. The output path was the hard-coded literal /tmp/beats_to_voice_{int(time.time())}.wav, with no tempfile import anywhere in the file. That is three problems at once: - it ignores the platform temp directory. On native Windows /tmp resolves to C:\tmp: where that exists (Git Bash provides it) the audio is written to a fixed, shared location at the drive root instead of TEMP; where it does not, open() raises FileNotFoundError and the broad OSError handler reports it as 'Connection failed', misattributing a local filesystem error to the network and discarding audio that was already synthesized. - the name is derived from whole seconds, so two calls in the same second silently overwrite each other and can return a path holding another request's audio. The new collision test demonstrates this directly: against the old code both calls return the identical path. - the name is predictable, so a local actor with access to that directory can pre-create a symlink there and redirect the write. Now tempfile.mkstemp(prefix=..., suffix='.wav'), which honours TMPDIR/TEMP, creates the file 0600, and never returns the same path twice. Separately, listen mode leaked every file it created. _handler extracts and publishes the CGP packet and never reads the WAV, so a sustained voice.agent.response.v1 stream left one file behind per trigger until the disk filled. The pipeline result is now cleaned up in a finally block, so the audio is dropped even when publishing raises. Tests cover both, and were confirmed to fail against the pre-fix module (7 of 8 fail there, 8 pass here) rather than passing vacuously. Surfaced by the #2511 review (Codex P1 + P2, CodeRabbit); not introduced by it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(beats_to_voice): only delete tempfiles this process created; clean up failed writes Two review findings on the listen-mode cleanup, both reproduced as failing tests before the fix. P1 — arbitrary deletion. `synthesize_prosodic` returns the decoded JSON body verbatim when Flute answers with a non-audio content-type, so the `synthesis` dict — and its `output` value — can come straight from the gateway. `_discard_synthesized_audio` then unlinked it unconditionally, so a remote or misconfigured endpoint answering `{"output": "/home/service/data.db"}` gets that file deleted by the listen loop, as any file the process can write. Cleanup is now restricted to paths this process created via mkstemp, tracked in `_OWNED_TEMPFILES` and consumed on use; anything else is refused with a message. P2 — orphaned tempfiles. mkstemp creates the file before the write, so an OSError while writing or closing left a zero-byte or partial file behind: the outer handler returns None, no caller learns a path to clean up, and each retry allocates a fresh unique name. Failure now closes and unlinks before re-raising. Closing the descriptor first is load-bearing and cost me a red test: `fdopen` only takes ownership of the fd when it succeeds, and Windows refuses to unlink a file that still has an open handle — so unlink alone left the file in place on exactly the platform this PR exists to support. Also hardened the chained `.get()` walk: a JSON body need not be an object, and `{"synthesis": []}` raised AttributeError inside the cleanup path. All four new tests fail on the pre-fix tool and pass after: test_refuses_a_path_this_process_did_not_create AssertionError: cleanup deleted a path the process never created test_second_discard_is_a_no_op AssertionError test_non_dict_synthesis_is_a_no_op AttributeError: 'list' object has no attribute 'get' test_failed_write_removes_the_tempfile AssertionError: the partially- written tempfile was left behind 12 passed after. The pre-existing `test_removes_the_synthesized_file` was rewritten to obtain its path from `synthesize_prosodic` rather than a bare mkstemp — under the ownership rule, deleting an unowned path is the behaviour being removed, so a test asserting it would have been asserting the defect. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…08-18) The claim register's last SPARK-KIMI entry was 2026-05-27; this session landed eight lanes that were never registered. One CLAIM+RELEASE entry registers them with live-main merge verification for each: - Hermes unblock chain (fork sync #3 + gitlink #2511) - P7 legacy stanza fix #2549 (+ pr-monitor bot classifier fix) - PMOVES-crush visual ecosystem (#10/#11 + promotion #2571) - pmoves-keygen adoption (fork #1 OPEN, parent #2591) — closes the pending-ml signing-card gap (24/25 cards h-only) - #2515 fleet handoffs docs - Hygiene: 86-commit stack proven landed and retired; 10 worktrees + 5 stashes cleared; cipher-mcp deletion corrected-to-restore - ~100GB disk recovery - P7 migrated to canonical service (13 rooms, NATS connected) Open follow-ups listed unclaimed for the next lane owners. 💘 Generated with Crush
…08-18) The claim register's last SPARK-KIMI entry was 2026-05-27; this session landed eight lanes that were never registered. One CLAIM+RELEASE entry registers them with live-main merge verification for each: - Hermes unblock chain (fork sync #3 + gitlink #2511) - P7 legacy stanza fix #2549 (+ pr-monitor bot classifier fix) - PMOVES-crush visual ecosystem (#10/#11 + promotion #2571) - pmoves-keygen adoption (fork #1 OPEN, parent #2591) — closes the pending-ml signing-card gap (24/25 cards h-only) - #2515 fleet handoffs docs - Hygiene: 86-commit stack proven landed and retired; 10 worktrees + 5 stashes cleared; cipher-mcp deletion corrected-to-restore - ~100GB disk recovery - P7 migrated to canonical service (13 rooms, NATS connected) Open follow-ups listed unclaimed for the next lane owners. 💘 Generated with Crush
…08-18) (#2596) * docs(agents): register the SPARK-KIMI convergence wave (2026-08-10 → 08-18) The claim register's last SPARK-KIMI entry was 2026-05-27; this session landed eight lanes that were never registered. One CLAIM+RELEASE entry registers them with live-main merge verification for each: - Hermes unblock chain (fork sync #3 + gitlink #2511) - P7 legacy stanza fix #2549 (+ pr-monitor bot classifier fix) - PMOVES-crush visual ecosystem (#10/#11 + promotion #2571) - pmoves-keygen adoption (fork #1 OPEN, parent #2591) — closes the pending-ml signing-card gap (24/25 cards h-only) - #2515 fleet handoffs docs - Hygiene: 86-commit stack proven landed and retired; 10 worktrees + 5 stashes cleared; cipher-mcp deletion corrected-to-restore - ~100GB disk recovery - P7 migrated to canonical service (13 rooms, NATS connected) Open follow-ups listed unclaimed for the next lane owners. 💘 Generated with Crush * docs(agnote): SPARK-KIMI lane refresh — coordination split acknowledged, stale VSS claim released Claims the active SPARK lanes under the operator's merge/fix split (4090 merges, Z890 tools, SPARK reviews + registers), and releases the stale feature/spark-vss-submodule-wiring claim after verifying it landed via squash #2277. Generated with Crush * docs(agnote): correct the Hermes commit count and the SPARK registration gap Two review findings on the register entry, both verified against source. Hermes fork-sync #3 advanced 42 upstream commits, not 49. The promotion commit f6c7936 corrects this in its own body ("42 commits advance on the hardened branch"); 49 was the original PR title. A provenance register that preserves a superseded count disagrees with the commit it summarizes. The "last SPARK-KIMI entry was 2026-05-27" claim was false. The same register already holds a SPARK-KIMI claim on 2026-06-01, a CLAIM/RELEASE pair on 2026-07-13, and KIMI-SPARK activity through 2026-07-29. The real unregistered interval is 2026-07-29 -> 2026-08-18. Overstating it by two months would have made lane reconciliation unreliable in exactly the direction that causes duplicate work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Agent Zero <agent.zero@pmoves.ai> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…2855) Fork PR #5 (un-strand the pmoves_bootstrap CGP consumer onto PMOVES.AI-Edition-Hardened) merged. Clean fast-forward (ahead 6, behind 0): 40765f76 -> 4595a549. Every hardened submodule checkout now ships pmoves_bootstrap (was zero — #2511 had skipped the commit). Claude-Session: https://claude.ai/code/session_017g8jC7dupS2ubafo6zPQY6 Co-authored-by: Mavis <Mavis@pmoves.local> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Promotes the
PMOVES-hermes-agentgitlink from863e3131→40765f769conPMOVES.AI-Edition-Hardened.Pure upstream sync — 42 commits advance on the hardened branch. Zero PMOVES-authored commits in the delta. Upstream =
NousResearch/hermes-agent@main, merged via fork-sync PR #3 (admin-merged; the only failing check was upstream contributor attribution which does not apply to a pure upstream sync).Why
Unblocks:
pmoves/docs/handoffs/SPARK_EVOLUTION_FABRIC_HANDOFF_2026-08-04.mdVerification
git ls-files --stage PMOVES-hermes-agent→160000 40765f769c...✓PMOVES.AI-Edition-Hardenedbranch tipTesting
git diff --cachedshows exactly 1 line change (subproject commit SHA)Summary by CodeRabbit